{ "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|
${messages}
`).update();\r\n\t}\r\n\tisGitbanned(result: PullRequest) {\r\n\t\tif (!gitData.bans) return false;\r\n\t\treturn gitData.bans[result.sender.login] || gitData.bans[result.pull_request.user.login];\r\n\t}\r\n\tisRateLimited(prNumber: number) {\r\n\t\tif (this.updates[prNumber]) {\r\n\t\t\tif (this.updates[prNumber] + COOLDOWN > Date.now()) return true;\r\n\t\t\tthis.updates[prNumber] = Date.now();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tthis.updates[prNumber] = Date.now();\r\n\t\treturn false;\r\n\t}\r\n\tisValidAction(action: string) {\r\n\t\tif (action === 'synchronize') return 'updated';\r\n\t\tif (action === 'review_requested') {\r\n\t\t\treturn 'requested a review for';\r\n\t\t} else if (action === 'review_request_removed') {\r\n\t\t\treturn 'removed a review request for';\r\n\t\t}\r\n\t\tif (['ready_for_review', 'labeled', 'unlabeled', 'converted_to_draft'].includes(action)) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn action;\r\n\t}\r\n\tgetUsername(name: string) {\r\n\t\treturn gitData.usernames?.[toID(name)] || name;\r\n\t}\r\n\tsave() {\r\n\t\tFS(\"config/chat-plugins/github.json\").writeUpdate(() => JSON.stringify(gitData));\r\n\t}\r\n};\r\n\r\nexport const commands: Chat.ChatCommands = {\r\n\tgh: 'github',\r\n\tgithub: {\r\n\t\t''() {\r\n\t\t\treturn this.parse('/help github');\r\n\t\t},\r\n\t\tban(target, room, user) {\r\n\t\t\troom = this.requireRoom('development');\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\tconst [username, reason] = Utils.splitFirst(target, ',').map(u => u.trim());\r\n\t\t\tif (!toID(target)) return this.parse(`/help github`);\r\n\t\t\tif (!toID(username)) return this.errorReply(\"Provide a username.\");\r\n\t\t\tif (room.auth.has(toID(GitHub.getUsername(username)))) {\r\n\t\t\t\treturn this.errorReply(\"That user is Dev roomauth. If you need to do this, demote them and try again.\");\r\n\t\t\t}\r\n\t\t\tif (!gitData.bans) gitData.bans = {};\r\n\t\t\tif (gitData.bans[toID(username)]) {\r\n\t\t\t\treturn this.errorReply(`${username} is already gitbanned.`);\r\n\t\t\t}\r\n\t\t\tgitData.bans[toID(username)] = reason || \" \"; // to ensure it's truthy\r\n\t\t\tGitHub.save();\r\n\t\t\tthis.privateModAction(`${user.name} banned the GitHub user ${username} from having their GitHub actions reported to this server.`);\r\n\t\t\tthis.modlog('GITHUB BAN', username, reason);\r\n\t\t},\r\n\t\tunban(target, room, user) {\r\n\t\t\troom = this.requireRoom('development');\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\ttarget = toID(target);\r\n\t\t\tif (!target) return this.parse('/help github');\r\n\t\t\tif (!gitData.bans?.[target]) return this.errorReply(\"That user is not gitbanned.\");\r\n\t\t\tdelete gitData.bans[target];\r\n\t\t\tif (!Object.keys(gitData.bans).length) delete gitData.bans;\r\n\t\t\tGitHub.save();\r\n\t\t\tthis.privateModAction(`${user.name} allowed the GitHub user ${target} to have their GitHub actions reported to this server.`);\r\n\t\t\tthis.modlog('GITHUB UNBAN', target);\r\n\t\t},\r\n\t\tbans() {\r\n\t\t\tconst room = this.requireRoom('development');\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\treturn this.parse('/j view-github-bans');\r\n\t\t},\r\n\t\tsetname: 'addusername',\r\n\t\taddusername(target, room, user) {\r\n\t\t\troom = this.requireRoom('development');\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\tconst [gitName, username] = Utils.splitFirst(target, ',').map(u => u.trim());\r\n\t\t\tif (!toID(gitName) || !toID(username)) return this.parse(`/help github`);\r\n\t\t\tif (!gitData.usernames) gitData.usernames = {};\r\n\t\t\tgitData.usernames[toID(gitName)] = username;\r\n\t\t\tGitHub.save();\r\n\t\t\tthis.privateModAction(`${user.name} set ${gitName}'s name on reported GitHub actions to be ${username}.`);\r\n\t\t\tthis.modlog('GITHUB SETNAME', null, `'${gitName}' to '${username}'`);\r\n\t\t},\r\n\t\tclearname: 'removeusername',\r\n\t\tremoveusername(target, room, user) {\r\n\t\t\troom = this.requireRoom('development');\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\ttarget = toID(target);\r\n\t\t\tif (!target) return this.parse(`/help github`);\r\n\t\t\tconst name = gitData.usernames?.[target];\r\n\t\t\tif (!name) return this.errorReply(`${target} is not a GitHub username on our list.`);\r\n\t\t\tdelete gitData.usernames?.[target];\r\n\t\t\tif (!Object.keys(gitData.usernames || {}).length) delete gitData.usernames;\r\n\t\t\tGitHub.save();\r\n\t\t\tthis.privateModAction(`${user.name} removed ${target}'s name from the GitHub username list.`);\r\n\t\t\tthis.modlog('GITHUB CLEARNAME', target, `from the name ${name}`);\r\n\t\t},\r\n\t\tnames() {\r\n\t\t\treturn this.parse('/j view-github-names');\r\n\t\t},\r\n\t},\r\n\tgithubhelp: [\r\n\t\t`/github ban [username], [reason] - Bans a GitHub user from having their GitHub actions reported to Dev room. Requires: % @ # &`,\r\n\t\t`/github unban [username] - Unbans a GitHub user from having their GitHub actions reported to Dev room. Requires: % @ # &`,\r\n\t\t`/github bans - Lists all GitHub users that are currently gitbanned. Requires: % @ # &`,\r\n\t\t`/github setname [username], [name] - Sets a GitHub user's name on reported GitHub actions to be [name]. Requires: % @ # &`,\r\n\t\t`/github clearname [username] - Removes a GitHub user's name from the GitHub username list. Requires: % @ # &`,\r\n\t\t`/github names - Lists all GitHub usernames that are currently on our list.`,\r\n\t],\r\n};\r\n\r\nexport const pages: Chat.PageTable = {\r\n\tgithub: {\r\n\t\tbans(query, user) {\r\n\t\t\tconst room = Rooms.get('development');\r\n\t\t\tif (!room) return this.errorReply(\"No Development room found.\");\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\tif (!gitData.bans) return this.errorReply(\"There are no gitbans at this time.\");\r\n\t\t\tlet buf = `

Current Gitbans:


    `;\r\n\t\t\tfor (const [username, reason] of Object.entries(gitData.bans)) {\r\n\t\t\t\tbuf += `
  1. ${username} - ${reason.trim() || '(No reason found)'}
  2. `;\r\n\t\t\t}\r\n\t\t\tbuf += `
`;\r\n\t\t\treturn buf;\r\n\t\t},\r\n\t\tnames() {\r\n\t\t\tif (!gitData.usernames) return this.errorReply(\"There are no GitHub usernames in the list.\");\r\n\t\t\tlet buf = `

Current GitHub username mappings:


    `;\r\n\t\t\tfor (const [username, name] of Object.entries(gitData.usernames)) {\r\n\t\t\t\tbuf += `
  1. ${username} - ${name}
  2. `;\r\n\t\t\t}\r\n\t\t\tbuf += `
`;\r\n\t\t\treturn buf;\r\n\t\t},\r\n\t},\r\n};\r\n\r\nexport function destroy() {\r\n\tGitHub.hook?.server.close();\r\n}\r\n"], "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,iBAAwB;AAExB,MAAM,cAAc,OAAO,cAAc;AAAA,EACxC;AAAA,EAAoB;AAAA,EAA2B;AAAA,EAAwB;AACxE;AACA,MAAM,WAAW,KAAK,KAAK;AAEpB,MAAM,UAAmB,KAAK,UAAM,eAAG,iCAAiC,EAAE,iBAAiB,KAAK,IAAI;AA4CpG,MAAM,SAAS,IAAI,MAAM;AAAA,EAG/B,cAAc;AAFd,SAAS,OAA8B;AACvC,mBAAiC,uBAAO,OAAO,IAAI;AAGlD,QAAI,CAAC,OAAO;AAAQ;AAEpB,QAAI;AACH,WAAK,OAAO,QAAQ,YAAY,EAAE;AAAA,QACjC,QAAQ;AAAA,UACP,KAAK,CAAC,SAAiB,QAAQ,MAAM,IAAI;AAAA,UACzC,OAAO,CAAC,SAAiB,QAAQ,OAAO,IAAI;AAAA,QAC7C;AAAA,QACA,GAAG,OAAO;AAAA,MACX,CAAC;AAAA,IACF,SAAS,KAAP;AACD,cAAQ,SAAS,KAAK,aAAa;AAAA,IACpC;AACA,SAAK,OAAO;AAAA,EACb;AAAA,EACA,SAAS;AACR,QAAI,CAAC,KAAK;AAAM;AAChB,SAAK,KAAK,OAAO;AACjB,SAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,KAAK,WAAW,KAAK,WAAW,MAAM,KAAK,MAAM,CAAC;AAC9E,SAAK,KAAK,GAAG,gBAAgB,CAAC,MAAM,KAAK,WAAW,KAAK,WAAW,MAAM,KAAK,MAAM,CAAC;AAAA,EACvF;AAAA,EACQ,YAAY,MAAc;AACjC,YAAQ,MAAM;AAAA,MACd,KAAK;AACJ,eAAO;AAAA,MACR,KAAK;AACJ,eAAO;AAAA,MACR,KAAK;AACJ,eAAO;AAAA,MACR;AACC,eAAO,KAAK,YAAY;AAAA,IACzB;AAAA,EACD;AAAA,EACA,WAAW,MAAc,KAAa,QAAc;AACnD,UAAM,SAAS,SAAS,KAAK,GAAG,IAAI,CAAC,KAAK;AAC1C,QAAI,WAAW;AAAU;AACzB,UAAM,WAAoC;AAAA,MACzC,OAAO,CAAC;AAAA,MACR,aAAa,CAAC;AAAA,IACf;AACA,eAAW,UAAU,OAAO,SAAS;AACpC,YAAM,EAAC,SAAS,IAAG,IAAI;AACvB,YAAM,CAAC,YAAY,IAAI,QAAQ,MAAM,MAAM;AAC3C,YAAM,WAAW,KAAK,YAAY,OAAO,OAAO,IAAI;AACpD,YAAM,WAAW,KAAK,YAAY,IAAI;AACtC,YAAM,KAAK,OAAO,GAAG,UAAU,GAAG,CAAC;AACnC,eAAS,YAAY;AAAA,QACpB,iBAAM,oCAAoC,6BAA6B,8BAA8B,UAAU,6CAA6C;AAAA,MAC7J;AACA,eAAS,MAAM,KAAK,iBAAM,oCAAoC,6BAA6B,QAAQ,iDAAiD,kBAAkB;AAAA,IACvK;AACA,eAAW,KAAK,UAAU;AACzB,WAAK,OAAO,GAAa,MAAM,SAAS,CAAW,CAAC;AAAA,IACrD;AAAA,EACD;AAAA,EACA,WAAW,MAAc,KAAyB,QAAqB;AACtE,QAAI,KAAK,cAAc,OAAO,MAAM;AAAG;AACvC,QAAI,KAAK,YAAY,MAAM;AAAG;AAC9B,UAAM,MAAM,OAAO,aAAa;AAChC,UAAM,SAAS,KAAK,cAAc,OAAO,MAAM;AAC/C,QAAI,CAAC;AAAQ;AACb,UAAM,WAAW,KAAK,YAAY,IAAI;AACtC,UAAM,WAAW,KAAK,YAAY,OAAO,OAAO,KAAK;AACrD,UAAM,QAAQ,OAAO,aAAa;AAClC,QAAI,MAAM,iBAAM,oCAAoC,gDAAgD;AACpG,WAAO,iBAAM,OAAO,mBAAmB,WAAW,OAAO,eAAe;AACxE,SAAK,OAAO,eAAe,MAAM,GAAG;AAAA,EACrC;AAAA,EACA,OAAO,QAAgB,MAAc,UAA6B;AACjE,QAAI,CAAC,YAAY,SAAS,IAAI,KAAK,WAAW;AAAS;AACvD,QAAI,MAAM,QAAQ,QAAQ;AAAG,iBAAW,SAAS,KAAK,QAAQ;AAC9D,UAAM,IAAI,MAAM,GAAG,IAAI,8BAA8B,gBAAgB,EAAE,OAAO;AAAA,EAC/E;AAAA,EACA,YAAY,QAAqB;AAChC,QAAI,CAAC,QAAQ;AAAM,aAAO;AAC1B,WAAO,QAAQ,KAAK,OAAO,OAAO,KAAK,KAAK,QAAQ,KAAK,OAAO,aAAa,KAAK,KAAK;AAAA,EACxF;AAAA,EACA,cAAc,UAAkB;AAC/B,QAAI,KAAK,QAAQ,QAAQ,GAAG;AAC3B,UAAI,KAAK,QAAQ,QAAQ,IAAI,WAAW,KAAK,IAAI;AAAG,eAAO;AAC3D,WAAK,QAAQ,QAAQ,IAAI,KAAK,IAAI;AAClC,aAAO;AAAA,IACR;AACA,SAAK,QAAQ,QAAQ,IAAI,KAAK,IAAI;AAClC,WAAO;AAAA,EACR;AAAA,EACA,cAAc,QAAgB;AAC7B,QAAI,WAAW;AAAe,aAAO;AACrC,QAAI,WAAW,oBAAoB;AAClC,aAAO;AAAA,IACR,WAAW,WAAW,0BAA0B;AAC/C,aAAO;AAAA,IACR;AACA,QAAI,CAAC,oBAAoB,WAAW,aAAa,oBAAoB,EAAE,SAAS,MAAM,GAAG;AACxF,aAAO;AAAA,IACR;AACA,WAAO;AAAA,EACR;AAAA,EACA,YAAY,MAAc;AACzB,WAAO,QAAQ,YAAY,KAAK,IAAI,CAAC,KAAK;AAAA,EAC3C;AAAA,EACA,OAAO;AACN,uBAAG,iCAAiC,EAAE,YAAY,MAAM,KAAK,UAAU,OAAO,CAAC;AAAA,EAChF;AACD;AAEO,MAAM,WAA8B;AAAA,EAC1C,IAAI;AAAA,EACJ,QAAQ;AAAA,IACP,KAAK;AACJ,aAAO,KAAK,MAAM,cAAc;AAAA,IACjC;AAAA,IACA,IAAI,QAAQ,MAAM,MAAM;AACvB,aAAO,KAAK,YAAY,aAAa;AACrC,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,YAAM,CAAC,UAAU,MAAM,IAAI,iBAAM,WAAW,QAAQ,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AAC1E,UAAI,CAAC,KAAK,MAAM;AAAG,eAAO,KAAK,MAAM,cAAc;AACnD,UAAI,CAAC,KAAK,QAAQ;AAAG,eAAO,KAAK,WAAW,qBAAqB;AACjE,UAAI,KAAK,KAAK,IAAI,KAAK,OAAO,YAAY,QAAQ,CAAC,CAAC,GAAG;AACtD,eAAO,KAAK,WAAW,+EAA+E;AAAA,MACvG;AACA,UAAI,CAAC,QAAQ;AAAM,gBAAQ,OAAO,CAAC;AACnC,UAAI,QAAQ,KAAK,KAAK,QAAQ,CAAC,GAAG;AACjC,eAAO,KAAK,WAAW,GAAG,gCAAgC;AAAA,MAC3D;AACA,cAAQ,KAAK,KAAK,QAAQ,CAAC,IAAI,UAAU;AACzC,aAAO,KAAK;AACZ,WAAK,iBAAiB,GAAG,KAAK,+BAA+B,oEAAoE;AACjI,WAAK,OAAO,cAAc,UAAU,MAAM;AAAA,IAC3C;AAAA,IACA,MAAM,QAAQ,MAAM,MAAM;AACzB,aAAO,KAAK,YAAY,aAAa;AACrC,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,eAAS,KAAK,MAAM;AACpB,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,cAAc;AAC7C,UAAI,CAAC,QAAQ,OAAO,MAAM;AAAG,eAAO,KAAK,WAAW,6BAA6B;AACjF,aAAO,QAAQ,KAAK,MAAM;AAC1B,UAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE;AAAQ,eAAO,QAAQ;AACtD,aAAO,KAAK;AACZ,WAAK,iBAAiB,GAAG,KAAK,gCAAgC,8DAA8D;AAC5H,WAAK,OAAO,gBAAgB,MAAM;AAAA,IACnC;AAAA,IACA,OAAO;AACN,YAAM,OAAO,KAAK,YAAY,aAAa;AAC3C,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,aAAO,KAAK,MAAM,qBAAqB;AAAA,IACxC;AAAA,IACA,SAAS;AAAA,IACT,YAAY,QAAQ,MAAM,MAAM;AAC/B,aAAO,KAAK,YAAY,aAAa;AACrC,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,YAAM,CAAC,SAAS,QAAQ,IAAI,iBAAM,WAAW,QAAQ,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AAC3E,UAAI,CAAC,KAAK,OAAO,KAAK,CAAC,KAAK,QAAQ;AAAG,eAAO,KAAK,MAAM,cAAc;AACvE,UAAI,CAAC,QAAQ;AAAW,gBAAQ,YAAY,CAAC;AAC7C,cAAQ,UAAU,KAAK,OAAO,CAAC,IAAI;AACnC,aAAO,KAAK;AACZ,WAAK,iBAAiB,GAAG,KAAK,YAAY,mDAAmD,WAAW;AACxG,WAAK,OAAO,kBAAkB,MAAM,IAAI,gBAAgB,WAAW;AAAA,IACpE;AAAA,IACA,WAAW;AAAA,IACX,eAAe,QAAQ,MAAM,MAAM;AAClC,aAAO,KAAK,YAAY,aAAa;AACrC,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,eAAS,KAAK,MAAM;AACpB,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,cAAc;AAC7C,YAAM,OAAO,QAAQ,YAAY,MAAM;AACvC,UAAI,CAAC;AAAM,eAAO,KAAK,WAAW,GAAG,8CAA8C;AACnF,aAAO,QAAQ,YAAY,MAAM;AACjC,UAAI,CAAC,OAAO,KAAK,QAAQ,aAAa,CAAC,CAAC,EAAE;AAAQ,eAAO,QAAQ;AACjE,aAAO,KAAK;AACZ,WAAK,iBAAiB,GAAG,KAAK,gBAAgB,8CAA8C;AAC5F,WAAK,OAAO,oBAAoB,QAAQ,iBAAiB,MAAM;AAAA,IAChE;AAAA,IACA,QAAQ;AACP,aAAO,KAAK,MAAM,sBAAsB;AAAA,IACzC;AAAA,EACD;AAAA,EACA,YAAY;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEO,MAAM,QAAwB;AAAA,EACpC,QAAQ;AAAA,IACP,KAAK,OAAO,MAAM;AACjB,YAAM,OAAO,MAAM,IAAI,aAAa;AACpC,UAAI,CAAC;AAAM,eAAO,KAAK,WAAW,4BAA4B;AAC9D,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAI,CAAC,QAAQ;AAAM,eAAO,KAAK,WAAW,oCAAoC;AAC9E,UAAI,MAAM;AACV,iBAAW,CAAC,UAAU,MAAM,KAAK,OAAO,QAAQ,QAAQ,IAAI,GAAG;AAC9D,eAAO,eAAe,uBAAuB,OAAO,KAAK,KAAK;AAAA,MAC/D;AACA,aAAO;AACP,aAAO;AAAA,IACR;AAAA,IACA,QAAQ;AACP,UAAI,CAAC,QAAQ;AAAW,eAAO,KAAK,WAAW,4CAA4C;AAC3F,UAAI,MAAM;AACV,iBAAW,CAAC,UAAU,IAAI,KAAK,OAAO,QAAQ,QAAQ,SAAS,GAAG;AACjE,eAAO,eAAe,uBAAuB;AAAA,MAC9C;AACA,aAAO;AACP,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAEO,SAAS,UAAU;AACzB,SAAO,MAAM,OAAO,MAAM;AAC3B;", "names": [] }