From 72eab94fc3edf022c88576e9c07632c385ee84d9 Mon Sep 17 00:00:00 2001 From: gtmnayan <50981692+gtm-nayan@users.noreply.github.com> Date: Mon, 27 Dec 2021 16:22:59 +0545 Subject: [PATCH] Github commands (#14) * Switch to ES Modules * Swap out fuzzysort for js-trgm * Use node-fetch v3 * Github commands * Remove dev * Remove empty default export * Extensions Co-authored-by: Nayan Gautam <50981692+698969@users.noreply.github.com> --- .env.example | 4 +- src/commands/github/_common.ts | 70 ++++++++++++++++++++++++++++++ src/commands/github/discussions.ts | 47 ++++++++++++++++++++ src/commands/github/issues.ts | 55 +++++++++++++++++++++++ src/commands/github/prs.ts | 59 +++++++++++++++++++++++++ src/config.ts | 2 + 6 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 src/commands/github/_common.ts create mode 100644 src/commands/github/discussions.ts create mode 100644 src/commands/github/issues.ts create mode 100644 src/commands/github/prs.ts diff --git a/.env.example b/.env.example index bda4408..afd54c2 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,7 @@ DISCORD_TOKEN= NODE_ENV= +GITHUB_TOKEN + SUPABASE_URL= -SUPABASE_KEY= \ No newline at end of file +SUPABASE_KEY= diff --git a/src/commands/github/_common.ts b/src/commands/github/_common.ts new file mode 100644 index 0000000..4c8072f --- /dev/null +++ b/src/commands/github/_common.ts @@ -0,0 +1,70 @@ +import { CommandInteraction } from 'discord.js'; +import fetch, { Headers } from 'node-fetch'; +import { GITHUB_TOKEN } from '../../config.js'; +import { listOfLinks } from '../../utils/embedBuilder.js'; +import { REPOS, REPO_DETAILS } from '../../utils/repositories.js'; + +async function githubSearch(body: { + query: string; + variables: Record; +}) { + const res = await fetch('https://api.github.com/graphql', { + method: 'POST', + body: JSON.stringify(body), + headers: new Headers({ + Authorization: `Bearer ${GITHUB_TOKEN}`, + 'Content-Type': 'application/json', + }), + }); + if (!res.ok) { + return null; + } + const results: Array> = ((await res.json()) as any).data + .search.nodes; + if (!results.length) { + return null; + } + return listOfLinks( + results.map( + (result) => `#[${result.number}](${result.url}): ${result.title}`, + ), + ); +} + +export async function githubCommandHandler( + interaction: CommandInteraction, + query: string, + is?: 'issue' | 'pr', +) { + const thisRepoDetails = + REPO_DETAILS[ + interaction.options.getInteger('repository', true) as REPOS + ]; + const topic = interaction.options.getString('topic'); + + const searchQuery = `${is ? `is:${is}` : ''} repo:${ + thisRepoDetails.REPOSITORY_NAME + } ${topic || ''}`; + + try { + let results = await githubSearch({ + query, + variables: { + searchQuery, + }, + }); + + if (results) { + await interaction.reply({ + embeds: [results], + }); + } else { + await interaction.reply({ + content: 'No results found.', + ephemeral: true, + }); + } + } catch { + // TODO: Do nothing or log the error or something + } +} diff --git a/src/commands/github/discussions.ts b/src/commands/github/discussions.ts new file mode 100644 index 0000000..9e3bc53 --- /dev/null +++ b/src/commands/github/discussions.ts @@ -0,0 +1,47 @@ +import { ApplicationCommandOptionTypes } from 'discord.js/typings/enums'; +import { command } from 'jellycommands'; +import { REPOS } from '../../utils/repositories.js'; +import { githubCommandHandler } from './_common.js'; + +const query = `query searchResults($searchQuery: String!) { + search(type: DISCUSSION, query: $searchQuery, first: 5) { + nodes { + ... on Discussion { + title + number + url + } + } + } +} +`; + +export default command({ + name: 'discussion', + description: 'Search for a discussion on github.', + global: true, + + options: [ + { + name: 'repository', + description: 'The repository to search within', + type: ApplicationCommandOptionTypes.INTEGER, + choices: [ + { + name: 'SvelteKit', + value: REPOS.SVELTEKIT, + }, + ], + required: true, + }, + { + name: 'topic', + description: 'What to search for', + type: ApplicationCommandOptionTypes.STRING, + }, + ], + + run: async ({ interaction }) => { + await githubCommandHandler(interaction, query); + }, +}); diff --git a/src/commands/github/issues.ts b/src/commands/github/issues.ts new file mode 100644 index 0000000..0f37fbe --- /dev/null +++ b/src/commands/github/issues.ts @@ -0,0 +1,55 @@ +import { ApplicationCommandOptionTypes } from 'discord.js/typings/enums'; +import { command } from 'jellycommands'; +import { REPOS } from '../../utils/repositories.js'; +import { githubCommandHandler } from './_common.js'; + +const query = `query searchResults($searchQuery: String!) { + search(type: ISSUE, query: $searchQuery, first: 5) { + nodes { + ... on Issue { + title + number + url + } + } + } +} +`; + +export default command({ + name: 'issue', + description: 'Search for an issue on github', + global: true, + + options: [ + { + name: 'repository', + description: 'The repository to search within', + type: ApplicationCommandOptionTypes.INTEGER, + choices: [ + { + name: 'Svelte', + value: REPOS.SVELTE, + }, + { + name: 'SvelteKit', + value: REPOS.SVELTEKIT, + }, + { + name: 'Language Tools', + value: REPOS.LANGUAGETOOLS, + }, + ], + required: true, + }, + { + name: 'topic', + description: 'What to search for', + type: ApplicationCommandOptionTypes.STRING, + }, + ], + + run: async ({ interaction }) => { + await githubCommandHandler(interaction, query, 'issue'); + }, +}); diff --git a/src/commands/github/prs.ts b/src/commands/github/prs.ts new file mode 100644 index 0000000..794403f --- /dev/null +++ b/src/commands/github/prs.ts @@ -0,0 +1,59 @@ +import { ApplicationCommandOptionTypes } from 'discord.js/typings/enums'; +import { command } from 'jellycommands'; +import { REPOS } from '../../utils/repositories.js'; +import { githubCommandHandler } from './_common.js'; + +const query = `query searchResults($searchQuery: String!) { + search(type: ISSUE, query: $searchQuery, first: 5) { + nodes { + ... on PullRequest { + title + number + url + } + } + } +} +`; + +export default command({ + name: 'pr', + description: 'Search for a pull request on github', + global: true, + + options: [ + { + name: 'repository', + description: 'The repository to search within', + type: ApplicationCommandOptionTypes.INTEGER, + choices: [ + { + name: 'Svelte', + value: REPOS.SVELTE, + }, + { + name: 'SvelteKit', + value: REPOS.SVELTEKIT, + }, + { + name: 'RFCs', + value: REPOS.RFCS, + }, + { + name: 'Language Tools', + value: REPOS.LANGUAGETOOLS, + }, + ], + required: true, + }, + { + name: 'topic', + description: 'What to search for', + type: ApplicationCommandOptionTypes.STRING, + }, + ], + + run: async ({ interaction }) => { + await githubCommandHandler(interaction, query, 'pr'); + }, +}); diff --git a/src/config.ts b/src/config.ts index d899ddd..8f9320f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,6 +8,8 @@ export const DISCORD_TOKEN = process.env.DISCORD_TOKEN; export const SVELTE_ORANGE = 0xff3e00; +export const GITHUB_TOKEN = process.env.GITHUB_TOKEN; + export const LINK_ONLY_CHANNELS = DEV_MODE ? [ // #test-link-validation