-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(global): ✨ publish the discord bot source for sentry (and why not)
Still doing the thing behind the scenes, will going to ship it soon.
- Loading branch information
1 parent
8928fc9
commit 97b3168
Showing
14 changed files
with
1,365 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import globals from "globals"; | ||
import pluginJs from "@eslint/js"; | ||
import tseslint from "typescript-eslint"; | ||
|
||
|
||
/** @type {import('eslint').Linter.Config[]} */ | ||
export default [ | ||
{files: ["**/*.{js,mjs,cjs,ts}"]}, | ||
{files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}}, | ||
{languageOptions: { globals: globals.node }}, | ||
pluginJs.configs.recommended, | ||
...tseslint.configs.recommended, | ||
{ | ||
rules: { | ||
indent: ["error", 2], | ||
} | ||
} | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ | |
"license": "MPL-2.0", | ||
"packageManager": "[email protected]", | ||
"scripts": { | ||
"start": "dotenvx run -f .env.production -- yarn node dist/index.js", | ||
"dev:build": "yarn build && dotenvx run -f .env.development -- yarn node dist/index.js", | ||
"dev": "dotenvx run -f .env.development -- ts-node-dev --loader ts-node/esm --respawn src/index.ts", | ||
"dev:commands": "dotenvx run -f .env.development -- ts-node src/scripts/deploy-commands.ts", | ||
"build": "tsc --build && yarn sentry:sourcemaps", | ||
|
@@ -20,13 +22,18 @@ | |
"hono": "^4.6.14" | ||
}, | ||
"devDependencies": { | ||
"@eslint/eslintrc": "^3.2.0", | ||
"@eslint/js": "^9.17.0", | ||
"@types/node": "^22.10.2", | ||
"eslint": "^9.17.0", | ||
"globals": "^15.14.0", | ||
"ts-node": "^10.9.2", | ||
"ts-node-dev": "^2.0.0", | ||
"typescript": "^5.7.2" | ||
"typescript": "^5.7.2", | ||
"typescript-eslint": "^8.18.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/recaptime-dev/hcb-explorer-discord.git" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ChatInputCommandInteraction, Client, CommandInteraction, Interaction, SlashCommandBuilder } from "discord.js"; | ||
import { fetchOrganization, handleOrgDataEmbed, notFoundEmbed } from "../lib/hcb"; | ||
|
||
export const hcb = { | ||
data: new SlashCommandBuilder() | ||
.setName("hcb") | ||
.setDescription("Access the HCB API via Discord") | ||
.addSubcommand(sub => | ||
sub.setName("org") | ||
.setDescription("See a HCB organization's information, such as their website and description.") | ||
.addStringOption(opt => | ||
opt.setName("name") | ||
.setDescription("The name or ID of the organization.") | ||
.setRequired(true) | ||
) | ||
), | ||
async execute(interaction: CommandInteraction & ChatInputCommandInteraction, client: Client) { | ||
const subcommand = interaction.options.getSubcommand(); | ||
|
||
if (subcommand === "org") { | ||
const name = interaction.options.getString("name") || "hq"; | ||
const api = await fetchOrganization(name); | ||
|
||
if (api.status == 404) { | ||
return await notFoundEmbed(interaction) | ||
} | ||
|
||
await handleOrgDataEmbed(interaction, api); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { | ||
SlashCommandBuilder, | ||
CommandInteraction, | ||
Client, | ||
EmbedBuilder | ||
} from "discord.js"; | ||
import projectConfig from "../config" | ||
|
||
export const ping = { | ||
data: new SlashCommandBuilder() | ||
.setName("ping") | ||
.setDescription("Replies with pong + latency"), | ||
async execute( | ||
interaction: CommandInteraction, | ||
client: Client | ||
) { | ||
const startTime = Date.now(); | ||
const wsPing = client.ws.ping; | ||
|
||
const pingOps = new EmbedBuilder({ | ||
title: "🏓 Pong!", | ||
description: `Websocket latency: ${wsPing}ms`, | ||
footer: { | ||
text: `Command executed in ${Date.now() - startTime}ms` | ||
} | ||
}).toJSON() | ||
|
||
await interaction.reply({ | ||
embeds: [pingOps] | ||
}); | ||
} | ||
}; | ||
|
||
export const donateLinks = { | ||
data: new SlashCommandBuilder() | ||
.setName("donate") | ||
.setDescription("Support the project by donating to RecapTime.dev"), | ||
async execute( | ||
interaction: CommandInteraction, | ||
client: Client | ||
) { | ||
const donateOps = new EmbedBuilder({ | ||
title: "Donate to RecapTime.dev", | ||
author: { | ||
name: "Recap Time Squad", | ||
icon_url: "https://avatars.githubusercontent.com/u/55875459?v=4", | ||
url: "https://recaptime.dev" | ||
}, | ||
description: "You can donate to RecapTime.dev to support the project through the following links:", | ||
fields: [ | ||
{ | ||
name: "HCB (recommended)", | ||
value: `https://hcb.hackclub.com/donations/start/${projectConfig.donate.hcb}` | ||
}, | ||
{ | ||
name: "Open Collective", | ||
value: `https://opencollective.com/${projectConfig.donate.opencollective}` | ||
}, | ||
{ | ||
name: "Crypto and other options", | ||
value: projectConfig.donate.more_details | ||
} | ||
], | ||
footer: { | ||
text: "Recap Time Squad is fiscally sponsored by The Hack Foundation (dba Hack Club), a US 501(c)(3) non-profit with EIN 81-2908499." | ||
} | ||
}).toJSON() | ||
|
||
await interaction.reply({ | ||
embeds: [donateOps] | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import pkgMetadata from "../package.json"; | ||
|
||
export default { | ||
port: Number(process.env.PORT) || 3000, | ||
appId: process.env.DISCORD_BOT_APP_ID, | ||
botToken: process.env.DISCORD_BOT_TOKEN, | ||
sentryDSN: process.env.SENTRY_DSN || "", | ||
repo: process.env.REPO_URL || pkgMetadata.repository.url, | ||
support: { | ||
discord: process.env.DISCORD_INVITE_CODE || "FyBYQrJtUX", | ||
slack: { | ||
team_id: process.env.SLACK_TEAM_ID || "T0266FRGM", | ||
channel_id: process.env.SLACK_CHANNEL_ID || "C07H1R2PW9W" | ||
}, | ||
zulip: { | ||
host: process.env.ZULIP_HOMESERVER_HOST || "recaptime-dev.zulipchat.com", | ||
channel: process.env.ZULIP_CHANNEL || "hcb-ops" | ||
} | ||
}, | ||
donate: { | ||
hcb: process.env.HCB_ORG_SLUG || "recaptime-dev", | ||
opencollective: process.env.OPENCOLLECTIVE_SLUG || "recaptime-dev", | ||
github_sposnors: process.env.GITHUB_USERNAME || "ajhalili2006", | ||
more_details: process.env.DONATE_DETAILS_URL || "https://recaptime.dev/donate" | ||
}, | ||
brand_icon_url: "https://hcb.hackclub.com/brand/hcb-icon-icon-dark.png", | ||
opensource_org_ids: [ | ||
"org_G3ud13", // https://hcb.hackclub.com/recaptime-dev | ||
"org_RRu9K4", // https://hcb.hackclub.com/lorebooks-wiki | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import "./lib/sentry"; | ||
import Sentry from './lib/sentry'; | ||
|
||
import { Events, GatewayIntentBits, ActivityType, Collection } from 'discord.js'; | ||
import { ExtendedClient } from './lib/extendedClient'; | ||
import { serve as honoServe, } from '@hono/node-server'; | ||
import { Hono, Context } from "hono"; | ||
import config from './config'; | ||
|
||
/** Check if we have the Discord bot token first */ | ||
if (!config.botToken) { | ||
throw Error("Discord token missing, try running via dotenvx/doppler?") | ||
} | ||
|
||
/** | ||
* Discord bot client initializer | ||
*/ | ||
const client = new ExtendedClient({ | ||
intents: [ | ||
GatewayIntentBits.Guilds | ||
], | ||
presence: { | ||
status: 'online', | ||
activities: [ | ||
{ | ||
name: "🏦 hcb.hackclub.com", | ||
type: ActivityType.Watching, | ||
url: "https://hackclub.com/hcb", | ||
state: "Monitoring Hack Club HQ finances and friends" | ||
} | ||
] | ||
} | ||
}) | ||
|
||
const app = new Hono() | ||
client.commands = new Collection(); | ||
|
||
app.get("/", (c) => { | ||
return c.redirect(config.repo) | ||
}) | ||
app.get("/ping", (c) => { | ||
return c.json({ ok: true, message: "Pong!" }) | ||
}) | ||
app.get("/invite", (c) => { | ||
return c.redirect(`https://discord.com/oauth2/authorize?client_id=${config.appId}`) | ||
}) | ||
|
||
client.once(Events.ClientReady, async readyClient => { | ||
console.log('[discord]',`Up and running as ${readyClient.user.tag} (app ID: ${readyClient.user.id})`); | ||
await honoServe({ | ||
fetch: app.fetch, | ||
port: config.port | ||
}); | ||
console.log('[api-server]', `Hono server running on port ${config.port}`); | ||
|
||
client.commands.set("ping", require('./commands/utility').ping); | ||
client.commands.set("donate", require('./commands/utility').donateLinks); | ||
client.commands.set("hcb", require('./commands/hcb').hcb); | ||
}) | ||
|
||
client.on(Events.InteractionCreate, async interaction => { | ||
if (interaction.isChatInputCommand()) { | ||
const command = client.commands.get(interaction.commandName); | ||
if (!command) { | ||
await interaction.reply({ | ||
content: ":warning: That command does not exist here or not yet implemented." | ||
}); | ||
return; | ||
} | ||
|
||
try { | ||
await command.execute(interaction, client); | ||
} catch (error) { | ||
console.error(error); | ||
Sentry.captureException(error); | ||
await interaction.reply({ | ||
embeds: [ | ||
{ | ||
description: "We are looking into it right now. If you need to, [file a new bug report](https://github.com/recaptime-dev/hcb-explorer-discord) in our repo.", | ||
fields: [], | ||
color: 15480656, | ||
title: ":cross: Something went wrong on our side" | ||
} | ||
], | ||
}) | ||
} | ||
}; | ||
}) | ||
|
||
client.login(config.botToken) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Client, ClientOptions, Collection } from 'discord.js'; | ||
import { SlashCommandBuilder } from '@discordjs/builders'; | ||
|
||
interface Command { | ||
data: SlashCommandBuilder; | ||
execute: Function; | ||
} | ||
|
||
export class ExtendedClient extends Client { | ||
commands: Collection<string, Command>; | ||
|
||
constructor(options: ClientOptions) { | ||
super(options); | ||
this.commands = new Collection(); | ||
} | ||
} |
Oops, something went wrong.