Читав днями
допис (до речі дуже подобається канал, рекомендую!), де чувак пише, як він підходить до завантажень відео з вебсайтів. А у мене як раз була подібна ситуація, коли я теж хотів щось злити з сайту, а там відоса як такого не було, і щось я не второпав, як це зробити.
Так ось я згадав, що то було. Дружина колись давно купила курс, який хоститься на сайті Gurucan (який, схоже, має росіянське коріння до речі), а ті прям хизуються своїм
video content protection 🙄
Короч. Чувак своїм дописом мене надихнув розібратися. І він мав рацію! Мені як не веб-девелоперу трохи складніше, але я посидів на вкладці Мережа в девтулах, познаходив там якісь лінки. Спочатку думав взагалі просто дампанути з девтулів сесію та парсити її, але згодом знайшов там виклики API. Після логіну прилітає токен, який можна потім просто передавати в куках разом з
User-Agent, і все працює.
Усі відоси розділені на шматки по 4 секунди й лежать на CDN, де також є
*.m3u8 плейліст, по якому воно їх і збирає. Я роблю те саме: завантажую всі шматки локально та комбіную їх
ffmpegʼом.
Написав все на #Nu (так, це мова в #Nushell) з використанням вбудованих засобів, тож єдина зовнішня залежність — це, власне,
ffmpeg (жодних блядь jq!). Дуже подобається, що все статично типізоване та компілюється, тож ще до виконання отримуєш пачку помилок.
І вкотре наголошую, в якому я захваті від передачі обʼєктів через пайп. Є, наприклад у мене команда з отакою сигнатурою:
def "api get" [url?: string]: [nothing -> record, string -> record] {
...
}Необовʼязковий параметр — це
url, щоб можна було викликати отак:
api get https://some.domain/api/call
Чому необовʼязковий? Бо натомість URL можна передати через пайп. І саме про це каже тип цієї команди, який можна читати так: якщо через пайп приходить
nothing, то команда поверне
record (але в цьому випадку треба вказати
url, що на жаль в сигнатурі не відображене), і якщо через пайп приходить
string, то також повертає
record. Жодні інші типи через пайп не прийматиме. Тож альтернативний виклик отакий:
'https://some.domain/api/call' | api get
При цьому авжеж тепер ліва частина може бути аутпутом з іншої команди. За бажання структуру
record, що повертається, також можна описати в типі, якщо вона заздалегідь відома.
Лайна в процесі також похавав. В якийсь момент мій код почав видавати отаку помилку:
× Variable not found
╭─[~/megamodule/mod.nu:137:1]
137 │
138 │ ╭─▶️ api purchases | each {|p|
139 │ │ api course $p._id | download course
140 │ ├─▶️ }
· ╰──── variable not found
141 │
╰────
І пиздець — ані туди, ані сюди. Причому це тупо в
main на верхньому рівні. Довелося коментувати код шматками, щоб докопатися до суті. Врешті виявилося, що десь в іншому модулі на хз якому рівні вкладеності я не перевірив одну зі змінних на
null перед використанням 😵💫
Втім все одно я в захваті! Nushell — вогонь, причому він активно розвивається.