UPDATE, removed discord jukebox for now

This commit is contained in:
Evert Prants 2021-09-03 20:23:56 +03:00
parent 8cce75646a
commit 4f887e3331
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
16 changed files with 1525 additions and 1760 deletions

View File

@ -2,8 +2,8 @@
"main": "plugin.js", "main": "plugin.js",
"name": "calendar", "name": "calendar",
"description": "Plugin for iCalendar/VCS room events", "description": "Plugin for iCalendar/VCS room events",
"version": "1.1.1", "version": "1.1.2",
"tags": ["commands", "utility", "calendar"], "tags": ["commands", "utility", "calendar"],
"dependencies": ["simplecommands"], "dependencies": ["simplecommands"],
"npmDependencies": ["node-ical@^0.12.3"] "npmDependencies": ["node-ical@^0.13.0"]
} }

View File

@ -135,7 +135,7 @@ async function fetchCalendars(interval: number): Promise<void> {
let events = 0; let events = 0;
try { try {
result = await ical.fromURL(cfg.url); result = await ical.fromURL(cfg.url);
} catch (e) { } catch (e: any) {
logger.error('Calendar %s fetch failed:', cfg.name, e.stack); logger.error('Calendar %s fetch failed:', cfg.name, e.stack);
} }

View File

@ -2,7 +2,7 @@
"main": "plugin.js", "main": "plugin.js",
"name": "debug", "name": "debug",
"description": "In-chat debugging tools", "description": "In-chat debugging tools",
"version": "1.1.0", "version": "1.1.1",
"tags": ["commands", "tools"], "tags": ["commands", "tools"],
"dependencies": ["simplecommands"], "dependencies": ["simplecommands"],
"npmDependencies": [] "npmDependencies": []

View File

@ -38,7 +38,7 @@ function addCommands(plugin: UtilityPlugin, commands: any): void {
return true; return true;
} }
msg.resolve(util.format(mesh)); msg.resolve(util.format(mesh));
} catch (e) { } catch (e: any) {
msg.resolve('Error: ' + e.message); msg.resolve('Error: ' + e.message);
} }

View File

@ -2,8 +2,8 @@
"main": "plugin.js", "main": "plugin.js",
"name": "gamedig", "name": "gamedig",
"description": "Game server status string", "description": "Game server status string",
"version": "1.1.3", "version": "1.1.4",
"tags": ["commands", "games"], "tags": ["commands", "games"],
"dependencies": ["simplecommands"], "dependencies": ["simplecommands"],
"npmDependencies": ["gamedig@^2.0.23"] "npmDependencies": ["gamedig@^3.0.7"]
} }

View File

@ -1,9 +0,0 @@
{
"main": "plugin.js",
"name": "jukebox",
"description": "Jukebox plugin for Discord",
"version": "1.1.1",
"tags": ["commands", "jukebox", "music"],
"dependencies": ["simplecommands"],
"npmDependencies": ["ytdl-core@^4.1.4","@discordjs/opus@^0.3.3","discord.js@^12.5.1","ytsr@1.0.4"]
}

View File

