diff options
author | Profpatsch <mail@profpatsch.de> | 2024-10-01T17·10+0200 |
---|---|---|
committer | Profpatsch <mail@profpatsch.de> | 2024-10-05T13·49+0000 |
commit | cf68a34b0d882374a02aa418eccae4f588483094 (patch) | |
tree | 0d9a0ffd8674b47edba2cc6d4dc52eae7a5b6ece /users/Profpatsch/lyric/extension/src/upload-lrc.ts | |
parent | ad711b15a06be8c3f6146f14454621f4a56997ba (diff) |
feat(users/Profpatsch/lyric/ext): add lrc upload & ms offset r/8767
This adds support for uploading the lyrics part of an .lrc file to lrclib, see https://lrclib.net/docs I pretty much only used ChatGPT to translate the rust “proof of work” challenge to nodejs and it worked first try lol. Before uploading the lyrics, I construct a webview with a preview of what is going to be uploaded, and then only upload when that is accepted. Pretty sweet. Also adds two commands for increasing/decreasing the current timestamp by 100ms and starting playback from 2 seconds before that, very handy for fine-tuning lines. Change-Id: Ia6adfe26d0c21c62554c8f8c55e97e2caec95d1e Reviewed-on: https://cl.tvl.fyi/c/depot/+/12561 Reviewed-by: Profpatsch <mail@profpatsch.de> Tested-by: BuildkiteCI
Diffstat (limited to 'users/Profpatsch/lyric/extension/src/upload-lrc.ts')
-rw-r--r-- | users/Profpatsch/lyric/extension/src/upload-lrc.ts | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/users/Profpatsch/lyric/extension/src/upload-lrc.ts b/users/Profpatsch/lyric/extension/src/upload-lrc.ts new file mode 100644 index 000000000000..6686483847d8 --- /dev/null +++ b/users/Profpatsch/lyric/extension/src/upload-lrc.ts @@ -0,0 +1,114 @@ +import * as crypto from 'crypto'; + +// Helper function to convert a hex string to a Buffer +function hexToBytes(hex: string): Buffer { + return Buffer.from(hex, 'hex'); +} + +// Function to verify the nonce +function verifyNonce(result: Buffer, target: Buffer): boolean { + if (result.length !== target.length) { + return false; + } + + for (let i = 0; i < result.length - 1; i++) { + if (result[i] > target[i]) { + return false; + } else if (result[i] < target[i]) { + break; + } + } + + return true; +} + +// Function to solve the challenge +function solveChallenge(prefix: string, targetHex: string): string { + let nonce = 0; + let hashed: Buffer; + const target = hexToBytes(targetHex); + + while (true) { + const input = `${prefix}${nonce}`; + hashed = crypto.createHash('sha256').update(input).digest(); + + if (verifyNonce(hashed, target)) { + break; + } else { + nonce += 1; + } + } + + return nonce.toString(); +} + +async function getUploadNonce() { + try { + const response = await fetch('https://lrclib.net/api/request-challenge', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': 'lyric tool (https://code.tvl.fyi/tree/users/Profpatsch/lyric)', + 'Lrclib-Client': 'lyric tool (https://code.tvl.fyi/tree/users/Profpatsch/lyric)', + }, + }); + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + + const challengeData = (await response.json()) as { prefix: string; target: string }; + + return { + prefix: challengeData.prefix, + nonce: solveChallenge(challengeData.prefix, challengeData.target), + }; + } catch (error) { + console.error('Error fetching the challenge:', error); + } +} + +// Interface for the request body +/** + * Represents a request to publish a track with its associated information. + */ +export interface PublishRequest { + trackName: string; + artistName: string; + albumName: string; + /** In seconds? Milliseconds? mm:ss? */ + duration: number; + plainLyrics: string; + syncedLyrics: string; +} + +// Function to publish lyrics using the solved challenge +export async function publishLyrics( + requestBody: PublishRequest, +): Promise<true | undefined> { + const challenge = await getUploadNonce(); + if (!challenge) { + return; + } + const publishToken = `${challenge.prefix}:${challenge.nonce}`; + + const response = await fetch('https://lrclib.net/api/publish', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': 'lyric tool (https://code.tvl.fyi/tree/users/Profpatsch/lyric)', + 'Lrclib-Client': 'lyric tool (https://code.tvl.fyi/tree/users/Profpatsch/lyric)', + 'X-Publish-Token': publishToken, + }, + body: JSON.stringify(requestBody), + }); + + if (response.status === 201) { + console.log('Lyrics successfully published.'); + return true; + } else { + const errorResponse = (await response.json()) as { [key: string]: string }; + console.error('Failed to publish lyrics:', errorResponse); + return; + } +} |