index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. const Discord = require('discord.js');
  2. const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] });
  3. const config = require('./config.json');
  4. var mysql = require('mysql');
  5. var emoji = require('node-emoji');
  6. var urlRegex = /^(ftp|http|https):\/\/[^ "]+$/;
  7. client.on('ready', () => {
  8. if (config.playing !== "") {
  9. client.user.setPresence({ status: 'online', game: { name: config.playing } });
  10. }
  11. console.log(getTimestamp(), `Logged in as ${client.user.tag}!`);
  12. console.log(getTimestamp(), `To send missing messages run ${config.prefix}dump [quantity]`);
  13. });
  14. client.on('message', async message => {
  15. var serverData = undefined;
  16. config.servers.forEach((server) => {
  17. if (message.channel.id==server.channel) serverData = server;
  18. });
  19. let godMode = config.godMode.includes(message.author.id);
  20. if (serverData==undefined && !godMode) return;
  21. if (message.author.bot== true && serverData.allowBots != true) return;
  22. if (godMode && message.content.startsWith(`${(serverData||config).prefix}ping`)) {
  23. message.channel.send('Pong! :ping_pong:');
  24. return;
  25. } else if (godMode && message.content.startsWith(`${(serverData||config).prefix}dump`)) {
  26. console.log(getTimestamp(), 'Warning, dump in progress! May cause slowdows.');
  27. let args = message.content.split(' ');
  28. let channel = null;
  29. try {
  30. if (message.channel.id != args[1]) {
  31. config.servers.forEach((server) => {
  32. if (args[1]==server.channel) serverData = server;
  33. });
  34. }
  35. channel = await client.channels.fetch(args[1]);
  36. } catch (e) {
  37. return;
  38. }
  39. number = Number(args[2]);
  40. //console.log(number);
  41. message.delete({});
  42. async function run(last) {
  43. var fetched = await channel.messages.fetch({limit: isNaN(number) ? 100 : Math.min(100, number), before: last}).then(res => res.array());
  44. if (!isNaN(number)) number -= fetched.length;
  45. var connection = mysql.createConnection({
  46. host : serverData.dbHost,
  47. port : serverData.dbPort,
  48. user : serverData.dbUser,
  49. password : serverData.dbPassword,
  50. database : serverData.db
  51. });
  52. var sql = 'SELECT * FROM `'+serverData.dbTable+'` ORDER BY `time` DESC';
  53. connection.connect();
  54. connection.query(sql, function (error, results, fields) {
  55. if (error) throw error;
  56. //console.log('Data recived from db. Result: ', results);
  57. var messages = [];
  58. var controlled = [];
  59. for (i = 0; i < number; i++) {
  60. controlled[i] = false;
  61. }
  62. fetched.forEach((messageNow) => {
  63. var found = false;
  64. var edited = true;
  65. for (j = 0; j < results.length; j++) {
  66. var msg = results[j];
  67. if (messageNow.id == msg.id || messageNow.id == message.id ) {
  68. found = true;
  69. controlled[j] = true;
  70. }
  71. //console.log('message:' + ((messageNow.editedTimestamp == null) ? "nope" : messageNow.editedTimestamp) + ' db: ' + msg.timeEdit);
  72. if (found == true && (messageNow.editedTimestamp || "") == msg.timeEdit) {
  73. edited = false;
  74. }
  75. }
  76. if (found==true && edited==true) {
  77. messages.push({"message":messageNow, "action":1});
  78. } else if (found==false) {
  79. messages.push({"message":messageNow, "action":0});
  80. }
  81. });
  82. //console.log(messages);
  83. sendLoop(messages, serverData, 100);
  84. if (isNaN(number) || number >= 0) setTimeout(run, 10000, (fetched[fetched.length-1] || {id:null}).id);
  85. });
  86. connection.end();
  87. }
  88. run();
  89. } else if (godMode && message.content.startsWith(`${(serverData||config).prefix}leave`)) {
  90. let args = message.content.split(' ');
  91. let guild = await client.guilds.fetch(args[1]);
  92. console.log(getTimestamp(), `Left guild "${guild.name}" id:${guild.id}`);
  93. guild.leave();
  94. return;
  95. } else if (godMode && serverData == undefined) {
  96. return;
  97. } else {
  98. sendToDB(message, serverData);
  99. }
  100. });
  101. client.on('messageUpdate', async (messageOld, messageNew) => {
  102. if (messageOld.partial) {
  103. // If the message was removed the fetching might result in an API error, which we need to handle
  104. try {
  105. await messageOld.fetch();
  106. } catch (error) {
  107. console.log(getTimestamp(), 'Something went wrong when fetching the message: ', error);
  108. }
  109. }
  110. if (messageNew.partial) {
  111. // If the message was removed the fetching might result in an API error, which we need to handle
  112. try {
  113. await messageNew.fetch();
  114. } catch (error) {
  115. console.log(getTimestamp(), 'Something went wrong when fetching the message: ', error);
  116. }
  117. }
  118. if (messageNew.author.bot==true) return;
  119. var serverData = undefined;
  120. config.servers.forEach(function(server) {
  121. if (messageNew.channel.id==server.channel) serverData = server;
  122. });
  123. if (serverData==undefined) return;
  124. var connection = mysql.createConnection({
  125. host : serverData.dbHost,
  126. port : serverData.dbPort,
  127. user : serverData.dbUser,
  128. password : serverData.dbPassword,
  129. database : serverData.db
  130. });
  131. var sql = 'SELECT * FROM `'+serverData.dbTable+'`';
  132. connection.connect();
  133. connection.query(sql, function (error, results, fields) {
  134. if (error) throw error;
  135. //console.log('Data recived from db. Result: ', results);
  136. var messages = [];
  137. results.forEach(messageNow => {
  138. if (messageNow.id == messageNew.id) {
  139. messages.push({"message":messageNew, "action":1});
  140. }
  141. });
  142. sendLoop(messages, serverData, 1000);
  143. });
  144. connection.end();
  145. });
  146. client.on('messageDelete', message => {
  147. if (message.author.bot==true) return;
  148. var serverData = undefined;
  149. config.servers.forEach(function(server) {
  150. if (message.channel.id==server.channel) serverData = server;
  151. });
  152. if (serverData==undefined) return;
  153. deleteFromDB(message, serverData);
  154. });
  155. client.login(config.token);
  156. async function sendLoop(messages, serverData, delay) {
  157. if (messages.length == 0) {
  158. return;
  159. }
  160. if (messages[0].action == 0) {
  161. await sendToDB(messages[0].message, serverData);
  162. } else if (messages[0].action == 1) {
  163. await updateDB(messages[0].message, serverData);
  164. } else if (messages[0].maction == 2) {
  165. deleteFromDB(messages[0].message, serverData);
  166. }
  167. messages.shift();
  168. setTimeout(sendLoop, delay, messages, serverData, delay);
  169. }
  170. async function updateDB(message, serverData) {
  171. var connection = mysql.createConnection({
  172. host : serverData.dbHost,
  173. port : serverData.dbPort,
  174. user : serverData.dbUser,
  175. password : serverData.dbPassword,
  176. database : serverData.db
  177. });
  178. var post = await prepareMessage(message, serverData);
  179. var sql = 'UPDATE '+serverData.dbTable+' SET ? WHERE id='+message.id;
  180. connection.connect();
  181. connection.query(sql, post, function (error, results, fields) {
  182. if (error) throw error;
  183. });
  184. connection.end();
  185. }
  186. async function sendToDB(message, serverData) {
  187. var connection = mysql.createConnection({
  188. host : serverData.dbHost,
  189. port : serverData.dbPort,
  190. user : serverData.dbUser,
  191. password : serverData.dbPassword,
  192. database : serverData.db
  193. });
  194. var post = await prepareMessage(message, serverData);
  195. var sql = 'INSERT INTO '+serverData.dbTable+' SET ?';
  196. connection.connect();
  197. connection.query(sql, post, function (error, results, fields) {
  198. if (error) throw error;
  199. });
  200. connection.end();
  201. }
  202. function deleteFromDB(message, serverData) {
  203. var connection = mysql.createConnection({
  204. host : serverData.dbHost,
  205. port : serverData.dbPort,
  206. user : serverData.dbUser,
  207. password : serverData.dbPassword,
  208. database : serverData.db
  209. });
  210. var sql = 'DELETE FROM '+serverData.dbTable+' WHERE id='+message.id;
  211. connection.connect();
  212. connection.query(sql, function (error, results, fields) {
  213. if (error) throw error;
  214. });
  215. connection.end();
  216. }
  217. function prepareMessage(message, serverData) {
  218. return new Promise(async (resolve) => {
  219. var l = [];
  220. var msgCopy = message.content;
  221. msgCopy.replace(urlRegex, function(url) {
  222. l.push(url);
  223. });
  224. var i = [];
  225. message.attachments.forEach(attachment => {
  226. i.push(attachment.url);
  227. });
  228. let messageContent = message.content;
  229. await asyncForEach(message.mentions.users.array(), async (user) => {
  230. console.log(user);
  231. if (serverData.userMentionsMode == 0) {
  232. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+user.id);
  233. } else if (serverData.userMentionsMode == 1) {
  234. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+user.username);
  235. } else if (serverData.userMentionsMode == 2) {
  236. let nickname = await message.guild.members.fetch(user.id).then(res => res.nickname);
  237. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+nickname);
  238. } else if (serverData.userMentionsMode == 3) {
  239. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+user.username+"#"+user.discriminator);
  240. } else if (serverData.userMentionsMode == 4) {
  241. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+user.id+"@");
  242. } else if (serverData.userMentionsMode == 5) {
  243. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+user.username+"@");
  244. } else {
  245. let nickname = await message.guild.members.fetch(user.id).then(res => res.nickname);
  246. messageContent = messageContent.replace(new RegExp("<@!"+user.id+">", 'g'), "@"+nickname+"@");
  247. }
  248. });
  249. var mentions = [];
  250. message.mentions.channels.forEach(channel => {
  251. mentions.push({"channelId": channel.id, "name": channel.name});
  252. });
  253. for (mention of mentions) {
  254. if(messageContent.includes(mention.channelId)) {
  255. if (serverData.channelMentionsMode == 0) {
  256. messageContent = messageContent.replace(new RegExp("<#"+mention.channelId+">", 'g'), "#"+mention.channelId);
  257. messageContent = messageContent.replace(new RegExp("<#!"+mention.channelId+">", 'g'), "#"+mention.channelId);
  258. } else if (serverData.channelMentionsMode == 1) {
  259. messageContent = messageContent.replace(new RegExp("<#"+mention.channelId+">", 'g'), "#"+mention.name);
  260. messageContent = messageContent.replace(new RegExp("<#!"+mention.channelId+">", 'g'), "#"+mention.name);
  261. } else if (serverData.channelMentionsMode == 2) {
  262. messageContent = messageContent.replace(new RegExp("<#"+mention.channelId+">", 'g'), "#"+mention.channelId+"#");
  263. messageContent = messageContent.replace(new RegExp("<#!"+mention.channelId+">", 'g'), "#"+mention.channelId+"#");
  264. } else {
  265. messageContent = messageContent.replace(new RegExp("<#"+mention.channelId+">", 'g'), "#"+mention.name+"#");
  266. messageContent = messageContent.replace(new RegExp("<#!"+mention.channelId+">", 'g'), "#"+mention.name+"#");
  267. }
  268. }
  269. }
  270. var mentions = [];
  271. message.mentions.roles.forEach(role => {
  272. mentions.push({"roleId": role.id, "name": role.name, "color": role.color.toString(16)});
  273. });
  274. for (mention of mentions) {
  275. if(messageContent.includes(mention.roleId)) {
  276. if (serverData.roleMentionsMode == 0) {
  277. messageContent = messageContent.replace(new RegExp("<@&"+mention.roleId+">", 'g'), "&"+mention.roleId);
  278. messageContent = messageContent.replace(new RegExp("<@&!"+mention.roleId+">", 'g'), "&"+mention.roleId);
  279. } else if (serverData.roleMentionsMode == 1) {
  280. messageContent = messageContent.replace(new RegExp("<@&"+mention.roleId+">", 'g'), "&"+mention.name);
  281. messageContent = messageContent.replace(new RegExp("<@&!"+mention.roleId+">", 'g'), "&"+mention.name);
  282. } else {
  283. messageContent = messageContent.replace(new RegExp("<@&"+mention.roleId+">", 'g'), "&"+mention.name+"#"+mention.color);
  284. messageContent = messageContent.replace(new RegExp("<@&!"+mention.roleId+">", 'g'), "&"+mention.name+"#"+mention.color);
  285. }
  286. }
  287. }
  288. if (serverData.authorMode == 0) {
  289. var author = message.author.id;
  290. } else if (serverData.authorMode == 1) {
  291. var author = message.author.username;
  292. } else if (serverData.authorMode == 2) {
  293. var author = message.author.tag;
  294. } else {
  295. var author = message.member.nickname || message.author.username;
  296. }
  297. resolve({message:emoji.unemojify(messageContent), id:message.id, time:message.createdTimestamp, timeEdit:(message.editedTimestamp || ""), user:author, links:JSON.stringify(l), images:JSON.stringify(i)});
  298. });
  299. }
  300. function getTimestamp() {
  301. var d = new Date();
  302. return "["+d.getDate()+"/"+(d.getMonth()+1)+"/"+d.getFullYear()+" - "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()+"."+d.getMilliseconds()+"]";
  303. }
  304. async function asyncForEach(array, callback) {
  305. for (let index = 0; index < array.length; index++) {
  306. await callback(array[index], index, array);
  307. }
  308. }