From eb6411dff11fd034a06e4f4f3c30c005eec861d8 Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Sun, 18 Feb 2024 18:27:19 +0200 Subject: [PATCH 1/6] add pyo3 crate --- Cargo.lock | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 3 +- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4ddd7c..e84ecf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -518,6 +518,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + [[package]] name = "ipnet" version = "2.8.0" @@ -566,6 +572,16 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.20" @@ -578,6 +594,15 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -620,6 +645,7 @@ version = "0.1.0" dependencies = [ "anyhow", "dotenv", + "pyo3", "teloxide", "tokio", ] @@ -726,6 +752,29 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "smallvec", + "windows-targets", +] + [[package]] name = "percent-encoding" version = "2.3.0" @@ -803,6 +852,67 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pyo3" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07426f0d8fe5a601f26293f300afd1a7b1ed5e78b2a705870c5f30893c5163be" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb7dec17e17766b46bca4f1a4215a85006b4c2ecde122076c562dd058da6cf1" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f738b4e40d50b5711957f142878cfa0f28e054aa0ebdfc3fd137a843f74ed3" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn 2.0.37", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc910d4851847827daf9d6cdd4a823fbdaab5b8818325c5e97a86da79e8881f" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "quote" version = "1.0.33" @@ -830,6 +940,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "reqwest" version = "0.11.22" @@ -1022,6 +1141,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + [[package]] name = "socket2" version = "0.4.9" @@ -1103,6 +1228,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e" +[[package]] +name = "target-lexicon" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" + [[package]] name = "teloxide" version = "0.12.2" @@ -1180,7 +1311,7 @@ checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", "windows-sys", ] @@ -1346,6 +1477,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + [[package]] name = "url" version = "2.4.1" diff --git a/Cargo.toml b/Cargo.toml index aac67f1..c44ef3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,6 @@ edition = "2021" [dependencies] anyhow = "1.0.75" dotenv = "0.15.0" -teloxide = { version = "0.12.2", features = ["macros"] } tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros"] } +teloxide = { version = "0.12.2", features = ["macros"] } +pyo3 = { version = "0.20.2", features = ["extension-module", "auto-initialize"] } From 8c8a4ad3ab3687329aa93041e2787218a57fb64f Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Sun, 18 Feb 2024 18:27:51 +0200 Subject: [PATCH 2/6] begin implementing downloader functionality --- src/dl.rs | 1 + src/dl/download.rs | 0 src/main.rs | 2 ++ 3 files changed, 3 insertions(+) create mode 100644 src/dl.rs create mode 100644 src/dl/download.rs diff --git a/src/dl.rs b/src/dl.rs new file mode 100644 index 0000000..3137393 --- /dev/null +++ b/src/dl.rs @@ -0,0 +1 @@ +pub mod download; \ No newline at end of file diff --git a/src/dl/download.rs b/src/dl/download.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index a09ffb3..f7a5612 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,8 @@ use teloxide::dispatching::dialogue::InMemStorage; use teloxide::dispatching::UpdateHandler; use teloxide::{prelude::*, update_listeners::Polling, utils::command::BotCommands}; +mod dl; + type State = (); type MyDialogue = Dialogue>; From 9929dc6606b756a7a32d90f1e06256a7ca9a55bd Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Sun, 18 Feb 2024 18:56:14 +0200 Subject: [PATCH 3/6] set teloxide to upstream git instead of crates one to fix issues --- Cargo.lock | 82 +++++++++++++++++++++++++++++++++++++++++------------- Cargo.toml | 2 +- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e84ecf4..9db0791 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -25,15 +38,16 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "aquamarine" -version = "0.1.12" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941c39708478e8eea39243b5983f1c42d2717b3620ee91f4a52115fd02ac43f" +checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" dependencies = [ + "include_dir", "itertools", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.37", ] [[package]] @@ -508,6 +522,25 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -532,9 +565,9 @@ checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "itertools" -version = "0.9.0" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -668,12 +701,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "never" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91" - [[package]] name = "num-traits" version = "0.2.16" @@ -1237,20 +1264,20 @@ checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" [[package]] name = "teloxide" version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c63345cf32a8850ebddcdd769dc2d5193d5e231262d5dada264b79da01a664da" +source = "git+https://github.com/teloxide/teloxide#4adfcecef37b6c86e0d189946079d8e93adbfb19" dependencies = [ + "ahash", "aquamarine", "bytes", "derive_more", "dptree", + "either", "futures", "log", "mime", "pin-project", "serde", "serde_json", - "serde_with_macros", "teloxide-core", "teloxide-macros", "thiserror", @@ -1263,8 +1290,7 @@ dependencies = [ [[package]] name = "teloxide-core" version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "303db260110c238e3af77bb9dff18bf7a5b5196f783059b0852aab75f91d5a16" +source = "git+https://github.com/teloxide/teloxide#4adfcecef37b6c86e0d189946079d8e93adbfb19" dependencies = [ "bitflags 1.3.2", "bytes", @@ -1274,7 +1300,6 @@ dependencies = [ "futures", "log", "mime", - "never", "once_cell", "pin-project", "rc-box", @@ -1294,8 +1319,7 @@ dependencies = [ [[package]] name = "teloxide-macros" version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1d653b093dba5e44cada57a516f572167df37b8a619443e59c8c517bb6d804" +source = "git+https://github.com/teloxide/teloxide#4adfcecef37b6c86e0d189946079d8e93adbfb19" dependencies = [ "heck", "proc-macro2", @@ -1717,3 +1741,23 @@ dependencies = [ "cfg-if", "windows-sys", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] diff --git a/Cargo.toml b/Cargo.toml index c44ef3f..e53bc80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,5 +9,5 @@ edition = "2021" anyhow = "1.0.75" dotenv = "0.15.0" tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros"] } -teloxide = { version = "0.12.2", features = ["macros"] } +teloxide = { version = "0.12.2", git ="https://github.com/teloxide/teloxide", features = ["macros"] } pyo3 = { version = "0.20.2", features = ["extension-module", "auto-initialize"] } From 14393d35be80b39203983c8410e519bc2d731a63 Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Sun, 18 Feb 2024 19:12:21 +0200 Subject: [PATCH 4/6] remove dead code --- src/main.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index f7a5612..ac0fc0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use anyhow; use dotenv::dotenv; +use teloxide::dispatching::dialogue::GetChatId; use std::env; use std::fmt; use std::str; @@ -11,6 +12,7 @@ use teloxide::dispatching::UpdateHandler; use teloxide::{prelude::*, update_listeners::Polling, utils::command::BotCommands}; mod dl; +use dl::download::download; type State = (); type MyDialogue = Dialogue>; @@ -59,7 +61,9 @@ fn schema() -> UpdateHandler { use dptree::case; let command_handler = - teloxide::filter_command::().branch(case![Command::Test].endpoint(test)); + teloxide::filter_command::() + .branch(case![Command::Test].endpoint(test)); + //.branch(case![Command::Download(download)].endpoint(download)); let message_handler = Update::filter_message().branch(command_handler); let raw_message_handler = Update::filter_message().branch(dptree::endpoint(handle_message)); @@ -73,6 +77,9 @@ fn schema() -> UpdateHandler { #[command(rename_rule = "lowercase")] enum Command { Test, + + #[command(alias = "dl")] + Download(String), } async fn test(bot: Bot, msg: Message) -> HandlerResult { @@ -91,13 +98,3 @@ async fn handle_message(_bot: Bot, _dialogue: MyDialogue, msg: Message) -> Handl Ok(()) } - -async fn _answer(bot: Bot, msg: Message, cmd: Command) -> ResponseResult<()> { - match cmd { - Command::Test => { - bot.send_message(msg.chat.id, "test response").await?; - } - } - - Ok(()) -} From 161138544e660108fcee1418d8abf97ecdc2875a Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Sun, 18 Feb 2024 19:29:36 +0200 Subject: [PATCH 5/6] implement yt-dlp FFI and working bot command to download --- src/dl.rs | 2 +- src/dl/download.rs | 28 ++++++++++++++++++++++++++++ src/main.rs | 16 ++++++++++++---- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/dl.rs b/src/dl.rs index 3137393..674b799 100644 --- a/src/dl.rs +++ b/src/dl.rs @@ -1 +1 @@ -pub mod download; \ No newline at end of file +pub mod download; diff --git a/src/dl/download.rs b/src/dl/download.rs index e69de29..2ee31cc 100644 --- a/src/dl/download.rs +++ b/src/dl/download.rs @@ -0,0 +1,28 @@ +use pyo3::prelude::*; +use tokio::task::{spawn_blocking, JoinError}; + +pub async fn download_url(url: String) -> Result { + spawn_blocking(move || { + let res: PyResult<()> = Python::with_gil(|py| { + let yt_dlp = PyModule::import(py, "yt_dlp")?; + let yt = yt_dlp.getattr("YoutubeDL")?; + + let yt_obj = yt.call((), None)?; + + yt_obj.call_method0("__enter__")?; + yt_obj.call_method1("download", (url,))?; + yt_obj.call_method0("__exit__")?; + + Ok(()) + }); + + match res { + Ok(_) => true, + Err(e) => { + println!("{}", e); + false + } + } + }) + .await +} diff --git a/src/main.rs b/src/main.rs index ac0fc0b..1eac791 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ use anyhow; use dotenv::dotenv; -use teloxide::dispatching::dialogue::GetChatId; use std::env; use std::fmt; use std::str; @@ -12,7 +11,7 @@ use teloxide::dispatching::UpdateHandler; use teloxide::{prelude::*, update_listeners::Polling, utils::command::BotCommands}; mod dl; -use dl::download::download; +use dl::download::download_url; type State = (); type MyDialogue = Dialogue>; @@ -62,8 +61,8 @@ fn schema() -> UpdateHandler { let command_handler = teloxide::filter_command::() - .branch(case![Command::Test].endpoint(test)); - //.branch(case![Command::Download(download)].endpoint(download)); + .branch(case![Command::Test].endpoint(test)) + .branch(case![Command::Download(url)].endpoint(download)); let message_handler = Update::filter_message().branch(command_handler); let raw_message_handler = Update::filter_message().branch(dptree::endpoint(handle_message)); @@ -88,6 +87,15 @@ async fn test(bot: Bot, msg: Message) -> HandlerResult { Ok(()) } +async fn download(bot: Bot, msg: Message, url: String) -> HandlerResult { + match download_url(url).await { + Ok(_) => bot.send_message(msg.chat.id, "downloaded"), + Err(_) => bot.send_message(msg.chat.id, "failed to download") + }.await?; + + Ok(()) +} + async fn handle_message(_bot: Bot, _dialogue: MyDialogue, msg: Message) -> HandlerResult { println!( "msg {} kind {:?} text {}", From 20f9aec334141eccaa752a866e6e371596da8447 Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Sun, 18 Feb 2024 20:02:32 +0200 Subject: [PATCH 6/6] add todo reminder to ditch pyo3 ffi because of lack subinterpreter support --- src/dl/download.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dl/download.rs b/src/dl/download.rs index 2ee31cc..f12903b 100644 --- a/src/dl/download.rs +++ b/src/dl/download.rs @@ -1,6 +1,7 @@ use pyo3::prelude::*; use tokio::task::{spawn_blocking, JoinError}; +// TODO: Switch to Command::new for true multithreading and async pub async fn download_url(url: String) -> Result { spawn_blocking(move || { let res: PyResult<()> = Python::with_gil(|py| {