Skip to content

Commit e440414

Browse files
committed
update rpc plugin
1 parent b04041e commit e440414

File tree

10 files changed

+319
-158
lines changed

10 files changed

+319
-158
lines changed

build.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ for (const plugin of plugins) {
2828
...repl._builtinLibs.map((m) => `node:${m}`),
2929
"@neptune",
3030
"@plugin",
31+
"electron"
3132
],
3233
platform: "browser",
3334
outfile,

bun.lockb

31.7 KB
Binary file not shown.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@
77
},
88
"devDependencies": {
99
"esbuild": "^0.18.20"
10+
},
11+
"dependencies": {
12+
"@xhayper/discord-rpc": "^1.2.0",
13+
"electron": "^32.1.2"
1014
}
1115
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { store } from "@neptune";
2+
import { interceptPromise } from "../intercept/interceptPromise";
3+
import getPlaybackControl from "../getPlaybackControl";
4+
5+
import { libTrace } from "../trace";
6+
7+
export class MediaItemCache {
8+
current(playbackContext) {
9+
const context = playbackContext ?? getPlaybackControl()?.playbackContext;
10+
if (context?.actualProductId === undefined) return undefined;
11+
return this.ensure(context.actualProductId);
12+
}
13+
async ensureTrack(itemId) {
14+
const mediaItem = await this.ensure(itemId);
15+
if (mediaItem?.contentType === "track") return mediaItem;
16+
return undefined;
17+
}
18+
async ensureVideo(itemId) {
19+
const mediaItem = await this.ensure(itemId);
20+
if (mediaItem?.contentType === "video") return mediaItem;
21+
return undefined;
22+
}
23+
async ensure(itemId) {
24+
if (itemId === undefined) return undefined;
25+
26+
const mediaItem = this._cache[itemId];
27+
if (mediaItem !== undefined) return mediaItem;
28+
29+
const mediaItems = store.getState().content.mediaItems;
30+
for (const itemId in mediaItems) {
31+
const item = mediaItems[itemId]?.item;
32+
this._cache[itemId] = item;
33+
}
34+
35+
if (this._cache[itemId] === undefined) {
36+
const currentPage = window.location.pathname;
37+
38+
const loadedTrack = await interceptPromise(
39+
() => neptune.actions.router.replace(`/track/${itemId}`),
40+
["page/IS_DONE_LOADING"],
41+
[],
42+
)
43+
.then(() => true)
44+
.catch(
45+
libTrace.warn.withContext(
46+
`TrackItemCache.ensure failed to load track ${itemId}`,
47+
),
48+
);
49+
// If we fail to load the track, maybe its a video, try that instead as a last ditch attempt
50+
if (!loadedTrack) {
51+
await interceptPromise(
52+
() => neptune.actions.router.replace(`/video/${itemId}`),
53+
["page/IS_DONE_LOADING"],
54+
[],
55+
).catch(
56+
libTrace.warn.withContext(
57+
`TrackItemCache.ensure failed to load video ${itemId}`,
58+
),
59+
);
60+
}
61+
neptune.actions.router.replace(currentPage);
62+
63+
const mediaItems = store.getState().content.mediaItems;
64+
const trackItem = mediaItems[+itemId]?.item;
65+
this._cache[itemId] = trackItem;
66+
}
67+
68+
return this._cache[itemId];
69+
}
70+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { store } from "@neptune";
2+
3+
export default () => store.getState()?.playbackControls ?? {};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { intercept } from "@neptune";
2+
3+
export const interceptPromise = () => {
4+
timeoutMs ??= 5000;
5+
cancel ??= false;
6+
let res;
7+
let rej;
8+
const p = new Promise((_res, _rej) => {
9+
res = _res;
10+
rej = _rej;
11+
});
12+
const unloadRes = intercept(
13+
resActionType,
14+
(payload) => {
15+
res(payload);
16+
if (cancel) return true;
17+
},
18+
true,
19+
);
20+
if (!rej) throw new Error("Rejection function is not defined");
21+
const unloadRej = intercept(rejActionType, rej, true);
22+
const timeout = setTimeout(
23+
() => rej(`${rejActionType ?? resActionType}_TIMEOUT`),
24+
timeoutMs,
25+
);
26+
trigger();
27+
return p.finally(() => {
28+
clearTimeout(timeout);
29+
unloadRes();
30+
unloadRej();
31+
});
32+
};

plugins/DiscordRPC/src/_lib/trace.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { actions } from "@neptune";
2+
3+
export const Tracer = (source) => {
4+
const createLogger = (logger) => {
5+
const _logger = (...data) => {
6+
logger(source, ...data);
7+
return undefined;
8+
};
9+
_logger.withContext =
10+
(context) =>
11+
(...data) => {
12+
logger(source, context, ...data);
13+
return undefined;
14+
};
15+
return _logger;
16+
};
17+
18+
const log = createLogger(console.log);
19+
const warn = createLogger(console.warn);
20+
const err = createLogger(console.error);
21+
const debug = createLogger(console.debug);
22+
23+
const createMessager = (logger, messager, severity) => {
24+
const _messager = (message) => {
25+
logger(message);
26+
messager({
27+
message: `${source} - ${message}`,
28+
category: "OTHER",
29+
severity,
30+
});
31+
return undefined;
32+
};
33+
_messager.withContext = (context) => {
34+
const loggerWithContext = logger.withContext(context);
35+
return (message) => {
36+
loggerWithContext(message);
37+
let finalMessage = message;
38+
if (message instanceof Error) finalMessage = message.message;
39+
messager({
40+
message: `${source}.${context} - ${message}`,
41+
category: "OTHER",
42+
severity,
43+
});
44+
return undefined;
45+
};
46+
};
47+
return _messager;
48+
};
49+
50+
return {
51+
log,
52+
warn,
53+
err,
54+
debug,
55+
msg: {
56+
log: createMessager(log, actions.message.messageInfo, "INFO"),
57+
warn: createMessager(warn, actions.message.messageWarn, "WARN"),
58+
err: createMessager(err, actions.message.messageError, "ERROR"),
59+
},
60+
};
61+
};
62+
63+
export const libTrace = Tracer("[lib]");
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Client } from "@xhayper/discord-rpc";
2+
import electron from "electron";
3+
4+
let rpcClient = null;
5+
async function getClient() {
6+
const isAvailable = rpcClient?.transport.isConnected && rpcClient.user;
7+
if (isAvailable) return rpcClient;
8+
9+
if (rpcClient) await rpcClient.destroy();
10+
rpcClient = new Client({ clientId: "1288341778637918208" });
11+
await rpcClient.connect();
12+
13+
return rpcClient;
14+
}
15+
16+
async function setActivity(event, activity) {
17+
const client = await getClient();
18+
if (!client.user) return;
19+
if (!activity) return client.user.clearActivity();
20+
return client.user.setActivity(activity);
21+
}
22+
23+
async function cleanup() {
24+
return rpcClient?.destroy();
25+
}
26+
27+
electron.ipcMain.removeHandler("DISCORD_SET_ACTIVITY");
28+
electron.ipcMain.removeHandler("DISCORD_CLEANUP");
29+
electron.ipcMain.handle("DISCORD_SET_ACTIVITY", setActivity);
30+
electron.ipcMain.handle("DISCORD_CLEANUP", cleanup);

0 commit comments

Comments
 (0)