mirror of
https://github.com/informaticker/discord-jellyfin-bot.git
synced 2024-11-23 18:21:55 +01:00
✨ Implement Summon and Disconnect
This commit is contained in:
parent
c581ef748a
commit
73f2f0eb5f
@ -61,3 +61,8 @@ $ npm run test:e2e
|
|||||||
# test coverage
|
# test coverage
|
||||||
$ npm run test:cov
|
$ npm run test:cov
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 👤 Credits
|
||||||
|
- https://tabler-icons.io/ (MIT)
|
||||||
|
- https://docs.nestjs.com/ (MIT)
|
||||||
|
- https://discord.js.org/ (Apache 2.0)
|
@ -24,6 +24,7 @@
|
|||||||
"@discord-nestjs/common": "^4.0.8",
|
"@discord-nestjs/common": "^4.0.8",
|
||||||
"@discord-nestjs/core": "^4.3.1",
|
"@discord-nestjs/core": "^4.3.1",
|
||||||
"@discordjs/opus": "^0.9.0",
|
"@discordjs/opus": "^0.9.0",
|
||||||
|
"@discordjs/voice": "^0.14.0",
|
||||||
"@jellyfin/sdk": "^0.7.0",
|
"@jellyfin/sdk": "^0.7.0",
|
||||||
"@nestjs/common": "^9.0.0",
|
"@nestjs/common": "^9.0.0",
|
||||||
"@nestjs/config": "^2.2.0",
|
"@nestjs/config": "^2.2.0",
|
||||||
|
@ -10,7 +10,7 @@ import { AppService } from './app.service';
|
|||||||
import { DiscordClientModule } from './clients/discord/discord.module';
|
import { DiscordClientModule } from './clients/discord/discord.module';
|
||||||
import { JellyfinClientModule } from './clients/jellyfin/jellyfin.module';
|
import { JellyfinClientModule } from './clients/jellyfin/jellyfin.module';
|
||||||
import { CommandModule } from './commands/command.module';
|
import { CommandModule } from './commands/command.module';
|
||||||
import { DiscordConfigService } from './clients/discord/jellyfin.config.service';
|
import { DiscordConfigService } from './clients/discord/discord.config.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -11,7 +11,12 @@ export class DiscordConfigService implements DiscordOptionsFactory {
|
|||||||
return {
|
return {
|
||||||
token: process.env.DISCORD_CLIENT_TOKEN,
|
token: process.env.DISCORD_CLIENT_TOKEN,
|
||||||
discordClientOptions: {
|
discordClientOptions: {
|
||||||
intents: [GatewayIntentBits.Guilds],
|
intents: [
|
||||||
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildMessages,
|
||||||
|
GatewayIntentBits.MessageContent,
|
||||||
|
GatewayIntentBits.GuildIntegrations,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { DiscordConfigService } from './jellyfin.config.service';
|
import { DiscordConfigService } from './discord.config.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
|
14
src/clients/discord/discord.voice.service.ts
Normal file
14
src/clients/discord/discord.voice.service.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { VoiceChannel } from "discord.js";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DiscordVoiceService {
|
||||||
|
|
||||||
|
summonClient(voiceChannel: VoiceChannel) {
|
||||||
|
// voiceChannel.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
startPlayback() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import { Api, Jellyfin } from '@jellyfin/sdk';
|
import { Api, Jellyfin } from '@jellyfin/sdk';
|
||||||
|
import { Constants } from '../../utils/constants';
|
||||||
import { Constants } from 'src/utils/constants';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JellyfinService {
|
export class JellyfinService {
|
||||||
@ -10,8 +9,6 @@ export class JellyfinService {
|
|||||||
private jellyfin: Jellyfin;
|
private jellyfin: Jellyfin;
|
||||||
private api: Api;
|
private api: Api;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.jellyfin = new Jellyfin({
|
this.jellyfin = new Jellyfin({
|
||||||
clientInfo: {
|
clientInfo: {
|
||||||
|
@ -1,23 +1,55 @@
|
|||||||
import { TransformPipe } from '@discord-nestjs/common';
|
import { TransformPipe } from '@discord-nestjs/common';
|
||||||
|
|
||||||
|
import { Command, DiscordCommand, UsePipes } from '@discord-nestjs/core';
|
||||||
import {
|
import {
|
||||||
Command,
|
CommandInteraction,
|
||||||
DiscordTransformedCommand,
|
EmbedBuilder,
|
||||||
TransformedCommandExecutionContext,
|
InteractionReplyOptions,
|
||||||
UsePipes,
|
} from 'discord.js';
|
||||||
} from '@discord-nestjs/core';
|
import { getVoiceConnection } from '@discordjs/voice';
|
||||||
import { InteractionReplyOptions } from 'discord.js';
|
import { DefaultJellyfinColor, ErrorJellyfinColor } from '../types/colors';
|
||||||
|
|
||||||
@Command({
|
@Command({
|
||||||
name: 'disconnect',
|
name: 'disconnect',
|
||||||
description: 'Join your current voice channel',
|
description: 'Join your current voice channel',
|
||||||
})
|
})
|
||||||
@UsePipes(TransformPipe)
|
@UsePipes(TransformPipe)
|
||||||
export class DisconnectCommand implements DiscordTransformedCommand<unknown> {
|
export class DisconnectCommand implements DiscordCommand {
|
||||||
handler(
|
handler(interaction: CommandInteraction): InteractionReplyOptions | string {
|
||||||
dto: unknown,
|
const connection = getVoiceConnection(interaction.guildId);
|
||||||
executionContext: TransformedCommandExecutionContext<any>,
|
|
||||||
): InteractionReplyOptions | string {
|
if (!connection) {
|
||||||
return 'nice';
|
return {
|
||||||
|
embeds: [
|
||||||
|
new EmbedBuilder()
|
||||||
|
.setColor(ErrorJellyfinColor)
|
||||||
|
.setAuthor({
|
||||||
|
name: 'Unable to disconnect from voice channel',
|
||||||
|
iconURL:
|
||||||
|
'https://github.com/manuel-rw/jellyfin-discord-music-bot/blob/nestjs-migration/images/icons/alert-circle.png?raw=true',
|
||||||
|
})
|
||||||
|
.setDescription(
|
||||||
|
'I am currently not connected to any voice channels',
|
||||||
|
)
|
||||||
|
.toJSON(),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.destroy();
|
||||||
|
|
||||||
|
return {
|
||||||
|
embeds: [
|
||||||
|
new EmbedBuilder()
|
||||||
|
.setColor(DefaultJellyfinColor)
|
||||||
|
.setAuthor({
|
||||||
|
name: 'Disconnected from your channel',
|
||||||
|
iconURL:
|
||||||
|
'https://github.com/manuel-rw/jellyfin-discord-music-bot/blob/nestjs-migration/images/icons/circle-check.png?raw=true',
|
||||||
|
})
|
||||||
|
.toJSON(),
|
||||||
|
],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { Client, InteractionReplyOptions, Status } from 'discord.js';
|
|||||||
import { DefaultJellyfinColor } from 'src/types/colors';
|
import { DefaultJellyfinColor } from 'src/types/colors';
|
||||||
|
|
||||||
import { formatDuration, intervalToDuration } from 'date-fns';
|
import { formatDuration, intervalToDuration } from 'date-fns';
|
||||||
import { Constants } from 'src/utils/constants';
|
import { Constants } from '../utils/constants';
|
||||||
|
|
||||||
@Command({
|
@Command({
|
||||||
name: 'status',
|
name: 'status',
|
||||||
|
@ -1,23 +1,64 @@
|
|||||||
import { TransformPipe } from '@discord-nestjs/common';
|
import { TransformPipe } from '@discord-nestjs/common';
|
||||||
|
|
||||||
|
import { Command, DiscordCommand, UsePipes } from '@discord-nestjs/core';
|
||||||
|
import { joinVoiceChannel } from '@discordjs/voice';
|
||||||
|
import { Logger } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
Command,
|
CommandInteraction,
|
||||||
DiscordTransformedCommand,
|
EmbedBuilder,
|
||||||
TransformedCommandExecutionContext,
|
GuildMember,
|
||||||
UsePipes,
|
InteractionReplyOptions
|
||||||
} from '@discord-nestjs/core';
|
} from 'discord.js';
|
||||||
import { InteractionReplyOptions } from 'discord.js';
|
import { DefaultJellyfinColor } from '../types/colors';
|
||||||
|
|
||||||
@Command({
|
@Command({
|
||||||
name: 'summon',
|
name: 'summon',
|
||||||
description: 'Join your current voice channel',
|
description: 'Join your current voice channel',
|
||||||
})
|
})
|
||||||
@UsePipes(TransformPipe)
|
@UsePipes(TransformPipe)
|
||||||
export class SummonCommand implements DiscordTransformedCommand<unknown> {
|
export class SummonCommand implements DiscordCommand {
|
||||||
handler(
|
private readonly logger = new Logger(SummonCommand.name);
|
||||||
dto: unknown,
|
|
||||||
executionContext: TransformedCommandExecutionContext<any>,
|
handler(interaction: CommandInteraction): InteractionReplyOptions | string {
|
||||||
): InteractionReplyOptions | string {
|
const guildMember = interaction.member as GuildMember;
|
||||||
return 'nice';
|
|
||||||
|
if (guildMember.voice.channel === null) {
|
||||||
|
return {
|
||||||
|
embeds: [
|
||||||
|
new EmbedBuilder()
|
||||||
|
.setColor(DefaultJellyfinColor)
|
||||||
|
.setAuthor({
|
||||||
|
name: 'Unable to join your channel',
|
||||||
|
iconURL:
|
||||||
|
'https://github.com/manuel-rw/jellyfin-discord-music-bot/blob/nestjs-migration/images/icons/alert-circle.png?raw=true',
|
||||||
|
})
|
||||||
|
.setDescription(
|
||||||
|
'You are in a channel, I am either unabelt to connect to or you aren&apost in a channel yet',
|
||||||
|
)
|
||||||
|
.toJSON(),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = guildMember.voice.channel;
|
||||||
|
|
||||||
|
joinVoiceChannel({
|
||||||
|
channelId: channel.id,
|
||||||
|
adapterCreator: channel.guild.voiceAdapterCreator,
|
||||||
|
guildId: channel.guildId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
embeds: [
|
||||||
|
new EmbedBuilder()
|
||||||
|
.setColor(DefaultJellyfinColor)
|
||||||
|
.setAuthor({
|
||||||
|
name: 'Joined your voicehannel',
|
||||||
|
iconURL:
|
||||||
|
'https://github.com/manuel-rw/jellyfin-discord-music-bot/blob/nestjs-migration/images/icons/circle-check.png?raw=true&test=a',
|
||||||
|
})
|
||||||
|
.toJSON(),
|
||||||
|
],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
import { RGBTuple } from 'discord.js';
|
import { RGBTuple } from 'discord.js';
|
||||||
|
|
||||||
export const DefaultJellyfinColor: RGBTuple = [119, 116, 204];
|
export const DefaultJellyfinColor: RGBTuple = [119, 116, 204];
|
||||||
|
export const ErrorJellyfinColor: RGBTuple = [242, 33, 95];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export const Constants = {
|
export const Constants = {
|
||||||
Metadata: {
|
Metadata: {
|
||||||
Version: "0.0.1",
|
Version: '0.0.1',
|
||||||
ApplicationName: "Discord Jellyfin Music Bot"
|
ApplicationName: 'Discord Jellyfin Music Bot',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
35
yarn.lock
35
yarn.lock
@ -597,6 +597,19 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@discordjs/voice@npm:^0.14.0":
|
||||||
|
version: 0.14.0
|
||||||
|
resolution: "@discordjs/voice@npm:0.14.0"
|
||||||
|
dependencies:
|
||||||
|
"@types/ws": ^8.5.3
|
||||||
|
discord-api-types: ^0.37.20
|
||||||
|
prism-media: ^1.3.4
|
||||||
|
tslib: ^2.4.1
|
||||||
|
ws: ^8.11.0
|
||||||
|
checksum: baa68a324f8c7b4a7863a966e7d10a01a4df93aa68800f867e7a6fef016fcd16306ff5a562674884192b0e6538e53e8404d114a7c9781f0637c8e0dea3bca368
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@eslint/eslintrc@npm:^1.3.3":
|
"@eslint/eslintrc@npm:^1.3.3":
|
||||||
version: 1.3.3
|
version: 1.3.3
|
||||||
resolution: "@eslint/eslintrc@npm:1.3.3"
|
resolution: "@eslint/eslintrc@npm:1.3.3"
|
||||||
@ -4438,6 +4451,7 @@ __metadata:
|
|||||||
"@discord-nestjs/common": ^4.0.8
|
"@discord-nestjs/common": ^4.0.8
|
||||||
"@discord-nestjs/core": ^4.3.1
|
"@discord-nestjs/core": ^4.3.1
|
||||||
"@discordjs/opus": ^0.9.0
|
"@discordjs/opus": ^0.9.0
|
||||||
|
"@discordjs/voice": ^0.14.0
|
||||||
"@jellyfin/sdk": ^0.7.0
|
"@jellyfin/sdk": ^0.7.0
|
||||||
"@nestjs/cli": ^9.0.0
|
"@nestjs/cli": ^9.0.0
|
||||||
"@nestjs/common": ^9.0.0
|
"@nestjs/common": ^9.0.0
|
||||||
@ -5961,6 +5975,27 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"prism-media@npm:^1.3.4":
|
||||||
|
version: 1.3.4
|
||||||
|
resolution: "prism-media@npm:1.3.4"
|
||||||
|
peerDependencies:
|
||||||
|
"@discordjs/opus": ^0.8.0
|
||||||
|
ffmpeg-static: ^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0
|
||||||
|
node-opus: ^0.3.3
|
||||||
|
opusscript: ^0.0.8
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@discordjs/opus":
|
||||||
|
optional: true
|
||||||
|
ffmpeg-static:
|
||||||
|
optional: true
|
||||||
|
node-opus:
|
||||||
|
optional: true
|
||||||
|
opusscript:
|
||||||
|
optional: true
|
||||||
|
checksum: 703be28c87b4694714a52a0ea84516b19d2e62e510d0f204efc074b044ad93dde00241d4b4741c25aa2e27a00e3b472e60ad0f6c94e88710f0827dc63889373a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"process-nextick-args@npm:~2.0.0":
|
"process-nextick-args@npm:~2.0.0":
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
resolution: "process-nextick-args@npm:2.0.1"
|
resolution: "process-nextick-args@npm:2.0.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user