@ -1,317 +0,0 @@
import { fullIDMatcher } from '@squeebot/core/lib/common';
import { logger } from '@squeebot/core/lib/core';
import {
Plugin,
Configurable,
EventListener,
DependencyLoad
} from '@squeebot/core/lib/plugin';
import { IMessage, MessageResolver } from '@squeebot/core/lib/types';
import { Readable } from 'stream';
import ytdl from 'ytdl-core';
import ytsr, { Video } from 'ytsr';
import { Client, Message, VoiceChannel, VoiceConnection } from 'discord.js';
interface Configuration {
control: string[];
voice?: string;
leaveAfter?: number;
}
interface Cached {
playing: boolean;
config: Configuration;
readable: Readable;
url: string;
connection?: VoiceConnection;
queue: string[];
}
/*
Discord config example: {
"control": ["discord/testing/s:<guild id>/*"],
"voice": "<voice channel id>",
}
*/
@Configurable({
youtube: true,
discord: [],
icecast: [],
})
class JukeboxPlugin extends Plugin {
public cache: Cached[] = [];
@EventListener('pluginUnload')
public unloadEventHandler(plugin: string | Plugin): void {
if (plugin === this.name || plugin === this) {
this.emit('pluginUnloaded', this);
}
}
getConfigByMessage(msg: IMessage): Configuration | null {
const rm = msg.fullRoomID;
if (!rm) {
return null;
}
for (const cfg of this.config.get('discord', []) as Configuration[]) {
let roomMatch = false;
for (const room of cfg.control) {
if (fullIDMatcher(rm, room)) {
roomMatch = true;
}
}
if (!roomMatch) {
continue;
}
return cfg;
}
return null;
}
getCachedConfig(cfg: Configuration): Cached | null {
for (const ch of this.cache) {
if (ch.config === cfg) {
return ch;
}
}
return null;
}
async getStream(link: string): Promise<Readable> {
if (link.indexOf('http') !== 0) {
const search = await ytsr(link, { limit: 1 });
link = (search.items[0] as Video).link;
}
return ytdl(link, { quality: 'highestaudio', dlChunkSize: 0 });
}
async playToDiscord(discord: Client, cfg: Configuration, link: string, msg: IMessage): Promise<void> {
const cached = this.getCachedConfig(cfg);
if (cached && cached.readable) {
cached.readable.destroy();
}
let channel;
if (!cfg.voice) {
const member = (msg.data as Message).member;
if (member && member.voice) {
const avc = member.voice.channel;
if (avc && avc.joinable) {
channel = avc;
}
}
} else {
channel = await discord.channels.fetch(cfg.voice as string);
}
if (!channel || channel.type !== 'voice') {
throw new Error('Invalid voice channel.');
}
const vc = await (channel as VoiceChannel).join();
const str = await this.getStream(link);
vc.play(str).on('finish', () => {
str.destroy();
const cacheCurrent = this.getCachedConfig(cfg);
if (!cacheCurrent) {
vc.disconnect();
return;
}
cacheCurrent.playing = false;
if (!cacheCurrent.queue || !cacheCurrent.queue.length) {
vc.disconnect();
cacheCurrent.connection = undefined;
return;
}
const next = cacheCurrent.queue.shift() as string;
this.playToDiscord(discord, cfg, next, msg).catch((e) => {
logger.error('[%s] Autoplay threw an error:', this.name, e.stack);
msg.resolve('Playing of the next track in the queue failed.');
});
});
if (cached) {
cached.playing = true;
cached.readable = str;
cached.url = link;
cached.connection = vc;
} else {
this.cache.push({
playing: true,
readable: str,
url: link,
config: cfg,
connection: vc,
queue: [],
});
}
}
@DependencyLoad('simplecommands')
addCommands(cmd: any): void {
const roomsWithJukeboxes = [];
for (const cfg of this.config.get('discord', []) as Configuration[]) {
roomsWithJukeboxes.push(...cfg.control);
}
cmd.registerCommand([{
name: 'play',
plugin: this.name,
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
if (!simplified[0]) {
msg.resolve('Please provide an URL or search term to play!');
return true;
}
const vcConfig = this.getConfigByMessage(msg);
if (!vcConfig) {
msg.resolve('This channel has no configuration for jukeboxes.');
return true;
}
if (msg.source.type !== 'DiscordProtocol') {
msg.resolve('Currently, only Discord is supported.');
return true;
}
try {
await this.playToDiscord((msg.source as any).client, vcConfig, simplified.join(' '), msg);
} catch (e) {
msg.resolve('Something went wrong!');
logger.error('[%s] Threw an error:', this.name, e.stack);
}
return true;
},
source: roomsWithJukeboxes,
usage: '<url>',
description: 'Play something',
},
{
name: 'stop',
plugin: this.name,
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
const vcConfig = this.getConfigByMessage(msg);
if (!vcConfig) {
msg.resolve('This channel has no configuration for jukeboxes.');
return true;
}
if (msg.source.type !== 'DiscordProtocol') {
msg.resolve('Currently, only Discord is supported.');
return true;
}
const cached = this.getCachedConfig(vcConfig);
if (cached && cached.playing) {
cached.playing = false;
cached.readable.destroy();
if (cached.connection) {
try {
cached.connection.disconnect();
cached.connection = undefined;
} catch (e) {}
}
msg.resolve('Stopped currently playing.');
}
return true;
},
source: roomsWithJukeboxes,
description: 'Stop the currently playing track',
},
{
name: 'enqueue',
plugin: this.name,
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
if (!simplified[0]) {
msg.resolve('Please provide an URL or search term to play!');
return true;
}
const vcConfig = this.getConfigByMessage(msg);
if (!vcConfig) {
msg.resolve('This channel has no configuration for jukeboxes.');
return true;
}
if (msg.source.type !== 'DiscordProtocol') {
msg.resolve('Currently, only Discord is supported.');
return true;
}
const track = simplified.join(' ');
const cached = this.getCachedConfig(vcConfig);
if (cached && cached.playing) {
cached.queue.push(track);
} else {
try {
await this.playToDiscord((msg.source as any).client, vcConfig, track, msg);
} catch (e) {
msg.resolve('Something went wrong!');
logger.error('[%s] Threw an error:', this.name, e.stack);
}
}
return true;
},
source: roomsWithJukeboxes,
usage: '<url>',
description: 'Queue a track',
aliases: ['queue'],
},
{
name: 'skip',
plugin: this.name,
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
const vcConfig = this.getConfigByMessage(msg);
if (!vcConfig) {
msg.resolve('This channel has no configuration for jukeboxes.');
return true;
}
if (msg.source.type !== 'DiscordProtocol') {
msg.resolve('Currently, only Discord is supported.');
return true;
}
const cached = this.getCachedConfig(vcConfig);
if (cached) {
if (cached.playing) {
cached.readable.destroy();
cached.playing = false;
if (cached.connection) {
try {
cached.connection.disconnect();
cached.connection = undefined;
} catch (e) {}
}
}
if (cached.queue.length) {
const next = cached.queue.shift() as string;
try {
await this.playToDiscord((msg.source as any).client, vcConfig, next, msg);
} catch (e) {
msg.resolve('Something went wrong!');
logger.error('[%s] Threw an error:', this.name, e.stack);
}
return true;
}
}
msg.resolve('The queue is empty.');
return true;
},
aliases: ['next'],
source: roomsWithJukeboxes,
description: 'Skip the current track',
}]);
}
}
module.exports = JukeboxPlugin;

