Skip to content

Commit

Permalink
Add kavita add config command
Browse files Browse the repository at this point in the history
  • Loading branch information
l7ssha committed Nov 13, 2024
1 parent 8249ecb commit 25d3972
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 16 deletions.
45 changes: 35 additions & 10 deletions lib/src/checks.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:injector/injector.dart';
import 'package:nyxx/nyxx.dart';
import 'package:nyxx_commands/nyxx_commands.dart';
Expand All @@ -11,24 +13,31 @@ const jellyfinFeatureEnabledCheckName = 'jellyfinFeatureEnabledCheck';
final administratorCheck = UserCheck.anyId(adminIds, name: 'Administrator check');
final administratorGuildCheck = GuildCheck.id(adminGuildId, name: 'Administrator Guild check');

final jellyfinFeatureEnabledCheck = Check(
(CommandContext context) {
if (context.guild == null) {
return true;
}
FutureOr<bool> _checkForSetting(Setting setting, CommandContext context) {
if (context.guild == null) {
return true;
}

return Injector.appInstance.get<FeatureSettingsService>().isEnabled(Setting.jellyfin, context.guild!.id);
},
return Injector.appInstance.get<FeatureSettingsService>().isEnabled(Setting.jellyfin, context.guild!.id);
}

final kavitaJellyfinCheck = Check(
(CommandContext context) => _checkForSetting(Setting.kavita, context),
name: jellyfinFeatureEnabledCheckName,
);

Future<(bool?, FeatureSetting?)> fetchAndCheckSetting(CommandContext context) async {
final jellyfinFeatureEnabledCheck = Check(
(CommandContext context) => _checkForSetting(Setting.jellyfin, context),
name: jellyfinFeatureEnabledCheckName,
);

Future<(bool?, FeatureSetting?)> fetchAndCheckSetting(CommandContext context, Setting settingToCheck) async {
if (context.guild == null) {
return (true, null);
}

final setting =
await Injector.appInstance.get<FeatureSettingsRepository>().fetchSetting(Setting.jellyfin, context.guild!.id);
await Injector.appInstance.get<FeatureSettingsRepository>().fetchSetting(settingToCheck, context.guild!.id);
if (setting == null) {
return (false, null);
}
Expand All @@ -42,7 +51,23 @@ Future<(bool?, FeatureSetting?)> fetchAndCheckSetting(CommandContext context) as

final jellyfinFeatureCreateInstanceCommandCheck = Check(
(CommandContext context) async {
final (checkResult, setting) = await fetchAndCheckSetting(context);
final (checkResult, setting) = await fetchAndCheckSetting(context, Setting.jellyfin);
if (checkResult != null) {
return checkResult;
}

if (context.member?.permissions?.isAdministrator ?? false) {
return true;
}

final roleId = Snowflake.parse(setting!.dataAsJson!['create_instance_role']);
return context.member!.roleIds.contains(roleId);
},
);

final kavitaFeatureCreateInstanceCommandCheck = Check(
(CommandContext context) async {
final (checkResult, setting) = await fetchAndCheckSetting(context, Setting.kavita);
if (checkResult != null) {
return checkResult;
}
Expand Down
48 changes: 44 additions & 4 deletions lib/src/commands/kavita.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import 'package:injector/injector.dart';
import 'package:nyxx/nyxx.dart';
import 'package:nyxx_commands/nyxx_commands.dart';
import 'package:nyxx_extensions/nyxx_extensions.dart';
import 'package:running_on_dart/src/checks.dart';
import 'package:running_on_dart/src/models/kavita.dart';
import 'package:running_on_dart/src/modules/kavita.dart';
import 'package:running_on_dart/src/repository/kavita.dart';
import 'package:running_on_dart/src/util/kavita.dart';
import 'package:running_on_dart/src/util/util.dart';

Expand All @@ -18,15 +20,47 @@ Future<AuthenticatedKavitaClient> getKavitaClient(KavitaUserConfig? config, Chat
return Injector.appInstance.get<KavitaModule>().createAuthenticatedClient(config);
}

final kavita = ChatGroup('kavita', 'Kavita related commands', children: [
final kavita = ChatGroup('kavita', 'Kavita related commands', checks: [
kavitaJellyfinCheck,
], children: [
ChatGroup(
'settings',
'Settings for Kavita',
children: [
ChatCommand(
'add-instance',
'Add new kavita instance',
id('kavita-settings-add-instance', (InteractionChatContext context) async {
final modalResponse = await context.getModal(title: "New Instance Configuration", components: [
TextInputBuilder(customId: "name", style: TextInputStyle.short, label: "Instance Name", isRequired: true),
TextInputBuilder(customId: "base_url", style: TextInputStyle.short, label: "Base Url", isRequired: true),
TextInputBuilder(customId: "is_default", style: TextInputStyle.short, label: "Is Default (True/False)"),
]);

final newlyCreatedConfig = await Injector.appInstance.get<KavitaRepository>().saveConfig(
KavitaConfig(
name: modalResponse['name']!,
basePath: modalResponse['base_url']!,
isDefault: modalResponse['is_default']?.toLowerCase() == 'true',
parentId: getParentIdFromContext(context),
),
);

modalResponse
.respond(MessageBuilder(content: "Added new jellyfin instance with name: ${newlyCreatedConfig.name}"));
}),
checks: [kavitaFeatureCreateInstanceCommandCheck]),
],
),
ChatGroup(
'user',
'User related kavita commands',
children: [
ChatCommand(
"login",
"Login user into given kavita instance",
id('kavita-user-login', (InteractionChatContext context, KavitaConfig config) async {
id('kavita-user-login',
(InteractionChatContext context, @Description('Kavita instance to be used') KavitaConfig config) async {
final kavitaModule = Injector.appInstance.get<KavitaModule>();

final modalResult = await context.getModal(title: "Login to Kavita", components: [
Expand All @@ -48,7 +82,8 @@ final kavita = ChatGroup('kavita', 'Kavita related commands', children: [
ChatCommand(
'search',
'Search kavita library',
id('kavita-test', (ChatContext context, String query, [KavitaUserConfig? config]) async {
id('kavita-test', (ChatContext context, @Description('Query string to search content with') String query,
[@Description('Kavita instance to be used. Default if not provided') KavitaUserConfig? config]) async {
final client = await getKavitaClient(config, context);

final items = await client.searchSeries(query);
Expand All @@ -60,10 +95,15 @@ final kavita = ChatGroup('kavita', 'Kavita related commands', children: [
'read',
'Read series',
id('kavita-read', (ChatContext context, int seriesId,
[bool saveReadProgress = true, KavitaUserConfig? config]) async {
[@Description('Whether save reading progress to kavita') bool saveReadProgress = true,
@Description('Kavita instance to be used. Default if not provided') KavitaUserConfig? config]) async {
final client = await getKavitaClient(config, context);

final continuePoint = await client.getContinuePoint(seriesId);
if (continuePoint.isBook) {
return context.respond(MessageBuilder(content: "Books are not currently supported."));
}

final paginator = await pagination.factories(
await generateReadingPaginationFactories(continuePoint, client, seriesId, saveReadProgress).toList(),
startIndex: continuePoint.pagesRead,
Expand Down
3 changes: 2 additions & 1 deletion lib/src/models/feature_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ enum Setting {
joinLogs('join_logs', 'Logs member join events into specified channel', true, DataType.channelMention),
modLogs('mod_logs', 'Logs administration event into specified channel', true, DataType.channelMention),
jellyfin('jellyfin', 'Allows usage of jellyfin commands', true, DataType.json),
mentions('mentions', 'Monitors messages for mention abuse', false);
mentions('mentions', 'Monitors messages for mention abuse', false),
kavita('kavita', 'Allows usage of jellyfin command', true, DataType.json);

/// name of setting
final String name;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/modules/kavita.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class AuthenticatedKavitaClient {

Future<String> getBookPage(int chapterId, int page) async {
final result =
await _get("/api/Book/$chapterId/book-page", parameters: {"page": page.toString()}, authApiKey: true);
await _get("/api/Book/$chapterId/book-page", parameters: {"page": page.toString()}, authApiKey: true);

return result.body;
}
Expand Down
19 changes: 19 additions & 0 deletions lib/src/repository/kavita.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ class KavitaRepository {
return KavitaUserConfig.fromDatabaseRowWithConfig(result.first.toColumnMap());
}

Future<KavitaConfig> saveConfig(KavitaConfig config) async {
final query = InsertQuery(KavitaConfig.tableName)
..addNamedInsert('name')
..addNamedInsert('base_path')
..addNamedInsert('is_default')
..addNamedInsert('parent_id')
..addReturning('id');

final result = await _database.executeQuery(query, parameters: {
'name': config.name,
'base_path': config.basePath,
'is_default': config.isDefault,
'parent_id': config.parentId.toString(),
});

config.id = result.first.first as int;
return config;
}

Future<KavitaUserConfig> saveUserConfig(KavitaUserConfig userConfig) async {
final query = InsertQuery(KavitaUserConfig.tableName)
..addNamedInsert("user_id")
Expand Down

0 comments on commit 25d3972

Please sign in to comment.