mirror of
https://framagit.org/veretcle/tootube.git
synced 2025-07-20 20:41:17 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1db91ec3dc | ||
![]() |
1d4ae8f152 | ||
![]() |
58f36a56f7 | ||
![]() |
e17ba6cf7e | ||
![]() |
3d53ad7bbd | ||
![]() |
3f482ff258 | ||
![]() |
ae3fa74d9b | ||
![]() |
62641f526f |
234
Cargo.lock
generated
234
Cargo.lock
generated
@@ -61,7 +61,7 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -71,7 +71,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
|
||||
dependencies = [
|
||||
"async-stream-impl",
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream-impl"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -109,9 +131,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
@@ -173,6 +195,19 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"unicode-width",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
@@ -189,6 +224,12 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.33"
|
||||
@@ -218,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -452,6 +493,28 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
|
||||
dependencies = [
|
||||
"console",
|
||||
"instant",
|
||||
"number_prefix",
|
||||
"portable-atomic",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.8.0"
|
||||
@@ -466,7 +529,7 @@ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -557,7 +620,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -588,6 +651,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
@@ -609,7 +678,7 @@ version = "0.10.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
@@ -667,7 +736,7 @@ dependencies = [
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -694,6 +763,12 @@ version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
@@ -723,9 +798,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.0"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -735,9 +810,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.1"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465c6fc0621e4abc4187a2bda0937bfd4f722c2730b29562e19689ea796c9a4b"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -746,9 +821,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
@@ -799,15 +874,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.18"
|
||||
version = "0.38.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c"
|
||||
checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -822,7 +897,7 @@ version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -856,18 +931,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
version = "1.0.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.188"
|
||||
version = "1.0.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -938,7 +1013,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -989,7 +1064,7 @@ dependencies = [
|
||||
"fastrand",
|
||||
"redox_syscall",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1032,7 +1107,7 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
"socket2 0.5.4",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1081,12 +1156,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tootube"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"bytes",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"indicatif",
|
||||
"log",
|
||||
"reqwest",
|
||||
"serde",
|
||||
@@ -1102,20 +1179,19 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
version = "0.1.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.31"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
|
||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
@@ -1156,6 +1232,12 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.4.1"
|
||||
@@ -1320,13 +1402,37 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1335,51 +1441,93 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
@@ -1393,5 +1541,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
10
Cargo.toml
10
Cargo.toml
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tootube"
|
||||
authors = ["VC <veretcle+framagit@mateu.be>"]
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -10,12 +10,14 @@ edition = "2021"
|
||||
reqwest = { version = "^0.11", features = ["json", "stream", "multipart"] }
|
||||
tokio = { version = "^1", features = ["full"] }
|
||||
clap = "^4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde = { version = "^1", features = ["derive"] }
|
||||
toml = "^0.5"
|
||||
log = "^0.4"
|
||||
env_logger = "^0.10"
|
||||
futures-core = "0.3.28"
|
||||
bytes = "1.5.0"
|
||||
bytes = "^1.5"
|
||||
indicatif = "^0.17"
|
||||
async-stream = "^0.3"
|
||||
futures-util = "^0.3"
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
|
55
README.md
55
README.md
@@ -6,50 +6,57 @@ This program takes the very last video published on a PeerTube instance and push
|
||||
|
||||
This is an early prototype not really suited for production purposes for now:
|
||||
* it still relies way too much on pre-determined value to upload the video to YouTube
|
||||
* it cannot determine the playlists it needs to put them in
|
||||
* it cannot determine the recording date (believe me, I tried!)
|
||||
* there are still a lot of static values that I would rather not have static (like the cache directory…)
|
||||
* it is 100% sync, meaning it’s clearly not optimal for now and probably won’t be for the next releases
|
||||
|
||||
So consider this a work in progress that will slowly get better with time
|
||||
So consider this a work in progress that will slowly get better with time.
|
||||
|
||||
# What does it do exactly?
|
||||
|
||||
* it downloads the latest PeerTube video from an instance
|
||||
* stores it in cache directory
|
||||
* uploads it to YouTube
|
||||
* it retrieves the latest PeerTube video download URL from an instance
|
||||
* it creates a resumable upload into the target YouTube account
|
||||
* it downloads/uploads the latest PeerTube video to YouTube without using a cache (stream-to-stream)
|
||||
|
||||
# What doesn’t it do exactly?
|
||||
|
||||
* it cannot register the original key (see below)
|
||||
* it relies on a local cache despite the fact that it might well be possible to just download from PT/upload to YT at the same time (I don’t see why not in fact)
|
||||
* it doesn’t retrieve ALL the original PeerTube video properties like licences, languages, categories, etc… again: early prototype
|
||||
|
||||
# Obtain Authorization Token from Google
|
||||
# Howtos
|
||||
## General usage
|
||||
|
||||
That the complicated part:
|
||||
* create an OAuth2.0 application with authorization for Youtube DATA Api v3 Upload
|
||||
Once you fill your `tootube.toml` config file (see below), you can run `tootube` like this:
|
||||
|
||||
```bash
|
||||
tootube --config tootube.toml --playlist playlist_1 "Things You Might Like"
|
||||
```
|
||||
|
||||
You can turn on debug using env var `RUST_LOG`.
|
||||
|
||||
## Obtain Authorization Token from Google
|
||||
|
||||
The complicated part:
|
||||
* create an OAuth2.0 application with authorization for Youtube DATA Api v3 Upload and Youtube DATA Api v3 (generally referenced as `../auth/youtube.upload` and `../auth/youtube`)
|
||||
* create a OAuth2.0 client with Desktop client
|
||||
|
||||
You’ll need:
|
||||
* the `client_id` from your OAuth2.0 client
|
||||
* the `client_secret` from you OAuth2.0 client
|
||||
|
||||
Then enter in:
|
||||
Create your `tootube.toml` config file:
|
||||
|
||||
```
|
||||
https://accounts.google.com/o/oauth2/v2/auth?client_id=XXX.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/youtube.upload&response_type=code
|
||||
```toml
|
||||
[peertube]
|
||||
base_url="https://p.nintendojo.fr"
|
||||
|
||||
[youtube]
|
||||
refresh_token="" # leave empty for now
|
||||
client_id="<YOUR CLIENT_ID>"
|
||||
client_secret="<YOUR CLIENT_SECRET>"
|
||||
```
|
||||
|
||||
And accept that your YouTube account might be modified. You’ll get a code then; enter this `curl` post:
|
||||
Then run:
|
||||
|
||||
```
|
||||
curl -s \
|
||||
--request POST \
|
||||
--data "code=[THE_CODE]&client_id=XXX.apps.googleusercontent.com&client_secret=[THE_CLIENT_SECRET]&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code" \
|
||||
https://accounts.google.com/o/oauth2/token
|
||||
```bash
|
||||
tootube register --config <PATH TO YOUR TOOTUBE.TOML FILE>
|
||||
```
|
||||
|
||||
You’ll get a Token. The only important part is the `refresh_token`
|
||||
|
||||
In your `tootube.toml` config file, put the `refresh_token`.
|
||||
You’ll be then prompted with all the necessary information to register `tootube`. You’ll end with a `refresh_token` that you can now paste inside your tootube configuration.
|
||||
|
19
src/lib.rs
19
src/lib.rs
@@ -1,5 +1,6 @@
|
||||
use bytes::Bytes;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_util::Stream;
|
||||
use log::debug;
|
||||
use std::error::Error;
|
||||
|
||||
mod error;
|
||||
@@ -17,8 +18,13 @@ use youtube::{add_video_to_playlists, create_resumable_upload, now_kiss};
|
||||
|
||||
async fn get_dl_video_stream(
|
||||
u: &str,
|
||||
) -> Result<impl Stream<Item = Result<Bytes, reqwest::Error>>, Box<dyn Error>> {
|
||||
Ok(reqwest::get(u).await?.bytes_stream())
|
||||
) -> Result<(impl Stream<Item = Result<Bytes, reqwest::Error>>, u64), Box<dyn Error>> {
|
||||
let res = reqwest::get(u).await?;
|
||||
let content_lengh = res
|
||||
.content_length()
|
||||
.ok_or(format!("Cannot get content length from {}", u))?;
|
||||
|
||||
Ok((res.bytes_stream(), content_lengh))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@@ -31,18 +37,21 @@ pub async fn run(config: Config, pl: Vec<String>) {
|
||||
});
|
||||
|
||||
let dl_url = get_max_resolution_dl(latest_vid.streaming_playlists.as_ref().unwrap());
|
||||
debug!("PT download URL: {}", &dl_url);
|
||||
|
||||
let pt_stream = get_dl_video_stream(&dl_url)
|
||||
let (pt_stream, size) = get_dl_video_stream(&dl_url)
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("Cannot download video at URL {}: {}", dl_url, e));
|
||||
|
||||
let resumable_upload_url = create_resumable_upload(&config.youtube, &latest_vid)
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("Cannot retrieve the upload’s resumable id: {e}"));
|
||||
debug!("YT upload URL: {}", &resumable_upload_url);
|
||||
|
||||
let yt_video_id = now_kiss(pt_stream, &resumable_upload_url, &config.youtube)
|
||||
let yt_video_id = now_kiss(size, pt_stream, &resumable_upload_url, &config.youtube)
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("Cannot resume upload!: {e}"));
|
||||
debug!("YT video ID: {}", &yt_video_id);
|
||||
|
||||
if !pl.is_empty() {
|
||||
add_video_to_playlists(&config.youtube, &yt_video_id, &pl)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use serde::Deserialize;
|
||||
use std::{boxed::Box, error::Error};
|
||||
use std::{boxed::Box, cmp::Ordering, error::Error};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct PeerTubeVideos {
|
||||
@@ -22,7 +22,7 @@ pub struct PeerTubeVideoStreamingPlaylists {
|
||||
pub files: Vec<PeerTubeVideoStreamingPlaylistsFiles>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Eq, Debug, Deserialize)]
|
||||
pub struct PeerTubeVideoStreamingPlaylistsFiles {
|
||||
pub id: u64,
|
||||
pub resolution: PeerTubeVideoStreamingPlaylistsFilesResolution,
|
||||
@@ -30,7 +30,25 @@ pub struct PeerTubeVideoStreamingPlaylistsFiles {
|
||||
pub file_download_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
impl Ord for PeerTubeVideoStreamingPlaylistsFiles {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.resolution.id.cmp(&other.resolution.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for PeerTubeVideoStreamingPlaylistsFiles {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PeerTubeVideoStreamingPlaylistsFiles {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.resolution.id == other.resolution.id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Debug, Deserialize, PartialEq)]
|
||||
pub struct PeerTubeVideoStreamingPlaylistsFilesResolution {
|
||||
pub id: u16,
|
||||
}
|
||||
@@ -49,17 +67,7 @@ pub async fn get_latest_video(u: &str) -> Result<PeerTubeVideo, Box<dyn Error>>
|
||||
|
||||
/// This returns the direct download URL for with the maximum resolution
|
||||
pub fn get_max_resolution_dl(p: &[PeerTubeVideoStreamingPlaylists]) -> String {
|
||||
let mut res = 0;
|
||||
let mut dl_url = String::new();
|
||||
|
||||
for i in p[0].files.iter() {
|
||||
if i.resolution.id > res {
|
||||
res = i.resolution.id;
|
||||
dl_url = i.file_download_url.clone();
|
||||
}
|
||||
}
|
||||
|
||||
dl_url
|
||||
p[0].files.iter().max().unwrap().file_download_url.clone()
|
||||
}
|
||||
|
||||
/// This gets all the crispy details about one particular video
|
||||
|
@@ -1,9 +1,17 @@
|
||||
use crate::{config::YoutubeConfig, error::TootubeError, peertube::PeerTubeVideo};
|
||||
use async_stream::stream;
|
||||
use bytes::Bytes;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_util::{Stream, StreamExt};
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use log::debug;
|
||||
use reqwest::{multipart::Form, Body, Client};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{error::Error, io::stdin};
|
||||
use std::{
|
||||
cmp::min,
|
||||
error::Error,
|
||||
io::stdin,
|
||||
marker::{Send, Sync, Unpin},
|
||||
};
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
static ACCESS_TOKEN: OnceCell<String> = OnceCell::const_new();
|
||||
@@ -207,6 +215,7 @@ async fn refresh_token(config: &YoutubeConfig) -> Result<String, reqwest::Error>
|
||||
|
||||
let access_token: AccessTokenResponse = res.json().await?;
|
||||
|
||||
debug!("YT Access Token: {}", &access_token.access_token);
|
||||
Ok(access_token.access_token)
|
||||
})
|
||||
.await
|
||||
@@ -250,6 +259,7 @@ async fn get_playlist_ids(
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Playlists IDs: {:?}", &playlists);
|
||||
Ok(playlists)
|
||||
}
|
||||
|
||||
@@ -273,8 +283,8 @@ pub async fn add_video_to_playlists(
|
||||
..Default::default()
|
||||
},
|
||||
};
|
||||
let client = Client::new();
|
||||
|
||||
let client = Client::new();
|
||||
let res = client
|
||||
.post("https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet")
|
||||
.header("Authorization", format!("Bearer {}", access_token))
|
||||
@@ -316,6 +326,7 @@ pub async fn create_resumable_upload(
|
||||
}
|
||||
},
|
||||
};
|
||||
debug!("YT upload params: {:?}", &upload_params);
|
||||
|
||||
let client = Client::new();
|
||||
let res = client.post("https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet%2Cstatus")
|
||||
@@ -337,23 +348,42 @@ pub async fn create_resumable_upload(
|
||||
|
||||
/// This takes the PT stream for download, connects it to YT stream for upload
|
||||
pub async fn now_kiss<'a>(
|
||||
stream: impl Stream<Item = Result<Bytes, reqwest::Error>>
|
||||
+ std::marker::Send
|
||||
+ std::marker::Sync
|
||||
+ 'a + 'static,
|
||||
size: u64,
|
||||
mut stream: impl Stream<Item = Result<Bytes, reqwest::Error>> + Send + Sync + Unpin + 'a + 'static,
|
||||
r_url: &'a str,
|
||||
config: &'a YoutubeConfig,
|
||||
) -> Result<String, Box<dyn Error>> {
|
||||
// Get access token
|
||||
let access_token = refresh_token(config).await?;
|
||||
|
||||
// Create the progress bar
|
||||
let pb = ProgressBar::new(size);
|
||||
pb.set_style(ProgressStyle::default_bar()
|
||||
.template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})")?
|
||||
.progress_chars("#>-"));
|
||||
pb.set_message("Transferring…");
|
||||
let mut transferring: u64 = 0;
|
||||
|
||||
let async_stream = stream! {
|
||||
while let Some(chunk) = stream.next().await {
|
||||
if let Ok(chunk) = &chunk {
|
||||
let new = min(transferring + (chunk.len() as u64), size);
|
||||
transferring = new;
|
||||
pb.set_position(new);
|
||||
if transferring >= size {
|
||||
pb.finish();
|
||||
}
|
||||
}
|
||||
yield chunk;
|
||||
}
|
||||
};
|
||||
|
||||
// Create client
|
||||
let client = Client::new();
|
||||
|
||||
let res = client
|
||||
.put(r_url)
|
||||
.header("Authorization", format!("Bearer {}", access_token))
|
||||
.body(Body::wrap_stream(stream))
|
||||
.body(Body::wrap_stream(async_stream))
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
|
Reference in New Issue
Block a user