mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-09-03 05:10:00 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
246e9ad7c5 | ||
|
|
569c5a8690 | ||
|
|
11f7299c0e | ||
|
|
8a6ae698a1 | ||
|
|
d6ed03028d | ||
|
|
2818d1d275 | ||
|
|
8127e4b6ce | ||
|
|
8e829a53b5 | ||
|
|
1562f8bffc |
@@ -1,6 +1,6 @@
|
||||
## Checklist before requesting a review
|
||||
|
||||
- [ ] I have read the [contributing guidelines.](../CONTRIBUTING.md)
|
||||
- [ ] I have read the [contributing guidelines.](../blob/master/CONTRIBUTING.md)
|
||||
|
||||
## Type of change
|
||||
|
||||
|
||||
@@ -39,9 +39,8 @@ jobs:
|
||||
working-directory: ./docsite
|
||||
|
||||
- name: Replace canonical
|
||||
working-directory: ./docsite/build
|
||||
# https://stackoverflow.com/a/74211242/1469797
|
||||
run: grep '<link data-rh="true" rel="canonical" href="https://foxxmd.github.io' . -lr | xargs sed -i 's/<link data-rh="true" rel="canonical" href="https:\/\/foxxmd.github.io\/docs/<link data-rh="true" rel="canonical" href="https:\/\/docs.multi-scrobbler.app/g'
|
||||
working-directory: ./docsite
|
||||
run: node --experimental-strip-types canonical-replace.ts ./build
|
||||
|
||||
# Popular action to deploy to GitHub Pages:
|
||||
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
|
||||
|
||||
+4
-1
@@ -151,4 +151,7 @@ tmp-*
|
||||
|
||||
*storybook.log
|
||||
storybook-static
|
||||
lib
|
||||
lib
|
||||
*.db
|
||||
*.db.*
|
||||
*.db-*lib
|
||||
Vendored
+13
@@ -1,6 +1,19 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Canonical Replace",
|
||||
"program": "${workspaceFolder}/docsite/canonical-replace.ts",
|
||||
"runtimeArgs": ["--experimental-strip-types"],
|
||||
"args": [
|
||||
"${workspaceFolder}/docsite/build"
|
||||
],
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"type": "node"
|
||||
},
|
||||
{
|
||||
"name": "dev",
|
||||
"type": "node",
|
||||
|
||||
@@ -18,3 +18,4 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lib
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
var args = process.argv.slice(2);
|
||||
|
||||
const linkRegex = new RegExp(/<link data-rh="true" rel="\w+"\shref="(https:\/\/foxxmd\.github\.io\/multi-scrobbler)/g,);
|
||||
const replacement = process.env.CANONICAL_HREF ?? 'https://docs.multi-scrobbler.app';
|
||||
|
||||
/**
|
||||
* Replace canonical and alternative <link> nodes with the "real" domain of the site
|
||||
* so that SEO (google) chooses the correct domain when showing search results
|
||||
*
|
||||
*/
|
||||
|
||||
(async function () {
|
||||
|
||||
if(replacement === undefined || replacement === '') {
|
||||
console.warn('No replacement value found in process.env.CANONICAL_HREF');
|
||||
return;
|
||||
}
|
||||
|
||||
const buildDir = path.resolve(args[0]);
|
||||
console.log(`Reading dir recursively ${buildDir}`);
|
||||
const files = (await fs.readdir(buildDir, { recursive: true })).filter(x => x.includes('.html'));
|
||||
console.log(`Found ${files.length} files with .html extensions`);
|
||||
let modifications = 0;
|
||||
|
||||
await Promise.all(files.map(async (x) => {
|
||||
const filePath = path.resolve(path.join(buildDir, x));
|
||||
//console.log(`Replacing at ${filePath}`);
|
||||
await fs.writeFile(filePath, (await fs.readFile(filePath)).toString().replace(linkRegex, (match, capture, offset, string, groups) => {
|
||||
// this may not be fully accurate since we're mutating concurrently/async
|
||||
// but its a good enough signal for logging to tell if replacements happened
|
||||
modifications++;
|
||||
return match.replace(capture, replacement);
|
||||
}));
|
||||
}));
|
||||
|
||||
console.log(`Done with ${modifications} replacements`);
|
||||
|
||||
}());
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "multi-scrobbler",
|
||||
"version": "0.13.2",
|
||||
"version": "0.13.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "multi-scrobbler",
|
||||
"version": "0.13.2",
|
||||
"version": "0.13.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "multi-scrobbler",
|
||||
"version": "0.13.2",
|
||||
"version": "0.13.3",
|
||||
"type": "module",
|
||||
"description": "scrobble plays from multiple sources to multiple clients",
|
||||
"scripts": {
|
||||
|
||||
@@ -61,12 +61,13 @@ export default abstract class AbstractTransformer<T = any, Y extends StageConfig
|
||||
protected abstract doParseConfig(data: StageConfig): Y;
|
||||
|
||||
public async handle(data: Y, play: PlayObject): Promise<PlayObject> {
|
||||
const cacheKey = `${this.configHash}-${hashObject(data)}-${hashObject(playContentInvariantTransform(play))}`
|
||||
const cacheKey = `transformResult-${this.configHash}-${hashObject(data)}-${hashObject(playContentInvariantTransform(play))}`
|
||||
try {
|
||||
const cachedTransform = await this.cache.get<PlayObject>(cacheKey);
|
||||
if(cachedTransform !== undefined) {
|
||||
const cachedTransformData = await this.cache.get<T>(cacheKey);
|
||||
if(cachedTransformData !== undefined) {
|
||||
this.logger.debug('Transform cache hit');
|
||||
return cachedTransform;
|
||||
const transformed = await this.doHandle(data, play, cachedTransformData);
|
||||
return transformed;
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.warn(new Error(`Could not fetch cache key ${cacheKey}`, {cause: e}));
|
||||
@@ -106,7 +107,7 @@ export default abstract class AbstractTransformer<T = any, Y extends StageConfig
|
||||
}
|
||||
|
||||
const transformed = await this.doHandle(data, play, transformData);
|
||||
await this.cache.set(cacheKey, transformed, this.config.options?.ttl ?? '15s');
|
||||
await this.cache.set(cacheKey, transformData, this.config.options?.ttl ?? '15s');
|
||||
return transformed;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -18,6 +18,7 @@ import { IncomingMessage } from "http";
|
||||
import { baseFormatPlayObj } from "../../utils/PlayTransformUtils.js";
|
||||
import { ScrobbleSubmitError, SimpleError } from "../errors/MSErrors.js";
|
||||
import { redactString } from "@foxxmd/redact-string";
|
||||
import dns from 'node:dns/promises';
|
||||
|
||||
const badErrors = [
|
||||
'api key suspended',
|
||||
@@ -226,7 +227,11 @@ export default class LastfmApiClient extends AbstractApiClient implements Pagina
|
||||
|
||||
testConnection = async() => {
|
||||
try {
|
||||
await isPortReachableConnect(this.url.port, { host: this.url.url.hostname });
|
||||
this.logger.trace(`Looking up IP for ${this.url.url.hostname}`);
|
||||
const resolved = await dns.lookup(this.url.url.hostname);
|
||||
this.logger.trace(`${this.url.url.hostname} resolved to ${resolved.address}`);
|
||||
this.logger.trace(`Checking if ${this.url.url.hostname}:${this.url.port} is reachable...`);
|
||||
await isPortReachableConnect(this.url.port, { host: this.url.url.hostname, timeout: 2000 });
|
||||
this.logger.verbose(`${this.url.url.hostname}:${this.url.port} is reachable.`);
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
||||
@@ -520,7 +520,7 @@ export default class SpotifySource extends MemoryPositionalSource implements Pag
|
||||
platformId: [combinePartsToString([shortDeviceId(device.id), device.name]), NO_USER],
|
||||
status,
|
||||
play: item !== null && item !== undefined ? SpotifySource.formatPlayObj(res.body, {newFromSource: true}) : undefined,
|
||||
stateUpdatedAt: dayjs(timestamp),
|
||||
stateUpdatedAt: dayjs(),
|
||||
position: progress_ms !== null && progress_ms !== undefined ? progress_ms / 1000 : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user