123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import crypto from 'crypto';
- import fs from 'fs';
- import {Client, Intents, MessageActionRow, MessageButton} from 'discord.js';
- import bancho from './bancho.js';
- import db from './database.js';
- import {sync_discord_info} from './discord_updates.js';
- import {capture_sentry_exception, gen_url} from './util/helpers.js';
- import Config from './util/config.js';
- const client = new Client({intents: [Intents.FLAGS.GUILDS]});
- function init() {
- return new Promise(async (resolve, reject) => {
- try {
- client.once('ready', async () => {
- client.on('interactionCreate', (interaction) => on_interaction(interaction).catch(capture_sentry_exception));
- console.log('Discord bot is ready.');
- resolve(client);
- });
- const {discord_token} = JSON.parse(fs.readFileSync('./config.json'));
- await client.login(discord_token);
- } catch (e) {
- reject(e);
- }
- });
- }
- async function on_interaction(interaction) {
- if (interaction.isCommand()) {
- if (interaction.commandName == 'profile') {
- let target = interaction.options.getUser('user');
- if (!target) {
- target = interaction.member;
- }
- const res = db.prepare(`SELECT * FROM user WHERE discord_user_id = ?`).get(target.id);
- if (res) {
- await interaction.reply(gen_url(0, `/u/${res.user_id}`));
- } else {
- await interaction.reply({
- content: 'That user hasn\'t linked their osu! account yet.',
- ephemeral: true,
- });
- }
- return;
- }
- if (interaction.commandName == 'eval') {
- if (interaction.member.id != Config.discord_admin) {
- await interaction.reply({
- content: 'Only the bot owner can use this command.',
- ephemeral: true,
- });
- return;
- }
- try {
- const eval_res = eval(interaction.options.getString('code'));
- await interaction.reply({
- content: `\`\`\`js\n${eval_res}\n\`\`\``,
- });
- } catch (err) {
- await interaction.reply({
- content: `\`ERROR\` \`\`\`xl\n${err}\n\`\`\``,
- });
- }
- return;
- }
- }
- try {
- if (interaction.customId && interaction.customId.indexOf('orl_get_lobby_invite_') == 0) {
- await on_lobby_invite_button_press(interaction);
- return;
- }
- if (interaction.customId == 'orl_link_osu_account') {
- await on_link_osu_account_press(interaction);
- return;
- }
- } catch (err) {
- // Discord API likes to fail.
- if (err.message != 'Unknown interaction') {
- capture_sentry_exception(err);
- }
- }
- }
- async function on_link_osu_account_press(interaction) {
- // Check if user already linked their account
- const user = db.prepare(`SELECT * FROM user WHERE discord_user_id = ?`).get(interaction.user.id);
- if (user) {
- await sync_discord_info(user, 'Account re-link request');
- await interaction.reply({
- content: `You already linked your account 👉 https://osu.ppy.sh/users/${user.user_id}\n
- (just in case, we have reset your role and nickname)`,
- ephemeral: true,
- });
- return;
- }
- // Create ephemeral token
- const ephemeral_token = crypto.randomBytes(16).toString('hex');
- db.prepare(
- `INSERT INTO token (token, created_at, discord_id) VALUES (?, ?, ?)`,
- ).run(ephemeral_token, Date.now(), interaction.user.id);
- // Send authorization link
- await interaction.reply({
- content: `Hello ${interaction.user}, let's get your account linked!`,
- ephemeral: true,
- components: [
- new MessageActionRow().addComponents([
- new MessageButton({
- url: `https://osu.ppy.sh/oauth/authorize?client_id=${Config.osu_v2api_client_id}&response_type=code&scope=identify&state=${ephemeral_token}&redirect_uri=${gen_url(0, '/auth')}`,
- label: 'Verify using osu!web',
- style: 'LINK',
- }),
- ]),
- ],
- });
- }
- async function on_lobby_invite_button_press(interaction) {
- const parts = interaction.customId.split('_');
- const lobby_id = parseInt(parts[parts.length - 1], 10);
- const user = db.prepare(`SELECT * FROM user WHERE discord_user_id = ?`).get(interaction.user.id);
- if (!user) {
- const welcome = await client.channels.cache.get(Config.discord_welcome_channel_id);
- await interaction.reply({
- content: `Before getting an invite, you need to click the button in ${welcome} to link your osu! account.`,
- ephemeral: true,
- });
- return;
- }
- await interaction.deferReply({ephemeral: true});
- for (const lobby of bancho.joined_lobbies) {
- if (lobby.channel == '#mp_' + lobby_id) {
- await bancho.privmsg(user.username, `${user.username}, here's your invite: [http://osump://${lobby.invite_id}/ ${lobby.name}]`);
- await interaction.editReply({
- content: 'An invite to the lobby has been sent. Check your in-game messages. 😌',
- ephemeral: true,
- });
- return;
- }
- }
- await interaction.editReply({
- content: 'Sorry, looks like that lobby just closed. <:tf:900417849179389992>',
- ephemeral: true,
- });
- await interaction.message.delete();
- }
- export {
- init,
- };
|