Skip to content

Conversation

@mosshaven
Copy link

(IT'S VIBECODE PLUGIN!)

i tested first version, and it seems working. ai refactored it, and i don't tested it. merge with caution, ig???
(idk why ai put api keys, bc last.fm requesting to log in if plugin started)

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

eslint

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········································ with ····················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ································ with ················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ································ with ················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················

label: 'API Secret',


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················

value: config.secret,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········································ with ····················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ································ with ················


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···························· with ··············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···························· with ··············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··············

...promptOptions(),


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···························· with ··············

setConfig({ apiKey: output[0] });


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···························· with ··············

setConfig({ secret: output[1] });


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <importPlugin/order> reported by reviewdog 🐶
There should be at least one empty line between import groups

import { BrowserWindow, net } from 'electron';


🚫 [eslint] <importPlugin/order> reported by reviewdog 🐶
node:crypto import should occur before import of electron

import crypto from 'node:crypto';


🚫 [eslint] <@typescript-eslint/consistent-type-imports> reported by reviewdog 🐶
Imports "SongInfo" are only used as type.

import {
registerCallback,
SongInfo,
SongInfoEvent,
} from '@/providers/song-info';


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

api_sig?: string;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··

Object.entries(params)


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

.sort(([a], [b]) => a.localeCompare(b))


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

.forEach(([key, value]) => {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

// 'format' and 'callback' are not included in the signature


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

if (key === 'format' || key === 'callback') return;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

sig += key + String(value);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

return crypto.createHash('md5').update(sig, 'utf-8').digest('hex');


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··

params: Record<string, unknown>,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

apiSignature: string,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

const queryParams = { ...params, api_sig: apiSignature };


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

const queryData = Object.entries(queryParams).map(


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

([key, value]) =>


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

return '?' + queryData.join('&');


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

const formData = new URLSearchParams();


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

for (const key in params) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (params[key] !== undefined) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

formData.append(key, String(params[key]));


🚫 [eslint] <@typescript-eslint/no-base-to-string> reported by reviewdog 🐶
'params[key]' may use Object's default stringification format ('[object Object]') when stringified.

formData.append(key, String(params[key]));


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

config?: LastFmConfig;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

window?: BrowserWindow;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

scrobbleTimer?: NodeJS.Timeout;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··

startAuth(config: LastFmConfig): Promise<void>;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

createSession(config: LastFmConfig): Promise<void>;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··

scrobble(songInfo: SongInfo, config: LastFmConfig): Promise<void>;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

updateNowPlaying(songInfo: SongInfo, config: LastFmConfig): Promise<void>;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

async start({ getConfig, setConfig, window }) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

this.config = await getConfig();


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

this.window = window;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

// If enabled but no session key, start the authentication flow


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

if (this.config.enabled && !this.config.sessionKey) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

await this.startAuth(this.config);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

await setConfig(this.config);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

// Register a callback to listen for song changes


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

registerCallback((songInfo: SongInfo, event) => {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

// Ignore time updates, we only care about track changes or pause/play


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

if (event === SongInfoEvent.TimeChanged) return;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

// Clear any pending scrobble timer to prevent duplicate scrobbles


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

clearTimeout(this.scrobbleTimer);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········

!songInfo.isPaused &&


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

this.config?.enabled &&


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········

this.config.sessionKey


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

// 1. Update "Now Playing" status on Last.fm


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

this.updateNowPlaying(songInfo, this.config);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

// 2. Schedule the Scrobble


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········

// Rule: Scrobble at 33% of the song duration OR 4 minutes, whichever comes first.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

const scrobbleThreshold = Math.min(


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········

Math.ceil(songInfo.songDuration * 0.33),


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········

4 * 60, // 4 minutes in seconds


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

const elapsed = songInfo.elapsedSeconds ?? 0;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········

if (scrobbleThreshold > elapsed) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········

const timeToWait = (scrobbleThreshold - elapsed) * 1000;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··········

this.scrobbleTimer = setTimeout(() => {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············

if (this.config) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··············

this.scrobble(songInfo, this.config);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

async onConfigChange(newConfig) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

this.config = newConfig;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

// Re-authenticate if the plugin is enabled but lacks a session key


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

if (this.config.enabled && !this.config.sessionKey) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

await this.startAuth(this.config);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ····· with ···

* Starts the Last.fm authentication process.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

* 1. Fetches a request token.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

* 2. Opens a browser window for the user to approve the application.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

* 3. Creates a session after approval.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

async startAuth(config: LastFmConfig) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

// Step 1: Get a Request Token


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

const tokenParams = {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

method: 'auth.gettoken',


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

api_key: config.apiKey,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const tokenSig = createApiSig(tokenParams, config.secret);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const tokenRes = await net.fetch(


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

`${config.apiRoot}${createQueryString(tokenParams, tokenSig)}`,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const tokenJson = (await tokenRes.json()) as { token?: string };


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (!tokenJson.token) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

console.error('Last.fm: Failed to get authentication token.');


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

config.token = tokenJson.token;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

// Step 2: Request User Approval via Browser Window


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const authUrl = `https://www.last.fm/api/auth/?api_key=${config.apiKey}&token=${config.token}`;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const authWindow = new BrowserWindow({


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

parent: this.window,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

autoHideMenuBar: true,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

authWindow.loadURL(authUrl);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

authWindow.show();


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

// Wait for the user to approve the app in the opened window


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

return new Promise<void>((resolve) => {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

authWindow.webContents.on('did-navigate', async (_, newUrl) => {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

const url = new URL(newUrl);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········

// Last.fm redirects to this URL after approval


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········

if (url.hostname.endsWith('last.fm') && url.pathname === '/api/auth') {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··········

// Check if the approval was successful by looking for the confirmation element


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········

// This is a heuristic; ideally we'd use a callback URL but this is a desktop app


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ··········const·isApproveScreen·= with const·isApproveScreen·=⏎···········

const isApproveScreen = await authWindow.webContents.executeJavaScript(


🚫 [eslint] <@typescript-eslint/no-unsafe-assignment> reported by reviewdog 🐶
Unsafe assignment of an any value.

const isApproveScreen = await authWindow.webContents.executeJavaScript(
"!!document.getElementsByName('confirm').length",
);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ··············

"!!document.getElementsByName('confirm').length",


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········

// If we are past the confirmation screen (or it didn't show), assume success


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··········

if (!isApproveScreen) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············

authWindow.close();


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ························ with ············

await this.createSession(config);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ············


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···················· with ··········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

// Handle window close by user (cancellation)


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

authWindow.on('closed', () => {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ····· with ···

* Exchanges the request token for a session key.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

async createSession(config: LastFmConfig) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (!config.token) return;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const params = {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

api_key: config.apiKey,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

method: 'auth.getsession',


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

token: config.token,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const sig = createApiSig(params, config.secret);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const res = await net.fetch(


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

`${config.apiRoot}${createQueryString(params, sig)}`,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const json = (await res.json()) as { session?: { key: string } };


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (json.session) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

config.sessionKey = json.session.key;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

console.log('Last.fm: Session created successfully.');


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

console.error('Last.fm: Failed to create session.', json);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

* Updates the "Now Playing" track on Last.fm.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

async updateNowPlaying(songInfo: SongInfo, config: LastFmConfig) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (!config.sessionKey) return;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

const params: LastFmApiParams = {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

method: 'track.updateNowPlaying',


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

track: songInfo.title,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

artist: songInfo.artist,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

duration: songInfo.songDuration,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

api_key: config.apiKey,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

sk: config.sessionKey,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (songInfo.album) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

params.album = songInfo.album;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const sig = createApiSig(params, config.secret);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const formData = createFormData({ ...params, api_sig: sig });


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

await net.fetch(config.apiRoot, {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

} catch (error) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

console.error('Last.fm: Failed to update Now Playing.', error);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

* Scrobbles a track to Last.fm.


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··

async scrobble(songInfo: SongInfo, config: LastFmConfig) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (!config.sessionKey) return;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const params: LastFmApiParams = {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

method: 'track.scrobble',


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

track: songInfo.title,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

artist: songInfo.artist,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

timestamp: Math.floor(Date.now() / 1000),


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

api_key: config.apiKey,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

sk: config.sessionKey,


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

if (songInfo.album) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······

params.album = songInfo.album;


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ········ with ····

const sig = createApiSig(params, config.secret);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····

const formData = createFormData({ ...params, api_sig: sig });


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

await net.fetch(config.apiRoot, {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ················ with ········


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············ with ······


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ············console.log(Last.fm:·Scrobble·successful·for·${songInfo.artist}·-·${songInfo.title}); with ······console.log(⏎········Last.fm:·Scrobble·successful·for·${songInfo.artist}·-·${songInfo.title},

console.log(`Last.fm: Scrobble successful for ${songInfo.artist} - ${songInfo.title}`);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Insert ··);⏎

} catch (error) {


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ······

console.error('Last.fm: Failed to scrobble.', error);


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ····


🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

* Configuration interface for the Last.fm plugin.
*/
export interface LastFmConfig {
enabled: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

Suggested change
enabled: boolean;
enabled: boolean;
*/
export interface LastFmConfig {
enabled: boolean;
token?: string; // Request token for authentication
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

Suggested change
token?: string; // Request token for authentication
token?: string; // Request token for authentication
export interface LastFmConfig {
enabled: boolean;
token?: string; // Request token for authentication
sessionKey?: string; // Session key obtained after user approval
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···· with ··

Suggested change
sessionKey?: string; // Session key obtained after user approval
sessionKey?: string; // Session key obtained after user approval
enabled: boolean;
token?: string; // Request token for authentication
sessionKey?: string; // Session key obtained after user approval
apiRoot: string; // Base URL for Last.fm API
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

Suggested change
apiRoot: string; // Base URL for Last.fm API
apiRoot: string; // Base URL for Last.fm API
token?: string; // Request token for authentication
sessionKey?: string; // Session key obtained after user approval
apiRoot: string; // Base URL for Last.fm API
apiKey: string; // Application API Key
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Delete ··

Suggested change
apiKey: string; // Application API Key
apiKey: string; // Application API Key
title: 'Last.fm API Settings',
label: 'Configure API Key and Secret',
type: 'multiInput',
multiInputOptions: [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···························· with ··············

Suggested change
multiInputOptions: [
multiInputOptions: [
label: 'Configure API Key and Secret',
type: 'multiInput',
multiInputOptions: [
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ································ with ················

Suggested change
{
{
type: 'multiInput',
multiInputOptions: [
{
label: 'API Key',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················

Suggested change
label: 'API Key',
label: 'API Key',
multiInputOptions: [
{
label: 'API Key',
value: config.apiKey,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················

Suggested change
value: config.apiKey,
value: config.apiKey,
{
label: 'API Key',
value: config.apiKey,
inputAttrs: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Replace ···································· with ··················

Suggested change
inputAttrs: {
inputAttrs: {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant