-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Sho Sakuma
authored
Sep 6, 2023
1 parent
8e7f1af
commit 0294cbc
Showing
10 changed files
with
251 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
DISCORD_TOKEN= | ||
MAIN_CHANNEL_ID= | ||
ENTRANCE_CHANNEL_ID= | ||
APPLICATION_ID= | ||
GUILD_ID= | ||
PREFIX=! | ||
FEATURE=MESSAGE_CREATE,MESSAGE_UPDATE,COMMAND,VOICE_ROOM,ROLE,EMOJI | ||
FEATURE=MESSAGE_CREATE,MESSAGE_UPDATE,COMMAND,VOICE_ROOM,ROLE,EMOJI,SLASH_COMMAND,MEMBER |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import type { Client, GuildMember } from 'discord.js'; | ||
|
||
import type { Snowflake } from '../../model/id.js'; | ||
import type { MemberResponseRunner } from '../../runner/member.js'; | ||
import type { NewMember as AllMemberModel } from '../../service/welcome-message.js'; | ||
|
||
const map = ({ id, user }: GuildMember): AllMemberModel => ({ | ||
userId: id as Snowflake, | ||
isBot: user.bot | ||
}); | ||
|
||
export const memberProxy = ( | ||
client: Client, | ||
runner: MemberResponseRunner<AllMemberModel> | ||
) => { | ||
client.on('guildMemberAdd', (member) => | ||
runner.triggerEvent('JOIN', map(member)) | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
export type MemberEvent = 'JOIN'; | ||
|
||
export interface MemberEventResponder<M> { | ||
on(event: MemberEvent, member: M): Promise<void>; | ||
} | ||
|
||
export const composeMemberEventResponders = <M>( | ||
...responders: readonly MemberEventResponder<M>[] | ||
): MemberEventResponder<M> => ({ | ||
async on(event, member) { | ||
await Promise.all( | ||
responders.map((responder) => responder.on(event, member)) | ||
); | ||
} | ||
}); | ||
|
||
export class MemberResponseRunner<M> { | ||
async triggerEvent(event: MemberEvent, member: M): Promise<void> { | ||
try { | ||
await Promise.all(this.responder.map((res) => res.on(event, member))); | ||
} catch (e) { | ||
console.error(e); | ||
} | ||
} | ||
|
||
private responder: MemberEventResponder<M>[] = []; | ||
|
||
addResponder(responder: MemberEventResponder<M>) { | ||
this.responder.push(responder); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,15 @@ | ||
import type { EmbedMessage } from '../model/embed-message.js'; | ||
|
||
/** | ||
* "#無法地帯" に埋め込みを送信する interface. | ||
*/ | ||
export interface StandardOutput { | ||
sendEmbed(embed: EmbedMessage): Promise<void>; | ||
} | ||
|
||
/** | ||
* "#玄関" に埋め込みを送信する interface. | ||
*/ | ||
export interface EntranceOutput { | ||
sendEmbedWithMention(embed: EmbedMessage, userId: string): Promise<void>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { afterEach, describe, expect, it, vi } from 'vitest'; | ||
|
||
import type { Snowflake } from '../model/id.js'; | ||
import type { EntranceOutput } from './output.js'; | ||
import { WelcomeMessage } from './welcome-message.js'; | ||
|
||
describe('WelcomeMessage', () => { | ||
afterEach(() => { | ||
vi.restoreAllMocks(); | ||
}); | ||
|
||
const output: EntranceOutput = { | ||
sendEmbedWithMention: () => Promise.resolve() | ||
}; | ||
const responder = new WelcomeMessage(output); | ||
|
||
it('send welcome message', async () => { | ||
const sendEmbed = vi.spyOn(output, 'sendEmbedWithMention'); | ||
|
||
await responder.on('JOIN', { | ||
userId: '586824421470109716' as Snowflake, | ||
isBot: false | ||
}); | ||
|
||
expect(sendEmbed).toHaveBeenCalledWith( | ||
{ | ||
title: '***†WELCOME TO UNDERGROUND†***', | ||
description: | ||
'司令官。ようこそ、限界開発鯖へ\nまずはじめに知っていてほしいことを教えるよ\n詳しい説明は [鯖民向けドキュメント](https://docs.approvers.dev/reference/getting-started) を見てね', | ||
fields: [ | ||
{ | ||
name: 'メンバーデータの追加', | ||
value: | ||
'限界開発鯖では各メンバーの情報をデータベースに保存し、それらを元に様々な機能を提供しているよ。\n限界開発鯖に参加したら、まずは自分のメンバーデータを追加してね\n', | ||
inline: false | ||
}, | ||
{ | ||
name: '自己紹介', | ||
value: | ||
'参加したら <#687977635132997634> で同じ司令官のみんなに自己紹介しよう', | ||
inline: false | ||
}, | ||
{ | ||
name: 'メインチャンネル', | ||
value: | ||
'限界開発鯖では以下のチャンネルがメインで使われているよ\n- <#690909527461199922>\n- <#891210643938611260>\n- <#683939861539192865>', | ||
inline: false | ||
}, | ||
{ | ||
name: 'Botの導入', | ||
value: | ||
'限界開発鯖では自分が開発したBotを導入できるよ。導入に関する詳しい説明は [Bot 製作ガイドライン](https://docs.approvers.dev/guideline/bot-create-guideline) を確認してね', | ||
inline: false | ||
} | ||
] | ||
}, | ||
'586824421470109716' | ||
); | ||
}); | ||
|
||
it('skip welcome message (join a bot)', async () => { | ||
const sendEmbed = vi.spyOn(output, 'sendEmbedWithMention'); | ||
|
||
await responder.on('JOIN', { | ||
userId: '586824421470109716' as Snowflake, | ||
isBot: true | ||
}); | ||
|
||
expect(sendEmbed).not.toHaveBeenCalled(); | ||
}); | ||
}); |
Oops, something went wrong.