Files
scientific-surfing/scientific_surfing/cli.py
2025-10-16 15:11:39 +08:00

208 lines
8.6 KiB
Python

"""
Command-line interface for scientific-surfing package.
"""
import argparse
import sys
from scientific_surfing.storage import StorageManager
from scientific_surfing.subscription_manager import SubscriptionManager
from scientific_surfing.corecfg_manager import CoreConfigManager
from scientific_surfing.core_manager import CoreManager
from scientific_surfing.hook_manager import HookManager
def create_parser() -> argparse.ArgumentParser:
"""Create the argument parser."""
parser = argparse.ArgumentParser(
description="Scientific Surfing - CLI for managing clash RSS subscriptions"
)
subparsers = parser.add_subparsers(dest='command', help='Available commands')
# Subscription commands
subscription_parser = subparsers.add_parser('subscription', help='Manage subscriptions')
subscription_subparsers = subscription_parser.add_subparsers(dest='subcommand', help='Subscription operations')
# Add subscription command
add_parser = subscription_subparsers.add_parser('add', help='Add a new subscription')
add_parser.add_argument('name', help='Custom name for the subscription')
add_parser.add_argument('url', help='Clash RSS subscription URL')
# Refresh subscription command
refresh_parser = subscription_subparsers.add_parser('refresh', help='Refresh a subscription')
refresh_parser.add_argument('name', help='Name of the subscription to refresh')
# Delete subscription command (rm)
delete_parser = subscription_subparsers.add_parser('rm', help='Delete a subscription')
delete_parser.add_argument('name', help='Name of the subscription to delete')
# Rename subscription command
rename_parser = subscription_subparsers.add_parser('rename', help='Rename a subscription')
rename_parser.add_argument('name', help='Current name of the subscription')
rename_parser.add_argument('new_name', help='New name for the subscription')
# Activate subscription command
activate_parser = subscription_subparsers.add_parser('activate', help='Activate a subscription')
activate_parser.add_argument('name', help='Name of the subscription to activate')
# List subscriptions command
list_parser = subscription_subparsers.add_parser('list', help='List all subscriptions')
# Storage info command
storage_parser = subscription_subparsers.add_parser('storage', help='Show storage information')
# Core config commands
core_config_parser = subparsers.add_parser('core-config', help='Manage core configuration')
core_config_subparsers = core_config_parser.add_subparsers(dest='core_config_command', help='Configuration operations')
# Import config
import_parser = core_config_subparsers.add_parser('import', help='Import configuration from file')
import_parser.add_argument('source', help='Path to configuration file to import')
# Export config
export_parser = core_config_subparsers.add_parser('export', help='Export configuration to file')
export_parser.add_argument('destination', help='Path to save configuration file')
# Edit config
edit_parser = core_config_subparsers.add_parser('edit', help='Edit configuration with system editor')
# Reset config
reset_parser = core_config_subparsers.add_parser('reset', help='Reset configuration to default values')
# Show config
show_parser = core_config_subparsers.add_parser('show', help='Show current configuration')
# Apply config
apply_parser = core_config_subparsers.add_parser('apply', help='Apply active subscription to generate final config')
# Core commands
core_parser = subparsers.add_parser('core', help='Manage scientific-surfing core components')
core_subparsers = core_parser.add_subparsers(dest='core_command', help='Core operations')
# Update core command
update_parser = core_subparsers.add_parser('update', help='Update scientific-surfing core components')
update_parser.add_argument('--version', help='Specific version to download (e.g., v1.18.5). If not specified, downloads latest')
update_parser.add_argument('--force', action='store_true', help='Force update even if binary already exists')
# Hook commands
hook_parser = subparsers.add_parser('hook', help='Manage hook scripts')
hook_subparsers = hook_parser.add_subparsers(dest='hook_command', help='Hook operations')
# Init hooks command
init_parser = hook_subparsers.add_parser('init', help='Initialize hooks directory with template scripts')
# Show hooks command
list_hooks_parser = hook_subparsers.add_parser('list', help='Show hooks directory location and list scripts')
# Edit hook command
edit_hook_parser = hook_subparsers.add_parser('edit', help='Edit a hook script')
edit_hook_parser.add_argument('script', help='Name of the script to edit')
# Remove hook command
rm_hook_parser = hook_subparsers.add_parser('rm', help='Remove a hook script')
rm_hook_parser.add_argument('script', help='Name of the script to remove')
return parser
def main() -> None:
"""Main CLI entry point."""
parser = create_parser()
args = parser.parse_args()
if not args.command:
parser.print_help()
return
storage = StorageManager()
subscription_manager = SubscriptionManager(storage)
core_config_manager = CoreConfigManager(subscription_manager)
core_manager = CoreManager(core_config_manager)
hook_manager = HookManager(storage)
try:
if args.command == 'subscription':
if not hasattr(args, 'subcommand') or not args.subcommand:
parser.parse_args(['subscription', '--help'])
return
if args.subcommand == 'add':
subscription_manager.add_subscription(args.name, args.url)
elif args.subcommand == 'refresh':
subscription_manager.refresh_subscription(args.name)
elif args.subcommand == 'rm':
subscription_manager.delete_subscription(args.name)
elif args.subcommand == 'rename':
subscription_manager.rename_subscription(args.name, args.new_name)
elif args.subcommand == 'activate':
subscription_manager.activate_subscription(args.name)
elif args.subcommand == 'list':
subscription_manager.list_subscriptions()
elif args.subcommand == 'storage':
subscription_manager.show_storage_info()
else:
parser.parse_args(['subscription', '--help'])
elif args.command == 'core-config':
if not hasattr(args, 'core_config_command') or not args.core_config_command:
parser.parse_args(['core-config', '--help'])
return
if args.core_config_command == 'import':
core_config_manager.import_config(args.source)
elif args.core_config_command == 'export':
core_config_manager.export_config(args.destination)
elif args.core_config_command == 'edit':
core_config_manager.edit_config()
elif args.core_config_command == 'reset':
core_config_manager.reset_config()
elif args.core_config_command == 'show':
core_config_manager.show_config()
elif args.core_config_command == 'apply':
core_config_manager.apply()
else:
parser.parse_args(['core-config', '--help'])
elif args.command == 'core':
if not hasattr(args, 'core_command') or not args.core_command:
parser.parse_args(['core', '--help'])
return
if args.core_command == 'update':
core_manager.update(version=args.version, force=args.force)
else:
parser.parse_args(['core', '--help'])
elif args.command == 'hook':
if not hasattr(args, 'hook_command') or not args.hook_command:
parser.parse_args(['hook', '--help'])
return
if args.hook_command == 'init':
hook_manager.init()
elif args.hook_command == 'list':
hook_manager.list()
elif args.hook_command == 'edit':
hook_manager.edit(args.script)
elif args.hook_command == 'rm':
hook_manager.rm(args.script)
else:
parser.parse_args(['hook', '--help'])
else:
parser.print_help()
except KeyboardInterrupt:
print("\n❌ Operation cancelled by user")
sys.exit(1)
except Exception as e:
print(f"❌ Error: {e}")
raise
sys.exit(1)
if __name__ == '__main__':
main()