guilds.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. const cheerio = require('cheerio');
  2. const {defaultPermissions} = require('../util/default.json');
  3. const Lang = require('./i18n.js');
  4. const allLangs = Lang.allLangs().names;
  5. const {settingsData, addWidgets, createNotice} = require('./util.js');
  6. const forms = {
  7. settings: require('./settings.js').get,
  8. verification: require('./verification.js').get,
  9. rcscript: require('./rcscript.js').get
  10. };
  11. const DiscordOauth2 = require('discord-oauth2');
  12. const oauth = new DiscordOauth2( {
  13. clientId: process.env.bot,
  14. clientSecret: process.env.secret,
  15. redirectUri: process.env.dashboard
  16. } );
  17. const file = require('fs').readFileSync('./dashboard/index.html');
  18. /**
  19. * Let a user view settings
  20. * @param {import('http').ServerResponse} res - The server response
  21. * @param {import('./i18n.js')} dashboardLang - The user language.
  22. * @param {String} theme - The display theme
  23. * @param {String} state - The user state
  24. * @param {URL} reqURL - The used url
  25. * @param {String} [action] - The action the user made
  26. * @param {String[]} [actionArgs] - The arguments for the action
  27. */
  28. function dashboard_guilds(res, dashboardLang, theme, state, reqURL, action, actionArgs) {
  29. reqURL.pathname = reqURL.pathname.replace( /^(\/(?:guild\/\d+(?:\/(?:settings|verification|rcscript)(?:\/(?:\d+|new))?)?)?)(?:\/.*)?$/, '$1' );
  30. var args = reqURL.pathname.split('/');
  31. args = reqURL.pathname.split('/');
  32. var settings = settingsData.get(state);
  33. if ( reqURL.searchParams.get('owner') && process.env.owner.split('|').includes(settings.user.id) ) {
  34. args[0] = 'owner';
  35. }
  36. dashboardLang = new Lang(...dashboardLang.fromCookie, settings.user.locale, dashboardLang.lang);
  37. res.setHeader('Content-Language', [dashboardLang.lang]);
  38. var $ = cheerio.load(file);
  39. $('html').attr('lang', dashboardLang.lang);
  40. if ( theme === 'light' ) $('html').addClass('theme-light');
  41. $('<script>').text(`
  42. const selectLanguage = '${dashboardLang.get('general.language').replace( /'/g, '\\$&' )}';
  43. const allLangs = ${JSON.stringify(allLangs)};
  44. `).insertBefore('script#langjs');
  45. $('head title').text(dashboardLang.get('general.title'));
  46. $('.channel#settings div').text(dashboardLang.get('general.settings'));
  47. $('.channel#verification div').text(dashboardLang.get('general.verification'));
  48. $('.channel#rcscript div').text(dashboardLang.get('general.rcscript'));
  49. $('.guild#invite a').attr('alt', dashboardLang.get('general.invite'));
  50. $('.guild#refresh a').attr('alt', dashboardLang.get('general.refresh'));
  51. $('.guild#theme-dark a').attr('alt', dashboardLang.get('general.theme-dark'));
  52. $('.guild#theme-light a').attr('alt', dashboardLang.get('general.theme-light'));
  53. $('#selector span').text(dashboardLang.get('general.selector'));
  54. $('#support span').text(dashboardLang.get('general.support'));
  55. $('#logout').attr('alt', dashboardLang.get('general.logout'));
  56. if ( process.env.READONLY ) createNotice($, 'readonly', dashboardLang);
  57. if ( action ) createNotice($, action, dashboardLang, actionArgs);
  58. $('head').append(
  59. $('<script>').text(`history.replaceState(null, null, '${reqURL.pathname}');`)
  60. );
  61. $('#logout img').attr('src', settings.user.avatar);
  62. $('#logout span').text(`${settings.user.username} #${settings.user.discriminator}`);
  63. $('.guild#invite a').attr('href', oauth.generateAuthUrl( {
  64. scope: ['identify', 'guilds', 'bot', 'applications.commands'],
  65. permissions: defaultPermissions, state
  66. } ));
  67. $('.guild#refresh a').attr('href', '/refresh?return=' + reqURL.pathname);
  68. if ( settings.guilds.isMember.size ) {
  69. $('<div class="guild">').append(
  70. $('<div class="separator">')
  71. ).insertBefore('.guild#last-separator');
  72. settings.guilds.isMember.forEach( guild => {
  73. $('<div class="guild">').attr('id', guild.id).append(
  74. $('<div class="bar">'),
  75. $('<a>').attr('href', `/guild/${guild.id}/settings`).attr('alt', guild.name).append(
  76. ( guild.icon ?
  77. $('<img class="avatar">').attr('src', `${guild.icon}?size=64`).attr('alt', guild.name)
  78. : $('<div class="avatar noicon">').text(guild.acronym) )
  79. )
  80. ).insertBefore('.guild#last-separator');
  81. } );
  82. }
  83. if ( settings.guilds.notMember.size ) {
  84. $('<div class="guild">').append(
  85. $('<div class="separator">')
  86. ).insertBefore('.guild#last-separator');
  87. settings.guilds.notMember.forEach( guild => {
  88. $('<div class="guild">').attr('id', guild.id).append(
  89. $('<div class="bar">'),
  90. $('<a>').attr('href', `/guild/${guild.id}`).attr('alt', guild.name).append(
  91. ( guild.icon ?
  92. $('<img class="avatar">').attr('src', `${guild.icon}?size=64`).attr('alt', guild.name)
  93. : $('<div class="avatar noicon">').text(guild.acronym) )
  94. )
  95. ).insertBefore('.guild#last-separator');
  96. } );
  97. }
  98. let id = args[2];
  99. if ( id ) $(`.guild#${id}`).addClass('selected');
  100. if ( settings.guilds.isMember.has(id) ) {
  101. let guild = settings.guilds.isMember.get(id);
  102. $('head title').text(`${guild.name} – ` + $('head title').text());
  103. $('<script>').text(`
  104. const isPatreon = ${guild.patreon};
  105. const i18n = ${JSON.stringify(dashboardLang.getWithFallback('indexjs'))};
  106. `).insertBefore('script#indexjs');
  107. $('.channel#settings').attr('href', `/guild/${guild.id}/settings`);
  108. $('.channel#verification').attr('href', `/guild/${guild.id}/verification`);
  109. $('.channel#rcscript').attr('href', `/guild/${guild.id}/rcscript`);
  110. if ( args[3] === 'settings' ) return forms.settings(res, $, guild, args, dashboardLang);
  111. if ( args[3] === 'verification' ) return forms.verification(res, $, guild, args, dashboardLang);
  112. if ( args[3] === 'rcscript' ) return forms.rcscript(res, $, guild, args, dashboardLang);
  113. return forms.settings(res, $, guild, args, dashboardLang);
  114. }
  115. else if ( settings.guilds.notMember.has(id) ) {
  116. let guild = settings.guilds.notMember.get(id);
  117. $('head title').text(`${guild.name} – ` + $('head title').text());
  118. res.setHeader('Set-Cookie', [`guild="${guild.id}/settings"; HttpOnly; Path=/`]);
  119. let url = oauth.generateAuthUrl( {
  120. scope: ['identify', 'guilds', 'bot', 'applications.commands'],
  121. permissions: defaultPermissions,
  122. guildId: guild.id, state
  123. } );
  124. $('#channellist').empty();
  125. $('<a class="channel channel-header">').attr('href', url).append(
  126. $('<img>').attr('src', '/src/settings.svg'),
  127. $('<div>').text(dashboardLang.get('general.invite'))
  128. ).appendTo('#channellist');
  129. $('#text .description').append(
  130. $('<p>').html(dashboardLang.get('selector.invite', true, $('<code>').text(guild.name), $('<a>').attr('href', url))),
  131. $('<a id="login-button">').attr('href', url).text(dashboardLang.get('general.invite')).prepend(
  132. $('<img alt="Discord">').attr('src', 'https://discord.com/assets/f8389ca1a741a115313bede9ac02e2c0.svg')
  133. )
  134. );
  135. addWidgets($, dashboardLang);
  136. }
  137. else if ( args[0] === 'owner' ) {
  138. let guild = {
  139. id, name: 'OWNER ACCESS',
  140. acronym: '', userPermissions: 1 << 3,
  141. patreon: true, botPermissions: 1 << 3,
  142. channels: [], roles: []
  143. };
  144. $('head title').text(`${guild.name} – ` + $('head title').text());
  145. $('<script>').text(`
  146. const isPatreon = ${guild.patreon};
  147. const i18n = ${JSON.stringify(dashboardLang.getWithFallback('indexjs'))};
  148. `).insertBefore('script#indexjs');
  149. $('.channel#settings').attr('href', `/guild/${guild.id}/settings?owner=true`);
  150. $('.channel#verification').attr('href', `/guild/${guild.id}/verification?owner=true`);
  151. $('.channel#rcscript').attr('href', `/guild/${guild.id}/rcscript?owner=true`);
  152. if ( args[3] === 'settings' ) return forms.settings(res, $, guild, args, dashboardLang);
  153. if ( args[3] === 'verification' ) return forms.verification(res, $, guild, args, dashboardLang);
  154. if ( args[3] === 'rcscript' ) return forms.rcscript(res, $, guild, args, dashboardLang);
  155. return forms.settings(res, $, guild, args, dashboardLang);
  156. }
  157. else {
  158. $('head title').text(dashboardLang.get('selector.title') + ' – ' + $('head title').text());
  159. $('#channellist').empty();
  160. $('<p>').html(dashboardLang.get('selector.desc', true, $('<code>'))).appendTo('#text .description');
  161. if ( settings.guilds.isMember.size ) {
  162. $('<h2 id="with-wikibot">').text(dashboardLang.get('selector.with')).appendTo('#text');
  163. $('<a class="channel">').attr('href', '#with-wikibot').append(
  164. $('<img>').attr('src', '/src/channel.svg'),
  165. $('<div>').text(dashboardLang.get('selector.with'))
  166. ).appendTo('#channellist');
  167. $('<div class="server-selector" id="isMember">').appendTo('#text');
  168. settings.guilds.isMember.forEach( guild => {
  169. $('<a class="server">').attr('href', `/guild/${guild.id}/settings`).append(
  170. ( guild.icon ?
  171. $('<img class="avatar">').attr('src', `${guild.icon}?size=256`).attr('alt', guild.name)
  172. : $('<div class="avatar noicon">').text(guild.acronym) ),
  173. $('<div class="server-name description">').text(guild.name)
  174. ).appendTo('.server-selector#isMember');
  175. } );
  176. }
  177. if ( settings.guilds.notMember.size ) {
  178. $('<h2 id="without-wikibot">').text(dashboardLang.get('selector.without')).appendTo('#text');
  179. $('<a class="channel">').attr('href', '#without-wikibot').append(
  180. $('<img>').attr('src', '/src/channel.svg'),
  181. $('<div>').text(dashboardLang.get('selector.without'))
  182. ).appendTo('#channellist');
  183. $('<div class="server-selector" id="notMember">').appendTo('#text');
  184. settings.guilds.notMember.forEach( guild => {
  185. $('<a class="server">').attr('href', `/guild/${guild.id}`).append(
  186. ( guild.icon ?
  187. $('<img class="avatar">').attr('src', `${guild.icon}?size=256`).attr('alt', guild.name)
  188. : $('<div class="avatar noicon">').text(guild.acronym) ),
  189. $('<div class="server-name description">').text(guild.name)
  190. ).appendTo('.server-selector#notMember');
  191. } );
  192. }
  193. if ( !settings.guilds.count ) {
  194. let url = oauth.generateAuthUrl( {
  195. scope: ['identify', 'guilds'],
  196. prompt: 'consent', state
  197. } );
  198. $('<a class="channel channel-header">').attr('href', url).append(
  199. $('<img>').attr('src', '/src/settings.svg'),
  200. $('<div>').text(dashboardLang.get('selector.switch'))
  201. ).appendTo('#channellist');
  202. $('#text .description').append(
  203. $('<p>').html(dashboardLang.get('selector.none', true, $('<code>'))),
  204. $('<a id="login-button">').attr('href', url).text(dashboardLang.get('selector.switch')).prepend(
  205. $('<img alt="Discord">').attr('src', 'https://discord.com/assets/f8389ca1a741a115313bede9ac02e2c0.svg')
  206. )
  207. );
  208. }
  209. addWidgets($, dashboardLang);
  210. }
  211. let body = $.html();
  212. res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
  213. res.write( body );
  214. return res.end();
  215. }
  216. module.exports = dashboard_guilds;