birthday.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. registerPlugin({
  2. name: 'Birthday Script',
  3. version: '1.1',
  4. description: 'create birthday notifications',
  5. author: 'mcj201',
  6. vars: [
  7. {
  8. name: 'message',
  9. title: 'The message that should be displayed. (%n = nickname, %b = list of birthdays)',
  10. type: 'multiline'
  11. },
  12. {
  13. name: 'type',
  14. title: 'Message-Type',
  15. type: 'select',
  16. options: [
  17. 'Private chat',
  18. 'Poke'
  19. ]
  20. },
  21. {
  22. name: 'nDays',
  23. title: 'send the notification upto this amount of days after birthday',
  24. type: 'number'
  25. },
  26. {
  27. name: 'serverGroup',
  28. title: 'Server group name/id for birthdays',
  29. type: 'string'
  30. }
  31. ],
  32. autorun: false,
  33. requiredModules: [
  34. 'net'
  35. ]
  36. }, function(sinusbot, config, meta) {
  37. const event = require('event')
  38. const engine = require('engine')
  39. const backend = require('backend')
  40. const format = require('format')
  41. const store = require('store');
  42. const net = require('net');
  43. engine.log(`Loaded ${meta.name} v${meta.version} by ${meta.author}.`)
  44. event.on('load', () => {
  45. const command = require('command');
  46. if (!command) {
  47. engine.log('command.js library not found! Please download command.js and enable it to be able use this script!');
  48. return;
  49. }
  50. let bDays = store.get('birthdays') || {};
  51. let notifs = store.get('birthday_notifications') || {};
  52. if (!net) {
  53. engine.log('net library not found! You will not be able to use webDAV sync!');
  54. } else {
  55. syncDavAddressBook();
  56. setInterval(syncDavAddressBook, 1000 * 60);
  57. }
  58. setInterval(updateServerGroups, 1000 * 60);
  59. event.on('clientMove', ({ client, fromChannel }) => {
  60. const avail = getNotifications(client, 30);
  61. if (avail.length < 1)
  62. return;
  63. let msgs = []
  64. for(const uid of avail) {
  65. msgs.push(`${getName(uid)}: ${formatDate(getBday(uid))}`);
  66. }
  67. const msg = config.message.replace('%n', client.name()).replace('%b', msgs.join('\r\n'))
  68. if (!fromChannel) {
  69. if (config.type == '0') {
  70. client.chat(msg)
  71. } else {
  72. client.poke(msg)
  73. }
  74. updateServerGroups();
  75. }
  76. })
  77. command.createCommand('birthdays')
  78. .help('Show user birthdays')
  79. .manual('Show user birthdays from DB.')
  80. .exec((client, args, reply, ev) => {
  81. let msgs = ["List of saved birthdays:"];
  82. for(const uid in bDays) {
  83. msgs.push(`${getName(uid)}: ${formatDate(getBday(uid))}`);
  84. }
  85. reply(msgs.join('\r\n'));
  86. });
  87. command.createCommand('birthday')
  88. .addArgument(command.createArgument('string').setName('date'))
  89. .help('Set user birthdays')
  90. .manual('Save user birthdays to DB.')
  91. .exec((client, args, reply, ev) => {
  92. var date = args.date.split('.');
  93. if(date.length >= 2) {
  94. let m = date[0];
  95. date[0] = date[1];
  96. date[1] = m;
  97. }
  98. date = new Date(date);
  99. if(args.date === "") {
  100. let date = getBday(ev.client.uid());
  101. if(date)
  102. reply(`Your birthday is ${formatDate(date)}.`);
  103. else
  104. reply(`Set your birthday first! e.g. !birthday 24.12.`);
  105. } else if(!isNaN(date)) {
  106. setBday(ev.client, date);
  107. reply(`Your birthday was set to ${formatDate(date)}.`);
  108. } else {
  109. setBday(ev.client, date);
  110. reply(`Your birthday has been cleared.`);
  111. }
  112. });
  113. function setBday(client, date) {
  114. if(isNaN(date) && bDays[client.uid()]) {
  115. delete bDays[client.uid()];
  116. } else if(!isNaN(date)) {
  117. bDays[client.uid()] = [client.name(), date, new Date()];
  118. }
  119. store.set('birthdays', bDays);
  120. }
  121. function getBday(uid) {
  122. if(!bDays[uid])
  123. return undefined;
  124. if(bDays[uid][1])
  125. return new Date(bDays[uid][1]);
  126. else
  127. return undefined;
  128. }
  129. function getName(uid) {
  130. return bDays[uid][0];
  131. }
  132. function getNotifications(client, nDays = 30) {
  133. const start = new Date();
  134. start.setDate(start.getDate()-nDays);
  135. const now = new Date();
  136. let sentNotifs = notifs[client.uid()] || {};
  137. let avail = [];
  138. for(const uid in bDays) {
  139. let bDay = new Date(bDays[uid][1]);
  140. bDay.setFullYear((new Date()).getFullYear());
  141. let lastNotif = new Date(sentNotifs[uid]);
  142. if(bDay >= start && bDay <= now && (isNaN(lastNotif) || lastNotif < start)) {
  143. avail.push(uid);
  144. sentNotifs[uid] = now;
  145. }
  146. }
  147. notifs[client.uid()] = sentNotifs;
  148. store.set('birthday_notifications', notifs);
  149. return avail;
  150. }
  151. function formatDate(dt) {
  152. if(dt)
  153. return `${dt.getDate()}.${dt.getMonth()+1}.`;
  154. else
  155. return 'invalid date';
  156. }
  157. function updateServerGroups() {
  158. if(config.serverGroup === "")
  159. return;
  160. const now = new Date();
  161. for(const client of backend.getClients()) {
  162. if(bDays[client.uid()]) {
  163. const bDay = new Date(bDays[client.uid()][1]);
  164. let hasGroup = false;
  165. for(const group of client.getServerGroups()) {
  166. hasGroup |= group.name() === config.serverGroup || group.id() == config.serverGroup;
  167. }
  168. if(bDay.getDate() === now.getDate() && bDay.getMonth() === now.getMonth()) {
  169. if(!hasGroup) client.addToServerGroup(config.serverGroup);
  170. } else {
  171. if(hasGroup) client.removeFromServerGroup(config.serverGroup);
  172. }
  173. }
  174. }
  175. }
  176. function syncDavAddressBook() {
  177. const conn = net.connect({
  178. url: 'ws://127.0.0.1:23845',
  179. port: 23845,
  180. protocol: 'ws'
  181. }, err => {
  182. // log connection errors if any
  183. if (err) {
  184. engine.log(err);
  185. }
  186. });
  187. if (conn) {
  188. conn.on('data', data => {
  189. engine.log('received data');
  190. engine.log(data.toString());
  191. bDays = JSON.parse(data);
  192. store.set('birthdays', bDays);
  193. })
  194. conn.write(JSON.stringify(bDays));
  195. } else {
  196. engine.log('ws connection unavailable');
  197. }
  198. }
  199. });
  200. });