Refractored downloader
Implemented add command Created config and merged it with cli
This commit is contained in:
parent
d216a5b83f
commit
3ba685448a
638
manifest.json
638
manifest.json
|
@ -1,147 +1,495 @@
|
||||||
{
|
{
|
||||||
"format": "m4a",
|
"format": "m4a",
|
||||||
"genres": {
|
"genres": {
|
||||||
"pop": [
|
"rave": [
|
||||||
{"name": "Green Day - Basket Case", "url": "https://www.youtube.com/watch?v=wZ8eZRxFA-0"},
|
{
|
||||||
{"name": "Icona Pop - I Love It", "url": "https://www.youtube.com/watch?v=UxxajLWwzqY"}
|
"name": "EVERYTHING WHAT",
|
||||||
],
|
"url": "https://www.youtube.com/watch?v=Gjdsq4kc5cA"
|
||||||
"hip-hop": [
|
},
|
||||||
{"name": "Afroman - Because I Got High", "url": "https://www.youtube.com/watch?v=WeYsTmIzjkw"}
|
{
|
||||||
],
|
"name": "Tricky Disco",
|
||||||
"rave": [
|
"url": "https://www.youtube.com/watch?v=t78qVdbAiXw"
|
||||||
{"name": "EVERYTHING WHAT", "url": "https://www.youtube.com/watch?v=Gjdsq4kc5cA"},
|
},
|
||||||
{"name": "Tricky Disco", "url": "https://www.youtube.com/watch?v=t78qVdbAiXw"},
|
{
|
||||||
{"name": "DR. VODKA - Tricky Disco", "url": "https://www.youtube.com/watch?v=IknAUhl3i2o"}
|
"name": "DR. VODKA - Tricky Disco",
|
||||||
],
|
"url": "https://www.youtube.com/watch?v=IknAUhl3i2o"
|
||||||
"techno": [
|
}
|
||||||
{"name": "Dance For Me", "url": "https://www.youtube.com/watch?v=5DTSvGO_944"},
|
],
|
||||||
{"name": "Give It To Me", "url": "https://www.youtube.com/watch?v=upQe8EeSyZU"},
|
"hip-hop": [
|
||||||
{"name": "Empire Of The Sun, southstar - We Are The People", "url": "https://www.youtube.com/watch?v=qguEGR5BK2k"},
|
{
|
||||||
{"name": "Beggin' (Techno)", "url": "https://www.youtube.com/watch?v=tXPs1FwW6lk"},
|
"name": "Afroman - Because I Got High",
|
||||||
{"name": "Lily Allen - Not Fair", "url": "https://www.youtube.com/watch?v=WON_YIbeLis"},
|
"url": "https://www.youtube.com/watch?v=WeYsTmIzjkw"
|
||||||
{"name": "I WAS MADE FOR LOVIN' YOU (TECHNO)", "url": "https://www.youtube.com/watch?v=asVznhccYao"},
|
},
|
||||||
{"name": "Nicolas Julian - Applause", "url": "https://www.youtube.com/watch?v=-pXlrWVICAE"},
|
{
|
||||||
{"name": "08 Blumchen - Blaue Augen", "url": "https://www.youtube.com/watch?v=mE4PZcUfiwE"},
|
"name": "Drenchill - Freed from Desire",
|
||||||
{"name": "MUTA - Party maker", "url": "https://www.youtube.com/watch?v=LT9VNK1aCXY"},
|
"url": "https://www.youtube.com/watch?v=6b6FBneAENQ"
|
||||||
{"name": "Restricted - Big Jet Plane", "url": "https://www.youtube.com/watch?v=NpVF0z5N-tE"}
|
}
|
||||||
],
|
],
|
||||||
"electronic": [
|
"rusiskos": [
|
||||||
{"name": "Zombie Nation - Kernkraft 400", "url": "https://www.youtube.com/watch?v=z5LW07FTJbI"},
|
{
|
||||||
{"name": "Benny Benassi - Satisfaction", "url": "https://www.youtube.com/watch?v=a0fkNdPiIL4"}
|
"name": "Topolini puh",
|
||||||
|
"url": "https://www.youtube.com/watch?v=UUryvYF8tUs"
|
||||||
],
|
},
|
||||||
"rock": [
|
{
|
||||||
{"name": "Black Sabbath", "url": "https://www.youtube.com/watch?v=BOTIIw76qiE"}
|
"name": "Raim & Artur feat. Zhenis - Diskoteka is 90 hit",
|
||||||
],
|
"url": "https://www.youtube.com/watch?v=GfBhxlNhrn0"
|
||||||
"house": [
|
},
|
||||||
{"name": "Ralph Castelli - Morning Sex (Mochakk Remix)", "url": "https://www.youtube.com/watch?v=6bCwJ_TIDG4"},
|
{
|
||||||
{"name": "Billie Eilish - Bossa Nova (Lewii Edit)", "url": "https://www.youtube.com/watch?v=gNawHj2NCxA"},
|
"name": "Pimp Schwab - vse shto nas ne Ubivaet",
|
||||||
{"name": "Fidde - I Only See Things I Dont Have", "url": "https://www.youtube.com/watch?v=vX_Ye_ZzI-Y"},
|
"url": "https://www.youtube.com/watch?v=NTEXFyUE9Ww"
|
||||||
{"name": "Bauhouse - After Marvins Dance (Marvin Gaye's 'After The Dance' Edit)", "url": "https://www.youtube.com/watch?v=J-cgyYiExh8"},
|
},
|
||||||
{"name": "Men I Trust - Tailwhip (Lewii Edit)", "url": "https://www.youtube.com/watch?v=XhyM-JUWwWQ"},
|
{
|
||||||
{"name": "Sweely - Le Son Dancefloor", "url": "https://www.youtube.com/watch?v=5uEvZgmoG6Y"},
|
"name": "Dzaro and hansa - Visky Kola karaleva trans pola",
|
||||||
{"name": "THEOS - Rhodes Trip", "url": "https://www.youtube.com/watch?v=m7guRO0Uz_c"},
|
"url": "https://www.youtube.com/watch?v=fflrMvZ2HtA"
|
||||||
{"name": "Baltra - Tears Drop", "url": "https://www.youtube.com/watch?v=EXXMtKPfuzY"},
|
}
|
||||||
{"name": "Fidde - If Theres A Heaven I Wanna See It", "url": "https://www.youtube.com/watch?v=l2Nw7cIh7qg"},
|
],
|
||||||
{"name": "Unknown Artist - Kcik 23", "url": "https://www.youtube.com/watch?v=SnnqDdZJpzA"}
|
"pop": [
|
||||||
],
|
{
|
||||||
"lietuviskos": [
|
"name": "Green Day - Basket Case",
|
||||||
{"name": "Adomas Vysniauskas - As Judu", "url": "https://www.youtube.com/watch?v=dMm16TzZrjg"},
|
"url": "https://www.youtube.com/watch?v=wZ8eZRxFA-0"
|
||||||
{"name": "RADVIS - KINO FILMAI", "url": "https://www.youtube.com/watch?v=vhAEkC3xNMo"},
|
},
|
||||||
{"name": "16Hz - Autostrada Vilnius - Kaunas", "url": "https://www.youtube.com/watch?v=ANS2TSegr40"},
|
{
|
||||||
{"name": "Zas - Zalias Pasas", "url": "https://www.youtube.com/watch?v=SZA7IjlCfyI"},
|
"name": "Icona Pop - I Love It",
|
||||||
{"name": "Dzordana Butkute - Nebenoriu Laukt", "url": "https://www.youtube.com/watch?v=_AozFrAqNMk"},
|
"url": "https://www.youtube.com/watch?v=UxxajLWwzqY"
|
||||||
{"name": "Juodas Garvezys (Remix)", "url": "https://www.youtube.com/watch?v=D-7qQbXHSAw"},
|
},
|
||||||
{"name": "morre - Kaip Diena", "url": "https://www.youtube.com/watch?v=6LDgLWCQSSM"},
|
{
|
||||||
{"name": "MC ENDRAY - AUDI", "url": "https://www.youtube.com/watch?v=oIjNoMGEuRg"},
|
"name": "Modern Talking - You're My Heart, You're My Soul",
|
||||||
{"name": "Mercy Dance - I Pajuri", "url": "https://www.youtube.com/watch?v=RPpkMh47l9w"},
|
"url": "https://www.youtube.com/watch?v=4kHl4FoK1Ys"
|
||||||
{"name": "NL - Pasitusinam", "url": "https://www.youtube.com/watch?v=WhSFudvloog"},
|
}
|
||||||
{"name": "SixthBoi - Nevaidink", "url": "https://www.youtube.com/watch?v=nOTNnnrqTII"},
|
],
|
||||||
{"name": "Mr.Bullet - UZ MUS IR JUS", "url": "https://www.youtube.com/watch?v=85q_7jXEgH8"},
|
"house": [
|
||||||
{"name": "Jovani, Karaliska Erdve - Is Leto Leidziasi Saule", "url": "https://www.youtube.com/watch?v=VqSu8iG1_DE"},
|
{
|
||||||
{"name": "Rondo - Margarita", "url": "https://www.youtube.com/watch?v=rF4w-Rxsiv4"},
|
"name": "Ralph Castelli - Morning Sex (Mochakk Remix)",
|
||||||
{"name": "Radvis - TU ESI MELAGIS (Techno Extended)", "url": "https://www.youtube.com/watch?v=kmvvP7GW_bw"},
|
"url": "https://www.youtube.com/watch?v=6bCwJ_TIDG4"
|
||||||
{"name": "Zas - Myliu kina", "url": "https://www.youtube.com/watch?v=ImFrfmi-qT8"},
|
},
|
||||||
{"name": "Zilvinas Zvagulis - Amerikonas grizo sunus", "url": "https://www.youtube.com/watch?v=UvzJEz5ADY8"},
|
{
|
||||||
{"name": "Raketa - I Kluba", "url": "https://www.youtube.com/watch?v=FkSjtpYN3EI"},
|
"name": "Billie Eilish - Bossa Nova (Lewii Edit)",
|
||||||
{"name": "Karaliska Erdve - Vakareja", "url": "https://www.youtube.com/watch?v=g0HmrlJ7fhE"},
|
"url": "https://www.youtube.com/watch?v=gNawHj2NCxA"
|
||||||
{"name": "Tnn - Parukom", "url": "https://www.youtube.com/watch?v=v9pBZK2RIPI"},
|
},
|
||||||
{"name": "DJ Dalgis - Kauniete", "url": "https://www.youtube.com/watch?v=b3xPE9Iyuzc"},
|
{
|
||||||
{"name": "Andzikas - I gamta", "url": "https://www.youtube.com/watch?v=UyLdjC-hihM"},
|
"name": "Fidde - I Only See Things I Dont Have",
|
||||||
{"name": "nemuno krantai - rytmecio rasos", "url": "https://www.youtube.com/watch?v=2-fGbsrofv4"},
|
"url": "https://www.youtube.com/watch?v=vX_Ye_ZzI-Y"
|
||||||
{"name": "Tipo grupe - Lovoj Vezi", "url": "https://www.youtube.com/watch?v=M3zVMzWCy_c"},
|
},
|
||||||
{"name": "Kastanenda - Sombrero", "url": "https://www.youtube.com/watch?v=3Z3_4TknCfQ"},
|
{
|
||||||
{"name": "Elektra - Juda Tavo rankos", "url": "https://www.youtube.com/watch?v=k2RuDoudnOE"},
|
"name": "Bauhouse - After Marvins Dance (Marvin Gaye's 'After The Dance' Edit)",
|
||||||
{"name": "Vilija ir Marijonas mikutavicius - Dabar Geriausi Musu Vakarai", "url": "https://www.youtube.com/watch?v=MPnZkEscWo0"},
|
"url": "https://www.youtube.com/watch?v=J-cgyYiExh8"
|
||||||
{"name": "Parnesk alaus OG", "url": "https://www.youtube.com/watch?v=e7cB1JIlZ2k"},
|
},
|
||||||
{"name": "Eugenijus Ostapenko - Dviratukas", "url": "https://www.youtube.com/watch?v=ILFHZQK33Mw"},
|
{
|
||||||
{"name": "Ciulpuoneliai - Jau Nutilo Sirgaliai", "url": "https://www.youtube.com/watch?v=s8qIVA1U0C0"},
|
"name": "Men I Trust - Tailwhip (Lewii Edit)",
|
||||||
{"name": "Tweaxx - Mersas", "url": "https://www.youtube.com/watch?v=7ljAzgALPdA"},
|
"url": "https://www.youtube.com/watch?v=XhyM-JUWwWQ"
|
||||||
{"name": "Dove - Naktinis Tusas", "url": "https://www.youtube.com/watch?v=pz-HEAwFEnk"},
|
},
|
||||||
{"name": "MAMA MANE RODYS PER FARUS", "url": "https://www.youtube.com/watch?v=F5HqXYRDZaE"},
|
{
|
||||||
{"name": "Kastaneda - Kelyje", "url": "https://www.youtube.com/watch?v=JVE6NQqKPL4"},
|
"name": "Sweely - Le Son Dancefloor",
|
||||||
{"name": "NL - Juodas Golfas", "url": "https://www.youtube.com/watch?v=f2-ZmElSvPc"},
|
"url": "https://www.youtube.com/watch?v=5uEvZgmoG6Y"
|
||||||
{"name": "DJ Dalgis - Zalia Siera", "url": "https://www.youtube.com/watch?v=nfentq_pez4"},
|
},
|
||||||
{"name": "L1GHT CASH - Whiskey Cola Lietuviskai (sultys degtinele) remix", "url": "https://www.youtube.com/watch?v=YVaqDaf1KXU"},
|
{
|
||||||
{"name": "Tipo grupe ir Kastaneda - Po stikliuka", "url": "https://www.youtube.com/watch?v=EtmE60nE7fI"},
|
"name": "THEOS - Rhodes Trip",
|
||||||
{"name": "MG INTERNATIONAL - JUODA ORCHIDEJA", "url": "https://www.youtube.com/watch?v=HQvceFRBq9M"},
|
"url": "https://www.youtube.com/watch?v=m7guRO0Uz_c"
|
||||||
{"name": "Ganja - Truputi", "url": "https://www.youtube.com/watch?v=Pxve7CwiCHM"},
|
},
|
||||||
{"name": "Riaukenzo - Trys Trys Trys", "url": "https://www.youtube.com/watch?v=qJv6GRQCnCk"},
|
{
|
||||||
{"name": "Grupiokai - Degtine", "url": "https://www.youtube.com/watch?v=8SqbG2VmEFw"},
|
"name": "Baltra - Tears Drop",
|
||||||
{"name": "Robertas Kupstas - Cia Mano Rojus", "url": "https://www.youtube.com/watch?v=xij_YeEInr8"},
|
"url": "https://www.youtube.com/watch?v=EXXMtKPfuzY"
|
||||||
{"name": "NIERKA - PENKTADIENIS", "url": "https://www.youtube.com/watch?v=h3TuZj_OAf0"},
|
},
|
||||||
{"name": "VAIKAI PO LELIJOM (REMIX)", "url": "https://www.youtube.com/watch?v=k1amBbsAZuo"},
|
{
|
||||||
{"name": "Vitalija Katunskyte - Robinzonas", "url": "https://www.youtube.com/watch?v=erDHG-QpbPY"},
|
"name": "Fidde - If Theres A Heaven I Wanna See It",
|
||||||
{"name": "Rycka klipas", "url": "https://www.youtube.com/watch?v=nuTUDSQ3BBI"},
|
"url": "https://www.youtube.com/watch?v=l2Nw7cIh7qg"
|
||||||
{"name": "Nezinau, Kodel...", "url": "https://www.youtube.com/watch?v=A-i2CkCnPoc"},
|
},
|
||||||
{"name": "NL - R1", "url": "https://www.youtube.com/watch?v=hSgav4fYnZ8"},
|
{
|
||||||
{"name": "DJ Dalgis - Negeriau", "url": "https://www.youtube.com/watch?v=c89YvG3MCcs"},
|
"name": "Unknown Artist - Kcik 23",
|
||||||
{"name": "Tipo Grupe - tipo daina", "url": "https://www.youtube.com/watch?v=PTIOaSjEgIU"},
|
"url": "https://www.youtube.com/watch?v=SnnqDdZJpzA"
|
||||||
{"name": "Depresinis feat. Deivas - 0,7", "url": "https://www.youtube.com/watch?v=rjwFjBgTzAA"},
|
}
|
||||||
{"name": "Depresinis & MERAKI2004 - VASARA ZJBS", "url": "https://www.youtube.com/watch?v=BD-pBjRy-5A"},
|
],
|
||||||
{"name": "Depresinis feat. Deivas - LEDUKAI", "url": "https://www.youtube.com/watch?v=R2-MtpkKgGI"},
|
"electronic": [
|
||||||
{"name": "Depresinis feat. Deivas - Pavasaris", "url": "https://www.youtube.com/watch?v=yWWAucfQdN4"},
|
{
|
||||||
{"name": "Depresinis - LEDINE", "url": "https://www.youtube.com/watch?v=qugvChkXMLk"},
|
"name": "Zombie Nation - Kernkraft 400",
|
||||||
{"name": "Depresinis, Jypas - O Mazuti", "url": "https://www.youtube.com/watch?v=4t_DPbe2r3M"},
|
"url": "https://www.youtube.com/watch?v=z5LW07FTJbI"
|
||||||
{"name": "AVA - Eik Tu NA", "url": "https://www.youtube.com/watch?v=yRf3ijaIgOg"},
|
},
|
||||||
{"name": "Judam Lietuvoj", "url": "https://www.youtube.com/watch?v=WDzWSEgSy5U"},
|
{
|
||||||
{"name": "16Hz - Baliavojam", "url": "https://www.youtube.com/watch?v=Ia-qERX8WLs"},
|
"name": "Benny Benassi - Satisfaction",
|
||||||
{"name": "Deivas - Klaipeda On Top", "url": "https://www.youtube.com/watch?v=g_h2M3e2OYU"},
|
"url": "https://www.youtube.com/watch?v=a0fkNdPiIL4"
|
||||||
{"name": "Depresinis - Volkswagina", "url": "https://www.youtube.com/watch?v=1lZR1VKsQHo"},
|
}
|
||||||
{"name": "SADBOY - Kaifuok", "url": "https://www.youtube.com/watch?v=vclryWgfy8I"},
|
],
|
||||||
{"name": "SADBOY - Blizgantys Naikai", "url": "https://www.youtube.com/watch?v=p5KsYJGcfOM"},
|
"lietuviskos/rave": [
|
||||||
{"name": "SADBOY - 1001 Naktis", "url": "https://www.youtube.com/watch?v=mLJIjGvWmKI"},
|
{
|
||||||
{"name": "SADBOY - Deginam", "url": "https://www.youtube.com/watch?v=w3R0Aq1EGXg"},
|
"name": "VainHouse - Malunas Prie Kelio",
|
||||||
{"name": "Wenona Waves - Topine Panele", "url": "https://www.youtube.com/watch?v=MPHuhmUomfE"},
|
"url": "https://www.youtube.com/watch?v=bbwuNjDXCiM"
|
||||||
{"name": "Andzikas - Virs debesu", "url": "https://www.youtube.com/watch?v=PHJcVGhxra8"},
|
},
|
||||||
{"name": "Grupe MX - 1.9 TDI", "url": "https://www.youtube.com/watch?v=8FBr5GQXsI8"},
|
{
|
||||||
{"name": "Patruliai - Kur Tu", "url": "https://www.youtube.com/watch?v=OPWhiu3cvj0"},
|
"name": "Sokoledas - Mano Skonis Sokolado (Matuze & Arnisxd Remix)",
|
||||||
{"name": "Ka Tu Ka Vakare", "url": "https://www.youtube.com/watch?v=6SOS4ljHbJY"}
|
"url": "https://www.youtube.com/watch?v=hb41bfQxiM0"
|
||||||
],
|
}
|
||||||
"lietuviskos/rave": [
|
],
|
||||||
{"name": "VainHouse - Malunas Prie Kelio", "url": "https://www.youtube.com/watch?v=bbwuNjDXCiM"},
|
"reggea": [
|
||||||
{"name": "Sokoledas - Mano Skonis Sokolado (Matuze & Arnisxd Remix)", "url": "https://www.youtube.com/watch?v=hb41bfQxiM0"}
|
{
|
||||||
],
|
"name": "Shaggy - It Wasn't Me",
|
||||||
"rusiskos": [
|
"url": "https://www.youtube.com/watch?v=ssVj50ombaM"
|
||||||
{"name": "Topolini puh", "url": "https://www.youtube.com/watch?v=UUryvYF8tUs"},
|
}
|
||||||
{"name": "Raim & Artur feat. Zhenis - Diskoteka is 90 hit", "url": "https://www.youtube.com/watch?v=GfBhxlNhrn0"},
|
],
|
||||||
{"name": "Pimp Schwab - vse shto nas ne Ubivaet", "url": "https://www.youtube.com/watch?v=NTEXFyUE9Ww"},
|
"rock": [
|
||||||
{"name": "Dzaro and hansa - Visky Kola karaleva trans pola", "url": "https://www.youtube.com/watch?v=fflrMvZ2HtA"}
|
{
|
||||||
],
|
"name": "Black Sabbath",
|
||||||
"noclue": [
|
"url": "https://www.youtube.com/watch?v=BOTIIw76qiE"
|
||||||
{"name": "Bad Boys", "url": "https://www.youtube.com/watch?v=NTC7RD8xzCY"},
|
}
|
||||||
{"name": "DR. VODKA - DZIEWCZYNO Z TIKTOKA", "url": "https://www.youtube.com/watch?v=HLbw1WQt64o"},
|
],
|
||||||
{"name": "Maco Mamuko - Whiskey, Cola i Tequila", "url": "https://www.youtube.com/watch?v=aBrN0k0Phtc"},
|
"noclue": [
|
||||||
{"name": "Discobitch - C'est Beau La Bourgeoisie", "url": "https://www.youtube.com/watch?v=RCeQN2aEWxo"}
|
{
|
||||||
|
"name": "Bad Boys",
|
||||||
],
|
"url": "https://www.youtube.com/watch?v=NTC7RD8xzCY"
|
||||||
"reggea": [
|
},
|
||||||
{"name": "Shaggy - It Wasn't Me", "url": "https://www.youtube.com/watch?v=ssVj50ombaM"}
|
{
|
||||||
],
|
"name": "DR. VODKA - DZIEWCZYNO Z TIKTOKA",
|
||||||
"alt": [
|
"url": "https://www.youtube.com/watch?v=HLbw1WQt64o"
|
||||||
{"name": "ROMANCEPLANET - FALL FROM THE SKY", "url": "https://www.youtube.com/watch?v=HMhzxzXBisw"},
|
},
|
||||||
{"name": "ROMANCEPLANET - PLAIN WHITE TEE", "url": "https://www.youtube.com/watch?v=tdVQbNwjGac"},
|
{
|
||||||
{"name": "ROMANCEPLANET - DANCE", "url": "https://www.youtube.com/watch?v=ircOfMb4gEw"}
|
"name": "Maco Mamuko - Whiskey, Cola i Tequila",
|
||||||
]
|
"url": "https://www.youtube.com/watch?v=aBrN0k0Phtc"
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"name": "Discobitch - C'est Beau La Bourgeoisie",
|
||||||
|
"url": "https://www.youtube.com/watch?v=RCeQN2aEWxo"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"techno": [
|
||||||
|
{
|
||||||
|
"name": "Dance For Me",
|
||||||
|
"url": "https://www.youtube.com/watch?v=5DTSvGO_944"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Give It To Me",
|
||||||
|
"url": "https://www.youtube.com/watch?v=upQe8EeSyZU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Empire Of The Sun, southstar - We Are The People",
|
||||||
|
"url": "https://www.youtube.com/watch?v=qguEGR5BK2k"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Beggin' (Techno)",
|
||||||
|
"url": "https://www.youtube.com/watch?v=tXPs1FwW6lk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Lily Allen - Not Fair",
|
||||||
|
"url": "https://www.youtube.com/watch?v=WON_YIbeLis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "I WAS MADE FOR LOVIN' YOU (TECHNO)",
|
||||||
|
"url": "https://www.youtube.com/watch?v=asVznhccYao"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nicolas Julian - Applause",
|
||||||
|
"url": "https://www.youtube.com/watch?v=-pXlrWVICAE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "08 Blumchen - Blaue Augen",
|
||||||
|
"url": "https://www.youtube.com/watch?v=mE4PZcUfiwE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MUTA - Party maker",
|
||||||
|
"url": "https://www.youtube.com/watch?v=LT9VNK1aCXY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Restricted - Big Jet Plane",
|
||||||
|
"url": "https://www.youtube.com/watch?v=NpVF0z5N-tE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lietuviskos": [
|
||||||
|
{
|
||||||
|
"name": "Adomas Vysniauskas - As Judu",
|
||||||
|
"url": "https://www.youtube.com/watch?v=dMm16TzZrjg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "RADVIS - KINO FILMAI",
|
||||||
|
"url": "https://www.youtube.com/watch?v=vhAEkC3xNMo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "16Hz - Autostrada Vilnius - Kaunas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=ANS2TSegr40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zas - Zalias Pasas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=SZA7IjlCfyI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dzordana Butkute - Nebenoriu Laukt",
|
||||||
|
"url": "https://www.youtube.com/watch?v=_AozFrAqNMk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Juodas Garvezys (Remix)",
|
||||||
|
"url": "https://www.youtube.com/watch?v=D-7qQbXHSAw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "morre - Kaip Diena",
|
||||||
|
"url": "https://www.youtube.com/watch?v=6LDgLWCQSSM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MC ENDRAY - AUDI",
|
||||||
|
"url": "https://www.youtube.com/watch?v=oIjNoMGEuRg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mercy Dance - I Pajuri",
|
||||||
|
"url": "https://www.youtube.com/watch?v=RPpkMh47l9w"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NL - Pasitusinam",
|
||||||
|
"url": "https://www.youtube.com/watch?v=WhSFudvloog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SixthBoi - Nevaidink",
|
||||||
|
"url": "https://www.youtube.com/watch?v=nOTNnnrqTII"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mr.Bullet - UZ MUS IR JUS",
|
||||||
|
"url": "https://www.youtube.com/watch?v=85q_7jXEgH8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jovani, Karaliska Erdve - Is Leto Leidziasi Saule",
|
||||||
|
"url": "https://www.youtube.com/watch?v=VqSu8iG1_DE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rondo - Margarita",
|
||||||
|
"url": "https://www.youtube.com/watch?v=rF4w-Rxsiv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Radvis - TU ESI MELAGIS (Techno Extended)",
|
||||||
|
"url": "https://www.youtube.com/watch?v=kmvvP7GW_bw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zas - Myliu kina",
|
||||||
|
"url": "https://www.youtube.com/watch?v=ImFrfmi-qT8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zilvinas Zvagulis - Amerikonas grizo sunus",
|
||||||
|
"url": "https://www.youtube.com/watch?v=UvzJEz5ADY8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Raketa - I Kluba",
|
||||||
|
"url": "https://www.youtube.com/watch?v=FkSjtpYN3EI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Karaliska Erdve - Vakareja",
|
||||||
|
"url": "https://www.youtube.com/watch?v=g0HmrlJ7fhE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tnn - Parukom",
|
||||||
|
"url": "https://www.youtube.com/watch?v=v9pBZK2RIPI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DJ Dalgis - Kauniete",
|
||||||
|
"url": "https://www.youtube.com/watch?v=b3xPE9Iyuzc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Andzikas - I gamta",
|
||||||
|
"url": "https://www.youtube.com/watch?v=UyLdjC-hihM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nemuno krantai - rytmecio rasos",
|
||||||
|
"url": "https://www.youtube.com/watch?v=2-fGbsrofv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tipo grupe - Lovoj Vezi",
|
||||||
|
"url": "https://www.youtube.com/watch?v=M3zVMzWCy_c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kastanenda - Sombrero",
|
||||||
|
"url": "https://www.youtube.com/watch?v=3Z3_4TknCfQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Elektra - Juda Tavo rankos",
|
||||||
|
"url": "https://www.youtube.com/watch?v=k2RuDoudnOE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vilija ir Marijonas mikutavicius - Dabar Geriausi Musu Vakarai",
|
||||||
|
"url": "https://www.youtube.com/watch?v=MPnZkEscWo0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Parnesk alaus OG",
|
||||||
|
"url": "https://www.youtube.com/watch?v=e7cB1JIlZ2k"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Eugenijus Ostapenko - Dviratukas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=ILFHZQK33Mw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ciulpuoneliai - Jau Nutilo Sirgaliai",
|
||||||
|
"url": "https://www.youtube.com/watch?v=s8qIVA1U0C0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tweaxx - Mersas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=7ljAzgALPdA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dove - Naktinis Tusas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=pz-HEAwFEnk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MAMA MANE RODYS PER FARUS",
|
||||||
|
"url": "https://www.youtube.com/watch?v=F5HqXYRDZaE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kastaneda - Kelyje",
|
||||||
|
"url": "https://www.youtube.com/watch?v=JVE6NQqKPL4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NL - Juodas Golfas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=f2-ZmElSvPc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DJ Dalgis - Zalia Siera",
|
||||||
|
"url": "https://www.youtube.com/watch?v=nfentq_pez4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "L1GHT CASH - Whiskey Cola Lietuviskai (sultys degtinele) remix",
|
||||||
|
"url": "https://www.youtube.com/watch?v=YVaqDaf1KXU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tipo grupe ir Kastaneda - Po stikliuka",
|
||||||
|
"url": "https://www.youtube.com/watch?v=EtmE60nE7fI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MG INTERNATIONAL - JUODA ORCHIDEJA",
|
||||||
|
"url": "https://www.youtube.com/watch?v=HQvceFRBq9M"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ganja - Truputi",
|
||||||
|
"url": "https://www.youtube.com/watch?v=Pxve7CwiCHM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Riaukenzo - Trys Trys Trys",
|
||||||
|
"url": "https://www.youtube.com/watch?v=qJv6GRQCnCk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Grupiokai - Degtine",
|
||||||
|
"url": "https://www.youtube.com/watch?v=8SqbG2VmEFw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Robertas Kupstas - Cia Mano Rojus",
|
||||||
|
"url": "https://www.youtube.com/watch?v=xij_YeEInr8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NIERKA - PENKTADIENIS",
|
||||||
|
"url": "https://www.youtube.com/watch?v=h3TuZj_OAf0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VAIKAI PO LELIJOM (REMIX)",
|
||||||
|
"url": "https://www.youtube.com/watch?v=k1amBbsAZuo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vitalija Katunskyte - Robinzonas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=erDHG-QpbPY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rycka klipas",
|
||||||
|
"url": "https://www.youtube.com/watch?v=nuTUDSQ3BBI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nezinau, Kodel...",
|
||||||
|
"url": "https://www.youtube.com/watch?v=A-i2CkCnPoc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NL - R1",
|
||||||
|
"url": "https://www.youtube.com/watch?v=hSgav4fYnZ8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DJ Dalgis - Negeriau",
|
||||||
|
"url": "https://www.youtube.com/watch?v=c89YvG3MCcs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tipo Grupe - tipo daina",
|
||||||
|
"url": "https://www.youtube.com/watch?v=PTIOaSjEgIU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis feat. Deivas - 0,7",
|
||||||
|
"url": "https://www.youtube.com/watch?v=rjwFjBgTzAA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis & MERAKI2004 - VASARA ZJBS",
|
||||||
|
"url": "https://www.youtube.com/watch?v=BD-pBjRy-5A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis feat. Deivas - LEDUKAI",
|
||||||
|
"url": "https://www.youtube.com/watch?v=R2-MtpkKgGI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis feat. Deivas - Pavasaris",
|
||||||
|
"url": "https://www.youtube.com/watch?v=yWWAucfQdN4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis - LEDINE",
|
||||||
|
"url": "https://www.youtube.com/watch?v=qugvChkXMLk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis, Jypas - O Mazuti",
|
||||||
|
"url": "https://www.youtube.com/watch?v=4t_DPbe2r3M"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AVA - Eik Tu NA",
|
||||||
|
"url": "https://www.youtube.com/watch?v=yRf3ijaIgOg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Judam Lietuvoj",
|
||||||
|
"url": "https://www.youtube.com/watch?v=WDzWSEgSy5U"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "16Hz - Baliavojam",
|
||||||
|
"url": "https://www.youtube.com/watch?v=Ia-qERX8WLs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Deivas - Klaipeda On Top",
|
||||||
|
"url": "https://www.youtube.com/watch?v=g_h2M3e2OYU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Depresinis - Volkswagina",
|
||||||
|
"url": "https://www.youtube.com/watch?v=1lZR1VKsQHo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SADBOY - Kaifuok",
|
||||||
|
"url": "https://www.youtube.com/watch?v=vclryWgfy8I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SADBOY - Blizgantys Naikai",
|
||||||
|
"url": "https://www.youtube.com/watch?v=p5KsYJGcfOM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SADBOY - 1001 Naktis",
|
||||||
|
"url": "https://www.youtube.com/watch?v=mLJIjGvWmKI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SADBOY - Deginam",
|
||||||
|
"url": "https://www.youtube.com/watch?v=w3R0Aq1EGXg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Wenona Waves - Topine Panele",
|
||||||
|
"url": "https://www.youtube.com/watch?v=MPHuhmUomfE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Andzikas - Virs debesu",
|
||||||
|
"url": "https://www.youtube.com/watch?v=PHJcVGhxra8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Grupe MX - 1.9 TDI",
|
||||||
|
"url": "https://www.youtube.com/watch?v=8FBr5GQXsI8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Patruliai - Kur Tu",
|
||||||
|
"url": "https://www.youtube.com/watch?v=OPWhiu3cvj0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ka Tu Ka Vakare",
|
||||||
|
"url": "https://www.youtube.com/watch?v=6SOS4ljHbJY"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"alt": [
|
||||||
|
{
|
||||||
|
"name": "ROMANCEPLANET - FALL FROM THE SKY",
|
||||||
|
"url": "https://www.youtube.com/watch?v=HMhzxzXBisw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ROMANCEPLANET - PLAIN WHITE TEE",
|
||||||
|
"url": "https://www.youtube.com/watch?v=tdVQbNwjGac"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ROMANCEPLANET - DANCE",
|
||||||
|
"url": "https://www.youtube.com/watch?v=ircOfMb4gEw"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
1154
music_mgr/Cargo.lock
generated
1154
music_mgr/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,9 @@ env_logger = "0.11.3"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2.153"
|
libc = "0.2.153"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
|
reqwest = "0.12.3"
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde_json = "1.0.115"
|
serde_json = "1.0.115"
|
||||||
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "process", "sync"] }
|
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "process", "sync"] }
|
||||||
windows = { version = "0.56.0", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_Console"] }
|
windows = { version = "0.56.0", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_Console"] }
|
||||||
|
zip-extensions = "0.6.2"
|
||||||
|
|
38
music_mgr/src/commands/add.rs
Normal file
38
music_mgr/src/commands/add.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use crate::{config::ConfigWrapper, downloader::Downloader, manifest::{Manifest, ManifestSong}};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn add(cfg: &ConfigWrapper, manifest: &mut Manifest, downloader: &mut Downloader, url: &Option<String>, name: &Option<String>, genre: &Option<String>) -> anyhow::Result<()> {
|
||||||
|
|
||||||
|
let genres = manifest.genres.keys().map(|f| f.clone()).collect::<Vec<String>>();
|
||||||
|
|
||||||
|
let genre = genre.clone().unwrap_or(
|
||||||
|
crate::prompt::prompt_with_list_or_str("Enter song genre", &genres)
|
||||||
|
);
|
||||||
|
|
||||||
|
log::debug!("Genre: {genre}");
|
||||||
|
|
||||||
|
let url = url.clone().unwrap_or(
|
||||||
|
crate::prompt::simple_prompt("Enter song youtube url, make sure its not a playlist, (yt only for now)")
|
||||||
|
);
|
||||||
|
|
||||||
|
let name = name.clone().unwrap_or(
|
||||||
|
crate::prompt::simple_prompt("Enter song name with like this: {Author} - {Song name}")
|
||||||
|
);
|
||||||
|
|
||||||
|
manifest.add_song(genre.clone(), name.clone(), url.clone())?;
|
||||||
|
manifest.save()?;
|
||||||
|
|
||||||
|
let should_download = crate::prompt::prompt_bool("Download song now?", Some(true));
|
||||||
|
|
||||||
|
if should_download {
|
||||||
|
let song = &ManifestSong {
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
};
|
||||||
|
|
||||||
|
downloader.download_song(cfg, song, &genre, &manifest.format()?).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,22 +1,27 @@
|
||||||
use crate::{cli::{CliArgs, CliCommand}, downloader::Downloader, manifest::Manifest, util};
|
mod add;
|
||||||
|
|
||||||
|
use crate::{config::{cli::CliCommand, ConfigWrapper}, downloader::Downloader, manifest::Manifest};
|
||||||
|
|
||||||
|
|
||||||
pub async fn command_run(cli: &CliArgs, manifest: &Manifest) {
|
|
||||||
let mut downloader = Downloader::new(util::get_ytdlp_path());
|
pub async fn command_run(cfg: &ConfigWrapper, manifest: &mut Manifest) -> anyhow::Result<()> {
|
||||||
match &cli.command {
|
let mut downloader = Downloader::new(cfg.cfg.ytdlp.path.clone());
|
||||||
|
match &cfg.cli.command {
|
||||||
None | Some(CliCommand::Download) => {
|
None | Some(CliCommand::Download) => {
|
||||||
if let Ok(count) = downloader.download_all(manifest, &cli).await {
|
if let Ok(count) = downloader.download_all(manifest, &cfg).await {
|
||||||
log::info!("Downloaded {count} songs");
|
log::info!("Downloaded {count} songs");
|
||||||
} else {
|
} else {
|
||||||
log::error!("Failed to download songs");
|
log::error!("Failed to download songs");
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(c) => {
|
Some(c) => {
|
||||||
match c {
|
match c {
|
||||||
CliCommand::Download => unreachable!(),
|
CliCommand::Download => unreachable!(),
|
||||||
CliCommand::Add { .. } => todo!(),
|
CliCommand::Add { url, name, genre } => add::add(cfg, manifest, &mut downloader, url, name, genre).await?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
use crate::util::isatty;
|
use crate::util::isatty;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser, Default)]
|
||||||
pub struct CliArgs {
|
pub struct CliArgs {
|
||||||
/// Show more info
|
/// Show more info
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
|
@ -17,11 +17,13 @@ pub struct CliArgs {
|
||||||
#[arg(long, short, default_value_t=Utf8PathBuf::from("./out"))]
|
#[arg(long, short, default_value_t=Utf8PathBuf::from("./out"))]
|
||||||
pub output: Utf8PathBuf,
|
pub output: Utf8PathBuf,
|
||||||
|
|
||||||
|
/// Config path
|
||||||
|
#[arg(long, short, default_value_t=Utf8PathBuf::from("./config.json"))]
|
||||||
|
pub config: Utf8PathBuf,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: Option<CliCommand>,
|
pub command: Option<CliCommand>,
|
||||||
|
|
||||||
#[clap(skip)]
|
|
||||||
pub is_tty: bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Subcommand, Default)]
|
#[derive(Debug, Subcommand, Default)]
|
||||||
|
@ -29,15 +31,8 @@ pub enum CliCommand {
|
||||||
#[default]
|
#[default]
|
||||||
Download,
|
Download,
|
||||||
Add {
|
Add {
|
||||||
url: String,
|
url: Option<String>,
|
||||||
name: String,
|
name: Option<String>,
|
||||||
genre: String
|
genre: Option<String>
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CliArgs {
|
|
||||||
pub fn populate_extra(&mut self) -> &mut Self{
|
|
||||||
self.is_tty = isatty();
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
132
music_mgr/src/config/mod.rs
Normal file
132
music_mgr/src/config/mod.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
pub mod cli;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use anyhow::Result;
|
||||||
|
use crate::util::{self, dl_to_file, isatty};
|
||||||
|
|
||||||
|
use self::cli::CliArgs;
|
||||||
|
|
||||||
|
const YTDLP_DL_URL: &'static str = "https://github.com/yt-dlp/yt-dlp/archive/refs/heads/master.zip";
|
||||||
|
const SPOTDL_DL_URL: &'static str = "https://github.com/spotDL/spotify-downloader/archive/refs/heads/master.zip";
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ConfigWrapper {
|
||||||
|
pub cfg: Config,
|
||||||
|
pub cli: cli::CliArgs,
|
||||||
|
pub isatty: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||||
|
pub struct Config {
|
||||||
|
pub ytdlp: ConfigYtdlp,
|
||||||
|
pub spotdl: ConfigSpotdl,
|
||||||
|
pub python: ConfigPython,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||||
|
pub struct ConfigYtdlp {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub is_python: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||||
|
pub struct ConfigSpotdl {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub is_python: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||||
|
pub struct ConfigPython {
|
||||||
|
pub path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ConfigWrapper {
|
||||||
|
pub async fn parse() -> Result<Self> {
|
||||||
|
let mut s = Self::default();
|
||||||
|
s.cli = cli::CliArgs::parse();
|
||||||
|
crate::logger::init_logger(s.cli.debug);
|
||||||
|
s.cfg = Config::parse(&s.cli).await?;
|
||||||
|
s.isatty = isatty();
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub async fn parse(cli: &CliArgs) -> Result<Self> {
|
||||||
|
if !cli.config.exists() {
|
||||||
|
return Self::setup_config(&cli).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = std::fs::read_to_string(&cli.config)?;
|
||||||
|
let data: Self = serde_json::from_str(&data)?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn setup_config(cli: &CliArgs) -> Result<Self> {
|
||||||
|
let mut s = Self::default();
|
||||||
|
|
||||||
|
let bin_dir = cli.output.clone().into_std_path_buf().join(".bin/");
|
||||||
|
let mut python_needed = false;
|
||||||
|
|
||||||
|
match util::is_program_in_path("yt-dlp") {
|
||||||
|
Some(p) => {
|
||||||
|
s.ytdlp.path = p;
|
||||||
|
s.ytdlp.is_python = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
None => {
|
||||||
|
python_needed = true;
|
||||||
|
s.ytdlp.is_python = true;
|
||||||
|
s.ytdlp.path = bin_dir.join("ytdlp");
|
||||||
|
dl_to_file(YTDLP_DL_URL, s.ytdlp.path.join("ytdlp.zip")).await?;
|
||||||
|
zip_extensions::zip_extract(&s.ytdlp.path.join("ytdlp.zip"), &s.ytdlp.path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match util::is_program_in_path("spotdl") {
|
||||||
|
Some(p) => {
|
||||||
|
s.spotdl.path = p;
|
||||||
|
s.spotdl.is_python = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
None => {
|
||||||
|
python_needed = true;
|
||||||
|
s.spotdl.is_python = true;
|
||||||
|
s.spotdl.path = bin_dir.join("ytdlp");
|
||||||
|
dl_to_file(SPOTDL_DL_URL, s.spotdl.path.join("spotdl.zip")).await?;
|
||||||
|
zip_extensions::zip_extract(&s.spotdl.path.join("spotdl.zip"), &s.ytdlp.path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let python_paths = &[
|
||||||
|
util::is_program_in_path("python"),
|
||||||
|
util::is_program_in_path("python3")
|
||||||
|
];
|
||||||
|
|
||||||
|
if python_needed {
|
||||||
|
let mut found = false;
|
||||||
|
for p in python_paths {
|
||||||
|
match p {
|
||||||
|
Some(p) => {
|
||||||
|
s.python.path = p.clone();
|
||||||
|
found = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
panic!("Python needs to be installed for this to work, or install ytdlp and spotdl manually, (dont forget to delete the config file after doing so)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
}
|
15
music_mgr/src/constants.rs
Normal file
15
music_mgr/src/constants.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
#[cfg(target_family="windows")]
|
||||||
|
mod constants {
|
||||||
|
pub const PATH_VAR_SEP: &'static str = ";";
|
||||||
|
pub const EXEC_EXT: &'static str = "exe";
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family="unix")]
|
||||||
|
mod constants {
|
||||||
|
pub const PATH_VAR_SEP: &'static str = ":";
|
||||||
|
pub const EXEC_EXT: &'static str = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub use constants::*;
|
|
@ -4,7 +4,7 @@ use lazy_static::lazy_static;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::{Mutex, RwLock};
|
||||||
|
|
||||||
use crate::{cli::CliArgs, manifest::Manifest};
|
use crate::{config::ConfigWrapper, manifest::{Manifest, ManifestSong}};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -20,12 +20,12 @@ lazy_static!(
|
||||||
|
|
||||||
pub struct Downloader {
|
pub struct Downloader {
|
||||||
count: usize,
|
count: usize,
|
||||||
ytdlp_path: String,
|
ytdlp_path: PathBuf,
|
||||||
id_itr: usize,
|
id_itr: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Downloader {
|
impl Downloader {
|
||||||
pub fn new(ytdlp_path: String) -> Self {
|
pub fn new(ytdlp_path: PathBuf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
count: 0,
|
count: 0,
|
||||||
ytdlp_path,
|
ytdlp_path,
|
||||||
|
@ -33,12 +33,12 @@ impl Downloader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn download_all(&mut self, manifest: &Manifest, cli: &CliArgs) -> anyhow::Result<usize> {
|
pub async fn download_all(&mut self, manifest: &Manifest, cfg: &ConfigWrapper) -> anyhow::Result<usize> {
|
||||||
let format = manifest.format()?;
|
let format = manifest.format()?;
|
||||||
|
|
||||||
for (genre, songs) in &manifest.genres {
|
for (genre, songs) in &manifest.genres {
|
||||||
for song in songs {
|
for song in songs {
|
||||||
self.download_song(format!("{}/{genre}/{}.{}", cli.output, song.name, &format), &format, &song.url).await?;
|
self.download_song(cfg, &song, &genre, &format).await?;
|
||||||
self.wait_for_procs(10).await?;
|
self.wait_for_procs(10).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,9 @@ impl Downloader {
|
||||||
Ok(self.count)
|
Ok(self.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn download_song(&mut self, path: String, audio_format: &String, url: &String) -> anyhow::Result<()> {
|
pub async fn download_song(&mut self, cfg: &ConfigWrapper, song: &ManifestSong, genre: &String, format: &String) -> anyhow::Result<()> {
|
||||||
|
let path = format!("{}/{genre}/{}.{}", cfg.cli.output, song.name, &format);
|
||||||
|
|
||||||
if PathBuf::from(&path).exists() {
|
if PathBuf::from(&path).exists() {
|
||||||
log::debug!("File {path} exists, skipping");
|
log::debug!("File {path} exists, skipping");
|
||||||
return Ok(())
|
return Ok(())
|
||||||
|
@ -55,10 +57,10 @@ impl Downloader {
|
||||||
let cmd = cmd.args([
|
let cmd = cmd.args([
|
||||||
"-x",
|
"-x",
|
||||||
"--audio-format",
|
"--audio-format",
|
||||||
audio_format.as_str(),
|
format.as_str(),
|
||||||
"-o",
|
"-o",
|
||||||
path.as_str(),
|
path.as_str(),
|
||||||
url.as_str()
|
song.url.as_str()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let cmd = if log::max_level() < Level::Debug {
|
let cmd = if log::max_level() < Level::Debug {
|
||||||
|
@ -77,7 +79,7 @@ impl Downloader {
|
||||||
|
|
||||||
log::info!("Downloading {path}");
|
log::info!("Downloading {path}");
|
||||||
PROCESSES.lock().await.write().await.insert(id, Proc {
|
PROCESSES.lock().await.write().await.insert(id, Proc {
|
||||||
url: url.clone(),
|
url: song.url.clone(),
|
||||||
path,
|
path,
|
||||||
finished: false,
|
finished: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,31 +1,30 @@
|
||||||
use clap::Parser;
|
use config::ConfigWrapper;
|
||||||
|
|
||||||
|
|
||||||
// TODO: Possibly use https://docs.rs/ytextract/latest/ytextract/ instead of ytdlp
|
// TODO: Possibly use https://docs.rs/ytextract/latest/ytextract/ instead of ytdlp
|
||||||
|
|
||||||
use crate::cli::CliArgs;
|
|
||||||
|
|
||||||
mod cli;
|
|
||||||
mod manifest;
|
mod manifest;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod downloader;
|
mod downloader;
|
||||||
mod util;
|
mod util;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod prompt;
|
mod prompt;
|
||||||
|
mod config;
|
||||||
|
mod constants;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let mut cli_args = CliArgs::parse();
|
let Ok(cfg) = ConfigWrapper::parse().await else {
|
||||||
cli_args.populate_extra();
|
return;
|
||||||
logger::init_logger(cli_args.debug);
|
};
|
||||||
|
|
||||||
let manifest = match manifest::Manifest::from_path(&cli_args.manifest.as_std_path()) {
|
let mut manifest = match manifest::Manifest::from_path(&cfg.cli.manifest.as_std_path()) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to parse manifest file {}: {e}", cli_args.manifest);
|
log::error!("Failed to parse manifest file {}: {e}", cfg.cli.manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
commands::command_run(&cli_args, &manifest).await;
|
let _ = commands::command_run(&cfg, &mut manifest).await;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::HashMap, fs::read_to_string, path::Path};
|
use std::{collections::HashMap, fs::read_to_string, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -11,6 +11,8 @@ type Genre = String;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Manifest {
|
pub struct Manifest {
|
||||||
|
#[serde(skip)]
|
||||||
|
path: PathBuf,
|
||||||
format: String,
|
format: String,
|
||||||
pub genres: HashMap<Genre, Vec<ManifestSong>>
|
pub genres: HashMap<Genre, Vec<ManifestSong>>
|
||||||
}
|
}
|
||||||
|
@ -35,13 +37,35 @@ pub struct ManifestSong {
|
||||||
|
|
||||||
|
|
||||||
impl Manifest {
|
impl Manifest {
|
||||||
pub fn from_string(s: String) -> anyhow::Result<Self> {
|
fn from_string(s: String) -> anyhow::Result<Self> {
|
||||||
let s = serde_json::from_str(&s)?;
|
let s = serde_json::from_str(&s)?;
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_path(p: &Path) -> anyhow::Result<Self> {
|
pub fn from_path(p: &Path) -> anyhow::Result<Self> {
|
||||||
let data = read_to_string(p)?;
|
let data = read_to_string(p)?;
|
||||||
Self::from_string(data)
|
let mut s = Self::from_string(data)?;
|
||||||
|
s.path = p.to_path_buf();
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_song(&mut self, genre: String, name: String, url: String) -> anyhow::Result<()> {
|
||||||
|
let Some(genre_ref) = self.genres.get_mut(&genre) else {
|
||||||
|
log::error!("Invalid genre '{}'", genre);
|
||||||
|
bail!("Invalid genre")
|
||||||
|
};
|
||||||
|
|
||||||
|
genre_ref.push(ManifestSong {
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> anyhow::Result<()> {
|
||||||
|
let data = serde_json::to_string_pretty(self)?;
|
||||||
|
std::fs::write(&self.path, data)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,9 +4,9 @@ use std::{collections::HashMap, io::Write};
|
||||||
|
|
||||||
pub fn simple_prompt(p: &str) -> String {
|
pub fn simple_prompt(p: &str) -> String {
|
||||||
|
|
||||||
print!("{c}prompt{r}: {p}",
|
print!("{c}prompt{r}: {p} > ",
|
||||||
c=anstyle::AnsiColor::Magenta.render_fg(),
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
r=anstyle::Style::new().render_reset()
|
r=anstyle::Reset.render()
|
||||||
);
|
);
|
||||||
|
|
||||||
// I dont care if it fails
|
// I dont care if it fails
|
||||||
|
@ -15,13 +15,13 @@ pub fn simple_prompt(p: &str) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let _ = std::io::stdin().read_line(&mut buf);
|
let _ = std::io::stdin().read_line(&mut buf);
|
||||||
|
|
||||||
buf
|
buf.trim().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prompt_with_options(p: &str, options: &[&str]) -> usize {
|
pub fn prompt_with_list(p: &str, options: &[&str]) -> usize {
|
||||||
println!("{c}prompt{r}: {p}",
|
println!("{c}prompt{r}: {p}",
|
||||||
c=anstyle::AnsiColor::Magenta.render_fg(),
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
r=anstyle::Style::new().render_reset()
|
r=anstyle::Reset.render()
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i, op) in options.iter().enumerate() {
|
for (i, op) in options.iter().enumerate() {
|
||||||
|
@ -39,19 +39,47 @@ pub fn prompt_with_options(p: &str, options: &[&str]) -> usize {
|
||||||
if num <= options.len() {
|
if num <= options.len() {
|
||||||
return num;
|
return num;
|
||||||
} else {
|
} else {
|
||||||
log::error!("Number not in range");
|
return prompt_with_list(p, options);
|
||||||
return prompt_with_options(p, options);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("Not a number");
|
return prompt_with_list(p, options);
|
||||||
return prompt_with_options(p, options);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prompt_with_named_options(p: &str, options: HashMap<&str, &str>) -> String {
|
pub fn prompt_with_list_or_str(p: &str, options: &[String]) -> String {
|
||||||
|
println!("{c}prompt{r}: {p} (select with number or input text)",
|
||||||
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
|
r=anstyle::Reset.render()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (i, op) in options.iter().enumerate() {
|
||||||
|
println!(" - {}: {}", i, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
print!("> ");
|
||||||
|
// I dont care if it fails
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
|
||||||
|
let mut buf = String::new();
|
||||||
|
let _ = std::io::stdin().read_line(&mut buf);
|
||||||
|
|
||||||
|
if let Ok(num) = buf.trim().parse::<usize>() {
|
||||||
|
if let Some(g) = options.get(num) {
|
||||||
|
return g.clone();
|
||||||
|
} else {
|
||||||
|
return prompt_with_list_or_str(p, options);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return buf.trim().to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn prompt_with_map(p: &str, options: HashMap<&str, &str>) -> String {
|
||||||
println!("{c}prompt{r}: {p}",
|
println!("{c}prompt{r}: {p}",
|
||||||
c=anstyle::AnsiColor::Magenta.render_fg(),
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
r=anstyle::Style::new().render_reset()
|
r=anstyle::Reset.render()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut keys = Vec::new();
|
let mut keys = Vec::new();
|
||||||
|
@ -69,7 +97,52 @@ pub fn prompt_with_named_options(p: &str, options: HashMap<&str, &str>) -> Strin
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let _ = std::io::stdin().read_line(&mut buf);
|
let _ = std::io::stdin().read_line(&mut buf);
|
||||||
if !keys.contains(&buf.trim().to_lowercase()) {
|
if !keys.contains(&buf.trim().to_lowercase()) {
|
||||||
return prompt_with_named_options(p, options);
|
return prompt_with_map(p, options);
|
||||||
|
}
|
||||||
|
buf.trim().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prompt_bool(p: &str, default: Option<bool>) -> bool {
|
||||||
|
if default == Some(true) {
|
||||||
|
println!("{c}prompt{r}: {p} (Y/n)",
|
||||||
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
|
r=anstyle::Reset.render()
|
||||||
|
);
|
||||||
|
} else if default == Some(false) {
|
||||||
|
println!("{c}prompt{r}: {p} (y/N)",
|
||||||
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
|
r=anstyle::Reset.render()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("{c}prompt{r}: {p} (y/n)",
|
||||||
|
c=anstyle::AnsiColor::Cyan.render_fg(),
|
||||||
|
r=anstyle::Reset.render()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
print!("> ");
|
||||||
|
|
||||||
|
// I dont care if it fails
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
|
||||||
|
let mut buf = String::new();
|
||||||
|
let _ = std::io::stdin().read_line(&mut buf);
|
||||||
|
|
||||||
|
if buf.trim().is_empty() {
|
||||||
|
match default {
|
||||||
|
Some(true) => return true,
|
||||||
|
Some(false) => return false,
|
||||||
|
None => {
|
||||||
|
return prompt_bool(p, default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match buf.to_lowercase().trim() {
|
||||||
|
"y" => true,
|
||||||
|
"n" => false,
|
||||||
|
c => {
|
||||||
|
log::error!("'{c}' is invalid, type y (yes) or n (no)");
|
||||||
|
return prompt_bool(p, default);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,22 @@
|
||||||
|
use std::{io::Write, path::PathBuf};
|
||||||
|
|
||||||
fn is_program_in_path(program: &str) -> Option<String> {
|
use crate::constants;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn is_program_in_path(program: &str) -> Option<PathBuf> {
|
||||||
if let Ok(path) = std::env::var("PATH") {
|
if let Ok(path) = std::env::var("PATH") {
|
||||||
for p in path.split(":") {
|
for p in path.split(constants::PATH_VAR_SEP) {
|
||||||
let p_str = format!("{}/{}", p, program);
|
let exec_path = PathBuf::from(p).join(program).with_extension(constants::EXEC_EXT);
|
||||||
if std::fs::metadata(&p_str).is_ok() {
|
if std::fs::metadata(&exec_path).is_ok() {
|
||||||
return Some(p_str);
|
return Some(exec_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn get_ytdlp_path() -> String {
|
|
||||||
if let Some(p) = is_program_in_path("yt-dlp") {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
// TODO: Download yt-dlp to ./.bin/yt-dlp if doesnt exist
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_family="unix")]
|
#[cfg(target_family="unix")]
|
||||||
pub fn isatty() -> bool {
|
pub fn isatty() -> bool {
|
||||||
use std::{ffi::c_int, os::fd::AsRawFd};
|
use std::{ffi::c_int, os::fd::AsRawFd};
|
||||||
|
@ -46,3 +42,13 @@ pub fn isatty() -> bool {
|
||||||
ret.is_ok()
|
ret.is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn dl_to_file(url: &str, p: PathBuf) -> anyhow::Result<()> {
|
||||||
|
log::info!("Downloading {} -> {:?}", url, p);
|
||||||
|
let ytdlp_req = reqwest::get(url).await?.bytes().await?;
|
||||||
|
log::debug!("Downloading {:?} finished, writing to file", p);
|
||||||
|
let mut fd = std::fs::File::create(&p)?;
|
||||||
|
fd.write(&ytdlp_req)?;
|
||||||
|
log::debug!("Finished writing {:?}", p);
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user