mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-22 10:51:02 +01:00
feat: apply default delay profile to arrs when adding a new one
This commit is contained in:
@@ -31,6 +31,7 @@ import { migration as migration026 } from './migrations/026_create_upgrade_runs.
|
|||||||
import { migration as migration027 } from './migrations/027_create_rename_runs.ts';
|
import { migration as migration027 } from './migrations/027_create_rename_runs.ts';
|
||||||
import { migration as migration028 } from './migrations/028_simplify_delay_profile_sync.ts';
|
import { migration as migration028 } from './migrations/028_simplify_delay_profile_sync.ts';
|
||||||
import { migration as migration029 } from './migrations/029_add_database_id_foreign_keys.ts';
|
import { migration as migration029 } from './migrations/029_add_database_id_foreign_keys.ts';
|
||||||
|
import { migration as migration030 } from './migrations/030_create_general_settings.ts';
|
||||||
|
|
||||||
export interface Migration {
|
export interface Migration {
|
||||||
version: number;
|
version: number;
|
||||||
@@ -274,7 +275,8 @@ export function loadMigrations(): Migration[] {
|
|||||||
migration026,
|
migration026,
|
||||||
migration027,
|
migration027,
|
||||||
migration028,
|
migration028,
|
||||||
migration029
|
migration029,
|
||||||
|
migration030
|
||||||
];
|
];
|
||||||
|
|
||||||
// Sort by version number
|
// Sort by version number
|
||||||
|
|||||||
31
src/lib/server/db/migrations/030_create_general_settings.ts
Normal file
31
src/lib/server/db/migrations/030_create_general_settings.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import type { Migration } from '../migrations.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create general_settings table for app-wide settings
|
||||||
|
* Initial setting: apply_default_delay_profiles (ON by default)
|
||||||
|
*/
|
||||||
|
export const migration: Migration = {
|
||||||
|
version: 30,
|
||||||
|
name: 'Create general_settings table',
|
||||||
|
|
||||||
|
up: `
|
||||||
|
-- General settings table (singleton pattern)
|
||||||
|
CREATE TABLE IF NOT EXISTS general_settings (
|
||||||
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||||
|
|
||||||
|
-- Default delay profile settings
|
||||||
|
apply_default_delay_profiles INTEGER NOT NULL DEFAULT 1, -- 1=apply defaults when adding arr, 0=don't
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Insert default row
|
||||||
|
INSERT INTO general_settings (id) VALUES (1);
|
||||||
|
`,
|
||||||
|
|
||||||
|
down: `
|
||||||
|
DROP TABLE IF EXISTS general_settings;
|
||||||
|
`
|
||||||
|
};
|
||||||
64
src/lib/server/db/queries/generalSettings.ts
Normal file
64
src/lib/server/db/queries/generalSettings.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { db } from '../db.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types for general_settings table
|
||||||
|
*/
|
||||||
|
export interface GeneralSettings {
|
||||||
|
id: number;
|
||||||
|
apply_default_delay_profiles: number; // 1=true, 0=false
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateGeneralSettingsInput {
|
||||||
|
applyDefaultDelayProfiles?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All queries for general_settings table
|
||||||
|
* Singleton pattern - only one settings record exists
|
||||||
|
*/
|
||||||
|
export const generalSettingsQueries = {
|
||||||
|
/**
|
||||||
|
* Get the general settings (singleton)
|
||||||
|
*/
|
||||||
|
get(): GeneralSettings | undefined {
|
||||||
|
return db.queryFirst<GeneralSettings>('SELECT * FROM general_settings WHERE id = 1');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if default delay profiles should be applied when adding arr
|
||||||
|
*/
|
||||||
|
shouldApplyDefaultDelayProfiles(): boolean {
|
||||||
|
const settings = this.get();
|
||||||
|
return settings?.apply_default_delay_profiles === 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update general settings
|
||||||
|
*/
|
||||||
|
update(input: UpdateGeneralSettingsInput): boolean {
|
||||||
|
const updates: string[] = [];
|
||||||
|
const params: (string | number)[] = [];
|
||||||
|
|
||||||
|
if (input.applyDefaultDelayProfiles !== undefined) {
|
||||||
|
updates.push('apply_default_delay_profiles = ?');
|
||||||
|
params.push(input.applyDefaultDelayProfiles ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updates.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add updated_at
|
||||||
|
updates.push('updated_at = CURRENT_TIMESTAMP');
|
||||||
|
params.push(1); // id is always 1
|
||||||
|
|
||||||
|
const affected = db.execute(
|
||||||
|
`UPDATE general_settings SET ${updates.join(', ')} WHERE id = ?`,
|
||||||
|
...params
|
||||||
|
);
|
||||||
|
|
||||||
|
return affected > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
-- Profilarr Database Schema
|
-- Profilarr Database Schema
|
||||||
-- This file documents the current database schema after all migrations
|
-- This file documents the current database schema after all migrations
|
||||||
-- DO NOT execute this file directly - use migrations instead
|
-- DO NOT execute this file directly - use migrations instead
|
||||||
-- Last updated: 2026-01-21
|
-- Last updated: 2026-01-22
|
||||||
|
|
||||||
-- ==============================================================================
|
-- ==============================================================================
|
||||||
-- TABLE: migrations
|
-- TABLE: migrations
|
||||||
@@ -603,3 +603,20 @@ CREATE TABLE rename_runs (
|
|||||||
CREATE INDEX idx_rename_runs_instance ON rename_runs(instance_id);
|
CREATE INDEX idx_rename_runs_instance ON rename_runs(instance_id);
|
||||||
CREATE INDEX idx_rename_runs_started_at ON rename_runs(started_at DESC);
|
CREATE INDEX idx_rename_runs_started_at ON rename_runs(started_at DESC);
|
||||||
CREATE INDEX idx_rename_runs_status ON rename_runs(status);
|
CREATE INDEX idx_rename_runs_status ON rename_runs(status);
|
||||||
|
|
||||||
|
-- ==============================================================================
|
||||||
|
-- TABLE: general_settings
|
||||||
|
-- Purpose: Store general app-wide settings (singleton pattern with id=1)
|
||||||
|
-- Migration: 030_create_general_settings.ts
|
||||||
|
-- ==============================================================================
|
||||||
|
|
||||||
|
CREATE TABLE general_settings (
|
||||||
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||||
|
|
||||||
|
-- Default delay profile settings
|
||||||
|
apply_default_delay_profiles INTEGER NOT NULL DEFAULT 1, -- 1=apply defaults when adding arr, 0=don't
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|||||||
64
src/lib/server/utils/arr/defaults.ts
Normal file
64
src/lib/server/utils/arr/defaults.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Default delay profiles for Radarr and Sonarr
|
||||||
|
*
|
||||||
|
* These are applied when a new arr instance is added (if enabled in general settings).
|
||||||
|
* Values can be updated based on community feedback.
|
||||||
|
*
|
||||||
|
* Protocol configuration (maps to UI options):
|
||||||
|
* - Prefer Usenet: enableUsenet=true, enableTorrent=true, preferredProtocol='usenet'
|
||||||
|
* - Prefer Torrent: enableUsenet=true, enableTorrent=true, preferredProtocol='torrent'
|
||||||
|
* - Only Usenet: enableUsenet=true, enableTorrent=false, preferredProtocol='usenet'
|
||||||
|
* - Only Torrent: enableUsenet=false, enableTorrent=true, preferredProtocol='torrent'
|
||||||
|
*
|
||||||
|
* TODO: Get final values from Seraphys
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ArrDelayProfile } from './types.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default delay profile for Radarr
|
||||||
|
* Applied to the default profile (id=1) when adding a new Radarr instance
|
||||||
|
*/
|
||||||
|
export const RADARR_DEFAULT_DELAY_PROFILE: Omit<ArrDelayProfile, 'id' | 'order'> = {
|
||||||
|
enableUsenet: true,
|
||||||
|
enableTorrent: true,
|
||||||
|
preferredProtocol: 'torrent',
|
||||||
|
usenetDelay: 600,
|
||||||
|
torrentDelay: 600,
|
||||||
|
bypassIfHighestQuality: false,
|
||||||
|
bypassIfAboveCustomFormatScore: false,
|
||||||
|
minimumCustomFormatScore: 0,
|
||||||
|
tags: []
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default delay profile for Sonarr
|
||||||
|
* Applied to the default profile (id=1) when adding a new Sonarr instance
|
||||||
|
*/
|
||||||
|
export const SONARR_DEFAULT_DELAY_PROFILE: Omit<ArrDelayProfile, 'id' | 'order'> = {
|
||||||
|
enableUsenet: true,
|
||||||
|
enableTorrent: true,
|
||||||
|
preferredProtocol: 'torrent',
|
||||||
|
usenetDelay: 600,
|
||||||
|
torrentDelay: 600,
|
||||||
|
bypassIfHighestQuality: false,
|
||||||
|
bypassIfAboveCustomFormatScore: false,
|
||||||
|
minimumCustomFormatScore: 0,
|
||||||
|
tags: []
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default delay profile for an arr type
|
||||||
|
*/
|
||||||
|
export function getDefaultDelayProfile(
|
||||||
|
arrType: 'radarr' | 'sonarr'
|
||||||
|
): Omit<ArrDelayProfile, 'id' | 'order'> {
|
||||||
|
switch (arrType) {
|
||||||
|
case 'radarr':
|
||||||
|
return RADARR_DEFAULT_DELAY_PROFILE;
|
||||||
|
case 'sonarr':
|
||||||
|
return SONARR_DEFAULT_DELAY_PROFILE;
|
||||||
|
default:
|
||||||
|
throw new Error(`No default delay profile for arr type: ${arrType}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { fail, redirect } from '@sveltejs/kit';
|
import { fail, redirect } from '@sveltejs/kit';
|
||||||
import type { Actions } from '@sveltejs/kit';
|
import type { Actions } from '@sveltejs/kit';
|
||||||
import { arrInstancesQueries } from '$db/queries/arrInstances.ts';
|
import { arrInstancesQueries } from '$db/queries/arrInstances.ts';
|
||||||
|
import { generalSettingsQueries } from '$db/queries/generalSettings.ts';
|
||||||
|
import { createArrClient } from '$arr/factory.ts';
|
||||||
|
import { getDefaultDelayProfile } from '$arr/defaults.ts';
|
||||||
|
import type { ArrType } from '$arr/types.ts';
|
||||||
import { logger } from '$logger/logger.ts';
|
import { logger } from '$logger/logger.ts';
|
||||||
|
|
||||||
const VALID_TYPES = ['radarr', 'sonarr'];
|
const VALID_TYPES = ['radarr', 'sonarr'];
|
||||||
@@ -86,6 +90,35 @@ export const actions = {
|
|||||||
source: 'arr/new',
|
source: 'arr/new',
|
||||||
meta: { id, name, type, url }
|
meta: { id, name, type, url }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Apply default delay profile if enabled
|
||||||
|
if (
|
||||||
|
(type === 'radarr' || type === 'sonarr') &&
|
||||||
|
generalSettingsQueries.shouldApplyDefaultDelayProfiles()
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const client = createArrClient(type as ArrType, url, apiKey);
|
||||||
|
const defaultProfile = getDefaultDelayProfile(type);
|
||||||
|
|
||||||
|
// Update the default delay profile (id=1)
|
||||||
|
await client.updateDelayProfile(1, {
|
||||||
|
...defaultProfile,
|
||||||
|
id: 1,
|
||||||
|
order: 2147483647 // Default profile order
|
||||||
|
});
|
||||||
|
|
||||||
|
await logger.info(`Applied default delay profile to ${name}`, {
|
||||||
|
source: 'arr/new',
|
||||||
|
meta: { id, type, profile: defaultProfile }
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// Log but don't fail - the instance was created successfully
|
||||||
|
await logger.warn(`Failed to apply default delay profile to ${name}`, {
|
||||||
|
source: 'arr/new',
|
||||||
|
meta: { id, type, error: error instanceof Error ? error.message : error }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await logger.error('Failed to create arr instance', {
|
await logger.error('Failed to create arr instance', {
|
||||||
source: 'arr/new',
|
source: 'arr/new',
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { logSettingsQueries } from '$db/queries/logSettings.ts';
|
|||||||
import { backupSettingsQueries } from '$db/queries/backupSettings.ts';
|
import { backupSettingsQueries } from '$db/queries/backupSettings.ts';
|
||||||
import { aiSettingsQueries } from '$db/queries/aiSettings.ts';
|
import { aiSettingsQueries } from '$db/queries/aiSettings.ts';
|
||||||
import { tmdbSettingsQueries } from '$db/queries/tmdbSettings.ts';
|
import { tmdbSettingsQueries } from '$db/queries/tmdbSettings.ts';
|
||||||
|
import { generalSettingsQueries } from '$db/queries/generalSettings.ts';
|
||||||
import { logSettings } from '$logger/settings.ts';
|
import { logSettings } from '$logger/settings.ts';
|
||||||
import { logger } from '$logger/logger.ts';
|
import { logger } from '$logger/logger.ts';
|
||||||
|
|
||||||
@@ -12,6 +13,7 @@ export const load = () => {
|
|||||||
const backupSetting = backupSettingsQueries.get();
|
const backupSetting = backupSettingsQueries.get();
|
||||||
const aiSetting = aiSettingsQueries.get();
|
const aiSetting = aiSettingsQueries.get();
|
||||||
const tmdbSetting = tmdbSettingsQueries.get();
|
const tmdbSetting = tmdbSettingsQueries.get();
|
||||||
|
const generalSetting = generalSettingsQueries.get();
|
||||||
|
|
||||||
if (!logSetting) {
|
if (!logSetting) {
|
||||||
throw new Error('Log settings not found in database');
|
throw new Error('Log settings not found in database');
|
||||||
@@ -29,6 +31,10 @@ export const load = () => {
|
|||||||
throw new Error('TMDB settings not found in database');
|
throw new Error('TMDB settings not found in database');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!generalSetting) {
|
||||||
|
throw new Error('General settings not found in database');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
logSettings: {
|
logSettings: {
|
||||||
retention_days: logSetting.retention_days,
|
retention_days: logSetting.retention_days,
|
||||||
@@ -52,6 +58,9 @@ export const load = () => {
|
|||||||
},
|
},
|
||||||
tmdbSettings: {
|
tmdbSettings: {
|
||||||
api_key: tmdbSetting.api_key
|
api_key: tmdbSetting.api_key
|
||||||
|
},
|
||||||
|
generalSettings: {
|
||||||
|
apply_default_delay_profiles: generalSetting.apply_default_delay_profiles === 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -243,6 +252,32 @@ export const actions: Actions = {
|
|||||||
source: 'settings/general'
|
source: 'settings/general'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
},
|
||||||
|
|
||||||
|
updateArrDefaults: async ({ request }: RequestEvent) => {
|
||||||
|
const formData = await request.formData();
|
||||||
|
|
||||||
|
// Parse form data
|
||||||
|
const applyDefaultDelayProfiles = formData.get('apply_default_delay_profiles') === 'on';
|
||||||
|
|
||||||
|
// Update settings
|
||||||
|
const updated = generalSettingsQueries.update({
|
||||||
|
applyDefaultDelayProfiles
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!updated) {
|
||||||
|
await logger.error('Failed to update arr default settings', {
|
||||||
|
source: 'settings/general'
|
||||||
|
});
|
||||||
|
return fail(500, { error: 'Failed to update settings' });
|
||||||
|
}
|
||||||
|
|
||||||
|
await logger.info('Arr default settings updated', {
|
||||||
|
source: 'settings/general',
|
||||||
|
meta: { applyDefaultDelayProfiles }
|
||||||
|
});
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import AISettings from './components/AISettings.svelte';
|
import AISettings from './components/AISettings.svelte';
|
||||||
import TMDBSettings from './components/TMDBSettings.svelte';
|
import TMDBSettings from './components/TMDBSettings.svelte';
|
||||||
import UISettings from './components/UISettings.svelte';
|
import UISettings from './components/UISettings.svelte';
|
||||||
|
import ArrDefaultsSettings from './components/ArrDefaultsSettings.svelte';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
@@ -21,6 +22,9 @@
|
|||||||
<!-- UI Preferences -->
|
<!-- UI Preferences -->
|
||||||
<UISettings />
|
<UISettings />
|
||||||
|
|
||||||
|
<!-- Arr Instance Defaults -->
|
||||||
|
<ArrDefaultsSettings settings={data.generalSettings} />
|
||||||
|
|
||||||
<!-- Backup Configuration -->
|
<!-- Backup Configuration -->
|
||||||
<BackupSettings settings={data.backupSettings} />
|
<BackupSettings settings={data.backupSettings} />
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { enhance } from '$app/forms';
|
||||||
|
import { alertStore } from '$alerts/store';
|
||||||
|
import { Save, Check } from 'lucide-svelte';
|
||||||
|
import IconCheckbox from '$ui/form/IconCheckbox.svelte';
|
||||||
|
import type { GeneralSettings } from './types';
|
||||||
|
|
||||||
|
export let settings: GeneralSettings;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="rounded-lg border border-neutral-200 bg-white dark:border-neutral-800 dark:bg-neutral-900"
|
||||||
|
>
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="border-b border-neutral-200 px-6 py-4 dark:border-neutral-800">
|
||||||
|
<h2 class="text-xl font-semibold text-neutral-900 dark:text-neutral-50">
|
||||||
|
Arr Instance Defaults
|
||||||
|
</h2>
|
||||||
|
<p class="mt-1 text-sm text-neutral-600 dark:text-neutral-400">
|
||||||
|
Configure default settings applied when adding new Radarr/Sonarr instances
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Form -->
|
||||||
|
<form
|
||||||
|
method="POST"
|
||||||
|
action="?/updateArrDefaults"
|
||||||
|
class="p-6"
|
||||||
|
use:enhance={() => {
|
||||||
|
return async ({ result, update }) => {
|
||||||
|
if (result.type === 'failure' && result.data) {
|
||||||
|
alertStore.add('error', (result.data as { error?: string }).error || 'Failed to save');
|
||||||
|
} else if (result.type === 'success') {
|
||||||
|
alertStore.add('success', 'Arr default settings saved successfully!');
|
||||||
|
}
|
||||||
|
await update();
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="space-y-6">
|
||||||
|
<!-- Delay Profile Defaults -->
|
||||||
|
<div class="space-y-3">
|
||||||
|
<h3 class="text-sm font-semibold text-neutral-900 dark:text-neutral-50">Delay Profiles</h3>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<IconCheckbox
|
||||||
|
icon={Check}
|
||||||
|
checked={settings.apply_default_delay_profiles}
|
||||||
|
on:click={() =>
|
||||||
|
(settings.apply_default_delay_profiles = !settings.apply_default_delay_profiles)}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="apply_default_delay_profiles"
|
||||||
|
value={settings.apply_default_delay_profiles ? 'on' : ''}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="flex-1 text-left"
|
||||||
|
on:click={() =>
|
||||||
|
(settings.apply_default_delay_profiles = !settings.apply_default_delay_profiles)}
|
||||||
|
>
|
||||||
|
<span class="text-sm font-medium text-neutral-900 dark:text-neutral-50">
|
||||||
|
Apply Default Delay Profile
|
||||||
|
</span>
|
||||||
|
<p class="text-xs text-neutral-500 dark:text-neutral-400">
|
||||||
|
Automatically configure the default delay profile when adding new arr instances
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="flex justify-end gap-3 border-t border-neutral-200 pt-6 dark:border-neutral-800">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="flex items-center gap-2 rounded-lg bg-accent-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-700 dark:bg-accent-500 dark:hover:bg-accent-600"
|
||||||
|
>
|
||||||
|
<Save size={16} />
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -28,3 +28,7 @@ export interface AISettings {
|
|||||||
export interface TMDBSettings {
|
export interface TMDBSettings {
|
||||||
api_key: string;
|
api_key: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GeneralSettings {
|
||||||
|
apply_default_delay_profiles: boolean;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user