2609
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,24 +11,20 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@discordjs/opus": "^0.3.3", "@squeebot/core": "^3.3.1",
"@squeebot/core": "file:../core", "cheerio": "^1.0.0-rc.10",
"cheerio": "^1.0.0-rc.3",
"convert-units": "^2.3.4", "convert-units": "^2.3.4",
"discord.js": "^12.5.1", "gamedig": "^3.0.7",
"gamedig": "^2.0.23", "mathjs": "^9.4.4",
"mathjs": "^8.0.1", "node-ical": "^0.13.0",
"node-ical": "^0.12.3", "twitter-lite": "^1.1.0",
"twitter-lite": "^0.14.0", "typescript": "^4.4.2"
"typescript": "^4.1.2",
"ytdl-core": "^4.1.3",
"ytsr": "^1.0.4"
}, },
"devDependencies": { "devDependencies": {
"@types/cheerio": "^0.22.22", "@types/cheerio": "^0.22.30",
"@types/convert-units": "^2.3.3", "@types/convert-units": "^2.3.5",
"@types/gamedig": "^2.0.1", "@types/gamedig": "^3.0.1",
"@types/mathjs": "^6.0.8", "@types/mathjs": "^9.4.1",
"@types/node": "^14.14.10" "@types/node": "^16.7.10"
} }
} }

View File

