Skip to main content

vk_bot_api/
utils.rs

1use chrono::{DateTime, Utc};
2use serde_json::json;
3
4#[cfg(feature = "uuid")]
5use uuid::Uuid;
6
7/// Generate random ID for messages
8pub fn generate_random_id() -> i64 {
9    #[cfg(feature = "uuid")]
10    {
11        let uuid = Uuid::new_v4();
12        (uuid.as_u128() & 0x7FFFFFFFFFFFFFFF) as i64
13    }
14
15    #[cfg(not(feature = "uuid"))]
16    {
17        use std::time::{SystemTime, UNIX_EPOCH};
18        SystemTime::now()
19            .duration_since(UNIX_EPOCH)
20            .map(|d| d.as_millis() as i64)
21            .unwrap_or(0)
22    }
23}
24
25/// Parse VK date string to DateTime
26pub fn parse_vk_date(date: i64) -> DateTime<Utc> {
27    DateTime::from_timestamp(date, 0).unwrap_or_else(Utc::now)
28}
29
30/// Format date for display
31pub fn format_date(date: i64) -> String {
32    let dt = parse_vk_date(date);
33    dt.format("%Y-%m-%d %H:%M:%S").to_string()
34}
35
36/// Create mention string for user
37pub fn create_mention(user_id: i64, text: &str) -> String {
38    format!("[id{}|{}]", user_id, text)
39}
40
41/// Create hash tag
42pub fn create_hashtag(tag: &str) -> String {
43    format!("#{}", tag.replace(' ', "_"))
44}
45
46/// Parse payload from string
47pub fn parse_payload(payload: &str) -> Option<serde_json::Value> {
48    serde_json::from_str(payload).ok()
49}
50
51/// Create payload for button
52pub fn create_payload(command: &str, data: Option<serde_json::Value>) -> serde_json::Value {
53    let mut payload = json!({
54        "command": command,
55    });
56
57    if let Some(data) = data
58        && let Some(obj) = payload.as_object_mut()
59    {
60        for (key, value) in data.as_object().unwrap() {
61            obj.insert(key.clone(), value.clone());
62        }
63    }
64
65    payload
66}
67
68/// Escape special characters for VK
69pub fn escape_text(text: &str) -> String {
70    text.replace('&', "&amp;")
71        .replace('<', "&lt;")
72        .replace('>', "&gt;")
73}
74
75/// Truncate text for preview
76pub fn truncate_text(text: &str, max_len: usize) -> String {
77    if text.len() <= max_len {
78        text.to_string()
79    } else {
80        format!("{}...", &text[..max_len - 3])
81    }
82}
83
84/// Split message into chunks (VK has 4096 char limit)
85pub fn split_message(text: &str, max_chunk_size: usize) -> Vec<String> {
86    let mut chunks = Vec::new();
87    let mut remaining = text;
88
89    while remaining.len() > max_chunk_size {
90        let split_pos = remaining[..max_chunk_size]
91            .rfind('\n')
92            .unwrap_or(max_chunk_size);
93
94        chunks.push(remaining[..split_pos].to_string());
95        remaining = &remaining[split_pos..];
96
97        if remaining.starts_with('\n') {
98            remaining = &remaining[1..];
99        }
100    }
101
102    if !remaining.is_empty() {
103        chunks.push(remaining.to_string());
104    }
105
106    chunks
107}