Skip to content

Commit

Permalink
feat: replace cache.json with deno kv
Browse files Browse the repository at this point in the history
  • Loading branch information
NextFire committed Aug 20, 2024
1 parent 9c247ae commit 8444026
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 83 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: denoland/setup-deno@v1
- name: Compile x86_64
run: |
deno compile --allow-env --allow-run --allow-net --allow-read --allow-write --unstable-ffi --allow-ffi --target x86_64-apple-darwin music-rpc.ts
deno compile --allow-env --allow-run --allow-net --allow-read --allow-write --unstable-ffi --allow-ffi --unstable-kv --target x86_64-apple-darwin music-rpc.ts
mv music-rpc music-rpc-${{ steps.version.outputs.commit_sha }}-x86_64-apple-darwin
- name: Upload x86_64
uses: actions/upload-artifact@v4
Expand All @@ -27,7 +27,7 @@ jobs:
path: music-rpc-${{ steps.version.outputs.commit_sha }}-x86_64-apple-darwin
- name: Compile aarch64
run: |
deno compile --allow-env --allow-run --allow-net --allow-read --allow-write --unstable-ffi --allow-ffi --target aarch64-apple-darwin music-rpc.ts
deno compile --allow-env --allow-run --allow-net --allow-read --allow-write --unstable-ffi --allow-ffi --unstable-kv --target aarch64-apple-darwin music-rpc.ts
mv music-rpc music-rpc-${{ steps.version.outputs.commit_sha }}-aarch64-apple-darwin
- name: Upload aarch64
uses: actions/upload-artifact@v4
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
.DS_Store
/cache_v?.sqlite3*
/music-rpc.log
/cache.json
120 changes: 41 additions & 79 deletions music-rpc.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,28 @@
#!/usr/bin/env deno run --allow-env --allow-run --allow-net --allow-read --allow-write --unstable-ffi --allow-ffi

#!/usr/bin/env deno run --allow-env --allow-run --allow-net --allow-read --allow-write --unstable-ffi --allow-ffi --unstable-kv
import type { Activity } from "https://deno.land/x/[email protected]/mod.ts";
import { Client } from "https://deno.land/x/[email protected]/mod.ts";
import type {} from "https://raw.githubusercontent.com/NextFire/jxa/v0.0.5/run/global.d.ts";
import { run } from "https://raw.githubusercontent.com/NextFire/jxa/v0.0.5/run/mod.ts";
import type { iTunes } from "https://raw.githubusercontent.com/NextFire/jxa/v0.0.5/run/types/core.d.ts";

// Cache

