Skip to content

Commit 3888c30

Browse files
committed
refactor: better typing
1 parent 65aef1d commit 3888c30

File tree

9 files changed

+67
-31
lines changed

9 files changed

+67
-31
lines changed

packages/server-runtime/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ router.get('/ws', defineWebSocketHandler({
2424

2525
websocketLogger.withFields({ peer: peer.id, message: event }).log('received message')
2626
switch (event.type) {
27-
case 'input:voice:discord:transcription':
27+
case 'input:text:voice':
2828
websocketLogger.withFields({ message: event }).log('transcribed')
2929
break
3030
}

packages/server-sdk/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
},
3939
"dependencies": {
4040
"@proj-airi/server-shared": "workspace:^",
41-
"crossws": "^0.3.1"
41+
"crossws": "^0.3.1",
42+
"defu": "^6.1.4"
4243
}
4344
}

packages/server-sdk/src/client.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
1-
import type { WebSocketEvent } from '@proj-airi/server-shared/types'
1+
import type { WebSocketEvent, WebSocketEvents } from '@proj-airi/server-shared/types'
22
import type { Blob } from 'node:buffer'
33
import WebSocket from 'crossws/websocket'
4+
import { defu } from 'defu'
5+
6+
export interface ClientOptions {
7+
url?: string
8+
name: string
9+
possibleEvents?: Array<(keyof WebSocketEvents)>
10+
}
411

512
export class Client {
613
private websocket: WebSocket
714

8-
constructor(url: string) {
9-
this.websocket = new WebSocket(url)
15+
constructor(options: ClientOptions) {
16+
const opts = defu<Required<ClientOptions>, Required<Omit<ClientOptions, 'name'>>[]>(options, { url: 'ws://localhost:6121/ws', possibleEvents: [] })
17+
18+
this.websocket = new WebSocket(opts.url)
19+
this.send({
20+
type: 'module:announce',
21+
data: {
22+
name: opts.name,
23+
possibleEvents: opts.possibleEvents,
24+
},
25+
})
1026
}
1127

1228
send(data: WebSocketEvent): void {

packages/server-shared/src/types/websocket/events.ts

+30-5
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
1+
export interface DiscordGuildMember {
2+
nickname: string
3+
displayName: string
4+
id: string
5+
}
6+
7+
export interface Discord {
8+
guildMember?: DiscordGuildMember
9+
guildId?: string
10+
channelId?: string
11+
}
12+
13+
interface InputSource {
14+
browser: string
15+
discord: Discord
16+
}
17+
118
export interface WebSocketBaseEvent<T, D> {
219
type: T
320
data: D
421
}
522

23+
export type WithInputSource<Source extends keyof InputSource> = {
24+
[S in Source]: InputSource[S]
25+
}
26+
627
// Thanks to:
728
//
829
// A little hack for creating extensible discriminated unions : r/typescript
930
// https://www.reddit.com/r/typescript/comments/1064ibt/a_little_hack_for_creating_extensible/
1031
export interface WebSocketEvents {
1132
'module:announce': {
1233
name: string
34+
possibleEvents: Array<(keyof WebSocketEvents)>
1335
}
14-
'input:voice:discord:transcription': {
36+
'input:text': {
1537
text: string
16-
username: string
17-
userDisplayName: string
18-
userId: string
19-
}
38+
} & Partial<WithInputSource<'browser' | 'discord'>>
39+
'input:text:voice': {
40+
transcription: string
41+
} & Partial<WithInputSource<'browser' | 'discord'>>
42+
'input:voice': {
43+
audio: ArrayBuffer
44+
} & Partial<WithInputSource<'browser' | 'discord'>>
2045
}
2146

2247
export type WebSocketEvent = {

packages/stage-web/src/typed-router.d.ts

-9
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,5 @@ declare module 'vue-router/auto-routes' {
1818
* Route name map generated by unplugin-vue-router
1919
*/
2020
export interface RouteNamedMap {
21-
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
22-
'/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue<true> }, { all: ParamValue<false> }>,
23-
'/audio': RouteRecordInfo<'/audio', '/audio', Record<never, never>, Record<never, never>>,
24-
'/devtools/image': RouteRecordInfo<'/devtools/image', '/devtools/image', Record<never, never>, Record<never, never>>,
25-
'/queue': RouteRecordInfo<'/queue', '/queue', Record<never, never>, Record<never, never>>,
26-
'/test/filter-message': RouteRecordInfo<'/test/filter-message', '/test/filter-message', Record<never, never>, Record<never, never>>,
27-
'/test/queues/delays': RouteRecordInfo<'/test/queues/delays', '/test/queues/delays', Record<never, never>, Record<never, never>>,
28-
'/test/queues/emotions': RouteRecordInfo<'/test/queues/emotions', '/test/queues/emotions', Record<never, never>, Record<never, never>>,
29-
'/test/queues/messages': RouteRecordInfo<'/test/queues/messages', '/test/queues/messages', Record<never, never>, Record<never, never>>,
3021
}
3122
}

pnpm-lock.yaml

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/discord-voice-bot/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
"@xsai/generate-text": "catalog:",
4343
"@xsai/providers": "catalog:",
4444
"@xsai/shared-chat": "catalog:",
45-
"crossws": "^0.3.1",
4645
"discord.js": "^14.17.3",
4746
"libsodium-wrappers": "^0.7.15",
4847
"opusscript": "^0.1.1",

services/discord-voice-bot/src/bots/discord/commands/summon.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,17 @@ export async function handleSummon(log: ReturnType<typeof useLogg>, interaction:
122122
const speakingUser = await interaction.guild.members.fetch(userId)
123123
const result = await transcribeTextFromAudioReceiveStream(listenStream)
124124

125-
airiClient.send({ type: 'input:voice:discord:transcription', data: {
126-
text: result,
127-
userDisplayName: speakingUser.displayName,
128-
userId,
129-
username: speakingUser.nickname,
125+
airiClient.send({ type: 'input:text:voice', data: {
126+
transcription: result,
127+
discord: {
128+
guildId: interaction.guild.id,
129+
channelId: currVoiceChannel.id,
130+
guildMember: {
131+
id: userId,
132+
nickname: speakingUser.nickname,
133+
displayName: speakingUser.displayName,
134+
},
135+
},
130136
} })
131137
}
132138
catch (err) {

services/discord-voice-bot/src/index.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ async function main() {
1717
await WhisperLargeV3Pipeline.getInstance()
1818

1919
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates] })
20-
const airiClient = new AiriClient('ws://localhost:6121/ws')
21-
22-
airiClient.send({ type: 'module:announce', data: { name: 'input:voice:discord' } })
20+
const airiClient = new AiriClient({ name: 'discord-voice-bot', possibleEvents: ['input:text', 'input:text:voice', 'input:voice'] })
2321

2422
// When the client is ready, run this code (only once).
2523
// The distinction between `client: Client<boolean>` and `readyClient: Client<true>` is important for TypeScript developers.

0 commit comments

Comments
 (0)