diff options
author | V <vendicated@riseup.net> | 2023-09-24 16:02:18 +0200 |
---|---|---|
committer | V <vendicated@riseup.net> | 2023-09-24 16:02:18 +0200 |
commit | 30ac25607023752031aa98060cbf8a736109992d (patch) | |
tree | 79bb82b6634ef601db6c98e751275607ec54dbea /src/plugins/lastfm.tsx | |
parent | d0e2a324717e600736a18b88fe89a21c640a406b (diff) | |
download | Vencord-30ac25607023752031aa98060cbf8a736109992d.tar.gz Vencord-30ac25607023752031aa98060cbf8a736109992d.tar.bz2 Vencord-30ac25607023752031aa98060cbf8a736109992d.zip |
migrate all plugins to folders
Diffstat (limited to 'src/plugins/lastfm.tsx')
-rw-r--r-- | src/plugins/lastfm.tsx | 337 |
1 files changed, 0 insertions, 337 deletions
diff --git a/src/plugins/lastfm.tsx b/src/plugins/lastfm.tsx deleted file mode 100644 index 7a42f8f..0000000 --- a/src/plugins/lastfm.tsx +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Sofia Lima - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { definePluginSettings } from "@api/Settings"; -import { Link } from "@components/Link"; -import { Devs } from "@utils/constants"; -import { Logger } from "@utils/Logger"; -import definePlugin, { OptionType } from "@utils/types"; -import { filters, findByPropsLazy, mapMangledModuleLazy } from "@webpack"; -import { FluxDispatcher, Forms } from "@webpack/common"; - -interface ActivityAssets { - large_image?: string; - large_text?: string; - small_image?: string; - small_text?: string; -} - - -interface ActivityButton { - label: string; - url: string; -} - -interface Activity { - state: string; - details?: string; - timestamps?: { - start?: number; - }; - assets?: ActivityAssets; - buttons?: Array<string>; - name: string; - application_id: string; - metadata?: { - button_urls?: Array<string>; - }; - type: number; - flags: number; -} - -interface TrackData { - name: string; - album: string; - artist: string; - url: string; - imageUrl?: string; -} - -// only relevant enum values -const enum ActivityType { - PLAYING = 0, - LISTENING = 2, -} - -const enum ActivityFlag { - INSTANCE = 1 << 0, -} - -const enum NameFormat { - StatusName = "status-name", - ArtistFirst = "artist-first", - SongFirst = "song-first", - ArtistOnly = "artist", - SongOnly = "song" -} - -const applicationId = "1108588077900898414"; -const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f"; - -const logger = new Logger("LastFMRichPresence"); - -const presenceStore = findByPropsLazy("getLocalPresence"); -const assetManager = mapMangledModuleLazy( - "getAssetImage: size must === [number, number] for Twitch", - { - getAsset: filters.byCode("apply("), - } -); - -async function getApplicationAsset(key: string): Promise<string> { - return (await assetManager.getAsset(applicationId, [key, undefined]))[0]; -} - -function setActivity(activity: Activity | null) { - FluxDispatcher.dispatch({ - type: "LOCAL_ACTIVITY_UPDATE", - activity, - socketId: "LastFM", - }); -} - -const settings = definePluginSettings({ - username: { - description: "last.fm username", - type: OptionType.STRING, - }, - apiKey: { - description: "last.fm api key", - type: OptionType.STRING, - }, - shareUsername: { - description: "show link to last.fm profile", - type: OptionType.BOOLEAN, - default: false, - }, - hideWithSpotify: { - description: "hide last.fm presence if spotify is running", - type: OptionType.BOOLEAN, - default: true, - }, - statusName: { - description: "custom status text", - type: OptionType.STRING, - default: "some music", - }, - nameFormat: { - description: "Show name of song and artist in status name", - type: OptionType.SELECT, - options: [ - { - label: "Use custom status name", - value: NameFormat.StatusName, - default: true - }, - { - label: "Use format 'artist - song'", - value: NameFormat.ArtistFirst - }, - { - label: "Use format 'song - artist'", - value: NameFormat.SongFirst - }, - { - label: "Use artist name only", - value: NameFormat.ArtistOnly - }, - { - label: "Use song name only", - value: NameFormat.SongOnly - } - ], - }, - useListeningStatus: { - description: 'show "Listening to" status instead of "Playing"', - type: OptionType.BOOLEAN, - default: false, - }, - missingArt: { - description: "When album or album art is missing", - type: OptionType.SELECT, - options: [ - { - label: "Use large Last.fm logo", - value: "lastfmLogo", - default: true - }, - { - label: "Use generic placeholder", - value: "placeholder" - } - ], - }, -}); - -export default definePlugin({ - name: "LastFMRichPresence", - description: "Little plugin for Last.fm rich presence", - authors: [Devs.dzshn, Devs.RuiNtD, Devs.blahajZip, Devs.archeruwu], - - settingsAboutComponent: () => ( - <> - <Forms.FormTitle tag="h3">How to get an API key</Forms.FormTitle> - <Forms.FormText> - An API key is required to fetch your current track. To get one, you can - visit <Link href="https://www.last.fm/api/account/create">this page</Link> and - fill in the following information: <br /> <br /> - - Application name: Discord Rich Presence <br /> - Application description: (personal use) <br /> <br /> - - And copy the API key (not the shared secret!) - </Forms.FormText> - </> - ), - - settings, - - start() { - this.updatePresence(); - this.updateInterval = setInterval(() => { this.updatePresence(); }, 16000); - }, - - stop() { - clearInterval(this.updateInterval); - }, - - async fetchTrackData(): Promise<TrackData | null> { - if (!settings.store.username || !settings.store.apiKey) - return null; - - try { - const params = new URLSearchParams({ - method: "user.getrecenttracks", - api_key: settings.store.apiKey, - user: settings.store.username, - limit: "1", - format: "json" - }); - - const res = await fetch(`https://ws.audioscrobbler.com/2.0/?${params}`); - if (!res.ok) throw `${res.status} ${res.statusText}`; - - const json = await res.json(); - if (json.error) { - logger.error("Error from Last.fm API", `${json.error}: ${json.message}`); - return null; - } - - const trackData = json.recenttracks?.track[0]; - - if (!trackData?.["@attr"]?.nowplaying) - return null; - - // why does the json api have xml structure - return { - name: trackData.name || "Unknown", - album: trackData.album["#text"], - artist: trackData.artist["#text"] || "Unknown", - url: trackData.url, - imageUrl: trackData.image?.find((x: any) => x.size === "large")?.["#text"] - }; - } catch (e) { - logger.error("Failed to query Last.fm API", e); - // will clear the rich presence if API fails - return null; - } - }, - - async updatePresence() { - setActivity(await this.getActivity()); - }, - - getLargeImage(track: TrackData): string | undefined { - if (track.imageUrl && !track.imageUrl.includes(placeholderId)) - return track.imageUrl; - - if (settings.store.missingArt === "placeholder") - return "placeholder"; - }, - - async getActivity(): Promise<Activity | null> { - if (settings.store.hideWithSpotify) { - for (const activity of presenceStore.getActivities()) { - if (activity.type === ActivityType.LISTENING && activity.application_id !== applicationId) { - // there is already music status because of Spotify or richerCider (probably more) - return null; - } - } - } - - const trackData = await this.fetchTrackData(); - if (!trackData) return null; - - const largeImage = this.getLargeImage(trackData); - const assets: ActivityAssets = largeImage ? - { - large_image: await getApplicationAsset(largeImage), - large_text: trackData.album || undefined, - small_image: await getApplicationAsset("lastfm-small"), - small_text: "Last.fm", - } : { - large_image: await getApplicationAsset("lastfm-large"), - large_text: trackData.album || undefined, - }; - - const buttons: ActivityButton[] = [ - { - label: "View Song", - url: trackData.url, - }, - ]; - - if (settings.store.shareUsername) - buttons.push({ - label: "Last.fm Profile", - url: `https://www.last.fm/user/${settings.store.username}`, - }); - - const statusName = (() => { - switch (settings.store.nameFormat) { - case NameFormat.ArtistFirst: - return trackData.artist + " - " + trackData.name; - case NameFormat.SongFirst: - return trackData.name + " - " + trackData.artist; - case NameFormat.ArtistOnly: - return trackData.artist; - case NameFormat.SongOnly: - return trackData.name; - default: - return settings.store.statusName; - } - })(); - - return { - application_id: applicationId, - name: statusName, - - details: trackData.name, - state: trackData.artist, - assets, - - buttons: buttons.map(v => v.label), - metadata: { - button_urls: buttons.map(v => v.url), - }, - - type: settings.store.useListeningStatus ? ActivityType.LISTENING : ActivityType.PLAYING, - flags: ActivityFlag.INSTANCE, - }; - } -}); |