{
"version": 3,
"sources": ["../../../../server/chat-plugins/github.ts"],
"sourcesContent": ["/**\r\n * Chat plugin to view GitHub events in a chatroom.\r\n * By Mia, with design / html from xfix's original bot, https://github.com/xfix/GitHub-Bot-Legacy/\r\n * @author mia-pi-git\r\n */\r\n\r\nimport {FS, Utils} from '../../lib';\r\n\r\nconst STAFF_REPOS = Config.staffrepos || [\r\n\t'pokemon-showdown', 'pokemon-showdown-client', 'Pokemon-Showdown-Dex', 'pokemon-showdown-loginserver',\r\n];\r\nconst COOLDOWN = 10 * 60 * 1000;\r\n\r\nexport const gitData: GitData = JSON.parse(FS(\"config/chat-plugins/github.json\").readIfExistsSync() || \"{}\");\r\n\r\ninterface GitHookHandler {\r\n\ton(event: 'pull_request', callback: (repo: string, ref: string | undefined, result: PullRequest) => void): void;\r\n\ton(event: 'push', callback: (repo: string, ref: string, result: Push) => void): void;\r\n\ton(event: string, callback: (repo: string, ref: string | undefined, result: any) => void): void;\r\n\tlisten(): void;\r\n\tserver: import('http').Server;\r\n}\r\n\r\ninterface Push {\r\n\tcommits: Commit[];\r\n\tsender: {login: string};\r\n\tcompare: string;\r\n}\r\n\r\ninterface PullRequest {\r\n\taction: string;\r\n\tnumber: number;\r\n\tpull_request: {\r\n\t\turl: string,\r\n\t\thtml_url: string,\r\n\t\ttitle: string,\r\n\t\tuser: {\r\n\t\t\tlogin: string,\r\n\t\t\thtml_url: string,\r\n\t\t},\r\n\t\tmerge_commit_sha: string,\r\n\t};\r\n\tsender: {login: string};\r\n}\r\n\r\ninterface Commit {\r\n\tid: string;\r\n\tmessage: string;\r\n\tauthor: {name: string, avatar_url: string};\r\n\turl: string;\r\n}\r\n\r\ninterface GitData {\r\n\tusernames?: {[username: string]: string};\r\n\tbans?: {[username: string]: string};\r\n}\r\n\r\nexport const GitHub = new class {\r\n\treadonly hook: GitHookHandler | null = null;\r\n\tupdates: {[k: string]: number} = Object.create(null);\r\n\tconstructor() {\r\n\t\t// config.github: https://github.com/nlf/node-github-hook#readme\r\n\t\tif (!Config.github) return;\r\n\r\n\t\ttry {\r\n\t\t\tthis.hook = require('githubhook')({\r\n\t\t\t\tlogger: {\r\n\t\t\t\t\tlog: (line: string) => Monitor.debug(line),\r\n\t\t\t\t\terror: (line: string) => Monitor.notice(line),\r\n\t\t\t\t},\r\n\t\t\t\t...Config.github,\r\n\t\t\t});\r\n\t\t} catch (err) {\r\n\t\t\tMonitor.crashlog(err, \"GitHub hook\");\r\n\t\t}\r\n\t\tthis.listen();\r\n\t}\r\n\tlisten() {\r\n\t\tif (!this.hook) return;\r\n\t\tthis.hook.listen();\r\n\t\tthis.hook.on('push', (repo, ref, result) => this.handlePush(repo, ref, result));\r\n\t\tthis.hook.on('pull_request', (repo, ref, result) => this.handlePull(repo, ref, result));\r\n\t}\r\n\tprivate getRepoName(repo: string) {\r\n\t\tswitch (repo) {\r\n\t\tcase 'pokemon-showdown':\r\n\t\t\treturn 'server';\r\n\t\tcase 'pokemon-showdown-client':\r\n\t\t\treturn 'client';\r\n\t\tcase 'Pokemon-Showdown-Dex':\r\n\t\t\treturn 'dex';\r\n\t\tdefault:\r\n\t\t\treturn repo.toLowerCase();\r\n\t\t}\r\n\t}\r\n\thandlePush(repo: string, ref: string, result: Push) {\r\n\t\tconst branch = /[^/]+$/.exec(ref)?.[0] || \"\";\r\n\t\tif (branch !== 'master') return;\r\n\t\tconst messages: {[k: string]: string[]} = {\r\n\t\t\tstaff: [],\r\n\t\t\tdevelopment: [],\r\n\t\t};\r\n\t\tfor (const commit of result.commits) {\r\n\t\t\tconst {message, url} = commit;\r\n\t\t\tconst [shortMessage] = message.split('\\n\\n');\r\n\t\t\tconst username = this.getUsername(commit.author.name);\r\n\t\t\tconst repoName = this.getRepoName(repo);\r\n\t\t\tconst id = commit.id.substring(0, 6);\r\n\t\t\tmessages.development.push(\r\n\t\t\t\tUtils.html`[${repoName}] ${id} ${shortMessage} (${username})`\r\n\t\t\t);\r\n\t\t\tmessages.staff.push(Utils.html`[${repoName}] ${shortMessage} (${username})`);\r\n\t\t}\r\n\t\tfor (const k in messages) {\r\n\t\t\tthis.report(k as RoomID, repo, messages[k as RoomID]);\r\n\t\t}\r\n\t}\r\n\thandlePull(repo: string, ref: string | undefined, result: PullRequest) {\r\n\t\tif (this.isRateLimited(result.number)) return;\r\n\t\tif (this.isGitbanned(result)) return;\r\n\t\tconst url = result.pull_request.html_url;\r\n\t\tconst action = this.isValidAction(result.action);\r\n\t\tif (!action) return;\r\n\t\tconst repoName = this.getRepoName(repo);\r\n\t\tconst userName = this.getUsername(result.sender.login);\r\n\t\tconst title = result.pull_request.title;\r\n\t\tlet buf = Utils.html`[${repoName}] ${userName} `;\r\n\t\tbuf += Utils.html`${action} PR#${result.number}: ${title}`;\r\n\t\tthis.report('development', repo, buf);\r\n\t}\r\n\treport(roomid: RoomID, repo: string, messages: string[] | string) {\r\n\t\tif (!STAFF_REPOS.includes(repo) && roomid === 'staff') return;\r\n\t\tif (Array.isArray(messages)) messages = messages.join('
');\r\n\t\tRooms.get(roomid)?.add(`|html|