~cadence/echo360-downloader

db09c426da224d6d30c92c0227a992f8df1257e9 — Cadence Ember 9 months ago 19c8f3b
First version of working script
1 files changed, 102 insertions(+), 0 deletions(-)

A download.fish
A download.fish => download.fish +102 -0
@@ 0,0 1,102 @@
#!/usr/bin/env fish

# functions

function exists
    count $argv > /dev/null
end

function se
    string sub -- $argv >&2
end

# ---

# preset arguments

set ytdl_executable yt-dlp
set ytdl_args --cookies cookies.txt -c
set download_in_parallel true
set preserve_cookies true

# script input argparse

argparse \
    (fish_opt --short n --long no-parallel --long-only) \
    -- $argv

# organise

if exists $_flag_no_parallel
    set download_in_parallel false
end

# ---

# checking for required arguments

if not exists $argv[1]
    se '[#] Give the echo360 URL ending with the section UUID as argument 1.'
    exit 1
end

# ---

# save original cookies
cp cookies.txt cookies.txt.original; or exit

se 'downloading course page...'
# download course listing (json) and extract lesson data
#       curl -Ss : download silencing all but errors
#       jq : find the list of lessons, and make a (-r for raw output) string consisting of their:
#           - timing (datetime the class was scheduled for)
#           - name (course name and date???)
#           - id (needed for page lookups)
#       while read -d : for each line of this output, split it by semicolon, then assign the fragments to the named variables. execute the following code block (which downloads the lesson). read the next line.
curl -Ss --cookie cookies.txt "$argv[1]/syllabus" | jq '.data | .[] | .lesson.lesson.timing.start + ";" + .lesson.lesson.name + ";" + .lesson.lesson.id' -r | while read -d ';' timing name id
    set name_parts (string split -m 1 / -- $name)
    if test (count $name_parts) = 1
        set folder default_folder
        set name $name_parts[1]
    else
        set folder $name_parts[1]
        set name "$name_parts[1]-$name_parts[2]"
    end
    set output_path "$folder/$timing - $name"
    se "[.] now finding video: $output_path"

    # download classroom page and extract video info
    #       curl -s : download, silencing errors (errors are produced by terminating the pipe to grep early due to -m 1)
    #       grep -F : find line with embedded json data in page
    #       string match : extract embedded json data
    #       tail -1 : select extracted part
    #       string unescape : the embedded json comes in string form. remove the string and unescape things inside
    #       jq : extract json field for video info
    #       string collect : combine everything into a single variable so it can be used with set (see string collect manpage)
    set video_json (curl -s --cookie cookies.txt "https://echo360.org.au/lesson/$id/classroom" | grep -F 'Echo["classroomApp"](' -m 1 | string match -r -e 'Echo\["classroomApp"\]\((.*)\)' | tail -1 | string unescape | jq '.video' | string collect); or exit

    if test $video_json = null
        se '[!] this video has no streams, skipping. (.video was null)'
    else

        # find best m3u8 url to download (the one with the most tracks, usually this will be ["Audio", "Video"] = 2)
        set playlist_uri (string sub -- $video_json | jq '.playableMedias | sort_by(-(.trackType | length)) | .[0].uri' -r); or exit
        se "[ ] got playlist with streams: $playlist_uri"

        # ytdl will save out cookies, this can cause issues and cannot be turned off. replace the original cookies before starting it.
        if $preserve_cookies
            cp cookies.txt.original cookies.txt
        end

        if $download_in_parallel
            # test run
            $ytdl_executable $ytdl_args $playlist_uri -o $output_path -s; or exit
            # all good, download m3u8 in background with ytdl!
            $ytdl_executable $ytdl_args $playlist_uri -o $output_path --no-progress &
            se "[ ] $ytdl_executable started; moving to next video"
        else
            # all good, download m3u8 with ytdl!
            $ytdl_executable $ytdl_args $playlist_uri -o $output_path; or exit
        end
    end
end