--replace bestellt Podcasts ab, die das Backup nicht hat, behält nur AntennaPods Warteschlange und lässt AntennaPod auch über spätere Änderungen in diora gewinnen. Die Oberfläche bringt den gemeinsamen Player und die Download-Übersicht (nur in der App sichtbar). sw v54. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
3.8 KiB
Python
68 lines
3.8 KiB
Python
import os
|
|
from datetime import datetime, timezone as dt_timezone
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.core.management.base import BaseCommand, CommandError
|
|
from django.utils.dateparse import parse_datetime
|
|
|
|
from podcasts.antennapod import AntennaPodImport, AntennaPodImportError, summary_lines
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = (
|
|
"Import an AntennaPod database backup (Settings > Database > Export) into one user's podcasts: "
|
|
'subscriptions with their settings, played/new/started episodes, favourites and the queue; '
|
|
'the episodes downloaded in AntennaPod are offered to the app for download. '
|
|
'Feeds it creates are fetched by the next refresh; running the import once more after that '
|
|
'also takes their older episodes that were not new in AntennaPod out of the inbox. '
|
|
'Running it twice changes nothing more.'
|
|
)
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument('path', help='AntennaPod backup (.db)')
|
|
parser.add_argument('--user', required=True, help='diora username')
|
|
parser.add_argument('--dry-run', action='store_true',
|
|
help='Do everything inside a transaction that is rolled back, print the summary')
|
|
parser.add_argument('--global-auto-download', choices=('on', 'off'), default='off',
|
|
help="Auto-download for feeds that use AntennaPod's global setting (default off)")
|
|
parser.add_argument('--replace', action='store_true',
|
|
help="A clean slate: unsubscribe podcasts the backup doesn't have, keep only "
|
|
"AntennaPod's queue, AntennaPod wins over later changes in diora")
|
|
parser.add_argument('--quiet-diora-only', action='store_true',
|
|
help='Podcasts only diora has (not in the backup): their episodes out before the backup '
|
|
'leave the inbox (the subscriptions stay)')
|
|
parser.add_argument('--no-downloads', action='store_true',
|
|
help="Don't offer AntennaPod's downloaded episodes to the app (they stay in AntennaPod)")
|
|
parser.add_argument('--backup-date',
|
|
help='When the backup was made (ISO date/time, UTC if no zone); default: the file date. '
|
|
'diora changes after it win over the backup.')
|
|
|
|
def handle(self, *args, **options):
|
|
path = options['path']
|
|
if not os.path.isfile(path):
|
|
raise CommandError(f'No such file: {path}')
|
|
try:
|
|
user = User.objects.get(username=options['user'])
|
|
except User.DoesNotExist:
|
|
raise CommandError(f"No such user: {options['user']}")
|
|
|
|
if options['backup_date']:
|
|
raw = options['backup_date']
|
|
backup_date = parse_datetime(raw) or parse_datetime(f'{raw}T00:00')
|
|
if backup_date is None:
|
|
raise CommandError(f'Invalid --backup-date: {raw}')
|
|
if backup_date.tzinfo is None:
|
|
backup_date = backup_date.replace(tzinfo=dt_timezone.utc)
|
|
else:
|
|
backup_date = datetime.fromtimestamp(os.path.getmtime(path), tz=dt_timezone.utc)
|
|
|
|
global_auto_download = options['global_auto_download'] == 'on'
|
|
try:
|
|
stats = AntennaPodImport(user, path, backup_date, global_auto_download,
|
|
offer_downloads=not options['no_downloads'],
|
|
quiet_diora_only=options['quiet_diora_only'],
|
|
replace=options['replace']).run(dry_run=options['dry_run'])
|
|
except AntennaPodImportError as e:
|
|
raise CommandError(str(e))
|
|
for line in summary_lines(stats, user.username, path, options['dry_run'], global_auto_download):
|
|
self.stdout.write(line)
|