@ -3,11 +3,11 @@
"plugins": [ "plugins": [
{ {
"name": "calendar", "name": "calendar",
"version": "1.1.1" "version": "1.1.2"
}, },
{ {
"name": "debug", "name": "debug",
"version": "1.1.0" "version": "1.1.1"
}, },
{ {
"name": "diction", "name": "diction",
@ -19,11 +19,7 @@
}, },
{ {
"name": "gamedig", "name": "gamedig",
"version": "1.1.3" "version": "1.1.4"
},
{
"name": "jukebox",
"version": "1.1.1"
}, },
{ {
"name": "timezone", "name": "timezone",
@ -39,15 +35,15 @@
}, },
{ {
"name": "url-twitter", "name": "url-twitter",
"version": "1.0.0" "version": "1.0.1"
}, },
{ {
"name": "urlreply", "name": "urlreply",
"version": "1.0.2" "version": "1.0.3"
}, },
{ {
"name": "utility", "name": "utility",
"version": "3.1.2" "version": "3.1.3"
} }
], ],
"typescript": true "typescript": true

View File

@ -2,8 +2,8 @@
"main": "plugin.js", "main": "plugin.js",
"name": "url-twitter", "name": "url-twitter",
"description": "Twitter URL", "description": "Twitter URL",
"version": "1.0.0", "version": "1.0.1",
"tags": ["urlreply", "twitter"], "tags": ["urlreply", "twitter"],
"dependencies": ["urlreply"], "dependencies": ["urlreply"],
"npmDependencies": ["twitter-lite@0.14.0"] "npmDependencies": ["twitter-lite@1.1.0"]
} }

View File

@ -2,8 +2,8 @@
"main": "plugin.js", "main": "plugin.js",
"name": "urlreply", "name": "urlreply",
"description": "Fetch titles from web pages, specifically made for IRC", "description": "Fetch titles from web pages, specifically made for IRC",
"version": "1.0.2", "version": "1.0.3",
"tags": ["irc"], "tags": ["irc"],
"dependencies": [], "dependencies": [],
"npmDependencies": ["cheerio@^1.0.0-rc.3"] "npmDependencies": ["cheerio@^1.0.0-rc.10"]
} }

View File

@ -285,7 +285,7 @@ class URLReplyPlugin extends Plugin {
const urlParsed = new urllib.URL(url); const urlParsed = new urllib.URL(url);
matched = await obj.action.apply(this, [urlParsed, msg]); matched = await obj.action.apply(this, [urlParsed, msg]);
} catch (e) { } catch (e: any) {
logger.error(e.stack); logger.error(e.stack);
matched = false; matched = false;
} }

View File

@ -6,7 +6,7 @@ function done(data: string): void {
} }
} }
process.once('message', (msg) => { process.once('message', (msg: string) => {
let expr = msg.toString(); let expr = msg.toString();
if (!expr) { if (!expr) {
@ -21,7 +21,7 @@ process.once('message', (msg) => {
try { try {
result = evaluate(expr); result = evaluate(expr);
} catch (e) { } catch (e: any) {
return done(e.message); return done(e.message);
} }

View File

@ -2,11 +2,11 @@
"main": "plugin.js", "main": "plugin.js",
"name": "utility", "name": "utility",
"description": "Utility commands and math operations", "description": "Utility commands and math operations",
"version": "3.1.2", "version": "3.1.3",
"tags": ["commands", "tools"], "tags": ["commands", "tools"],
"dependencies": ["simplecommands"], "dependencies": ["simplecommands"],
"npmDependencies": [ "npmDependencies": [
"mathjs@^8.0.1", "mathjs@^9.4.4",
"convert-units@^2.3.4" "convert-units@^2.3.4"
] ]
} }

View File

@ -422,7 +422,7 @@ function addCommands(plugin: UtilityPlugin, commands: any): void {
try { try {
const repl = await opMath(wholeRow); const repl = await opMath(wholeRow);
msg.resolve(repl); msg.resolve(repl);
} catch (e) { } catch (e: any) {
msg.resolve('Could not evaluate expression:', e.message); msg.resolve('Could not evaluate expression:', e.message);
} }
@ -587,7 +587,7 @@ function addCommands(plugin: UtilityPlugin, commands: any): void {
try { try {
status = await pingTcpServer(host, port); status = await pingTcpServer(host, port);
statusString = msg.source.format.format('bold', 'open'); statusString = msg.source.format.format('bold', 'open');
} catch (e) { } catch (e: any) {
status = e.message; status = e.message;
} }