Skip to content

[hitandblow] Migrate to ChannelLimitedBot for #tsgbot-games support#1150

Open
Copilot wants to merge 2 commits intomasterfrom
copilot/update-hitandblow-bot
Open

[hitandblow] Migrate to ChannelLimitedBot for #tsgbot-games support#1150
Copilot wants to merge 2 commits intomasterfrom
copilot/update-hitandblow-bot

Conversation

Copy link
Contributor

Copilot AI commented Jan 21, 2026

Refactor hitandblow bot to extend ChannelLimitedBot, enabling execution in #tsgbot-games channel with automatic channel restriction and progress tracking.

Changes

  • Class-based architecture: Converted functional export to HitAndBlowBot class extending ChannelLimitedBot
  • Channel enforcement: Bot now runs in CHANNEL_GAMES by default, with automatic redirect and message cleanup for disallowed channels
  • Progress notifications: Posts game-in-progress messages to CHANNEL_SANDBOX, cleaned up on game completion (timeout or win)
  • onWakeWord pattern: Game start logic moved to onWakeWord() with Deferred-based promise handling
  • Unified messaging: All Slack API calls replaced with this.postMessage() for consistent username/icon
class HitAndBlowBot extends ChannelLimitedBot {
  protected override readonly wakeWordRegex = /^hitandblow( \d+)?$/;
  protected override readonly username = 'Hit & Blow';
  protected override readonly iconEmoji = '1234';

  protected override async onWakeWord(message: GenericMessageEvent, channel: string): Promise<string | null> {
    // Game initialization returns message timestamp for progress tracking
  }
}

Follows established pattern from anime (#1138), character-quiz (#1122), and achievement-quiz (#1124) migrations.

Original prompt

This section details on the original issue you should resolve

<issue_title>[hitandblow] #tsgbot-games 対応 & ChannelLimitedBotクラスを導入</issue_title>
<issue_description>Issue #1099 の対応の一環として、 hitandblow BOTの改修を行う。

Slackの #tsgbot-games チャンネルからの起動に対応できるようにする。また、 lib/channelLimitedBot.ts で定義されたChannelLimitedBotクラスを利用し、起動チャンネルの指定と進行中のゲームの通知を導入する。

改修にあたっては、すでに行われた以下の3つのBOTの同様の修正の修正内容を必ず参照し、これらのスタイルを可能な限り踏襲する。

なお、対象のBOTがJavaScriptで書かれている場合は、今回の改修でTypeScriptに書き換える必要はない。このプロジェクトではJavaScriptとTypeScriptを混在させることができる。また、そのほか改修に関係ない改良を加える必要はない。

anime bot

character-quiz bot

achievement-quiz bot

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: hakatashi <3126484+hakatashi@users.noreply.github.com>
@sonarqubecloud
Copy link

Copilot AI changed the title [WIP] Update hitandblow bot for #tsgbot-games channel [hitandblow] Migrate to ChannelLimitedBot for #tsgbot-games support Jan 21, 2026
Copilot AI requested a review from hakatashi January 21, 2026 04:11
@hakatashi hakatashi marked this pull request as ready for review February 3, 2026 10:28
@hakatashi hakatashi requested a review from settyan117 as a code owner February 3, 2026 10:28
Copilot AI review requested due to automatic review settings February 3, 2026 10:28
@tsg-ut-gemini-assistant
Copy link
Contributor

えへ~

ありがとう!

レビューさせてもらうにゃ!

🔍️🔍️🔍️️

Copy link
Contributor

@tsg-ut-gemini-assistant tsg-ut-gemini-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review Summary

このプルリクエストは、hitandblow ボットを ChannelLimitedBot に移行して、#tsgbot-games チャンネルに対応させるものだにゃ。全体的に、以前のボットの移行パターンにうまく従っていて、とても良いリファクタリングだと思うにゃ!コードもきれいになったにゃししっ!

🔍 General Feedback

  • ボットを ChannelLimitedBot に移行することで、チャンネル制限や進行状況の通知が自動的にできるようになるのはすごく便利だにゃ!
  • テストファイル (index.test.ts) の jest.mock の変更も、新しいアーキテクチャに合わせてていい感じだにゃ!
  • onWakeWordonMessageEvent の実装も、新しいクラスベースの構造に合っていて、ちゃんとエラーハンドリングもしてるのがえらいにゃ!

}) => {
const state = new HitAndBlowState();
class HitAndBlowBot extends ChannelLimitedBot {
protected override readonly wakeWordRegex = /^hitandblow( \d+)?$/;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 アイコン絵文字がプレースホルダーのままだにゃ!ちゃんとした絵文字に差し替えるのを忘れないようにするんだにゃ!にゃししっ!

protected override readonly iconEmoji = '1234';

private state = new HitAndBlowState();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 うなの考えでは、このコメントはもういらないんじゃないかと思うにゃ!だって、うながゲームを開始するときにちゃんとchannelを設定してるんだにゃ!だから、nullになる心配はないんだにゃ!

Suggested change
channel: this.state.channel,

message === null ||
!message.text ||
message.subtype
) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 このコメントもいらないと思うにゃ!うなの独り言はコードに残さないほうがいいんだにゃ!

Suggested change
) {
hits.size
} Hit ${blows.size - hits.size} Blow`,

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request migrates the hitandblow bot to use the ChannelLimitedBot base class, enabling it to run in the #tsgbot-games channel with automatic channel restrictions and progress tracking. The refactoring follows the established patterns from similar migrations (anime #1138, character-quiz #1122, achievement-quiz #1124).

Changes:

  • Converted the bot from functional export to class-based architecture extending ChannelLimitedBot
  • Implemented channel enforcement with automatic message redirect and cleanup for disallowed channels
  • Added progress notifications to #tsgbot-games that are cleaned up on game completion

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
hitandblow/index.ts Refactored to HitAndBlowBot class extending ChannelLimitedBot; replaced direct Slack API calls with unified postMessage method; added onWakeWord for game initialization with Deferred-based promise handling; implemented onMessageEvent override for game logic; added deleteProgressMessage calls on game end
hitandblow/index.test.ts Simplified test mocking by removing specific isPlayground mock and using generic slackUtils mock, consistent with ChannelLimitedBot pattern

class HitAndBlowBot extends ChannelLimitedBot {
protected override readonly wakeWordRegex = /^hitandblow( \d+)?$/;
protected override readonly username = 'Hit & Blow';
protected override readonly iconEmoji = '1234';
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The iconEmoji should use Slack emoji format with colons. Change '1234' to ':1234:' to match the pattern used by other bots in the codebase (see achievement-quiz/index.ts:111, character-quiz/index.ts:343, wordhero/crossword.ts:107, etc.). Without colons, Slack may not properly render the emoji.

Copilot uses AI. Check for mistakes.
答えは \`${this.state.answer
.map((dig: number) => String(dig))
.join('')}\` だよ:cry:`,
channel: process.env.CHANNEL_SANDBOX as string,
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out giveup feature has hardcoded reference to CHANNEL_SANDBOX. If this feature is re-enabled, line 329 should be updated to use this.state.channel instead of process.env.CHANNEL_SANDBOX as string to match the pattern used elsewhere in the code.

