-
Notifications
You must be signed in to change notification settings - Fork 13
[map-guessr] Support #tsgbot-games channel via ChannelLimitedBot #1165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c5797ed
616443f
59035a6
80bc765
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,16 +5,18 @@ import puppeteer from "puppeteer"; | |||||
| import { AteQuizProblem, AteQuizResult } from "../atequiz"; | ||||||
| import { | ||||||
| ChatPostMessageArguments, | ||||||
| GenericMessageEvent, | ||||||
| WebClient, | ||||||
| } from "@slack/web-api"; | ||||||
| import { increment } from "../achievements"; | ||||||
| import { ChannelLimitedBot } from "../lib/channelLimitedBot"; | ||||||
| import { Deferred } from "../lib/utils"; | ||||||
| import { EventEmitter } from 'events'; | ||||||
| const { Mutex } = require("async-mutex"); | ||||||
| const { AteQuiz } = require("../atequiz/index.ts"); | ||||||
| const cloudinary = require("cloudinary"); | ||||||
|
|
||||||
| const API_KEY = process.env.GOOGLE_MAPS_API_KEY; | ||||||
| const CHANNEL = process.env.CHANNEL_SANDBOX; | ||||||
| const mutex = new Mutex(); | ||||||
|
|
||||||
| const img_size = 1000; | ||||||
|
|
@@ -174,7 +176,6 @@ const mesHelp = { | |||||
| }, | ||||||
| }, | ||||||
| ], | ||||||
| channel: CHANNEL, | ||||||
| }; | ||||||
|
|
||||||
| function countriesListMessageGen(aliases: Record<string, string[]>): any { | ||||||
|
|
@@ -212,7 +213,6 @@ function countriesListMessageGen(aliases: Record<string, string[]>): any { | |||||
| return { type: "section", text: { type: "mrkdwn", text: text } }; | ||||||
| }), | ||||||
| ], | ||||||
| channel: CHANNEL, | ||||||
| }; | ||||||
| return mesCountries; | ||||||
| } | ||||||
|
|
@@ -582,13 +582,14 @@ function problemFormat( | |||||
| img_url: string, | ||||||
| latitude: number, | ||||||
| longitude: number, | ||||||
| thread_ts: string | ||||||
| thread_ts: string, | ||||||
| channel: string | ||||||
| ) { | ||||||
| const answer = latLngFormat(latitude, longitude); | ||||||
|
|
||||||
| const problem: CoordAteQuizProblem = { | ||||||
| problemMessage: { | ||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| thread_ts, | ||||||
| text: `緯度と経度を当ててね。サイズは${distFormat(size)}四方だよ。`, | ||||||
| blocks: [ | ||||||
|
|
@@ -608,36 +609,36 @@ function problemFormat( | |||||
| }, | ||||||
| hintMessages: [ | ||||||
| { | ||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| text: `画像の中心点は${country.properties.NAME_JA}にあるよ:triangular_flag_on_post:`, | ||||||
| }, | ||||||
| ], | ||||||
| immediateMessage: { channel: CHANNEL, text: "制限時間: 300秒" }, | ||||||
| immediateMessage: { channel, text: "制限時間: 300秒" }, | ||||||
| solvedMessage: { | ||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| text: ``, | ||||||
| reply_broadcast: true, | ||||||
| thread_ts, | ||||||
| unfurl_links: false, | ||||||
| unfurl_media: false, | ||||||
| }, | ||||||
| incorrectMessage: { | ||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| text: ``, | ||||||
| unfurl_links: false, | ||||||
| unfurl_media: false, | ||||||
| }, | ||||||
| unsolvedMessage: { | ||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| text: `もう、しっかりして!\n中心点の座標は <https://maps.google.co.jp/maps?ll=${latitude},${longitude}&q=${latitude},${longitude}&&t=k|${answer}> だよ:anger:`, | ||||||
| reply_broadcast: true, | ||||||
| thread_ts, | ||||||
| unfurl_links: false, | ||||||
| unfurl_media: false, | ||||||
| }, | ||||||
| answer: [latitude, longitude], | ||||||
| zoom: zoom, | ||||||
| size: size, | ||||||
| zoom, | ||||||
| size, | ||||||
| correctAnswers: [] as string[], | ||||||
| }; | ||||||
| return problem; | ||||||
|
|
@@ -647,11 +648,12 @@ async function prepareProblem( | |||||
| slack: any, | ||||||
| message: any, | ||||||
| aliases: Record<string, string[]>, | ||||||
| world: any, | ||||||
| thread_ts: string | ||||||
| world: Turf.FeatureCollection<Turf.MultiPolygon>, | ||||||
| thread_ts: string, | ||||||
| channel: string | ||||||
| ) { | ||||||
| await slack.chat.postEphemeral({ | ||||||
|
hakatashi marked this conversation as resolved.
|
||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| text: "問題を生成中...", | ||||||
| user: message.user, | ||||||
| ...postOptions, | ||||||
|
|
@@ -664,7 +666,7 @@ async function prepareProblem( | |||||
| if (errorText.length > 0) { | ||||||
| await slack.chat.postMessage({ | ||||||
| text: errorText, | ||||||
| channel: CHANNEL, | ||||||
| channel, | ||||||
| ...postOptions, | ||||||
| }); | ||||||
| return; | ||||||
|
|
@@ -686,106 +688,125 @@ async function prepareProblem( | |||||
| img_url, | ||||||
| latitude, | ||||||
| longitude, | ||||||
| thread_ts | ||||||
| thread_ts, | ||||||
| channel | ||||||
| ); | ||||||
| return problem; | ||||||
| } | ||||||
|
|
||||||
| export default async ({ eventClient, webClient: slack }: SlackInterface) => { | ||||||
| const aliases = (await fs.readJson( | ||||||
| __dirname + "/country_names.json" | ||||||
| )) as Record<string, string[]>; | ||||||
| class MapGuessr extends ChannelLimitedBot { | ||||||
| protected override readonly wakeWordRegex = /^座標[当あ]て/; | ||||||
|
|
||||||
| const world = await fs.readJson(__dirname + "/countries.geojson"); | ||||||
| eventClient.on("message", async (message) => { | ||||||
| if ( | ||||||
| message.channel !== CHANNEL || | ||||||
| message.thread_ts || | ||||||
| !( | ||||||
| message.text?.startsWith("座標当て") || | ||||||
| message.text?.startsWith("座標あて") | ||||||
| ) | ||||||
| ) { | ||||||
| return; | ||||||
| } | ||||||
| const messageTs = { thread_ts: message.ts }; | ||||||
| protected override readonly username = 'coord-quiz'; | ||||||
|
|
||||||
| if (message.text.includes("help")) { | ||||||
| await slack.chat.postMessage({ | ||||||
| protected override readonly iconEmoji = ':globe_with_meridians:'; | ||||||
|
|
||||||
| private readonly aliases: Record<string, string[]>; | ||||||
|
|
||||||
| private readonly world: Turf.FeatureCollection<Turf.MultiPolygon>; | ||||||
|
|
||||||
| constructor(slackClients: SlackInterface, aliases: Record<string, string[]>, world: Turf.FeatureCollection<Turf.MultiPolygon>) { | ||||||
| super(slackClients); | ||||||
| this.aliases = aliases; | ||||||
| this.world = world; | ||||||
| } | ||||||
|
|
||||||
| protected override onWakeWord(message: GenericMessageEvent, channel: string): Promise<string | null> { | ||||||
| if (message.text.includes('help')) { | ||||||
| this.postMessage({ | ||||||
| ...mesHelp, | ||||||
| ...postOptions, | ||||||
| ...messageTs, | ||||||
| channel, | ||||||
| thread_ts: message.ts, | ||||||
| }); | ||||||
|
Comment on lines
+715
to
720
|
||||||
| return; | ||||||
| return Promise.resolve(null); | ||||||
| } | ||||||
|
|
||||||
| if (message.text.includes("countries")) { | ||||||
| await slack.chat.postMessage({ | ||||||
| ...countriesListMessageGen(aliases), | ||||||
| ...postOptions, | ||||||
| ...messageTs, | ||||||
| if (message.text.includes('countries')) { | ||||||
| this.postMessage({ | ||||||
| ...countriesListMessageGen(this.aliases), | ||||||
| channel, | ||||||
| thread_ts: message.ts, | ||||||
| }); | ||||||
| return; | ||||||
| return Promise.resolve(null); | ||||||
| } | ||||||
|
|
||||||
| if (mutex.isLocked()) { | ||||||
| slack.chat.postMessage({ | ||||||
| channel: CHANNEL, | ||||||
| text: "今クイズ中だよ:angry:", | ||||||
| ...messageTs, | ||||||
| ...postOptions, | ||||||
| this.postMessage({ | ||||||
| channel, | ||||||
| text: '今クイズ中だよ:angry:', | ||||||
| thread_ts: message.ts, | ||||||
| }); | ||||||
| return; | ||||||
| return Promise.resolve(null); | ||||||
| } | ||||||
|
|
||||||
| const [result, startTime, size] = await mutex.runExclusive(async () => { | ||||||
| const arr = await Promise.race([ | ||||||
| (async () => { | ||||||
| const problem: CoordAteQuizProblem = await prepareProblem( | ||||||
| slack, | ||||||
| message, | ||||||
| aliases, | ||||||
| world, | ||||||
| message.ts | ||||||
| ); | ||||||
|
|
||||||
| const ateQuiz = new CoordAteQuiz(eventClient, slack, problem); | ||||||
| const st = Date.now(); | ||||||
| const res = await ateQuiz.start(); | ||||||
|
|
||||||
| return [res, st, problem.size]; | ||||||
| })(), | ||||||
| (async () => { | ||||||
| await new Promise((resolve) => { | ||||||
| return setTimeout(resolve, 600 * 1000); | ||||||
| }); | ||||||
| return [null, null, null] as any[]; | ||||||
| })(), | ||||||
| ]); | ||||||
| return arr; | ||||||
| const quizMessageDeferred = new Deferred<string | null>(); | ||||||
|
|
||||||
| mutex.runExclusive(async () => { | ||||||
| try { | ||||||
| const problem: CoordAteQuizProblem = await prepareProblem( | ||||||
| this.slack, | ||||||
| message, | ||||||
| this.aliases, | ||||||
| this.world, | ||||||
| message.ts, | ||||||
|
||||||
| message.ts, | |
| channel === message.channel ? message.ts : undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import:
AteQuizResultis imported but never referenced in this file. Please remove it to keep imports clean and avoid confusing readers about expected return types.