From 6511816229a7b431ffba485414314b9bad470fe6 Mon Sep 17 00:00:00 2001 From: xHyroM Date: Wed, 13 Jul 2022 17:49:09 +0200 Subject: [PATCH] feat: sqlite instead memory cache --- files/database.sqlite | Bin 0 -> 143360 bytes src/commands/github.ts | 6 +- src/index.ts | 17 ++--- src/structures/Option.ts | 4 +- src/utils/githubUtils.ts | 161 ++++++++++++++++++++++++--------------- 5 files changed, 113 insertions(+), 75 deletions(-) create mode 100644 files/database.sqlite diff --git a/files/database.sqlite b/files/database.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..e22ac7d70414f179ebb0ed94ebd66421a0c28fc9 GIT binary patch literal 143360 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 GhyM>t8Nx*X literal 0 HcmV?d00001 diff --git a/src/commands/github.ts b/src/commands/github.ts index d13a98b..cef951b 100644 --- a/src/commands/github.ts +++ b/src/commands/github.ts @@ -23,8 +23,8 @@ new Command({ description: 'Issue numer/name, PR number/name or direct link to Github Issue or PR', type: ApplicationCommandOptionType.String, required: true, - run: (ctx) => { - return ctx.respond(search(ctx.value, ctx?.options?.[1]?.value as string || 'oven-sh/bun')); + run: async(ctx) => { + return ctx.respond(await search(ctx.value, ctx?.options?.[1]?.value as string || 'oven-sh/bun')); } }, { @@ -64,7 +64,7 @@ new Command({ const repositoryOwner = repositorySplit[0]; const repositoryName = repositorySplit[1]; - let issueOrPR = getIssueOrPR(parseInt(query), repository); + let issueOrPR = await getIssueOrPR(parseInt(query), repository); if (!issueOrPR) { const res = await fetch(`https://api.github.com/search/issues?q=${encodeURIComponent(query)}${encodeURIComponent(' repo:oven-sh/bun')}`); diff --git a/src/index.ts b/src/index.ts index 35bd1e6..512fc08 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,7 @@ import { Commands } from './managers/CommandManager'; import registerCommands from './utils/registerCommands'; import { Option, OptionOptions } from './structures/Option'; import { AutocompleteContext } from './structures/contexts/AutocompleteContext'; -import { deleteIssue, deletePullRequest, fetchIssues, fetchPullRequests, issues, setIssue, setPullRequest } from './utils/githubUtils'; +import { deleteIssueOrPR, fetchIssues, fetchPullRequests, setIssue, setPullRequest } from './utils/githubUtils'; import createHmac from 'create-hmac'; await fetchIssues(); @@ -95,15 +95,14 @@ app.post('/github_webhook', bodyParse(), (c) => { const issueOrPr = c.req.parsedBody; if (issueOrPr.action !== 'deleted') { if (issueOrPr.issue) { - console.log('issue'); setIssue({ id: issueOrPr.issue.number, repository: issueOrPr.issue.repository_url.replace('https://api.github.com/repos/', ''), title: issueOrPr.issue.title, number: issueOrPr.issue.number, state: issueOrPr.issue.state, - created_at: new Date(issueOrPr.issue.created_at), - closed_at: new Date(issueOrPr.issue.closed_at), + created_at: issueOrPr.issue.created_at, + closed_at: issueOrPr.issue.closed_at, html_url: issueOrPr.issue.html_url, user_login: issueOrPr.issue.user.login, user_html_url: issueOrPr.issue.user.html_url, @@ -117,9 +116,9 @@ app.post('/github_webhook', bodyParse(), (c) => { title: issueOrPr.pull_request.title, number: issueOrPr.pull_request.number, state: issueOrPr.pull_request.state, - created_at: new Date(issueOrPr.pull_request.created_at), - closed_at: new Date(issueOrPr.pull_request.closed_at), - merged_at: new Date(issueOrPr.pull_request.merged_at), + created_at: issueOrPr.pull_request.created_at, + closed_at: issueOrPr.pull_request.closed_at, + merged_at: issueOrPr.pull_request.merged_at, html_url: issueOrPr.pull_request.html_url, user_login: issueOrPr.pull_request.user.login, user_html_url: issueOrPr.pull_request.user.html_url, @@ -127,10 +126,10 @@ app.post('/github_webhook', bodyParse(), (c) => { }) } } else { - if (issueOrPr.issue) deleteIssue( + if (issueOrPr.issue) deleteIssueOrPR( issueOrPr.issue.number, issueOrPr.issue.repository_url.replace('https://api.github.com/repos/', '') ); - else deletePullRequest( + else deleteIssueOrPR( issueOrPr.pull_request.number, issueOrPr.pull_request.html_url .replace('https://github.com/', '') diff --git a/src/structures/Option.ts b/src/structures/Option.ts index 9ed1739..e4683a9 100644 --- a/src/structures/Option.ts +++ b/src/structures/Option.ts @@ -23,7 +23,7 @@ export interface OptionOptions { maxValue?: number; minLength?: number; maxLength?: number; - run?: (ctx: AutocompleteContext) => Response; + run?: (ctx: AutocompleteContext) => Response | Promise; } export class Option { @@ -40,7 +40,7 @@ export class Option { public maxValue?: number; public minLength?: number; public maxLength?: number; - public run?: (ctx: AutocompleteContext) => Response; + public run?: (ctx: AutocompleteContext) => Response | Promise; public constructor(options: OptionOptions) { this.name = options.name; diff --git a/src/utils/githubUtils.ts b/src/utils/githubUtils.ts index 5c289d9..7e65e2e 100644 --- a/src/utils/githubUtils.ts +++ b/src/utils/githubUtils.ts @@ -5,6 +5,7 @@ import utilities from '../../files/utilities.toml'; import MiniSearch from 'minisearch'; import { Logger } from './Logger'; import { APIApplicationCommandOptionChoice } from 'discord-api-types/v10'; +import { Database } from 'bun:sqlite'; interface Issue { id: number; @@ -12,8 +13,8 @@ interface Issue { title: string; number: number; state: 'open' | 'closed', - created_at: Date; - closed_at: Date | null; + created_at: string; + closed_at: string | null; html_url: string; user_login: string; user_html_url: string; @@ -21,11 +22,19 @@ interface Issue { } interface PullRequest extends Issue { - merged_at: Date | null; + merged_at: string | null; } -export let issues: Issue[] = []; -export let pulls: PullRequest[] = []; +export const db = new Database('./files/database.sqlite'); +await db.exec('DROP TABLE IF EXISTS issuesandprs'); +await db.exec('CREATE TABLE issuesandprs (id INTEGER PRIMARY KEY, repository TEXT, title TEXT, number INTEGER, state TEXT, created_at TEXT, closed_at TEXT, merged_at TEXT, html_url TEXT, user_login TEXT, user_html_url TEXT, type TEXT)'); + +const addToDb = db.prepare( + 'INSERT INTO issuesandprs (repository, title, number, state, created_at, closed_at, merged_at, html_url, user_login, user_html_url, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' +); + +export let issues: number = 0; +export let pulls: number = 0; export const fetchIssues = async() => { for await (const repository of utilities.github.repositories) { @@ -43,22 +52,24 @@ export const fetchIssues = async() => { for (const issue of res) { if ('pull_request' in issue) continue; - issues.push({ - id: issue.number, - repository: issue.repository_url.replace('https://api.github.com/repos/', ''), - title: issue.title, - number: issue.number, - state: issue.state, - created_at: new Date(issue.created_at), - closed_at: new Date(issue.closed_at), - html_url: issue.html_url, - user_login: issue.user.login, - user_html_url: issue.user.html_url, - type: '(ISSUE)' - }) + // @ts-expect-error it works + addToDb.run([ + issue.repository_url.replace('https://api.github.com/repos/', ''), + issue.title, + issue.number, + issue.state, + issue.created_at, + issue.closed_at, + null, + issue.html_url, + issue.user.login, + issue.user.html_url, + '(ISSUE)' + ]); + issues++; } - Logger.debug(`Fetching issues for ${repository} - ${issues.length} * ${page}`); + Logger.debug(`Fetching issues for ${repository} - ${issues} * ${page}`); page++; if (res.length === 0) { @@ -66,7 +77,8 @@ export const fetchIssues = async() => { } } - Logger.success(`Issues have been fetched for ${repository} - ${issues.length}`); + Logger.success(`Issues have been fetched for ${repository} - ${issues}`); + issues = 0; } } @@ -84,23 +96,24 @@ export const fetchPullRequests = async() => { })).json() as any; for (const pull of res) { - pulls.push({ - id: pull.number, - repository: pull.html_url.replace('https://github.com/', '').replace(`/pull/${pull.number}`, ''), - title: pull.title, - number: pull.number, - state: pull.state, - created_at: new Date(pull.created_at), - closed_at: new Date(pull.closed_at), - merged_at: new Date(pull.merged_at), - html_url: pull.html_url, - user_login: pull.user.login, - user_html_url: pull.user.html_url, - type: '(PR)', - }) + // @ts-expect-error it works + addToDb.run([ + pull.html_url.replace('https://github.com/', '').replace(`/pull/${pull.number}`, ''), + pull.title, + pull.number, + pull.state, + pull.created_at, + pull.closed_at, + pull.merged_at, + pull.html_url, + pull.user.login, + pull.user.html_url, + '(PR)' + ]); + pulls++; } - Logger.debug(`Fetching pull requests for ${repository} - ${pulls.length} * ${page}`); + Logger.debug(`Fetching pull requests for ${repository} - ${pulls} * ${page}`); page++; if (res.length === 0) { @@ -108,45 +121,71 @@ export const fetchPullRequests = async() => { } } - Logger.success(`Pull requests have been fetched for ${repository} - ${pulls.length}`); + Logger.success(`Pull requests have been fetched for ${repository} - ${pulls}`); + pulls = 0; } } -export const setIssue = (issue: Issue) => { - const exists = issues.findIndex(i => i.number === issue.number && i.repository === issue.repository); - if (exists >= 0) issues[exists] = issue; - else issues.push(issue); +export const setIssue = async(issue: Issue) => { + const exists = await db.prepare(`SELECT * FROM issuesandprs WHERE number = ${issue.number} AND repository = '${issue.repository}'`).get(); + if (typeof exists == 'object') { + db.exec(`UPDATE issuesandprs SET state = '${issue.state}', closed_at = '${issue.closed_at}', title = '${issue.title}' WHERE number = ${issue.number} AND repository = '${issue.repository}'`); + } else { + // @ts-expect-error + addToDb.run([ + issue.repository.replace('https://api.github.com/repos/', ''), + issue.title, + issue.number, + issue.state, + issue.created_at, + issue.closed_at, + null, + issue.html_url, + issue.user_login, + issue.user_html_url, + '(ISSUE)' + ]); + } } -export const setPullRequest = (pull: PullRequest) => { - const exists = pulls.findIndex(i => i.number === pull.number); - if (exists >= 0) pulls[exists] = pull; - else pulls.push(pull); +export const setPullRequest = async(pull: PullRequest) => { + const exists = await db.prepare(`SELECT * FROM issuesandprs WHERE number = ${pull.number} AND repository = '${pull.repository}'`).get(); + if (typeof exists == 'object') { + db.exec(`UPDATE issuesandprs SET state = '${pull.state}', closed_at = '${pull.closed_at}', merged_at = '${pull.merged_at}', title = '${pull.title}' WHERE number = ${pull.number} AND repository = '${pull.repository}'`); + } else { + // @ts-expect-error + addToDb.run([ + pull.repository.replace('https://api.github.com/repos/', ''), + pull.title, + pull.number, + pull.state, + pull.created_at, + pull.closed_at, + pull.merged_at, + pull.html_url, + pull.user_login, + pull.user_html_url, + '(ISSUE)' + ]); + } } -export const deleteIssue = (number: number, repository: string) => { - issues = issues.filter(i => i.number === number && i.repository === repository); +export const deleteIssueOrPR = (number: number, repository: string) => { + db.exec(`DELETE FROM issuesandprs WHERE repository = '${repository}' AND number = ${number}`); } -export const deletePullRequest = (number: number, repository: string) => { - pulls = pulls.filter(p => p.number === number && p.repository === repository); -} - -export const search = (query: string, repository: string): APIApplicationCommandOptionChoice[] => { +export const search = async(query: string, repository: string): Promise => { try { - const pullsFiltered = pulls.filter(pull => pull.repository === repository); - const issuesFiltered = issues.filter(issue => issue.repository === repository); + const arrayFiltered = await db.prepare(`SELECT * FROM issuesandprs WHERE repository = '${repository}'`).all(); if (!query) { - const array = [].concat(pullsFiltered.slice(0, 13), issuesFiltered.slice(0, 12)); + const array = arrayFiltered.slice(0, 25); return array.map((issueOrPr: Issue | PullRequest) => new Object({ - name: `${issueOrPr.type} ${issueOrPr.title.slice(0, 93)}`, + name: `${issueOrPr.type} ${issueOrPr.title.slice(0, 93).replace(/[^a-z0-9 ]/gi, '')}`, value: issueOrPr.number.toString() })) as APIApplicationCommandOptionChoice[] } - const array = [].concat(pullsFiltered, issuesFiltered); - const searcher = new MiniSearch({ fields: ['title', 'number', 'type'], storeFields: ['title', 'number', 'type'], @@ -156,7 +195,7 @@ export const search = (query: string, repository: string): APIApplicationCommand }, }); - searcher.addAll(array); + searcher.addAll(arrayFiltered); const result = searcher.search(query); @@ -169,7 +208,7 @@ export const search = (query: string, repository: string): APIApplicationCommand } } -export const getIssueOrPR = (number: number, repository: string): Issue | PullRequest => { - return issues.find(issue => issue.number === number && issue.repository === repository) || - pulls.find(pull => pull.number === number && pull.repository === repository); +export const getIssueOrPR = async(number: number, repository: string): Promise => { + const issueOrPR = await db.prepare(`SELECT * FROM issuesandprs WHERE repository = '${repository}' AND number = ${number}`).get(); + return issueOrPR; } \ No newline at end of file