mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-16 20:52:06 +00:00
@ -10,14 +10,15 @@ import { createBackend } from '@/utils';
|
|||||||
import { JWTPayloadSchema } from './scheme';
|
import { JWTPayloadSchema } from './scheme';
|
||||||
import { registerAuth, registerControl } from './routes';
|
import { registerAuth, registerControl } from './routes';
|
||||||
|
|
||||||
import type { APIServerConfig } from '../config';
|
import { type APIServerConfig, AuthStrategy } from '../config';
|
||||||
|
|
||||||
import type { BackendType } from './types';
|
import type { BackendType } from './types';
|
||||||
|
|
||||||
export const backend = createBackend<BackendType, APIServerConfig>({
|
export const backend = createBackend<BackendType, APIServerConfig>({
|
||||||
async start(ctx) {
|
async start(ctx) {
|
||||||
const config = await ctx.getConfig();
|
const config = await ctx.getConfig();
|
||||||
|
|
||||||
this.init(ctx);
|
await this.init(ctx);
|
||||||
registerCallback((songInfo) => {
|
registerCallback((songInfo) => {
|
||||||
this.songInfo = songInfo;
|
this.songInfo = songInfo;
|
||||||
});
|
});
|
||||||
@ -49,17 +50,20 @@ export const backend = createBackend<BackendType, APIServerConfig>({
|
|||||||
this.app.use('*', cors());
|
this.app.use('*', cors());
|
||||||
|
|
||||||
// middlewares
|
// middlewares
|
||||||
this.app.use(
|
this.app.use('/api/*', async (ctx, next) => {
|
||||||
'/api/*',
|
if (config.authStrategy !== AuthStrategy.NONE) {
|
||||||
jwt({
|
return await jwt({
|
||||||
secret: config.secret,
|
secret: config.secret,
|
||||||
}),
|
})(ctx, next);
|
||||||
);
|
}
|
||||||
|
await next();
|
||||||
|
});
|
||||||
this.app.use('/api/*', async (ctx, next) => {
|
this.app.use('/api/*', async (ctx, next) => {
|
||||||
const result = await JWTPayloadSchema.spa(await ctx.get('jwtPayload'));
|
const result = await JWTPayloadSchema.spa(await ctx.get('jwtPayload'));
|
||||||
|
|
||||||
const isAuthorized =
|
const isAuthorized =
|
||||||
result.success && config.authorizedClients.includes(result.data.id);
|
config.authStrategy === AuthStrategy.NONE ||
|
||||||
|
(result.success && config.authorizedClients.includes(result.data.id));
|
||||||
if (!isAuthorized) {
|
if (!isAuthorized) {
|
||||||
ctx.status(401);
|
ctx.status(401);
|
||||||
return ctx.body('Unauthorized');
|
return ctx.body('Unauthorized');
|
||||||
|
|||||||
@ -6,9 +6,9 @@ import { getConnInfo } from '@hono/node-server/conninfo';
|
|||||||
|
|
||||||
import { t } from '@/i18n';
|
import { t } from '@/i18n';
|
||||||
|
|
||||||
import { APIServerConfig } from '../../config';
|
import { type APIServerConfig, AuthStrategy } from '../../config';
|
||||||
import { JWTPayload } from '../scheme';
|
|
||||||
|
|
||||||
|
import type { JWTPayload } from '../scheme';
|
||||||
import type { HonoApp } from '../types';
|
import type { HonoApp } from '../types';
|
||||||
import type { BackendContext } from '@/types/contexts';
|
import type { BackendContext } from '@/types/contexts';
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export const register = (
|
|||||||
|
|
||||||
if (config.authorizedClients.includes(id)) {
|
if (config.authorizedClients.includes(id)) {
|
||||||
// SKIP CHECK
|
// SKIP CHECK
|
||||||
} else if (config.authStrategy === 'AUTH_AT_FIRST') {
|
} else if (config.authStrategy === AuthStrategy.AUTH_AT_FIRST) {
|
||||||
const result = await dialog.showMessageBox({
|
const result = await dialog.showMessageBox({
|
||||||
title: t('plugins.api-server.dialog.request.title'),
|
title: t('plugins.api-server.dialog.request.title'),
|
||||||
message: t('plugins.api-server.dialog.request.message', {
|
message: t('plugins.api-server.dialog.request.message', {
|
||||||
@ -71,7 +71,7 @@ export const register = (
|
|||||||
ctx.status(403);
|
ctx.status(403);
|
||||||
return ctx.body(null);
|
return ctx.body(null);
|
||||||
}
|
}
|
||||||
} else if (config.authStrategy === 'NONE') {
|
} else if (config.authStrategy === AuthStrategy.NONE) {
|
||||||
// SKIP CHECK
|
// SKIP CHECK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export type BackendType = {
|
|||||||
oldConfig?: APIServerConfig;
|
oldConfig?: APIServerConfig;
|
||||||
songInfo?: SongInfo;
|
songInfo?: SongInfo;
|
||||||
|
|
||||||
init: (ctx: BackendContext<APIServerConfig>) => void;
|
init: (ctx: BackendContext<APIServerConfig>) => Promise<void>;
|
||||||
run: (hostname: string, port: number) => void;
|
run: (hostname: string, port: number) => void;
|
||||||
end: () => void;
|
end: () => void;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
|
export enum AuthStrategy {
|
||||||
|
AUTH_AT_FIRST = 'AUTH_AT_FIRST',
|
||||||
|
NONE = 'NONE',
|
||||||
|
}
|
||||||
|
|
||||||
export interface APIServerConfig {
|
export interface APIServerConfig {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
port: number;
|
port: number;
|
||||||
authStrategy: 'AUTH_AT_FIRST' | 'NONE';
|
authStrategy: AuthStrategy;
|
||||||
secret: string;
|
secret: string;
|
||||||
|
|
||||||
authorizedClients: string[];
|
authorizedClients: string[];
|
||||||
@ -12,7 +17,7 @@ export const defaultAPIServerConfig: APIServerConfig = {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
hostname: '0.0.0.0',
|
hostname: '0.0.0.0',
|
||||||
port: 26538,
|
port: 26538,
|
||||||
authStrategy: 'AUTH_AT_FIRST',
|
authStrategy: AuthStrategy.AUTH_AT_FIRST,
|
||||||
secret: Date.now().toString(36),
|
secret: Date.now().toString(36),
|
||||||
|
|
||||||
authorizedClients: [],
|
authorizedClients: [],
|
||||||
|
|||||||
@ -3,7 +3,11 @@ import prompt from 'custom-electron-prompt';
|
|||||||
import { t } from '@/i18n';
|
import { t } from '@/i18n';
|
||||||
import promptOptions from '@/providers/prompt-options';
|
import promptOptions from '@/providers/prompt-options';
|
||||||
|
|
||||||
import { APIServerConfig, defaultAPIServerConfig } from './config';
|
import {
|
||||||
|
type APIServerConfig,
|
||||||
|
AuthStrategy,
|
||||||
|
defaultAPIServerConfig,
|
||||||
|
} from './config';
|
||||||
|
|
||||||
import type { MenuContext } from '@/types/contexts';
|
import type { MenuContext } from '@/types/contexts';
|
||||||
import type { MenuTemplate } from '@/menu';
|
import type { MenuTemplate } from '@/menu';
|
||||||
@ -74,17 +78,17 @@ export const onMenu = async ({
|
|||||||
'plugins.api-server.menu.auth-strategy.submenu.auth-at-first.label',
|
'plugins.api-server.menu.auth-strategy.submenu.auth-at-first.label',
|
||||||
),
|
),
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
checked: config.authStrategy === 'AUTH_AT_FIRST',
|
checked: config.authStrategy === AuthStrategy.AUTH_AT_FIRST,
|
||||||
click() {
|
click() {
|
||||||
setConfig({ ...config, authStrategy: 'AUTH_AT_FIRST' });
|
setConfig({ ...config, authStrategy: AuthStrategy.AUTH_AT_FIRST });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('plugins.api-server.menu.auth-strategy.submenu.none.label'),
|
label: t('plugins.api-server.menu.auth-strategy.submenu.none.label'),
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
checked: config.authStrategy === 'NONE',
|
checked: config.authStrategy === AuthStrategy.NONE,
|
||||||
click() {
|
click() {
|
||||||
setConfig({ ...config, authStrategy: 'NONE' });
|
setConfig({ ...config, authStrategy: AuthStrategy.NONE });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -129,8 +129,8 @@ async function onApiLoaded() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.ipcRenderer.on('ytmd:get-fullscreen', (event) => {
|
window.ipcRenderer.on('ytmd:get-fullscreen', () => {
|
||||||
event.sender.send('ytmd:set-fullscreen', isFullscreen());
|
window.ipcRenderer.send('ytmd:set-fullscreen', isFullscreen());
|
||||||
});
|
});
|
||||||
|
|
||||||
window.ipcRenderer.on(
|
window.ipcRenderer.on(
|
||||||
@ -148,9 +148,9 @@ async function onApiLoaded() {
|
|||||||
?.onVolumeTap();
|
?.onVolumeTap();
|
||||||
});
|
});
|
||||||
|
|
||||||
window.ipcRenderer.on('ytmd:get-queue', (event) => {
|
window.ipcRenderer.on('ytmd:get-queue', () => {
|
||||||
const queue = document.querySelector<QueueElement>('#queue');
|
const queue = document.querySelector<QueueElement>('#queue');
|
||||||
event.sender.send('ytmd:get-queue-response', {
|
window.ipcRenderer.send('ytmd:get-queue-response', {
|
||||||
items: queue?.queue.getItems(),
|
items: queue?.queue.getItems(),
|
||||||
autoPlaying: queue?.queue.autoPlaying,
|
autoPlaying: queue?.queue.autoPlaying,
|
||||||
continuation: queue?.queue.continuation,
|
continuation: queue?.queue.continuation,
|
||||||
|
|||||||
Reference in New Issue
Block a user