From a20b0b27a8aed105a89f94fcb5925e8ebe91a3c6 Mon Sep 17 00:00:00 2001 From: Ludwig Lehnert Date: Thu, 11 Jul 2024 23:11:00 +0200 Subject: [PATCH] some small improvements --- README.md | 17 +++++++++++++-- dl | 35 ++++++++++++++++++++++-------- lib.py | 65 ++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 81 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 0c63c26..ca7cefc 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,22 @@ This software is provided without warranty. Usage is discouraged! Usage of this ## Usage ```bash -./dl '' '[output directory]' '[starter url]' +usage: dl [-h] [--outDir OUTDIR] [--starterUrl STARTERURL] + [--startAt STARTAT] + courseId + +Download clips from a course + +positional arguments: + courseId Course ID + +options: + -h, --help show this help message and exit + --outDir OUTDIR Output directory + --starterUrl STARTERURL Starter URL + --startAt STARTAT Skip all previous indizes (starts at 1) ``` -# Procedure +## Procedure Upon starting, a firefox instance is opened, prompting you to log in using IDM SSO. As soon as the url changes to something starting with `https://www.fau.tv`, download will be starting. If you do not want to provide your credentials, you can provide `https://www.fau.tv` as a starter url. diff --git a/dl b/dl index 159db9b..9546d0d 100755 --- a/dl +++ b/dl @@ -1,21 +1,38 @@ #!/usr/bin/env python3 -from .lib import * +from lib import * import sys import os +import argparse + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Download clips from a course', + ) + + parser.add_argument('courseId', type=str, help='Course ID') + parser.add_argument('--outDir', type=str, + help='Output directory', default='./out') + parser.add_argument('--starterUrl', type=str, + help='Starter URL', default="https://www.fau.tv/auth/sso") + parser.add_argument('--startAt', type=int, + help='Skip all previous indizes (starts at 1)', default=1) + + return parser.parse_args() def main(): - course_id = sys.argv[1] - out_dir = sys.argv[2] if len(sys.argv) >= 3 else './out' - auth_url = sys.argv[3] if len(sys.argv) >= 4 else None + args = parse_args() - load_token(auth_url) if auth_url is not None else load_token() + load_token(args.starterUrl) - os.makedirs(out_dir, exist_ok=True) + os.makedirs(args.outDir, exist_ok=True) - for index, clip_id in enumerate(get_course_clip_ids(course_id)): - print(f'downloading clip {clip_id}') - download_clip(clip_id, f'{out_dir}/{index+1: 04d}_{clip_id}.mp4') + for index, clip_id in enumerate(get_course_clip_ids(args.courseId)): + if index < args.startAt - 1: + continue + + download_clip(clip_id, f'{args.outDir}/{index+1: 04d}_{clip_id}.mp4') if __name__ == '__main__': diff --git a/lib.py b/lib.py index 646f3f1..b954f84 100644 --- a/lib.py +++ b/lib.py @@ -17,15 +17,24 @@ class Token(): session_ci: str def cookies(self): - return { - "SimpleSAMLAuthToken": self.auth_token, - "SimpleSAMLSessionID": self.session_id, - "session_ci": self.session_ci, - } + cookies = {} + + if self.auth_token is not None: + cookies["SimpleSAMLAuthToken"] = self.auth_token + + if self.session_id is not None: + cookies["SimpleSAMLSessionID"] = self.session_id + + if self.session_ci is not None: + cookies["session_ci"] = self.session_ci + + return cookies @dataclass class ClipDetails(): + clip_id: str + combined_media_id: str = None combined_playlist_url: str = None camera_media_id: str = None @@ -33,8 +42,22 @@ class ClipDetails(): slides_media_id: str = None slides_playlist_url: str = None + def media_ids(self): + return [id for id in [ + self.combined_media_id, + self.camera_media_id, + self.slides_media_id, + ] if id is not None] -def load_token(auth_url: str = "https://www.fau.tv/auth/sso"): + def playlist_urls(self): + return [url for url in [ + self.combined_playlist_url, + self.camera_playlist_url, + self.slides_playlist_url, + ] if url is not None] + + +def load_token(auth_url: str): global _token driver = webdriver.Firefox() @@ -55,8 +78,6 @@ def load_token(auth_url: str = "https://www.fau.tv/auth/sso"): session_ci=get_value(driver.get_cookie("session_ci")), ) - print(_token) - driver.close() @@ -80,7 +101,7 @@ def get_clip_details(clip_id: str) -> ClipDetails: global _token url = f'https://www.fau.tv/clip/id/{clip_id}' - details = ClipDetails() + details = ClipDetails(clip_id=clip_id) with requests.get(url, cookies=_token.cookies()) as r: def get_details(keyword: str): @@ -130,25 +151,19 @@ def download_playlist(playlist_url: str, outfile_path: str): '-i', playlist_url, '-c', 'copy', outfile_path, - ]) + ], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) def download_clip(clip_id: str, outfile_path: str): details = get_clip_details(clip_id) - media_id = next(id for id in [ - details.combined_media_id, - details.camera_media_id, - details.slides_media_id, - ] if id is not None) + if len(details.media_ids()) > 0: + media_id = details.media_ids()[0] + print(f"Trying to download clip {clip_id} using media id {media_id}") + if download_media(media_id, outfile_path): + return - if download_media(media_id, outfile_path): - return - - url = next(url for url in [ - details.combined_playlist_url, - details.camera_playlist_url, - details.slides_playlist_url, - ] if url is not None) - - download_playlist(url, outfile_path) + if len(details.playlist_urls()) > 0: + playlist_url = details.playlist_urls()[0] + print(f"Trying to download clip {clip_id} using playlist url {playlist_url}") + download_playlist(playlist_url, outfile_path)