feat: add MusicLinker plugin (#1048)
* feat: add MusicLinker plugin * Update constants.ts * mostly done * Update index.tsx * ServerListAPI: Add Priority --------- Co-authored-by: thororen <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
parent
f99bacba91
commit
e08a20e917
7 changed files with 118 additions and 34 deletions
|
|
@ -25,11 +25,11 @@ export const enum ServerListRenderPosition {
|
|||
Below,
|
||||
}
|
||||
|
||||
const componentsIn = new Set<ComponentType>();
|
||||
const componentsAbove = new Set<ComponentType>();
|
||||
const componentsBelow = new Set<ComponentType>();
|
||||
const componentsIn = new Map<ComponentType, number>();
|
||||
const componentsAbove = new Map<ComponentType, number>();
|
||||
const componentsBelow = new Map<ComponentType, number>();
|
||||
|
||||
function getRenderFunctions(position: ServerListRenderPosition) {
|
||||
function getRenderMap(position: ServerListRenderPosition) {
|
||||
switch (position) {
|
||||
case ServerListRenderPosition.Above:
|
||||
return componentsAbove;
|
||||
|
|
@ -40,21 +40,20 @@ function getRenderFunctions(position: ServerListRenderPosition) {
|
|||
}
|
||||
}
|
||||
|
||||
export function addServerListElement(position: ServerListRenderPosition, renderFunction: ComponentType) {
|
||||
getRenderFunctions(position).add(renderFunction);
|
||||
export function addServerListElement(position: ServerListRenderPosition, renderFunction: ComponentType, priority = 0) {
|
||||
getRenderMap(position).set(renderFunction, priority);
|
||||
}
|
||||
|
||||
export function removeServerListElement(position: ServerListRenderPosition, renderFunction: ComponentType) {
|
||||
getRenderFunctions(position).delete(renderFunction);
|
||||
getRenderMap(position).delete(renderFunction);
|
||||
}
|
||||
|
||||
export const renderAll = (position: ServerListRenderPosition) => {
|
||||
return Array.from(
|
||||
getRenderFunctions(position),
|
||||
(Component, i) => (
|
||||
return Array.from(getRenderMap(position).entries())
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.map(([Component], i) => (
|
||||
<ErrorBoundary noop key={i}>
|
||||
<Component />
|
||||
</ErrorBoundary>
|
||||
)
|
||||
);
|
||||
));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
initializeRestartTracking(settings);
|
||||
addServerListElement(ServerListRenderPosition.Above, this.renderQuestifyButton);
|
||||
addServerListElement(ServerListRenderPosition.Above, this.renderQuestifyButton, 1);
|
||||
|
||||
onceReady.then(() => {
|
||||
if (!settings.store.disableQuestsEverything) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -8,7 +8,7 @@ import { FormSwitch } from "@components/FormSwitch";
|
|||
import { HeadingTertiary } from "@components/Heading";
|
||||
|
||||
import { settings } from ".";
|
||||
import Providers from "./Providers";
|
||||
import { Providers } from "./Providers";
|
||||
|
||||
export function Settings() {
|
||||
const blazinglyFastSettings = settings.use(["servicesSettings"]);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { HeadphonesIcon } from "@components/Icons";
|
|||
import { Button, useEffect, useState } from "@webpack/common";
|
||||
|
||||
import pl, { Native, settings, SongLinkResult } from ".";
|
||||
import Providers from "./Providers";
|
||||
import { Providers } from "./Providers";
|
||||
|
||||
export default function SongLinker({ url }: { url: string; }) {
|
||||
const [songData, setSongData] = useState<SongLinkResult>();
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { sendMessage } from "@utils/discord";
|
||||
import definePlugin, { OptionType, PluginNative } from "@utils/types";
|
||||
|
||||
import Providers from "./Providers";
|
||||
import { Providers } from "./Providers";
|
||||
import { Settings } from "./Settings";
|
||||
import SongLinker from "./SongLinker";
|
||||
|
||||
|
|
@ -27,6 +29,11 @@ export const settings = definePluginSettings({
|
|||
description: "Country used for lookup (Two letter country code)",
|
||||
default: "US"
|
||||
},
|
||||
includeMetadata: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Include the track title and artist name as a header.",
|
||||
default: true,
|
||||
},
|
||||
servicesComponent: {
|
||||
type: OptionType.COMPONENT,
|
||||
component: () => <Settings />
|
||||
|
|
@ -48,12 +55,40 @@ export type SongLinkResult = {
|
|||
|
||||
export const Native = VencordNative.pluginHelpers.SongLink as PluginNative<typeof import("./native")>;
|
||||
|
||||
function formatMessage(data: SongLinkResult): string | null {
|
||||
const lines: string[] = [];
|
||||
|
||||
for (const [serviceKey, service] of Object.entries(settings.store.servicesSettings)) {
|
||||
if (!service.enabled) continue;
|
||||
|
||||
const platformData = data.links[serviceKey];
|
||||
if (!platformData?.url) continue;
|
||||
|
||||
const provider = Providers[serviceKey];
|
||||
const name = provider?.name ?? serviceKey;
|
||||
|
||||
lines.push(`- [${name}](<${platformData.url}>)`);
|
||||
}
|
||||
|
||||
if (lines.length === 0) return null;
|
||||
|
||||
const parts: string[] = [];
|
||||
|
||||
if (settings.store.includeMetadata && data.info?.title && data.info?.artist) {
|
||||
parts.push(`### **${data.info.title}** — *${data.info.artist}*`);
|
||||
}
|
||||
|
||||
parts.push(lines.join("\n"));
|
||||
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "SongLink",
|
||||
description: "Adds streaming service buttons below song links",
|
||||
dependencies: ["MessageAccessoriesAPI"],
|
||||
tags: ["Media", "Utility"],
|
||||
authors: [Devs.nin0dev],
|
||||
authors: [Devs.nin0dev, EquicordDevs.NassCT],
|
||||
settings,
|
||||
Providers,
|
||||
cache: ({} as Record<string, SongLinkResult>),
|
||||
|
|
@ -85,5 +120,53 @@ export default definePlugin({
|
|||
musicLinks.map(item => <SongLinker key={item} url={item} />)
|
||||
}
|
||||
</div>;
|
||||
}
|
||||
},
|
||||
commands: [
|
||||
{
|
||||
name: "musiclink",
|
||||
description: "Convert a music link to other streaming platforms.",
|
||||
inputType: ApplicationCommandInputType.BUILT_IN,
|
||||
options: [
|
||||
{
|
||||
name: "url",
|
||||
description: "Music link (Spotify, Deezer, YouTube, Tidal, Apple Music, SoundCloud)",
|
||||
type: ApplicationCommandOptionType.STRING,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
execute: async (opts, ctx) => {
|
||||
const url = findOption<string>(opts, "url", "");
|
||||
|
||||
if (!url) {
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content: "Please provide a music link.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content: "This will take a moment...",
|
||||
});
|
||||
|
||||
try {
|
||||
const data = await Native.getTrackData(url);
|
||||
const formatted = formatMessage(data);
|
||||
|
||||
if (!formatted) {
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content:
|
||||
"No alternative platforms found for this link.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessage(ctx.channel.id, { content: formatted });
|
||||
} catch (e: any) {
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content: "Failed to resolve music link",
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1223,7 +1223,7 @@ export const EquicordDevs = Object.freeze({
|
|||
},
|
||||
prism: {
|
||||
name: "prism",
|
||||
id: 390884143749136386n,
|
||||
id: 390884143749136386n
|
||||
},
|
||||
square: {
|
||||
name: "square",
|
||||
|
|
@ -1251,7 +1251,7 @@ export const EquicordDevs = Object.freeze({
|
|||
},
|
||||
PWall: {
|
||||
name: "PWall",
|
||||
id: 0n,
|
||||
id: 0n
|
||||
},
|
||||
busyboxkitty: {
|
||||
name: "busyboxkitty",
|
||||
|
|
@ -1259,31 +1259,31 @@ export const EquicordDevs = Object.freeze({
|
|||
},
|
||||
BioTomateDE: {
|
||||
name: "BioTomateDE",
|
||||
id: 553499669226061844n,
|
||||
id: 553499669226061844n
|
||||
},
|
||||
korzi: {
|
||||
name: "korzi",
|
||||
id: 740966310875365416n,
|
||||
id: 740966310875365416n
|
||||
},
|
||||
davri: {
|
||||
name: "Davri",
|
||||
id: 457579346282938368n,
|
||||
id: 457579346282938368n
|
||||
},
|
||||
yash: {
|
||||
name: "yash",
|
||||
id: 889150838658977874n,
|
||||
id: 889150838658977874n
|
||||
},
|
||||
Leon135: {
|
||||
name: "Leon135",
|
||||
id: 309275452231385088n,
|
||||
id: 309275452231385088n
|
||||
},
|
||||
bbpltergiest: {
|
||||
name: "bbpltergiest",
|
||||
id: 279448683672502274n,
|
||||
id: 279448683672502274n
|
||||
},
|
||||
mshl: {
|
||||
name: "m.shl",
|
||||
id: 1025245410224263258n,
|
||||
id: 1025245410224263258n
|
||||
},
|
||||
ScattrdBlade: {
|
||||
name: "ScattrdBlade",
|
||||
|
|
@ -1291,11 +1291,11 @@ export const EquicordDevs = Object.freeze({
|
|||
},
|
||||
Ape: {
|
||||
name: "Ape",
|
||||
id: 722832640360841308n,
|
||||
id: 722832640360841308n
|
||||
},
|
||||
Kiri: {
|
||||
name: "Kiri",
|
||||
id: 310525496771346434n,
|
||||
id: 310525496771346434n
|
||||
},
|
||||
pointy: {
|
||||
name: "pointy",
|
||||
|
|
@ -1307,7 +1307,7 @@ export const EquicordDevs = Object.freeze({
|
|||
},
|
||||
Gir0fa: {
|
||||
name: "gir0fa",
|
||||
id: 1282734265955520545n,
|
||||
id: 1282734265955520545n
|
||||
},
|
||||
yonn2222: {
|
||||
name: "yonn2222",
|
||||
|
|
@ -1321,6 +1321,10 @@ export const EquicordDevs = Object.freeze({
|
|||
name: "sketchmyname",
|
||||
id: 1412164910443663491n
|
||||
},
|
||||
NassCT: {
|
||||
name: "NassCT",
|
||||
id: 354996937868705793n
|
||||
},
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
// iife so #__PURE__ works correctly
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue