This commit is contained in:
Minecon724 2025-06-14 15:55:21 +02:00
commit 60a0b8e582
Signed by: Minecon724
GPG key ID: A02E6E67AB961189
6 changed files with 30 additions and 25 deletions

View file

@ -0,0 +1,14 @@
This program exports user data from a Postgres database to an Invidious-importable JSON.
```
usage: invidious-exporter [-h] -u USERNAME -d DATABASE
This program exports user data from a Postgres database to an Invidious-importable JSON. Output is written to stdout.
options:
-h, --help show this help message and exit
-u, --username USERNAME
The user to export
-d, --database DATABASE
The database connection string
```

View file

@ -15,7 +15,7 @@ dependencies = [
packages = [{include = "invidious_exporter", from = "src"}]
[tool.poetry.scripts]
export = "invidious_exporter.__init__:main"
export = "invidious_exporter:main"
[build-system]

View file

@ -1,31 +1,22 @@
import psycopg
import json
from argparse import ArgumentParser
from os import makedirs, path
from . import database
def export_user_to_file(connection_string: str, user_email: str, output_filename: str):
with psycopg.connect(connection_string, row_factory = psycopg.rows.namedtuple_row) as conn:
with conn.cursor() as cur:
data_export = database.export_user(cur, user_email)
export_dict = data_export.to_dict()
with open(output_filename, 'w') as file:
file.write(json.dumps(export_dict))
print("Saved to " + output_filename)
def main():
parser = ArgumentParser(
prog='invidious-exporter',
description='This program exports user data to an Invidious-importable .json from a database')
description='This program exports user data from a Postgres database to an Invidious-importable JSON. Output is written to stdout.')
parser.add_argument('username', help="The user to export")
parser.add_argument('-d', '--database', required=True, default="The database connection string")
parser.add_argument('-o', '--output', required=False, help="The output .json file")
parser.add_argument('-u', '--username', required=True, help="The user to export")
parser.add_argument('-d', '--database', required=True, help="The database connection string")
args = parser.parse_args()
export_user_to_file(args.database, args.username, args.output if args.output is not None else args.username + '.json')
with psycopg.connect(args.database, row_factory = psycopg.rows.namedtuple_row) as conn:
with conn.cursor() as cur:
data_export = database.export_user(cur, args.username)
print(data_export.to_dict(), end='')

View file

@ -1,6 +1,6 @@
from psycopg import Cursor
from .objects import Channel, Video, Playlist, PlaylistPrivacy, DataExport
from .objects import Channel, Video, Playlist, PlaylistPrivacy, InvidiousJsonDataExport
import json
@ -33,7 +33,7 @@ def get_playlists(cur: Cursor, user_email: str) -> list[Playlist]:
for row in cur.fetchall()
]
def export_user(cur: Cursor, user_email: str) -> DataExport:
def export_user(cur: Cursor, user_email: str) -> InvidiousJsonDataExport:
cur.execute("SELECT subscriptions, watched, preferences FROM users WHERE email = %s", (user_email,))
data = cur.fetchone()
@ -43,7 +43,7 @@ def export_user(cur: Cursor, user_email: str) -> DataExport:
playlists = get_playlists(cur, user_email)
data_export = DataExport(
data_export = InvidiousJsonDataExport(
subscriptions = [Channel(id=c_id) for c_id in subscribed_channels_ids],
watch_history = [Video(id=v_id) for v_id in watched_videos_ids],
playlists = playlists,

View file

@ -1,6 +1,6 @@
from .channel import Channel
from .video import Video
from .playlist import Playlist, PlaylistPrivacy
from .data_export import DataExport
from .export import InvidiousJsonDataExport
__all__ = [Channel, Video, Playlist, PlaylistPrivacy, DataExport]
__all__ = [Channel, Video, Playlist, PlaylistPrivacy, InvidiousJsonDataExport]

View file

@ -3,7 +3,7 @@ from dataclasses import dataclass
from . import Channel, Video, Playlist
@dataclass
class DataExport:
class InvidiousJsonDataExport:
subscriptions: list[Channel]
watch_history: list[Video]
playlists: list[Playlist]