implement telegram bot

This commit is contained in:
Oleg Sobolev 2024-03-25 16:22:00 +07:00
parent d00353fd5e
commit cae6454f96
6 changed files with 1442 additions and 29 deletions

1317
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,4 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
futures = "0.3.30"
rodio = "0.17.3" rodio = "0.17.3"
teloxide = { version = "0.12", features = ["macros"] }
log = "0.4"
pretty_env_logger = "0.5"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }

View file

@ -1,7 +1,7 @@
mod track;
pub mod channel; pub mod channel;
pub mod download; pub mod download;
pub mod player; pub mod player;
pub mod telegram;
mod track;
pub use track::TrackInfo; pub use track::TrackInfo;

View file

@ -1,15 +1,7 @@
use music_bot::{download, MusicPlayer, TrackInfo}; use music_bot::{player::MusicPlayer, telegram};
use std::{path::Path, process::Command, thread, time::Duration};
fn main() { fn main() {
// let url = "https://www.youtube.com/watch?v=UnIhRpIT7nc"; let player = MusicPlayer::new();
let url = "https://www.youtube.com/watch?v=8bB0FNGlrEs"; let mut bot = telegram::TelegramBot::build(player);
let track = download::download_from_youtube(url); bot.telegram_main();
let mut player = MusicPlayer::new();
player.enqueue(track.clone());
player.enqueue(track.clone());
thread::sleep(Duration::from_secs(5));
player.skip_one();
thread::sleep(Duration::from_secs(600));
} }

View file

@ -1,13 +1,7 @@
use crate::channel::{self, Requester, Responder, TryRecvError}; use crate::channel::{self, Requester, Responder, TryRecvError};
use crate::track::TrackInfo; use crate::track::TrackInfo;
use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink}; use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink};
use std::{ use std::{collections::VecDeque, fs::File, io::BufReader, thread, thread::JoinHandle};
collections::VecDeque,
fs::File,
io::BufReader,
thread,
thread::JoinHandle,
};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum WorkerRequest { enum WorkerRequest {

121
src/telegram.rs Normal file
View file

@ -0,0 +1,121 @@
use std::{
path::Path,
sync::{Arc, Mutex},
};
use teloxide::{prelude::*, utils::command::BotCommands};
use crate::{player::MusicPlayer, TrackInfo};
#[derive(BotCommands, Clone)]
#[command(
rename_rule = "lowercase",
description = "These commands are supported:"
)]
enum Command {
#[command(description = "play youtube url.")]
Play(String),
#[command(description = "stop playing.")]
Stop,
#[command(description = "pause playing.")]
Pause,
#[command(description = "resume playing.")]
Resume,
#[command(description = "skip the track that is playing.")]
Skip,
#[command(description = "list all tracks in queue.")]
List,
}
#[derive(Clone, Default)]
enum State {
#[default]
Start,
}
pub struct TelegramBot {
player: Arc<Mutex<MusicPlayer>>,
}
impl TelegramBot {
async fn handle_command(
bot: Bot,
msg: Message,
player: Arc<Mutex<MusicPlayer>>,
cmd: Command,
) -> Result<(), teloxide::RequestError> {
match cmd {
Command::Play(url) => {
println!("{}", url);
player
.lock()
.unwrap()
.enqueue(TrackInfo::new(Path::new("8bB0FNGlrEs.mp3")));
bot.send_message(msg.chat.id, "Added to the queue.").await?;
}
Command::Stop => {
player.lock().unwrap().stop();
bot.send_message(msg.chat.id, "Stopped.").await?;
}
Command::Pause => {
player.lock().unwrap().pause();
bot.send_message(msg.chat.id, "Paused.").await?;
}
Command::Resume => {
player.lock().unwrap().play();
bot.send_message(msg.chat.id, "Resumed.").await?;
}
Command::Skip => {
player.lock().unwrap().skip_one();
bot.send_message(msg.chat.id, "Skipped.").await?;
}
Command::List => {
let tracks = player.lock().unwrap().list_tracks();
bot.send_message(
msg.chat.id,
tracks
.iter()
.map(|t| t.path.to_str().unwrap())
.collect::<Vec<&str>>()
.join("\n"),
)
.await?;
}
};
Ok(())
}
async fn async_telegram_main(&mut self) {
pretty_env_logger::init();
log::info!("Starting bot...");
let bot = Bot::from_env();
Dispatcher::builder(
bot,
Update::filter_message().branch(
dptree::entry()
.filter_command::<Command>()
.endpoint(Self::handle_command),
),
)
.dependencies(dptree::deps![self.player.clone()])
.build()
.dispatch()
.await;
}
pub fn telegram_main(&mut self) {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(async move { self.async_telegram_main().await })
}
pub fn build(player: MusicPlayer) -> TelegramBot {
TelegramBot {
player: Arc::new(Mutex::new(player)),
}
}
}