11import { readFile } from 'fs/promises' ;
22import path from 'path' ;
33import { SlackMessageAdapter } from '@slack/interactive-messages' ;
4- import type { ChatPostMessageArguments , ImageElement , KnownBlock , WebClient } from '@slack/web-api' ;
4+ import type { ImageElement , KnownBlock , WebClient } from '@slack/web-api' ;
55import { Mutex } from 'async-mutex' ;
66import { oneLine , stripIndent } from 'common-tags' ;
7+ import type { FastifyPluginCallback } from 'fastify' ;
8+ import plugin from 'fastify-plugin' ;
79// @ts -expect-error: Not typed
810import { hiraganize } from 'japanese' ;
911import yaml from 'js-yaml' ;
@@ -13,7 +15,7 @@ import type OpenAI from 'openai';
1315import { increment } from '../achievements' ;
1416import logger from '../lib/logger' ;
1517import openai from '../lib/openai' ;
16- import type { SlackInterface } from '../lib/slack' ;
18+ import type { SlashCommandEndpoint , SlackInterface } from '../lib/slack' ;
1719import State from '../lib/state' ;
1820import { Loader } from '../lib/utils' ;
1921import { getUserIcon , getUserMention , getUserName } from './util' ;
@@ -786,21 +788,32 @@ class SlowQuiz {
786788 }
787789
788790 await this . checkGameEnd ( ) ;
789-
790791 if ( this . state . games . some ( ( game ) => game . status === 'inprogress' ) ) {
791- const blocks = await this . getGameBlocks ( ) ;
792- const messages = await this . postMessage ( {
792+ await this . postGameStatus ( true ) ;
793+ }
794+ await this . createBotAnswers ( ) ;
795+ }
796+
797+ async postGameStatus ( replaceLatestStatusMessages : boolean , channels : string [ ] = [ ] ) {
798+ const blocks = await this . getGameBlocks ( ) ;
799+ const messages = await this . postMessage (
800+ {
793801 text : '現在開催中の1日1文字クイズ一覧' ,
794802 blocks,
795- } ) ;
803+ } ,
804+ ...( channels . length > 0 ? [ channels ] : [ ] ) ,
805+ ) ;
796806
797- this . state . latestStatusMessages = messages . map ( ( message ) => ( {
798- ts : message . ts ,
799- channel : message . channel ,
800- } ) ) ;
801- }
807+ const newStatusMessages = messages . map ( ( message ) => ( {
808+ ts : message . ts ,
809+ channel : message . channel ,
810+ } ) ) ;
802811
803- await this . createBotAnswers ( ) ;
812+ if ( replaceLatestStatusMessages ) {
813+ this . state . latestStatusMessages = newStatusMessages ;
814+ } else {
815+ this . state . latestStatusMessages . push ( ...newStatusMessages ) ;
816+ }
804817 }
805818
806819 chooseNewGame ( ) {
@@ -1067,10 +1080,13 @@ class SlowQuiz {
10671080 return { text, invisibleCharacters} ;
10681081 }
10691082
1070- async postMessage ( message : { text : string , blocks : KnownBlock [ ] } ) {
1083+ async postMessage (
1084+ message : { text : string , blocks : KnownBlock [ ] } ,
1085+ channels : string [ ] = [ process . env . CHANNEL_SANDBOX , process . env . CHANNEL_QUIZ ] ,
1086+ ) {
10711087 const messages = [ ] ;
10721088
1073- for ( const channel of [ process . env . CHANNEL_SANDBOX , process . env . CHANNEL_QUIZ ] ) {
1089+ for ( const channel of channels ) {
10741090 const response = await this . slack . chat . postMessage ( {
10751091 channel,
10761092 username : '1日1文字クイズ' ,
@@ -1105,13 +1121,36 @@ class SlowQuiz {
11051121 }
11061122}
11071123
1108- export default async ( { webClient : slack , messageClient : slackInteractions } : SlackInterface ) => {
1109- const slowquiz = new SlowQuiz ( { slack, slackInteractions} ) ;
1110- await slowquiz . initialize ( ) ;
1124+ export const server = ( { webClient : slack , messageClient : slackInteractions } : SlackInterface ) => {
1125+ const callback : FastifyPluginCallback = async ( fastify , opts , next ) => {
1126+ const slowquiz = new SlowQuiz ( { slack, slackInteractions} ) ;
1127+ await slowquiz . initialize ( ) ;
11111128
1112- scheduleJob ( '0 10 * * *' , ( ) => {
1113- mutex . runExclusive ( ( ) => {
1114- slowquiz . progressGames ( ) ;
1129+ fastify . post < SlashCommandEndpoint > ( '/slash/slow-quiz' , ( req , res ) => {
1130+ if ( req . body . token !== process . env . SLACK_VERIFICATION_TOKEN ) {
1131+ res . code ( 400 ) ;
1132+ return 'Bad Request' ;
1133+ }
1134+
1135+ mutex . runExclusive ( async ( ) => {
1136+ log . info ( 'Received /slow-quiz command' ) ;
1137+ await slowquiz . postGameStatus ( false , [ req . body . channel_id ] ) ;
1138+ } ) ;
1139+
1140+ return {
1141+ response_type : 'in_channel' ,
1142+ text : 'Working...' ,
1143+ } ;
11151144 } ) ;
1116- } ) ;
1145+
1146+ scheduleJob ( '0 10 * * *' , ( ) => {
1147+ mutex . runExclusive ( ( ) => {
1148+ slowquiz . progressGames ( ) ;
1149+ } ) ;
1150+ } ) ;
1151+
1152+ next ( ) ;
1153+ } ;
1154+
1155+ return plugin ( callback ) ;
11171156} ;
0 commit comments