Merged main

This commit is contained in:
Noah Heague
2021-08-22 17:07:38 +10:00
13 changed files with 168 additions and 13 deletions
+7
View File
@@ -31,6 +31,13 @@
"semi": [
"error",
"always"
],
"object-curly-spacing": [
"error",
"always"
],
"@typescript-eslint/no-unused-vars": [
"error"
]
}
}
+2 -2
View File
@@ -2,13 +2,13 @@
Automatically translate streaming service links.
> [Invite the bot](https://discordapp.com/oauth2/authorize?client_id=686462477956808742&permissions=8&scope=bot)
> [Invite the bot](https://discord.com/api/oauth2/authorize?client_id=686462477956808742&permissions=0&scope=applications.commands%20bot)
> [Join the Server](https://discord.gg/a5a7NQV)
## Platform Support
This bot supports every platform the [song.link](song.link) platform supports as it takes advantage of its API.
This bot supports every platform the [song.link](https://song.link) platform supports as it takes advantage of its API.
Currently, it detects the following URL Schemes:
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable no-undef */
module.exports = {
presets: [
[
+3
View File
@@ -12,11 +12,14 @@
"@types/jest": "^27.0.1",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/parser": "^4.29.1",
"discord-api-types": "^0.22.0",
"eslint": "^7.32.0",
"jest": "^27.0.6",
"typescript": "^4.3.5"
},
"dependencies": {
"@discordjs/builders": "^0.5.0",
"@discordjs/rest": "^0.1.0-canary.0",
"deezer-api-ts": "^1.2.1",
"discord.js": "^13.1.0",
"songlink-api": "^1.0.0",
+2
View File
@@ -1,3 +1,4 @@
// noinspection JSUnusedGlobalSymbols
/** @deprecated replace with database call & cache */
export const allowedChannels = [
"876321394005254214"
@@ -8,6 +9,7 @@ export enum LoggerLayers {
songLink = "songLink",
embedGenerator = "embedGenerator",
deezerMetadata = "deezerMetadata",
slashCommands = "slashCommands"
}
export const platformRegex = [
+1 -1
View File
@@ -1,5 +1,5 @@
import { SonglinkResponse } from "songlink-api/lib/types/Response";
import {getDetailedMetadata, getIdFromEntity} from "./getSongLink";
import { getDetailedMetadata, getIdFromEntity } from "./getSongLink";
interface MockSonglinkResponse extends Omit<Omit<SonglinkResponse, "linksByPlatform">, "entitiesByUniqueId"> {
linksByPlatform: {
+1 -1
View File
@@ -50,7 +50,7 @@ export const getSongLinkResponse = async (url: string): Promise<SongLinkData> =>
logger.info("Fetching songLink");
try {
const rawData = await getLinks({url: url}, {apiKey: process.env.SONGLINKAPIKEY});
const rawData = await getLinks({ url: url }, { apiKey: process.env.SONGLINKAPIKEY });
const firstEntity = rawData.entitiesByUniqueId[Object.keys(rawData.entitiesByUniqueId)[0]];
const basicMetadata: MetaData = {
+5
View File
@@ -0,0 +1,5 @@
import { CommandInteraction } from "discord.js";
export const help = async (interaction: CommandInteraction): Promise<void> => {
await interaction.reply("Send a link to a streaming service and I will reply with a rich embed.\nPrepend youtube links with `?`\n\nGithub: https://github.com/Puffycheeses/music_linkr\nDiscord: https://discord.gg/a5a7NQV");
};
+28 -4
View File
@@ -2,6 +2,7 @@ import { Client, Intents } from "discord.js";
import { LoggerLayers, platformRegex } from "./config";
import { createLinkReply } from "./createEmbed/createEmbed";
import { getSongLinkResponse } from "./getSongLink/getSongLink";
import { registerSlashCommands, slashCommands, tidyGuildCommands, SlashCommand } from "./slashCommands/register";
import { createLayeredLogger } from "./utils/logger";
import { shouldReply } from "./utils/utils";
@@ -37,8 +38,31 @@ client.on("messageCreate", async (message) => {
return;
});
client.login(process.env.DISCORDTOKEN).then(() => {
logger.info("Logged in successfully \n");
}).catch((err) => {
logger.error("Log in Failed:", err);
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;
try {
const command = slashCommands.find((command: SlashCommand) => {
return command.info.name === interaction.commandName;
});
if (command && command.exec) {
logger.info(`Running ${command.info.name} interaction`);
command.exec(interaction);
}
} catch (e) {
logger.error("Failed to run interaction");
}
});
(async () => {
try {
await client.login(process.env.DISCORDTOKEN);
logger.info(`Logged in successfully to ${client.guilds.cache.size} guilds`);
} catch (e) {
logger.error("Log in Failed:", e);
} finally {
await tidyGuildCommands(client);
await registerSlashCommands(client);
}
})();
+64
View File
@@ -0,0 +1,64 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { REST } from "@discordjs/rest";
import { APIApplicationCommandOption } from "discord-api-types";
import { Routes } from "discord-api-types/v9";
import { Client, CommandInteraction } from "discord.js";
import { LoggerLayers } from "../config";
import { help } from "../help/help";
import { createLayeredLogger } from "../utils/logger";
const logger = createLayeredLogger(LoggerLayers.slashCommands);
export interface SlashCommand {
info: {
name: string;
description: string;
options: APIApplicationCommandOption[];
};
exec(interaction: CommandInteraction): Promise<void>;
}
export const slashCommands: SlashCommand[] = [
{
info: new SlashCommandBuilder()
.setName("help")
.setDescription("Shows information about Music Linkr")
.toJSON(),
exec: async (interaction: CommandInteraction) => await help(interaction),
}
];
const rest = new REST({ version: "9" }).setToken(process.env.DISCORDTOKEN);
export const registerSlashCommands = async (client: Client): Promise<void> => {
try {
logger.info("Registering slash commands");
await rest.put(
Routes.applicationCommands(client.application.id),
{
body: slashCommands.map(command => command.info)
}
);
} catch (e) {
logger.error("Failed to register slash commands", e);
} finally {
logger.info("Successfully registered slash commands");
}
};
/** @deprecated Remove once no guilds have legacy commands */
export const tidyGuildCommands = async (client: Client): Promise<void> => {
try {
logger.info("Removing legacy slash commands");
const guilds = client.guilds.cache;
guilds.forEach(guild => {
const commands = guild.commands.cache;
commands.forEach(command => {
command.delete();
});
});
} catch (e) {
logger.error("Failed to remove legacy slash commands");
} finally {
logger.info("Successfully removed legacy slash commands");
}
};
+2 -2
View File
@@ -2,7 +2,7 @@ import { createLogger, transports, format, Logger } from "winston";
import { LoggerLayers } from "../config";
const { combine, timestamp, label, printf, align, colorize } = format;
const loggerFormat = printf(({level, message, label, timestamp}) => {
const loggerFormat = printf(({ level, message, label, timestamp }) => {
return `${timestamp} [${label}] ${level} ${message}`;
});
@@ -11,7 +11,7 @@ export const createLayeredLogger = (layer: LoggerLayers): Logger => {
return createLogger({
transports: [ new transports.Console() ],
format: combine(
label({label: layer}),
label({ label: layer }),
colorize(),
timestamp(),
align(),
-1
View File
@@ -1,5 +1,4 @@
import { Message } from "discord.js";
import { allowedChannels } from "../config";
export const shouldReply = (message: Message): boolean =>
message.author.id !== "876320894295887944" &&
+52 -2
View File
@@ -942,7 +942,7 @@
"@discordjs/builders@^0.5.0":
version "0.5.0"
resolved "https://registry.npmjs.org/@discordjs/builders/-/builders-0.5.0.tgz"
resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.5.0.tgz#646cbea9cc67f68639e6fb70ed1278b26dacdb14"
integrity sha512-HP5y4Rqw68o61Qv4qM5tVmDbWi4mdTFftqIOGRo33SNPpLJ1Ga3KEIR2ibKofkmsoQhEpLmopD1AZDs3cKpHuw==
dependencies:
"@sindresorhus/is" "^4.0.1"
@@ -951,6 +951,11 @@
ts-mixer "^6.0.0"
tslib "^2.3.0"
"@discordjs/collection@^0.1.6":
version "0.1.6"
resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.1.6.tgz#9e9a7637f4e4e0688fd8b2b5c63133c91607682c"
integrity sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==
"@discordjs/collection@^0.2.1":
version "0.2.1"
resolved "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz"
@@ -965,6 +970,20 @@
combined-stream "^1.0.8"
mime-types "^2.1.12"
"@discordjs/rest@^0.1.0-canary.0":
version "0.1.0-canary.0"
resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-0.1.0-canary.0.tgz#666f9a1a0c1f2f5a09a3a79f77aeddaeafbcbcc1"
integrity sha512-d+s//ISYVV+e0w/926wMEeO7vju+Pn11x1JM4tcmVMCHSDgpi6pnFCNAXF1TEdnDcy7xf9tq5cf2pQkb/7ySTQ==
dependencies:
"@discordjs/collection" "^0.1.6"
"@sapphire/async-queue" "^1.1.4"
"@sapphire/snowflake" "^1.3.5"
abort-controller "^3.0.0"
discord-api-types "^0.18.1"
form-data "^4.0.0"
node-fetch "^2.6.1"
tslib "^2.3.0"
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz"
@@ -1205,6 +1224,11 @@
resolved "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz"
integrity sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA==
"@sapphire/snowflake@^1.3.5":
version "1.3.6"
resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-1.3.6.tgz#166e8c5c08d01c861edd7e2edc80b5739741715f"
integrity sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg==
"@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz"
@@ -1465,6 +1489,13 @@ abab@^2.0.3, abab@^2.0.5:
resolved "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
dependencies:
event-target-shim "^5.0.0"
acorn-globals@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz"
@@ -2069,9 +2100,14 @@ dir-glob@^3.0.1:
dependencies:
path-type "^4.0.0"
discord-api-types@^0.18.1:
version "0.18.1"
resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.18.1.tgz#5d08ed1263236be9c21a22065d0e6b51f790f492"
integrity sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg==
discord-api-types@^0.22.0:
version "0.22.0"
resolved "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz"
resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.22.0.tgz#34dc57fe8e016e5eaac5e393646cd42a7e1ccc2a"
integrity sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==
discord.js@^13.1.0:
@@ -2296,6 +2332,11 @@ esutils@^2.0.2:
resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
@@ -2434,6 +2475,15 @@ form-data@^3.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"