mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-09 15:13:32 -07:00
[codex] Restart Jellyfin remote session after setup login (#112)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
type: fixed
|
||||||
|
area: jellyfin
|
||||||
|
|
||||||
|
- Restarted the Jellyfin remote session after successful setup login so websocket reconnects use the freshly saved credentials.
|
||||||
|
- Stopped the Jellyfin remote session on setup logout.
|
||||||
@@ -1,6 +1,37 @@
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import { composeJellyfinRuntimeHandlers } from './jellyfin-runtime-composer';
|
import {
|
||||||
|
composeJellyfinRuntimeHandlers,
|
||||||
|
createRestartJellyfinRemoteSessionAfterSetupLoginHandler,
|
||||||
|
} from './jellyfin-runtime-composer';
|
||||||
|
|
||||||
|
test('setup login restart uses auto-connect path without an active remote session', async () => {
|
||||||
|
const startOptions: Array<{ explicit?: boolean } | undefined> = [];
|
||||||
|
const restart = createRestartJellyfinRemoteSessionAfterSetupLoginHandler({
|
||||||
|
getCurrentSession: () => null,
|
||||||
|
startJellyfinRemoteSession: async (options) => {
|
||||||
|
startOptions.push(options);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await restart();
|
||||||
|
|
||||||
|
assert.deepEqual(startOptions, [undefined]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setup login restart explicitly refreshes an active remote session', async () => {
|
||||||
|
const startOptions: Array<{ explicit?: boolean } | undefined> = [];
|
||||||
|
const restart = createRestartJellyfinRemoteSessionAfterSetupLoginHandler({
|
||||||
|
getCurrentSession: () => ({ stop: () => {} }),
|
||||||
|
startJellyfinRemoteSession: async (options) => {
|
||||||
|
startOptions.push(options);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await restart();
|
||||||
|
|
||||||
|
assert.deepEqual(startOptions, [{ explicit: true }]);
|
||||||
|
});
|
||||||
|
|
||||||
test('composeJellyfinRuntimeHandlers returns callable jellyfin runtime handlers', () => {
|
test('composeJellyfinRuntimeHandlers returns callable jellyfin runtime handlers', () => {
|
||||||
let activePlayback: unknown = null;
|
let activePlayback: unknown = null;
|
||||||
|
|||||||
@@ -153,6 +153,16 @@ export type JellyfinRuntimeComposerResult = ComposerOutputs<{
|
|||||||
openJellyfinSetupWindow: ReturnType<typeof createOpenJellyfinSetupWindowHandler>;
|
openJellyfinSetupWindow: ReturnType<typeof createOpenJellyfinSetupWindowHandler>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
export function createRestartJellyfinRemoteSessionAfterSetupLoginHandler(deps: {
|
||||||
|
getCurrentSession: () => unknown | null;
|
||||||
|
startJellyfinRemoteSession: (options?: { explicit?: boolean }) => Promise<void>;
|
||||||
|
}) {
|
||||||
|
return async (): Promise<void> => {
|
||||||
|
const hasActiveSession = deps.getCurrentSession() !== null;
|
||||||
|
await deps.startJellyfinRemoteSession(hasActiveSession ? { explicit: true } : undefined);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function composeJellyfinRuntimeHandlers(
|
export function composeJellyfinRuntimeHandlers(
|
||||||
options: JellyfinRuntimeComposerOptions,
|
options: JellyfinRuntimeComposerOptions,
|
||||||
): JellyfinRuntimeComposerResult {
|
): JellyfinRuntimeComposerResult {
|
||||||
@@ -268,12 +278,19 @@ export function composeJellyfinRuntimeHandlers(
|
|||||||
const maybeFocusExistingJellyfinSetupWindow = createMaybeFocusExistingJellyfinSetupWindowHandler(
|
const maybeFocusExistingJellyfinSetupWindow = createMaybeFocusExistingJellyfinSetupWindowHandler(
|
||||||
options.maybeFocusExistingJellyfinSetupWindowMainDeps,
|
options.maybeFocusExistingJellyfinSetupWindowMainDeps,
|
||||||
);
|
);
|
||||||
|
const restartJellyfinRemoteSessionAfterSetupLogin =
|
||||||
|
createRestartJellyfinRemoteSessionAfterSetupLoginHandler({
|
||||||
|
getCurrentSession: () => options.startJellyfinRemoteSessionMainDeps.getCurrentSession(),
|
||||||
|
startJellyfinRemoteSession: (startOptions) => startJellyfinRemoteSession(startOptions),
|
||||||
|
});
|
||||||
const openJellyfinSetupWindow = createOpenJellyfinSetupWindowHandler(
|
const openJellyfinSetupWindow = createOpenJellyfinSetupWindowHandler(
|
||||||
createBuildOpenJellyfinSetupWindowMainDepsHandler({
|
createBuildOpenJellyfinSetupWindowMainDepsHandler({
|
||||||
...options.openJellyfinSetupWindowMainDeps,
|
...options.openJellyfinSetupWindowMainDeps,
|
||||||
maybeFocusExistingSetupWindow: maybeFocusExistingJellyfinSetupWindow,
|
maybeFocusExistingSetupWindow: maybeFocusExistingJellyfinSetupWindow,
|
||||||
getResolvedJellyfinConfig: () => getResolvedJellyfinConfig(),
|
getResolvedJellyfinConfig: () => getResolvedJellyfinConfig(),
|
||||||
getJellyfinClientInfo: () => getJellyfinClientInfo(),
|
getJellyfinClientInfo: () => getJellyfinClientInfo(),
|
||||||
|
restartRemoteSession: () => restartJellyfinRemoteSessionAfterSetupLogin(),
|
||||||
|
stopRemoteSession: () => stopJellyfinRemoteSession(),
|
||||||
})(),
|
})(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ test('open jellyfin setup window main deps builder maps callbacks', async () =>
|
|||||||
clearStoredSession: () => calls.push('clear-session'),
|
clearStoredSession: () => calls.push('clear-session'),
|
||||||
patchJellyfinConfig: () => calls.push('patch'),
|
patchJellyfinConfig: () => calls.push('patch'),
|
||||||
persistAuthenticatedSession: () => calls.push('persist'),
|
persistAuthenticatedSession: () => calls.push('persist'),
|
||||||
|
restartRemoteSession: () => {
|
||||||
|
calls.push('restart-remote');
|
||||||
|
},
|
||||||
|
stopRemoteSession: () => calls.push('stop-remote'),
|
||||||
logInfo: (message) => calls.push(`info:${message}`),
|
logInfo: (message) => calls.push(`info:${message}`),
|
||||||
logError: (message) => calls.push(`error:${message}`),
|
logError: (message) => calls.push(`error:${message}`),
|
||||||
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
||||||
@@ -95,6 +99,8 @@ test('open jellyfin setup window main deps builder maps callbacks', async () =>
|
|||||||
},
|
},
|
||||||
deps.getJellyfinClientInfo(),
|
deps.getJellyfinClientInfo(),
|
||||||
);
|
);
|
||||||
|
await deps.restartRemoteSession?.();
|
||||||
|
deps.stopRemoteSession?.();
|
||||||
deps.logInfo('ok');
|
deps.logInfo('ok');
|
||||||
deps.logError('bad', null);
|
deps.logError('bad', null);
|
||||||
deps.showMpvOsd('toast');
|
deps.showMpvOsd('toast');
|
||||||
@@ -110,6 +116,8 @@ test('open jellyfin setup window main deps builder maps callbacks', async () =>
|
|||||||
'clear-session',
|
'clear-session',
|
||||||
'patch',
|
'patch',
|
||||||
'persist',
|
'persist',
|
||||||
|
'restart-remote',
|
||||||
|
'stop-remote',
|
||||||
'info:ok',
|
'info:ok',
|
||||||
'error:bad',
|
'error:bad',
|
||||||
'osd:toast',
|
'osd:toast',
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ export function createBuildOpenJellyfinSetupWindowMainDepsHandler(
|
|||||||
persistAuthenticatedSession: deps.persistAuthenticatedSession
|
persistAuthenticatedSession: deps.persistAuthenticatedSession
|
||||||
? (session, clientInfo) => deps.persistAuthenticatedSession?.(session, clientInfo)
|
? (session, clientInfo) => deps.persistAuthenticatedSession?.(session, clientInfo)
|
||||||
: undefined,
|
: undefined,
|
||||||
|
restartRemoteSession: deps.restartRemoteSession
|
||||||
|
? () => deps.restartRemoteSession?.()
|
||||||
|
: undefined,
|
||||||
|
stopRemoteSession: deps.stopRemoteSession ? () => deps.stopRemoteSession?.() : undefined,
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
logInfo: (message: string) => deps.logInfo(message),
|
||||||
logError: (message: string, error: unknown) => deps.logError(message, error),
|
logError: (message: string, error: unknown) => deps.logError(message, error),
|
||||||
showMpvOsd: (message: string) => deps.showMpvOsd(message),
|
showMpvOsd: (message: string) => deps.showMpvOsd(message),
|
||||||
|
|||||||
@@ -160,6 +160,9 @@ test('createHandleJellyfinSetupSubmissionHandler applies successful login', asyn
|
|||||||
patchPayload = session;
|
patchPayload = session;
|
||||||
calls.push('patch');
|
calls.push('patch');
|
||||||
},
|
},
|
||||||
|
restartRemoteSession: async () => {
|
||||||
|
calls.push('restart-remote');
|
||||||
|
},
|
||||||
logInfo: () => calls.push('info'),
|
logInfo: () => calls.push('info'),
|
||||||
logError: () => calls.push('error'),
|
logError: () => calls.push('error'),
|
||||||
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
||||||
@@ -172,7 +175,14 @@ test('createHandleJellyfinSetupSubmissionHandler applies successful login', asyn
|
|||||||
'b',
|
'b',
|
||||||
);
|
);
|
||||||
assert.equal(handled, true);
|
assert.equal(handled, true);
|
||||||
assert.deepEqual(calls, ['save', 'patch', 'info', 'osd:Jellyfin login success', 'reload']);
|
assert.deepEqual(calls, [
|
||||||
|
'save',
|
||||||
|
'patch',
|
||||||
|
'restart-remote',
|
||||||
|
'info',
|
||||||
|
'osd:Jellyfin login success',
|
||||||
|
'reload',
|
||||||
|
]);
|
||||||
assert.equal(authPassword, 'b');
|
assert.equal(authPassword, 'b');
|
||||||
assert.deepEqual(savedSession, { accessToken: 'token', userId: 'uid' });
|
assert.deepEqual(savedSession, { accessToken: 'token', userId: 'uid' });
|
||||||
assert.deepEqual(patchPayload, {
|
assert.deepEqual(patchPayload, {
|
||||||
@@ -329,6 +339,7 @@ test('createHandleJellyfinSetupSubmissionHandler handles logout and done', async
|
|||||||
saveStoredSession: () => calls.push('save'),
|
saveStoredSession: () => calls.push('save'),
|
||||||
clearStoredSession: () => calls.push('clear'),
|
clearStoredSession: () => calls.push('clear'),
|
||||||
patchJellyfinConfig: () => calls.push('patch'),
|
patchJellyfinConfig: () => calls.push('patch'),
|
||||||
|
stopRemoteSession: () => calls.push('stop-remote'),
|
||||||
logInfo: (message) => calls.push(message),
|
logInfo: (message) => calls.push(message),
|
||||||
logError: () => calls.push('error'),
|
logError: () => calls.push('error'),
|
||||||
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
||||||
@@ -340,6 +351,7 @@ test('createHandleJellyfinSetupSubmissionHandler handles logout and done', async
|
|||||||
assert.equal(await handler('subminer://jellyfin-setup?action=done'), true);
|
assert.equal(await handler('subminer://jellyfin-setup?action=done'), true);
|
||||||
assert.deepEqual(calls, [
|
assert.deepEqual(calls, [
|
||||||
'clear',
|
'clear',
|
||||||
|
'stop-remote',
|
||||||
'Cleared stored Jellyfin auth session.',
|
'Cleared stored Jellyfin auth session.',
|
||||||
'osd:Jellyfin logged out',
|
'osd:Jellyfin logged out',
|
||||||
'reload',
|
'reload',
|
||||||
|
|||||||
@@ -425,6 +425,8 @@ export function createHandleJellyfinSetupSubmissionHandler(deps: {
|
|||||||
clearStoredSession: () => void;
|
clearStoredSession: () => void;
|
||||||
patchJellyfinConfig: (session: JellyfinSession) => void;
|
patchJellyfinConfig: (session: JellyfinSession) => void;
|
||||||
persistAuthenticatedSession?: (session: JellyfinSession, clientInfo: JellyfinClientInfo) => void;
|
persistAuthenticatedSession?: (session: JellyfinSession, clientInfo: JellyfinClientInfo) => void;
|
||||||
|
restartRemoteSession?: () => Promise<void> | void;
|
||||||
|
stopRemoteSession?: () => void;
|
||||||
logInfo: (message: string) => void;
|
logInfo: (message: string) => void;
|
||||||
logError: (message: string, error: unknown) => void;
|
logError: (message: string, error: unknown) => void;
|
||||||
showMpvOsd: (message: string) => void;
|
showMpvOsd: (message: string) => void;
|
||||||
@@ -447,6 +449,7 @@ export function createHandleJellyfinSetupSubmissionHandler(deps: {
|
|||||||
if (submission.action === 'logout') {
|
if (submission.action === 'logout') {
|
||||||
try {
|
try {
|
||||||
deps.clearStoredSession();
|
deps.clearStoredSession();
|
||||||
|
deps.stopRemoteSession?.();
|
||||||
deps.logInfo('Cleared stored Jellyfin auth session.');
|
deps.logInfo('Cleared stored Jellyfin auth session.');
|
||||||
deps.showMpvOsd('Jellyfin logged out');
|
deps.showMpvOsd('Jellyfin logged out');
|
||||||
deps.reloadSetupWindow({
|
deps.reloadSetupWindow({
|
||||||
@@ -491,6 +494,7 @@ export function createHandleJellyfinSetupSubmissionHandler(deps: {
|
|||||||
deps.saveStoredSession({ accessToken: session.accessToken, userId: session.userId });
|
deps.saveStoredSession({ accessToken: session.accessToken, userId: session.userId });
|
||||||
deps.patchJellyfinConfig(session);
|
deps.patchJellyfinConfig(session);
|
||||||
}
|
}
|
||||||
|
await deps.restartRemoteSession?.();
|
||||||
deps.logInfo(`Jellyfin setup saved for ${session.username}.`);
|
deps.logInfo(`Jellyfin setup saved for ${session.username}.`);
|
||||||
deps.showMpvOsd('Jellyfin login success');
|
deps.showMpvOsd('Jellyfin login success');
|
||||||
deps.reloadSetupWindow({
|
deps.reloadSetupWindow({
|
||||||
@@ -593,6 +597,8 @@ export function createOpenJellyfinSetupWindowHandler<
|
|||||||
clearStoredSession: () => void;
|
clearStoredSession: () => void;
|
||||||
patchJellyfinConfig: (session: JellyfinSession) => void;
|
patchJellyfinConfig: (session: JellyfinSession) => void;
|
||||||
persistAuthenticatedSession?: (session: JellyfinSession, clientInfo: JellyfinClientInfo) => void;
|
persistAuthenticatedSession?: (session: JellyfinSession, clientInfo: JellyfinClientInfo) => void;
|
||||||
|
restartRemoteSession?: () => Promise<void> | void;
|
||||||
|
stopRemoteSession?: () => void;
|
||||||
logInfo: (message: string) => void;
|
logInfo: (message: string) => void;
|
||||||
logError: (message: string, error: unknown) => void;
|
logError: (message: string, error: unknown) => void;
|
||||||
showMpvOsd: (message: string) => void;
|
showMpvOsd: (message: string) => void;
|
||||||
@@ -633,6 +639,10 @@ export function createOpenJellyfinSetupWindowHandler<
|
|||||||
persistAuthenticatedSession: deps.persistAuthenticatedSession
|
persistAuthenticatedSession: deps.persistAuthenticatedSession
|
||||||
? (session, clientInfo) => deps.persistAuthenticatedSession?.(session, clientInfo)
|
? (session, clientInfo) => deps.persistAuthenticatedSession?.(session, clientInfo)
|
||||||
: undefined,
|
: undefined,
|
||||||
|
restartRemoteSession: deps.restartRemoteSession
|
||||||
|
? () => deps.restartRemoteSession?.()
|
||||||
|
: undefined,
|
||||||
|
stopRemoteSession: deps.stopRemoteSession ? () => deps.stopRemoteSession?.() : undefined,
|
||||||
logInfo: (message) => deps.logInfo(message),
|
logInfo: (message) => deps.logInfo(message),
|
||||||
logError: (message, error) => deps.logError(message, error),
|
logError: (message, error) => deps.logError(message, error),
|
||||||
showMpvOsd: (message) => deps.showMpvOsd(message),
|
showMpvOsd: (message) => deps.showMpvOsd(message),
|
||||||
|
|||||||
Reference in New Issue
Block a user