mirror of
https://github.com/informaticker/discord-jellyfin-bot.git
synced 2024-11-23 10:11:56 +01:00
✨ Add nestjs discord package
This commit is contained in:
parent
0e70791284
commit
beb34b7d7c
@ -21,6 +21,8 @@
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@discord-nestjs/common": "^4.0.8",
|
||||
"@discord-nestjs/core": "^4.3.1",
|
||||
"@discordjs/opus": "^0.9.0",
|
||||
"@jellyfin/sdk": "^0.7.0",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
|
@ -1,14 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import * as Joi from 'joi';
|
||||
|
||||
import { EventEmitterModule } from '@nestjs/event-emitter';
|
||||
import { DiscordModule } from '@discord-nestjs/core';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { EventEmitterModule } from '@nestjs/event-emitter';
|
||||
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { DiscordClientModule } from './clients/discord/discord.module';
|
||||
import { CommandHandlerModule } from './commands/handler/command-handler.module';
|
||||
import { JellyfinClientModule } from './clients/jellyfin/jellyfin.module';
|
||||
import { CommandModule } from './commands/command.module';
|
||||
import { DiscordConfigService } from './clients/discord/jellyfin.config.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -20,10 +22,14 @@ import { JellyfinClientModule } from './clients/jellyfin/jellyfin.module';
|
||||
JELLYFIN_AUTHENTICATION_PASSWORD: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
DiscordModule.forRootAsync({
|
||||
useClass: DiscordConfigService,
|
||||
}),
|
||||
DiscordModule,
|
||||
EventEmitterModule.forRoot(),
|
||||
CommandModule,
|
||||
DiscordClientModule,
|
||||
JellyfinClientModule,
|
||||
CommandHandlerModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
|
@ -1,21 +1,10 @@
|
||||
import { Module, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
||||
import { DiscordService } from './discord.service';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DiscordConfigService } from './jellyfin.config.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [],
|
||||
providers: [DiscordService],
|
||||
exports: [DiscordService],
|
||||
providers: [DiscordConfigService],
|
||||
exports: [DiscordConfigService],
|
||||
})
|
||||
export class DiscordClientModule implements OnModuleInit, OnModuleDestroy {
|
||||
constructor(private discordService: DiscordService) {}
|
||||
onModuleDestroy() {
|
||||
this.discordService.destroyClient();
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.discordService.initializeClient();
|
||||
this.discordService.registerEventHandlers();
|
||||
this.discordService.connectAndLogin();
|
||||
}
|
||||
}
|
||||
export class DiscordClientModule {}
|
||||
|
@ -1,46 +0,0 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
|
||||
import { Client } from 'discord.js';
|
||||
|
||||
@Injectable()
|
||||
export class DiscordService {
|
||||
private readonly logger = new Logger(DiscordService.name);
|
||||
private client: Client;
|
||||
|
||||
constructor(private eventEmitter: EventEmitter2) {}
|
||||
|
||||
initializeClient() {
|
||||
this.client = new Client({
|
||||
intents: ['Guilds', 'GuildMessages', 'MessageContent'],
|
||||
});
|
||||
this.logger.debug('Initialized Discord client');
|
||||
}
|
||||
|
||||
connectAndLogin() {
|
||||
this.client.login(process.env.DISCORD_CLIENT_TOKEN);
|
||||
}
|
||||
|
||||
registerEventHandlers() {
|
||||
this.client.on('ready', () => {
|
||||
this.logger.debug(`Connected as '${this.client.user.tag}' and ready!`);
|
||||
this.eventEmitter.emit('client.discord.ready');
|
||||
});
|
||||
|
||||
this.client.on('messageCreate', async (message) => {
|
||||
if (message.author.bot) {
|
||||
return;
|
||||
}
|
||||
|
||||
await message.channel.send('nice');
|
||||
});
|
||||
}
|
||||
|
||||
destroyClient() {
|
||||
this.client.destroy();
|
||||
}
|
||||
|
||||
getClient() {
|
||||
return this.client;
|
||||
}
|
||||
}
|
18
src/clients/discord/jellyfin.config.service.ts
Normal file
18
src/clients/discord/jellyfin.config.service.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import {
|
||||
DiscordModuleOption,
|
||||
DiscordOptionsFactory,
|
||||
} from '@discord-nestjs/core';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { GatewayIntentBits } from 'discord.js';
|
||||
|
||||
@Injectable()
|
||||
export class DiscordConfigService implements DiscordOptionsFactory {
|
||||
createDiscordOptions(): DiscordModuleOption {
|
||||
return {
|
||||
token: process.env.DISCORD_CLIENT_TOKEN,
|
||||
discordClientOptions: {
|
||||
intents: [GatewayIntentBits.Guilds],
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
@ -35,10 +35,18 @@ export class JellyfinService {
|
||||
process.env.JELLYFIN_AUTHENTICATION_PASSWORD,
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.data.SessionInfo === undefined) {
|
||||
this.logger.error(
|
||||
`Failed to authenticate with response code ${response.status}: '${response.data}'`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.debug(
|
||||
`Connected using user '${response.data.SessionInfo.UserId}'`,
|
||||
);
|
||||
}).catch((test) => {
|
||||
})
|
||||
.catch((test) => {
|
||||
this.logger.error(test);
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
import { SlashCommandBuilder } from "discord.js";
|
||||
|
||||
export abstract class Command {
|
||||
abstract builder(): SlashCommandBuilder;
|
||||
abstract execute(): void;
|
||||
}
|
12
src/commands/command.module.ts
Normal file
12
src/commands/command.module.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DiscordModule } from '@discord-nestjs/core';
|
||||
|
||||
import { HelpCommand } from './help.command';
|
||||
|
||||
@Module({
|
||||
imports: [DiscordModule.forFeature()],
|
||||
controllers: [],
|
||||
providers: [HelpCommand],
|
||||
exports: [],
|
||||
})
|
||||
export class CommandModule {}
|
@ -1,10 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DiscordClientModule } from '../../clients/discord/discord.module';
|
||||
import { CommandHandlerService } from './command-handler.service';
|
||||
|
||||
@Module({
|
||||
imports: [DiscordClientModule],
|
||||
controllers: [],
|
||||
providers: [CommandHandlerService],
|
||||
})
|
||||
export class CommandHandlerModule {}
|
@ -1,107 +0,0 @@
|
||||
import { EmbedBuilder } from '@discordjs/builders';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import {
|
||||
ApplicationCommand,
|
||||
SlashCommandBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from 'discord.js';
|
||||
import { DiscordService } from 'src/clients/discord/discord.service';
|
||||
import { Command } from '../abstractCommand';
|
||||
|
||||
@Injectable()
|
||||
export class CommandHandlerService {
|
||||
private logger: Logger = new Logger(CommandHandlerService.name);
|
||||
|
||||
constructor(private discordService: DiscordService) {}
|
||||
|
||||
@OnEvent('client.discord.ready')
|
||||
async handleOnDiscordClientReady() {
|
||||
var commands = [
|
||||
new SlashCommandBuilder()
|
||||
.setName('play')
|
||||
.setDescription('Immideatly play a track')
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName('track')
|
||||
.setDescription('the track name')
|
||||
.setRequired(true),
|
||||
),
|
||||
new SlashCommandBuilder()
|
||||
.setName('summon')
|
||||
.setDescription('Join your current voice channel'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('disconnect')
|
||||
.setDescription('Disconnect from the current voice channel'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('enqueue')
|
||||
.setDescription('Enqueue a track to the current playlist')
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName('track')
|
||||
.setDescription('the track name')
|
||||
.setRequired(true),
|
||||
),
|
||||
new SlashCommandBuilder()
|
||||
.setName('current')
|
||||
.setDescription('Print the current track information'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('pause')
|
||||
.setDescription('Pause or resume the playback of the current track'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('skip')
|
||||
.setDescription('Skip the current track'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('stop')
|
||||
.setDescription(
|
||||
'Stop playback entirely and clear the current playlist',
|
||||
),
|
||||
new SlashCommandBuilder()
|
||||
.setName('help')
|
||||
.setDescription('Get help for this Discord Bot'),
|
||||
];
|
||||
|
||||
await this.discordService
|
||||
.getClient()
|
||||
.application.commands.set(commands.map((x) => x.toJSON()));
|
||||
|
||||
this.discordService
|
||||
.getClient()
|
||||
.on('interactionCreate', async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) {
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.reply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: 'Jellyfin Discord Bot',
|
||||
iconURL:
|
||||
'https://github.com/walkxcode/dashboard-icons/blob/main/png/jellyfin.png?raw=true',
|
||||
url: 'https://github.com/manuel-rw/jellyfin-discord-music-bot',
|
||||
})
|
||||
.setTitle('Help Information')
|
||||
.setDescription(
|
||||
'Jellyfin Discord Music bot is an easy way to broadcast your music collection to a Discord voicechannel.',
|
||||
)
|
||||
.addFields([
|
||||
{
|
||||
name: 'Report an issue',
|
||||
value:
|
||||
'https://github.com/manuel-rw/jellyfin-discord-music-bot/issues/new/choose',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Source code',
|
||||
value:
|
||||
'https://github.com/manuel-rw/jellyfin-discord-music-bot',
|
||||
inline: true,
|
||||
},
|
||||
])
|
||||
.toJSON(),
|
||||
],
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
90
src/commands/help.command.ts
Normal file
90
src/commands/help.command.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { TransformPipe } from '@discord-nestjs/common';
|
||||
|
||||
import {
|
||||
Command,
|
||||
DiscordTransformedCommand,
|
||||
TransformedCommandExecutionContext,
|
||||
UsePipes,
|
||||
} from '@discord-nestjs/core';
|
||||
import { EmbedBuilder } from '@discordjs/builders';
|
||||
import { InteractionReplyOptions, MessagePayload } from 'discord.js';
|
||||
|
||||
@Command({
|
||||
name: 'help',
|
||||
description: 'ejifejf',
|
||||
})
|
||||
@UsePipes(TransformPipe)
|
||||
export class HelpCommand implements DiscordTransformedCommand<unknown> {
|
||||
handler(
|
||||
dto: unknown,
|
||||
executionContext: TransformedCommandExecutionContext<any>,
|
||||
):
|
||||
| string
|
||||
| void
|
||||
| MessagePayload
|
||||
| InteractionReplyOptions
|
||||
| Promise<string | void | MessagePayload | InteractionReplyOptions> {
|
||||
return {
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: 'Jellyfin Discord Bot',
|
||||
iconURL:
|
||||
'https://github.com/walkxcode/dashboard-icons/blob/main/png/jellyfin.png?raw=true',
|
||||
url: 'https://github.com/manuel-rw/jellyfin-discord-music-bot',
|
||||
})
|
||||
.setTitle('Help Information')
|
||||
.setDescription(
|
||||
'Jellyfin Discord Music bot is an easy way to broadcast your music collection to a Discord voicechannel.',
|
||||
)
|
||||
.addFields([
|
||||
{
|
||||
name: 'Report an issue',
|
||||
value:
|
||||
'https://github.com/manuel-rw/jellyfin-discord-music-bot/issues/new/choose',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Source code',
|
||||
value: 'https://github.com/manuel-rw/jellyfin-discord-music-bot',
|
||||
inline: true,
|
||||
},
|
||||
])
|
||||
.toJSON(),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
handler(
|
||||
dto: unknown,
|
||||
executionContext: TransformedCommandExecutionContext<any>,
|
||||
) {
|
||||
return new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: 'Jellyfin Discord Bot',
|
||||
iconURL:
|
||||
'https://github.com/walkxcode/dashboard-icons/blob/main/png/jellyfin.png?raw=true',
|
||||
url: 'https://github.com/manuel-rw/jellyfin-discord-music-bot',
|
||||
})
|
||||
.setTitle('Help Information')
|
||||
.setDescription(
|
||||
'Jellyfin Discord Music bot is an easy way to broadcast your music collection to a Discord voicechannel.',
|
||||
)
|
||||
.addFields([
|
||||
{
|
||||
name: 'Report an issue',
|
||||
value:
|
||||
'https://github.com/manuel-rw/jellyfin-discord-music-bot/issues/new/choose',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Source code',
|
||||
value: 'https://github.com/manuel-rw/jellyfin-discord-music-bot',
|
||||
inline: true,
|
||||
},
|
||||
])
|
||||
.toJSON();
|
||||
}
|
||||
*/
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
"noFallthroughCasesInSwitch": false
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
"useDefineForClassFields": true
|
||||
}
|
||||
}
|
||||
|
83
yarn.lock
83
yarn.lock
@ -491,6 +491,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@discord-nestjs/common@npm:^4.0.8":
|
||||
version: 4.0.8
|
||||
resolution: "@discord-nestjs/common@npm:4.0.8"
|
||||
dependencies:
|
||||
"@nestjs/mapped-types": 1.2.0
|
||||
class-transformer: 0.5.1
|
||||
class-validator: 0.13.2
|
||||
peerDependencies:
|
||||
"@discord-nestjs/core": "*"
|
||||
"@nestjs/common": 8.* || 9.*
|
||||
"@nestjs/core": 8.* || 9.*
|
||||
discord.js: 14.*
|
||||
reflect-metadata: ^0.1.13
|
||||
rxjs: ^7.*
|
||||
checksum: 254f740d6762f3cfe827500b7c0b0a1357c631032a95fe82a1425dbbebe97e442add85a5d85dfaf333a53cb16caea293a8345bb8e17832f8f67c605676bca69f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@discord-nestjs/core@npm:^4.3.1":
|
||||
version: 4.3.1
|
||||
resolution: "@discord-nestjs/core@npm:4.3.1"
|
||||
dependencies:
|
||||
class-transformer: 0.5.1
|
||||
peerDependencies:
|
||||
"@nestjs/common": 8.* || 9.*
|
||||
"@nestjs/core": 8.* || 9.*
|
||||
discord.js: 14.*
|
||||
reflect-metadata: ^0.1.13
|
||||
rxjs: ^7.*
|
||||
checksum: 2a9013126359520d9133fa547f4a08f46eb9f3d7329aa516ef22c9c779794815ba4b1e1cb5b7e899a9e16c11568931d8a14f9cb52e3944d80bf8e292e6a6daba
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@discordjs/builders@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@discordjs/builders@npm:1.4.0"
|
||||
@ -1076,6 +1109,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@nestjs/mapped-types@npm:1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@nestjs/mapped-types@npm:1.2.0"
|
||||
peerDependencies:
|
||||
"@nestjs/common": ^7.0.8 || ^8.0.0 || ^9.0.0
|
||||
class-transformer: ^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0
|
||||
class-validator: ^0.11.1 || ^0.12.0 || ^0.13.0
|
||||
reflect-metadata: ^0.1.12
|
||||
peerDependenciesMeta:
|
||||
class-transformer:
|
||||
optional: true
|
||||
class-validator:
|
||||
optional: true
|
||||
checksum: cc625310873c5caf69521bc03c75a6780467f662fd4c8b2402f6e65228268eec1244c131dbf65c81c985680feacee50dae7d3c1f2b7bced7bad79922389aa38f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@nestjs/platform-express@npm:^9.0.0":
|
||||
version: 9.2.1
|
||||
resolution: "@nestjs/platform-express@npm:9.2.1"
|
||||
@ -2547,6 +2597,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"class-transformer@npm:0.5.1":
|
||||
version: 0.5.1
|
||||
resolution: "class-transformer@npm:0.5.1"
|
||||
checksum: f191c8b4cc4239990f5efdd790cabdd852c243ed66248e39f6616a349c910c6eed2d9fd1fbf7ee6ea89f69b4f1d0b493b27347fe0cd0ae26b47c3745a805b6d3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"class-validator@npm:0.13.2":
|
||||
version: 0.13.2
|
||||
resolution: "class-validator@npm:0.13.2"
|
||||
dependencies:
|
||||
libphonenumber-js: ^1.9.43
|
||||
validator: ^13.7.0
|
||||
checksum: 0deb4c29faa18345f6989fd7eaaaa07b05caae5298603fcd6485531c6daad503e5d2b24cc1342e4fc88ae5ba0acffdc24d0fc333110ef3f21a667cd8a79e1258
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-stack@npm:^2.0.0":
|
||||
version: 2.2.0
|
||||
resolution: "clean-stack@npm:2.2.0"
|
||||
@ -4361,6 +4428,8 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "jellyfin-discord-music-bot@workspace:."
|
||||
dependencies:
|
||||
"@discord-nestjs/common": ^4.0.8
|
||||
"@discord-nestjs/core": ^4.3.1
|
||||
"@discordjs/opus": ^0.9.0
|
||||
"@jellyfin/sdk": ^0.7.0
|
||||
"@nestjs/cli": ^9.0.0
|
||||
@ -4995,6 +5064,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"libphonenumber-js@npm:^1.9.43":
|
||||
version: 1.10.15
|
||||
resolution: "libphonenumber-js@npm:1.10.15"
|
||||
checksum: 94283206159b9eaf07e4af9c002dda2b0b171099a8116baa0b6871f6312475112ec92121cca85916968fa9fb1220641205f6ee2349a1cc33197d811a69572198
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lines-and-columns@npm:^1.1.6":
|
||||
version: 1.2.4
|
||||
resolution: "lines-and-columns@npm:1.2.4"
|
||||
@ -7137,6 +7213,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"validator@npm:^13.7.0":
|
||||
version: 13.7.0
|
||||
resolution: "validator@npm:13.7.0"
|
||||
checksum: 2b83283de1222ca549a7ef57f46e8d49c6669213348db78b7045bce36a3b5843ff1e9f709ebf74574e06223461ee1f264f8cc9a26a0060a79a27de079d8286ef
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vary@npm:^1, vary@npm:~1.1.2":
|
||||
version: 1.1.2
|
||||
resolution: "vary@npm:1.1.2"
|
||||
|
Loading…
Reference in New Issue
Block a user