Suggested change
channel: process.env.CHANNEL_SANDBOX as string,
channel: this.state.channel,

Copilot uses AI. Check for mistakes.
reply_broadcast: true,
});
postHistory(state.history);
await this.postHistory(this.state.history);
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out giveup feature is missing a call to await this.deleteProgressMessage(this.state.thread) before clearing the state. This should be added (after line 333) to match the pattern used in the timeUp method (line 145) and the win condition (line 311), ensuring progress messages are cleaned up when the game ends.

Suggested change
await this.postHistory(this.state.history);
await this.postHistory(this.state.history);
await this.deleteProgressMessage(this.state.thread);

Copilot uses AI. Check for mistakes.
Comment on lines +202 to +207
})().catch((error: unknown) => {
this.log.error('Failed to start hitandblow game', error);
const errorText =
error instanceof Error && error.stack !== undefined
? error.stack : String(error);
this.postMessage({
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing await on postMessage call in error handler. This postMessage call should be awaited to ensure the error message is sent before resolving the deferred promise. Without await, the error message may not be posted if the function returns too quickly.

Suggested change
})().catch((error: unknown) => {
this.log.error('Failed to start hitandblow game', error);
const errorText =
error instanceof Error && error.stack !== undefined
? error.stack : String(error);
this.postMessage({
})().catch(async (error: unknown) => {
this.log.error('Failed to start hitandblow game', error);
const errorText =
error instanceof Error && error.stack !== undefined
? error.stack : String(error);
await this.postMessage({

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[hitandblow] #tsgbot-games 対応 & ChannelLimitedBotクラスを導入

3 participants