class Cache {
static VERSION = 5;
static CACHE_FILE = "cache.json";
static #data: Map<string, TrackExtras> = new Map();

static get(key: string) {
return this.#data.get(key);
}

static set(key: string, value: TrackExtras) {
this.#data.set(key, value);
this.saveCache();
}

static async loadCache() {
try {
const text = await Deno.readTextFile(this.CACHE_FILE);
const data = JSON.parse(text);
if (data.version !== this.VERSION) throw new Error("Old cache");
this.#data = new Map(data.data);
} catch (err) {
console.error(
err,
`No valid ${this.CACHE_FILE} found, generating a new cache...`
);
}
}

static async saveCache() {
try {
await Deno.writeTextFile(
this.CACHE_FILE,
JSON.stringify({
version: this.VERSION,
data: Array.from(this.#data.entries()),
})
);
} catch (err) {
console.error(err);
}
}
}

// Main part

//#region entrypoint
const MACOS_VER = await getMacOSVersion();
const IS_APPLE_MUSIC = MACOS_VER >= 10.15;
const APP_NAME: iTunesAppName = IS_APPLE_MUSIC ? "Music" : "iTunes";
const CLIENT_ID = IS_APPLE_MUSIC ? "773825528921849856" : "979297966739300416";
const DEFAULT_TIMEOUT = 15e3;

start();
const KV_VERSION = 0;
const kv = await Deno.openKv(`cache_v${KV_VERSION}.sqlite3`);

async function start() {
await Cache.loadCache();
const rpc = new Client({ id: CLIENT_ID });
while (true) {
try {
await main(rpc);
} catch (err) {
console.error(err);
await new Promise((resolve) => setTimeout(resolve, DEFAULT_TIMEOUT));
}
const DEFAULT_TIMEOUT = 15e3;

const rpc = new Client({ id: CLIENT_ID });
while (true) {
try {
await main(rpc);
} catch (err) {
console.error(err);
await sleep(DEFAULT_TIMEOUT);
}
}

Expand All @@ -79,12 +31,16 @@ async function main(rpc: Client) {
console.log(rpc);
while (true) {
const timeout = await setActivity(rpc);
await new Promise((resolve) => setTimeout(resolve, timeout));
await sleep(timeout);
}
}

// macOS/JXA functions
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
//#endregion

//#region macOS/JXA functions
async function getMacOSVersion(): Promise<number> {
const cmd = new Deno.Command("sw_vers", { args: ["-productVersion"] });
const output = await cmd.output();
Expand Down Expand Up @@ -115,22 +71,23 @@ function getProps(): Promise<iTunesProps> {
};
}, APP_NAME);
}
//#endregion

//#region iTunes Search API
async function getTrackExtras(props: iTunesProps): Promise<TrackExtras> {
const { name, artist, album } = props;
const cacheIndex = `${name} ${artist} ${album}`;
let infos = Cache.get(cacheIndex);
const entry = await kv.get<TrackExtras>(["extras", cacheIndex]);
let infos = entry.value;

if (!infos) {
infos = await _getTrackExtras(name, artist, album);
Cache.set(cacheIndex, infos);
await kv.set(["extras", cacheIndex], infos);
}

return infos;
}

// iTunes Search API

async function _getTrackExtras(
song: string,
artist: string,
Expand Down Expand Up @@ -174,20 +131,16 @@ async function _getTrackExtras(
const iTunesUrl = result?.trackViewUrl ?? null;
return { artworkUrl, iTunesUrl };
}
//#endregion

// MusicBrainz Artwork Getter

const MB_EXCLUDED_NAMES = ["", "Various Artist"];
const luceneEscape = (term: string) =>
term.replace(/([+\-&|!(){}\[\]^"~*?:\\])/g, "\\$1");
const removeParenthesesContent = (term: string) =>
term.replace(/\([^)]*\)/g, "").trim();

//#region MusicBrainz
async function _getMBArtwork(
artist: string,
song: string,
album: string
): Promise<string | undefined> {
const MB_EXCLUDED_NAMES = ["", "Various Artist"];

const queryTerms = [];
if (!MB_EXCLUDED_NAMES.every((elem) => artist.includes(elem))) {
queryTerms.push(
Expand Down Expand Up @@ -226,8 +179,16 @@ async function _getMBArtwork(
return result;
}

// Activity setter
function luceneEscape(term: string): string {
return term.replace(/([+\-&|!(){}\[\]^"~*?:\\])/g, "\\$1");
}

function removeParenthesesContent(term: string): string {
return term.replace(/\([^)]*\)/g, "").trim();
}
//#endregion

//#region Activity setter
async function setActivity(rpc: Client): Promise<number> {
const open = await isOpen();
console.log("isOpen:", open);
Expand Down Expand Up @@ -321,14 +282,14 @@ async function setActivity(rpc: Client): Promise<number> {
* @param maxLength
* @returns Formatted string
*/
function formatStr(s: string, minLength = 2, maxLength = 128) {
function formatStr(s: string, minLength = 2, maxLength = 128): string {
return s.length <= maxLength
? s.padEnd(minLength)
: `${s.slice(0, maxLength - 3)}...`;
}
//#endregion

// TypeScript

//#region TypeScript
type iTunesAppName = "iTunes" | "Music";

interface iTunesProps {
Expand Down Expand Up @@ -365,3 +326,4 @@ interface MBReleaseLookupResponse {
interface MBRelease {
id: string;
}
//#endregion

0 comments on commit 8444026

Please sign in to comment.