A discord bot for the Nouvelle Aube Airsoft Association
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
9.2 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. const Discord = require('discord.js');
  2. const client = new Discord.Client();
  3. const { Sequelize, Model, DataTypes } = require('sequelize');
  4. const sequelize = new Sequelize({
  5. dialect: 'sqlite',
  6. storage: './database.sqlite'
  7. });
  8. const format = require('util').format;
  9. var ADMIN_ROLENAME = "Cadre du Parti";
  10. var MEMBER_ROLENAME = "Membre du Parti";
  11. var MEMBER_CHANNEL_NAME = "annonces-au-peuple";
  12. var EVERYONE_CHANNEL_NAME = "general";
  13. client.login('token');
  14. class Partie extends Model { }
  15. Partie.init({
  16. date_partie: {
  17. type: DataTypes.DATE,
  18. primaryKey: true,
  19. },
  20. date_fin_exclu: DataTypes.DATE,
  21. max_joueurs: DataTypes.INTEGER
  22. }, { sequelize, modelName: 'Partie' });
  23. class Joueur extends Model { }
  24. Joueur.init({
  25. discord_id: {
  26. type: DataTypes.STRING,
  27. primaryKey: true
  28. }
  29. }, { sequelize, modelName: 'Joueur' });
  30. class Joueur_Partie extends Model { }
  31. Joueur_Partie.init({
  32. id: {
  33. type: DataTypes.INTEGER,
  34. primaryKey: true,
  35. autoIncrement: true
  36. },
  37. participe: {
  38. type: DataTypes.BOOLEAN,
  39. defaultValue: false
  40. },
  41. membre: {
  42. type: DataTypes.BOOLEAN,
  43. defaultValue: false
  44. },
  45. barbeque: {
  46. type: DataTypes.BOOLEAN,
  47. defaultValue: false
  48. },
  49. location: {
  50. type: DataTypes.BOOLEAN,
  51. defaultValue: false
  52. },
  53. envoi_dm: {
  54. type: DataTypes.BOOLEAN,
  55. defaultValue: false
  56. },
  57. date_inscription: {
  58. type: DataTypes.DATE
  59. },
  60. partie_date_partie: {
  61. type: DataTypes.DATE
  62. },
  63. joueur_discord_id: {
  64. type: DataTypes.STRING
  65. },
  66. }, { sequelize, modelName: 'Joueur_Partie' });
  67. Partie.sync({ alter: true });
  68. Joueur.sync({ alter: true });
  69. Joueur_Partie.sync({ alter: true });
  70. function adjust_date(date) {
  71. const today = new Date();
  72. const base_date = new Date(
  73. today.getFullYear(),
  74. date[2].startsWith('0') ? date[2].substring(1, 2) - 1 : date[2] - 1,
  75. date[1].startsWith('0') ? date[1].substring(1, 2) : date[1]
  76. );
  77. if (today < base_date) {
  78. return base_date;
  79. } else {
  80. return new Date(
  81. base_date.getFullYear() + 1,
  82. base_date.getMonth(),
  83. base_date.getDay()
  84. );
  85. }
  86. }
  87. client.on('ready', () => {
  88. console.log(`Logged in as ${client.user.tag}!`);
  89. });
  90. client.on('message', async function(msg) {
  91. if(msg.guild == undefined) return; // Pour que les DM trigger pas les call
  92. const admin_role = msg.guild.roles.cache.find(r => (r.name == ADMIN_ROLENAME));
  93. const member_role = msg.guild.roles.cache.find(r => (r.name == MEMBER_ROLENAME));
  94. const member_channel = msg.guild.channels.cache.find(r => (r.name == MEMBER_CHANNEL_NAME));
  95. const is_admin = msg.member.roles.cache.find(r => (r == admin_role));
  96. if (msg.content.startsWith('/organiser ') && is_admin) {
  97. const args = msg.content.split(/(\s+)/).filter(e => (e.trim().length > 0));
  98. const parser = /^(\d{2})\/(\d{2})$/;
  99. const date_de_partie = adjust_date(args[1].match(parser)).toISOString();
  100. const date_fin_exclu = adjust_date(args[2].match(parser)).toISOString();
  101. const nb_joueurs = parseInt(args[3].match(parser));
  102. const partie = Partie.build({
  103. date_partie: date_de_partie,
  104. date_fin_exclu: date_fin_exclu,
  105. max_joueurs: nb_joueurs
  106. });
  107. partie.save();
  108. const message = await member_channel.send(format(
  109. `
  110. Une partie est organisée le %s!
  111. Réagissez avec 👍 pour recevoir le formulaire d'inscription!
  112. `
  113. , args[1]));
  114. message.react('👍');
  115. const collector = message.createReactionCollector(v => (true), {});
  116. collector.on('collect', async function(m) {
  117. try{
  118. m.users.cache.forEach(async function(user, _) {
  119. const member = await msg.guild.members.fetch(user.id);
  120. console.log(user.id);
  121. const is_member = member.roles.cache.find(r => (r == member_role));
  122. console.log(user);
  123. if(user.id == client.user.id) return;
  124. const j = await Joueur.findOrCreate({where: {discord_id: user.id}, default: {discord_id: user.id}});
  125. var [p, _] = await Joueur_Partie.findOrCreate({
  126. where: {joueur_discord_id: user.id, partie_date_partie: partie.date_partie},
  127. default: {joueur_discord_id: user.id, partie_date_partie: partie.date_partie}
  128. });
  129. if(!p.envoi_dm) {
  130. const discord_user = await client.users.fetch(user.id);
  131. const dms = await discord_user.createDM();
  132. if(is_member || date_fin_exclu <= new Date()) {
  133. const sent_dm = await dms.send(
  134. format(`
  135. Pour vous inscrire à la partie du %s, réagissez à ce message avec l'émote appropriée:
  136. 🔫: Participe à la partie
  137. 🍴: Participe au repas
  138. 🥺: Loue une réplique
  139. : Ce bot n'as pas encore de fonctionalité pour annuler votre inscription, en cas d'annulation, prévenez @asitiglutama#1025
  140. `, args[1]));
  141. await p.save();
  142. await sent_dm.react('🔫');
  143. await sent_dm.react('🍴');
  144. await sent_dm.react('🥺');
  145. const personal_collector = sent_dm.createReactionCollector(v => (true), {});
  146. personal_collector.on('collect', async function(m) {
  147. try {
  148. console.log(m._emoji.name);
  149. for(var [user, rest] of m.users.cache) {
  150. if(user != client.user.id) {
  151. var element = await Joueur_Partie.findOne({where: {joueur_discord_id: user, partie_date_partie: date_de_partie}});
  152. if(m._emoji.name == '🔫') {
  153. const partie = await Partie.findOne({where: {date_partie: date_de_partie}});
  154. const participants = await Joueur_Partie.count({where: {partie_date_partie: date_de_partie, participe: true}});
  155. if(participants >= nb_joueurs) {
  156. const sent_dm = await dms.send("Impossible de vous inscrire, la partie est pleine");
  157. } else {
  158. element.participe = true;
  159. element.date_inscription = new Date();
  160. await element.save();
  161. }
  162. } else if(m._emoji.name == '🍴') {
  163. element.barbeque = true;
  164. await element.save();
  165. } else if(m._emoji.name =='🥺') {
  166. element.location = true;
  167. await element.save();
  168. }
  169. }
  170. }
  171. } catch (ex) {
  172. }
  173. });
  174. p.envoi_dm = true;
  175. await p.save();
  176. } else {
  177. const sent_dm = await dms.send(
  178. format(`
  179. Pour vous inscrire à la partie du %s, vous devez être membre de la NvA ou attendre la fin de l'exclusivité le %s!
  180. `, args[1], args[2]));
  181. }
  182. }
  183. });
  184. } catch(ex) {
  185. console.log(ex);
  186. }
  187. })
  188. } else if (msg.content.startsWith('/liste ') && msg.member.roles.cache.find(r => (r == admin_role))) {
  189. const args = msg.content.split(/(\s+)/).filter(e => (e.trim().length > 0));
  190. const parser = /^(\d{2})\/(\d{2})$/;
  191. const date_de_partie = adjust_date(args[1].match(parser)).toISOString();
  192. const liste = await Joueur_Partie.findAll({where: {partie_date_partie: date_de_partie}});
  193. const dm = await msg.author.createDM();
  194. const participants = await Joueur_Partie.count({where: {partie_date_partie: date_de_partie, participe: true}});
  195. const repas = await Joueur_Partie.count({where: {partie_date_partie: date_de_partie, barbeque: true}});
  196. const loca = await Joueur_Partie.count({where: {partie_date_partie: date_de_partie, location: true}});
  197. await dm.send(format("Liste de la partie du %s\ninscrits=%i\nrepas=%i\nloca=%i", args[1], participants, repas, loca));
  198. for(const element of liste) {
  199. const inscrit = await client.users.fetch(element.joueur_discord_id);
  200. await dm.send(format(inscrit.username)+" "+(inscrit.participe ? "🔫" : "")+(inscrit.barbeque ? "🍴" : "")+(inscrit.location ? "🥺" : ""));
  201. }
  202. }
  203. });