1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use grammers_client::types::{Chat, Message};
use grammers_client::{Client, InputMessage};
use reqwest;
use std::error::Error;

use crate::db::Database;

use super::{get_message_video, whisper};

pub async fn handle_message(
    tg: &mut Client,
    message: &Message,
    db: &mut Database,
) -> Result<(), Box<dyn std::error::Error>> {
    let output = if is_youtube_url(message.text()) {
        let youtube_url = message.text().to_string();
        if is_youtube_video(&youtube_url).await {
            let args = vec!["-y", &youtube_url, "-p", "extract_wisdom"];
            super::fabric::execute_fabric_command(&args).await?
        } else {
            "Invalid YouTube URL or not a video".to_owned()
        }
    } else if crate::handlers::has_video(&message) {
        // let _ = send_response(tg, &message.chat(), "/w", Some(message.id())).await;

        let message_media = get_message_video(&message);

        let media_path = match message_media {
            Some(media) => Some(crate::handlers::download_media(tg, media, message.id()).await),
            None => None,
        };

        let mut output = match media_path {
            Some(path) => whisper::whisper_rs(&path, db.get_whisper_model()).await,
            None => "".to_owned(),
        };

        if output.starts_with("🚫") {
            output = "".to_owned();
        }

        output
    } else {
        "".to_owned()
    };

    if !output.is_empty() {
        send_response(tg, &message.chat(), &output, message.reply_to_message_id()).await
    } else {
        Ok(())
    }
}

async fn is_youtube_video(youtube_url: &str) -> bool {
    let checker_url = format!("https://www.youtube.com/oembed?url={}", youtube_url);
    match reqwest::get(&checker_url).await {
        Ok(response) => response.status().is_success(),
        Err(_) => false,
    }
}

fn is_youtube_url(text: &str) -> bool {
    text.contains("youtube.com") || text.contains("youtu.be")
}

async fn send_response(
    tg: &Client,
    chat: &Chat,
    message: &str,
    reply_to: Option<i32>,
) -> Result<(), Box<dyn Error>> {
    // println!("message: {}", message);
    let chunk_size = 4096;

    // Handle the message in chunks
    let mut start = 0;
    let mut end;

    while start < message.len() {
        end = start + chunk_size;

        // Make sure we don't exceed the message length
        if end > message.len() {
            end = message.len();
        } else {
            // Ensure that we split at valid UTF-8 character boundaries
            while !message.is_char_boundary(end) {
                end -= 1;
            }

            // Now try to find the last whitespace (or newline) before the limit to split cleanly
            if let Some(last_space) = message[start..end].rfind(|c: char| c == ' ' || c == '\n') {
                end = start + last_space;
            }
        }

        // Send the chunk (from start to end)
        // println!("send_message: {}", &message[start..end]);
        tg.send_message(
            chat,
            InputMessage::text(&message[start..end]).reply_to(reply_to),
        )
        .await?;

        // Move start to end to process the next chunk
        start = end;

        // Skip any leading whitespace or newline in the next chunk
        while start < message.len() && message[start..].starts_with(|c: char| c == ' ' || c == '\n')
        {
            start += 1;
        }
    }

    Ok(())
}