- Neuer Befehl `manage.py import_antennapod <backup.db> --user <name> [--dry-run] [--global-auto-download on|off] [--backup-date ...]`: übernimmt aus einer AntennaPod-Datenbanksicherung die Abos (Abgleich über normalisierte URL, fehlende werden angelegt, lokale übersprungen), die Podcast-Einstellungen (Tempo, Intro/Outro, Lautstärke, Filter mit Phrasen in Anführungszeichen, Mindestlänge, neue Folgen, „nicht aktualisieren“ -> ignorieren, automatischer Download), den Zustand jeder Folge mit Zustand (gehört, neu, Position, Favorit, Zeitpunkt), die Warteschlange (AntennaPods Reihenfolge zuerst) und nimmt bekannte, dort nicht neue Folgen aus „Neu“. Neuere Änderungen in diora bleiben, Favoriten werden vereinigt. Alles in einer Transaktion; ein zweiter Lauf ändert nichts mehr. - PodcastFeed.auto_download (Einstellung pro Podcast, in feeds/, state/ und feeds/<id>/settings/) und PodcastSettings.auto_download_default (in settings/ und state/), mit dem neue Abos (Hinzufügen, OPML, gpodder, Import) starten. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
2.8 KiB
Python
56 lines
2.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. '
|
|
'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('--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).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)
|