Last.fm: use storage
This commit is contained in:
parent
f36416a76c
commit
c218b5cc8a
2 changed files with 59 additions and 41 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import { logger, patcher } from "@vendetta";
|
import { logger, patcher, plugin } from "@vendetta";
|
||||||
import { findByProps, findByStoreName } from '@vendetta/metro';
|
import { findByProps, findByStoreName } from '@vendetta/metro';
|
||||||
import { FluxDispatcher } from '@vendetta/metro/common';
|
import { FluxDispatcher } from '@vendetta/metro/common';
|
||||||
|
import Settings from "./settings";
|
||||||
|
|
||||||
let stopped: Boolean,
|
let stopped: Boolean,
|
||||||
lastActivity: Activity,
|
lastActivity: Activity,
|
||||||
|
|
@ -8,13 +9,14 @@ let stopped: Boolean,
|
||||||
lastTrackUrl: string,
|
lastTrackUrl: string,
|
||||||
activityTypeUnpatch: () => void;
|
activityTypeUnpatch: () => void;
|
||||||
|
|
||||||
// These are hardcoded for now until settings panel is implemented
|
const settings = plugin.storage as {
|
||||||
const appName = "Music";
|
appName: string;
|
||||||
const username = "slyde99";
|
username: string;
|
||||||
const showTimestamp = true;
|
showTimestamp: string;
|
||||||
const timeInterval = 5000;
|
timeInterval: number;
|
||||||
const listeningTo = true;
|
listeningTo: boolean;
|
||||||
const verboseLogging = true;
|
verboseLogging: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
// Constants for the API calls (perhaps these should be options?)
|
// Constants for the API calls (perhaps these should be options?)
|
||||||
const APPLICATION_ID = "1054951789318909972";
|
const APPLICATION_ID = "1054951789318909972";
|
||||||
|
|
@ -75,39 +77,30 @@ type Track = {
|
||||||
const UserStore = findByStoreName("UserStore")
|
const UserStore = findByStoreName("UserStore")
|
||||||
const SET_ACTIVITY = findByProps('SET_ACTIVITY').SET_ACTIVITY;
|
const SET_ACTIVITY = findByProps('SET_ACTIVITY').SET_ACTIVITY;
|
||||||
|
|
||||||
const verboseLog = (...message: any) => verboseLogging && logger.log(...message);
|
const verboseLog = (...message: any) => settings.verboseLogging && logger.log(...message);
|
||||||
|
|
||||||
async function fetchCurrentScrobble(): Promise<Track> {
|
async function fetchCurrentScrobble(): Promise<Track> {
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
'method': 'user.getrecenttracks',
|
'method': 'user.getrecenttracks',
|
||||||
'user': username,
|
'user': settings.username,
|
||||||
'api_key': LFM_API_KEY,
|
'api_key': LFM_API_KEY,
|
||||||
'format': 'json',
|
'format': 'json',
|
||||||
'limit': '1',
|
'limit': '1',
|
||||||
'extended': '1'
|
'extended': '1'
|
||||||
}).toString();
|
}).toString();
|
||||||
|
|
||||||
try {
|
const info = await fetch(`https://ws.audioscrobbler.com/2.0/?${params}`).then(x => x.json());
|
||||||
const {
|
const lastTrack = info.recenttracks?.track?.[0] || Promise.reject(info);
|
||||||
recenttracks: {
|
return {
|
||||||
track: [lastTrack]
|
name: lastTrack.name,
|
||||||
}
|
artist: lastTrack.artist.name,
|
||||||
} = await fetch(`https://ws.audioscrobbler.com/2.0/?${params}`).then(x => x.json());
|
album: lastTrack.album['#text'],
|
||||||
|
albumArt: filterAlbumCover(lastTrack.image[3]['#text']),
|
||||||
return {
|
url: lastTrack.url,
|
||||||
name: lastTrack.name,
|
date: lastTrack.date?.['#text'] ?? 'now',
|
||||||
artist: lastTrack.artist.name,
|
nowPlaying: Boolean(lastTrack['@attr']?.nowplaying),
|
||||||
album: lastTrack.album['#text'],
|
loved: lastTrack.loved === '1',
|
||||||
albumArt: filterAlbumCover(lastTrack.image[3]['#text']),
|
} as Track;
|
||||||
url: lastTrack.url,
|
|
||||||
date: lastTrack.date?.['#text'] ?? 'now',
|
|
||||||
nowPlaying: Boolean(lastTrack['@attr']?.nowplaying),
|
|
||||||
loved: lastTrack.loved === '1',
|
|
||||||
} as Track;
|
|
||||||
} catch (error) {
|
|
||||||
logger.error("Last.fm: An error occured while fetching user's track:\n", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently ditches the default album covers (they're ugly)
|
// Currently ditches the default album covers (they're ugly)
|
||||||
|
|
@ -121,6 +114,7 @@ function filterAlbumCover(cover: string): string {
|
||||||
|
|
||||||
// Clears the activity
|
// Clears the activity
|
||||||
function clearActivity(): Promise<ResultActivity> {
|
function clearActivity(): Promise<ResultActivity> {
|
||||||
|
lastActivity && verboseLog("--> Clearing activity...");
|
||||||
return sendRequest(null);
|
return sendRequest(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +149,10 @@ async function sendRequest(activity: Activity): Promise<ResultActivity> {
|
||||||
// This is the main function that is called every 5 seconds (or whatever the user has set)
|
// This is the main function that is called every 5 seconds (or whatever the user has set)
|
||||||
async function update() {
|
async function update() {
|
||||||
verboseLog("--> Fetching last track...");
|
verboseLog("--> Fetching last track...");
|
||||||
const lastTrack = await fetchCurrentScrobble();
|
const lastTrack = await fetchCurrentScrobble().catch((err) => {
|
||||||
|
verboseLog("--> An error occurred while fetching the last track, aborting...");
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
if (!lastTrack.nowPlaying) {
|
if (!lastTrack.nowPlaying) {
|
||||||
verboseLog("--> Last track is not currently playing, aborting...");
|
verboseLog("--> Last track is not currently playing, aborting...");
|
||||||
|
|
@ -170,15 +167,15 @@ async function update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const activity = {
|
const activity = {
|
||||||
name: appName || "Music",
|
name: settings.appName || "Music",
|
||||||
type: listeningTo ? 2 : 0,
|
type: settings.listeningTo ? 2 : 0,
|
||||||
details: lastTrack.name,
|
details: lastTrack.name,
|
||||||
state: `by ${lastTrack.artist}`,
|
state: `by ${lastTrack.artist}`,
|
||||||
} as Activity;
|
} as Activity;
|
||||||
|
|
||||||
lastTrackUrl = lastTrack.url;
|
lastTrackUrl = lastTrack.url;
|
||||||
|
|
||||||
if (showTimestamp) {
|
if (settings.showTimestamp) {
|
||||||
activity.timestamps = {
|
activity.timestamps = {
|
||||||
start: Date.now() / 1000 | 0
|
start: Date.now() / 1000 | 0
|
||||||
};
|
};
|
||||||
|
|
@ -191,7 +188,10 @@ async function update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await sendRequest(activity);
|
const response = await sendRequest(activity).catch((err) => {
|
||||||
|
verboseLog("--> An error occurred while setting the activity");
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
verboseLog("--> Successfully set activity!");
|
verboseLog("--> Successfully set activity!");
|
||||||
verboseLog(response);
|
verboseLog(response);
|
||||||
|
|
@ -225,7 +225,7 @@ async function initialize() {
|
||||||
clearInterval(updateInterval);
|
clearInterval(updateInterval);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
timeInterval
|
settings.timeInterval
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,9 +242,9 @@ function patchActivityType() {
|
||||||
const { actionHandler } = nodes.find((x: any) => x.name === "LocalActivityStore") as any;
|
const { actionHandler } = nodes.find((x: any) => x.name === "LocalActivityStore") as any;
|
||||||
|
|
||||||
activityTypeUnpatch = patcher.before("LOCAL_ACTIVITY_UPDATE", actionHandler, ([{ activity }]) => {
|
activityTypeUnpatch = patcher.before("LOCAL_ACTIVITY_UPDATE", actionHandler, ([{ activity }]) => {
|
||||||
if (activity.name !== lastActivity.name) return;
|
if (activity.name === lastActivity.name) {
|
||||||
|
activity.type = lastActivity.type;
|
||||||
activity.type = lastActivity.type;
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,6 +254,14 @@ export default {
|
||||||
console.log("Starting last.fm plugin..");
|
console.log("Starting last.fm plugin..");
|
||||||
patchActivityType();
|
patchActivityType();
|
||||||
|
|
||||||
|
// Options
|
||||||
|
// settings.appName = "Music";
|
||||||
|
// settings.username = "slyde99";
|
||||||
|
// settings.showTimestamp = true;
|
||||||
|
// settings.timeInterval = 5000;
|
||||||
|
// settings.listeningTo = true;
|
||||||
|
// settings.verboseLogging = false;
|
||||||
|
|
||||||
// If the user is already logged in (brrr connection), initialize the plugin
|
// If the user is already logged in (brrr connection), initialize the plugin
|
||||||
if (UserStore.getCurrentUser()) {
|
if (UserStore.getCurrentUser()) {
|
||||||
console.log("User is already logged in, initializing...");
|
console.log("User is already logged in, initializing...");
|
||||||
|
|
@ -275,5 +283,6 @@ export default {
|
||||||
clearActivity();
|
clearActivity();
|
||||||
activityTypeUnpatch?.();
|
activityTypeUnpatch?.();
|
||||||
activityTypeUnpatch = null;
|
activityTypeUnpatch = null;
|
||||||
}
|
},
|
||||||
|
settings: Settings
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
plugins/Last.fm/src/settings.tsx
Normal file
9
plugins/Last.fm/src/settings.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { React, ReactNative } from "@vendetta/metro/common";
|
||||||
|
|
||||||
|
export default function Settings() {
|
||||||
|
return (
|
||||||
|
<ReactNative.Text>
|
||||||
|
Hello World!
|
||||||
|
</ReactNative.Text>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue