From 906f5d4a58bb9aa06ab451c87c031968188b3eba Mon Sep 17 00:00:00 2001 From: nyakokitsu <140620899+nyakokitsu@users.noreply.github.com> Date: Mon, 1 Jan 2024 22:54:57 +0300 Subject: [PATCH] v0.0.1 --- .github/dependabot.yaml | 4 +- README.md | 6 +- lib/src/commands/kodik_command.dart | 89 +++++++++++++++------- pubspec.yaml | 1 + test/src/commands/sample_command_test.dart | 58 -------------- 5 files changed, 69 insertions(+), 89 deletions(-) delete mode 100644 test/src/commands/sample_command_test.dart diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 63b035c..4c36e3c 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -4,8 +4,8 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "daily" + interval: "weekly" - package-ecosystem: "pub" directory: "/" schedule: - interval: "daily" + interval: "weekly" diff --git a/README.md b/README.md index 569fbbc..851f491 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,13 @@ Or locally via: dart pub global activate --source=path ``` +Also you can use portable version in Releases page. + ## Usage ```sh -# Sample command -$ maco sample +# Parse direct mp4 url for kodik player. +$ maco kodik -u //kodik.info/seria/428055/cf7b8847a36a6904743111e46c2b77d1/720p # Sample command option $ maco sample --cyan diff --git a/lib/src/commands/kodik_command.dart b/lib/src/commands/kodik_command.dart index d302cc3..3a9a12d 100644 --- a/lib/src/commands/kodik_command.dart +++ b/lib/src/commands/kodik_command.dart @@ -1,8 +1,9 @@ import 'package:args/command_runner.dart'; +// ignore: depend_on_referenced_packages +import 'package:dio/dio.dart'; +import 'package:libanime/libanime.dart'; import 'package:libanime/structures/video.dart'; import 'package:mason_logger/mason_logger.dart'; -import 'package:libanime/libanime.dart'; -import 'package:dio/dio.dart'; /// @@ -18,13 +19,23 @@ class KodikCommand extends Command { ..addOption( 'url', abbr: 'u', - help: 'Url to player for download', + help: 'Player Url', + ) + ..addOption( + 'path', + abbr: 'p', + help: 'Path for downloading. (Default ./video.mp4)', + ) + ..addFlag( + 'info', + abbr: 'i', + help: 'Log additional anime info', ) ..addFlag( 'download', abbr: 'd', - help: 'Automaticly download into current directory.', - negatable: false + help: 'Download video. Use path option for downloading path change.', + negatable: false, ) ..addOption( 'token', @@ -40,48 +51,72 @@ class KodikCommand extends Command { String get name => 'kodik'; final Logger _logger; + final dio = Dio(); @override Future run() async { - final token = "b7cc4293ed475c4ad1fd599d114f4435"; - if (argResults?.wasParsed("url") == false) { - _logger.err(lightRed.wrap("Url param cannot be null.")!); + final url = argResults!['url'].toString().startsWith('//') ? 'https:${argResults!['url']}' : argResults!['url'].toString(); + dynamic token = 'b7cc4293ed475c4ad1fd599d114f4435'; + if (argResults?.wasParsed('url') == false) { + _logger.err(lightRed.wrap('Url option cannot be null.')); return ExitCode.noInput.code; } - if (argResults?.wasParsed("token") == false) { - _logger.info(cyan.wrap("Token not set using default.")!); + if (argResults?.wasParsed('token') == false) { + _logger.info(cyan.wrap('Token not set using default.')); + } else { + token = argResults!['token']; } - final kodik = Kodik(token); + final kodik = Kodik(token.toString()); Map? links = {}; - final progress = _logger.progress("Begging video extracing."); + final progress = _logger.progress('Begging video extracing.'); try { - links = await kodik.parse(argResults!['url'].toString(), true); + links = await kodik.parse(url, true); } on Exception { - progress.fail("An error occurred"); - _logger.err(lightRed.wrap("Link decode error!")); + progress.fail('An error occurred'); + _logger.err(lightRed.wrap('Link decode error!')); return ExitCode.unavailable.code; } + progress.complete('Fetching complete!'); + // ignore: use_if_null_to_convert_nulls_to_bools + if (argResults?.wasParsed('info') == true) { + dynamic info; + try { + // ignore: inference_failure_on_function_invocation + final infoRq = await dio.get('https://kodikapi.com/search?token=$token&player_link=$url'); + // ignore: avoid_dynamic_calls + info = infoRq.data['results'][0]; + } on DioException { + progress.fail('An error occurred'); + _logger.err(lightRed.wrap('Info requesting error')); + return ExitCode.unavailable.code; + } - progress.complete("Fetching complete!"); + + // ignore: avoid_dynamic_calls, lines_longer_than_80_chars + _logger.info('\n${styleBold.wrap('Title Original')}: ${info!["title_orig"]}\n${styleBold.wrap('Title RU')}: ${info!["title"]}\n${styleBold.wrap('Release Year')}: ${info!["year"]}\n${styleBold.wrap('Translator Name')}: ${info!["translation"]["title"]}\n${styleBold.wrap('Shikimori')}: https://shikimori.one/animes/${info!["shikimori_id"]}\n'); + } final quality = _logger.chooseOne( 'Choose quality:', choices: ['360', '480', '720'], defaultValue: '480', ); - final url = links![quality]?.url; - _logger.info(url); - if (argResults?["download"] == true) { - final dio = Dio(); - final downloadProgress = _logger.progress("Starting downloading."); + final mp4Url = links![quality]?.url; + _logger.info(mp4Url); + if (argResults?['download'] == true) { + + var path = './video.mp4'; + // ignore: use_if_null_to_convert_nulls_to_bools + if (argResults?.wasParsed('path') == true) { + path = argResults!['path'].toString(); + } + final downloadProgress = _logger.progress('Downloading.'); try { - final path = "" + "video.mp4"; - await dio.download(url!, path); + await dio.download(mp4Url!, path); } catch (e) { - downloadProgress.fail("An error occurred while downloading"); - } finally { - downloadProgress.complete("Downloaded at ${path}") + downloadProgress.fail('An error occurred while downloading'); + _logger.detail('Error: $e'); } - + downloadProgress.complete('Downloaded at $path'); } return ExitCode.success.code; diff --git a/pubspec.yaml b/pubspec.yaml index 3552bf0..03fb1f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,6 +22,7 @@ dependencies: libanime: ^0.0.8 mason_logger: ^0.2.5 path_provider: ^2.1.1 + platform: ^3.1.3 pub_updater: ^0.3.1 dev_dependencies: diff --git a/test/src/commands/sample_command_test.dart b/test/src/commands/sample_command_test.dart deleted file mode 100644 index d8b803e..0000000 --- a/test/src/commands/sample_command_test.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:mason_logger/mason_logger.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:maco/src/command_runner.dart'; -import 'package:test/test.dart'; - -class _MockLogger extends Mock implements Logger {} - -void main() { - group('sample', () { - late Logger logger; - late MacoCommandRunner commandRunner; - - setUp(() { - logger = _MockLogger(); - commandRunner = MacoCommandRunner(logger: logger); - }); - - test('tells a joke', () async { - final exitCode = await commandRunner.run(['sample']); - - expect(exitCode, ExitCode.success.code); - - verify( - () => logger.info('Which unicorn has a cold? The Achoo-nicorn!'), - ).called(1); - }); - test('tells a joke in cyan', () async { - final exitCode = await commandRunner.run(['sample', '-c']); - - expect(exitCode, ExitCode.success.code); - - verify( - () => logger.info( - lightCyan.wrap('Which unicorn has a cold? The Achoo-nicorn!'), - ), - ).called(1); - }); - - test('wrong usage', () async { - final exitCode = await commandRunner.run(['sample', '-p']); - - expect(exitCode, ExitCode.usage.code); - - verify(() => logger.err('Could not find an option or flag "-p".')) - .called(1); - verify( - () => logger.info( - ''' -Usage: $executableName sample [arguments] --h, --help Print this usage information. --c, --cyan Prints the same joke, but in cyan - -Run "$executableName help" to see global options.''', - ), - ).called(1); - }); - }); -}