From b62ccfe7b12b7d62f692281d538c5cda769fe323 Mon Sep 17 00:00:00 2001 From: Iris <68797873+iryis@users.noreply.github.com> Date: Tue, 24 Dec 2024 19:45:19 -0500 Subject: [PATCH] feat(amuse): song query api (add amuse plugin) (#2723) Co-authored-by: JellyBrick --- src/i18n/resources/en.json | 7 ++++ src/plugins/amuse/backend.ts | 71 ++++++++++++++++++++++++++++++++++++ src/plugins/amuse/index.ts | 20 ++++++++++ src/plugins/amuse/types.ts | 20 ++++++++++ 4 files changed, 118 insertions(+) create mode 100644 src/plugins/amuse/backend.ts create mode 100644 src/plugins/amuse/index.ts create mode 100644 src/plugins/amuse/types.ts diff --git a/src/i18n/resources/en.json b/src/i18n/resources/en.json index 74ae0d2b..29ca0629 100644 --- a/src/i18n/resources/en.json +++ b/src/i18n/resources/en.json @@ -279,6 +279,13 @@ }, "name": "Ambient Mode" }, + "amuse": { + "description": "Adds YouTube Music support for the Amuse now playing widget by 6K Labs", + "name": "Amuse", + "response": { + "query": "Amuse API server is running. GET /query to get song info." + } + }, "api-server": { "description": "Adds an API server to control the player", "dialog": { diff --git a/src/plugins/amuse/backend.ts b/src/plugins/amuse/backend.ts new file mode 100644 index 00000000..8f6b56be --- /dev/null +++ b/src/plugins/amuse/backend.ts @@ -0,0 +1,71 @@ +import { t } from 'i18next'; + +import { type Context, Hono } from 'hono'; +import { cors } from 'hono/cors'; +import { serve } from '@hono/node-server'; + +import registerCallback, { type SongInfo } from '@/providers/song-info'; +import { createBackend } from '@/utils'; + +import type { AmuseSongInfo } from './types'; + +const amusePort = 9863; + +const formatSongInfo = (info: SongInfo) => { + const formattedSongInfo: AmuseSongInfo = { + player: { + hasSong: !!(info.artist && info.title), + isPaused: info.isPaused ?? false, + seekbarCurrentPosition: info.elapsedSeconds ?? 0, + }, + track: { + duration: info.songDuration, + title: info.title, + author: info.artist, + cover: info.imageSrc ?? '', + url: info.url ?? '', + id: info.videoId, + isAdvertisement: false, + }, + }; + return formattedSongInfo; +}; + +export default createBackend({ + currentSongInfo: {} as SongInfo, + app: null as Hono | null, + server: null as ReturnType | null, + start() { + registerCallback((songInfo) => { + this.currentSongInfo = songInfo; + }); + + this.app = new Hono(); + this.app.use('*', cors()); + this.app.get('/', (ctx) => + ctx.body(t('plugins.amuse.response.query'), 200), + ); + + const queryAndApiHandler = (ctx: Context) => { + return ctx.json(formatSongInfo(this.currentSongInfo), 200); + }; + + this.app.get('/query', queryAndApiHandler); + this.app.get('/api', queryAndApiHandler); + + try { + this.server = serve({ + fetch: this.app.fetch.bind(this.app), + port: amusePort, + }); + } catch (err) { + console.error(err); + } + }, + + stop() { + if (this.server) { + this.server?.close(); + } + }, +}); diff --git a/src/plugins/amuse/index.ts b/src/plugins/amuse/index.ts new file mode 100644 index 00000000..206c70e4 --- /dev/null +++ b/src/plugins/amuse/index.ts @@ -0,0 +1,20 @@ +import { createPlugin } from '@/utils'; +import backend from './backend'; +import { t } from '@/i18n'; + +export interface MusicWidgetConfig { + enabled: boolean; +} + +export const defaultConfig: MusicWidgetConfig = { + enabled: false, +}; + +export default createPlugin({ + name: () => t('plugins.amuse.name'), + description: () => t('plugins.amuse.description'), + addedVersion: '3.7.X', + restartNeeded: true, + config: defaultConfig, + backend, +}); diff --git a/src/plugins/amuse/types.ts b/src/plugins/amuse/types.ts new file mode 100644 index 00000000..ef42d69c --- /dev/null +++ b/src/plugins/amuse/types.ts @@ -0,0 +1,20 @@ +export interface PlayerInfo { + hasSong: boolean; + isPaused: boolean; + seekbarCurrentPosition: number; +} + +export interface TrackInfo { + author: string; + title: string; + cover: string; + duration: number; + url: string; + id: string; + isAdvertisement: boolean; +} + +export interface AmuseSongInfo { + player: PlayerInfo; + track: TrackInfo; +}