161 lines
5.2 KiB
Rust
161 lines
5.2 KiB
Rust
use std::ffi::CString;
|
||
use std::os::raw::c_char;
|
||
|
||
#[link(name = "tdjson")]
|
||
extern "C" {
|
||
fn td_execute(request: *const c_char) -> *const c_char;
|
||
}
|
||
|
||
/// Отключаем логи TDLib синхронно, до создания клиента
|
||
pub fn disable_tdlib_logs() {
|
||
let request = r#"{"@type":"setLogVerbosityLevel","new_verbosity_level":0}"#;
|
||
let c_request = CString::new(request).unwrap();
|
||
unsafe {
|
||
let _ = td_execute(c_request.as_ptr());
|
||
}
|
||
|
||
// Также перенаправляем логи в никуда
|
||
let request2 = r#"{"@type":"setLogStream","log_stream":{"@type":"logStreamEmpty"}}"#;
|
||
let c_request2 = CString::new(request2).unwrap();
|
||
unsafe {
|
||
let _ = td_execute(c_request2.as_ptr());
|
||
}
|
||
}
|
||
|
||
/// Форматирование timestamp в время HH:MM с учётом timezone offset
|
||
/// timezone_str: строка формата "+03:00" или "-05:00"
|
||
pub fn format_timestamp_with_tz(timestamp: i32, timezone_str: &str) -> String {
|
||
let secs = timestamp as i64;
|
||
|
||
// Парсим timezone offset (например "+03:00" -> 3 часа)
|
||
let offset_hours = parse_timezone_offset(timezone_str);
|
||
|
||
let hours = ((secs % 86400) / 3600) as i32;
|
||
let minutes = ((secs % 3600) / 60) as u32;
|
||
|
||
// Применяем timezone offset
|
||
let local_hours = ((hours + offset_hours) % 24 + 24) % 24;
|
||
|
||
format!("{:02}:{:02}", local_hours, minutes)
|
||
}
|
||
|
||
/// Парсит timezone строку типа "+03:00" в количество часов
|
||
fn parse_timezone_offset(tz: &str) -> i32 {
|
||
// Простой парсинг "+03:00" или "-05:00"
|
||
if tz.len() >= 3 {
|
||
let sign = if tz.starts_with('-') { -1 } else { 1 };
|
||
let hours_str = &tz[1..3];
|
||
if let Ok(hours) = hours_str.parse::<i32>() {
|
||
return sign * hours;
|
||
}
|
||
}
|
||
3 // fallback к MSK
|
||
}
|
||
|
||
/// Устаревшая функция для обратной совместимости (используется дефолтный +03:00)
|
||
#[allow(dead_code)]
|
||
pub fn format_timestamp(timestamp: i32) -> String {
|
||
format_timestamp_with_tz(timestamp, "+03:00")
|
||
}
|
||
|
||
/// Форматирование timestamp в дату для разделителя
|
||
pub fn format_date(timestamp: i32) -> String {
|
||
use std::time::{SystemTime, UNIX_EPOCH};
|
||
|
||
let now = SystemTime::now()
|
||
.duration_since(UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs() as i64;
|
||
|
||
let msg_day = timestamp as i64 / 86400;
|
||
let today = now / 86400;
|
||
|
||
if msg_day == today {
|
||
"Сегодня".to_string()
|
||
} else if msg_day == today - 1 {
|
||
"Вчера".to_string()
|
||
} else {
|
||
// Простое форматирование даты
|
||
let days_since_epoch = timestamp as i64 / 86400;
|
||
// Приблизительный расчёт даты (без учёта високосных годов)
|
||
let year = 1970 + (days_since_epoch / 365) as i32;
|
||
let day_of_year = days_since_epoch % 365;
|
||
|
||
let months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||
let mut month = 0;
|
||
let mut day = day_of_year as i32;
|
||
|
||
for (i, &m) in months.iter().enumerate() {
|
||
if day < m {
|
||
month = i + 1;
|
||
break;
|
||
}
|
||
day -= m;
|
||
}
|
||
|
||
format!("{:02}.{:02}.{}", day + 1, month, year)
|
||
}
|
||
}
|
||
|
||
/// Получить день из timestamp для группировки
|
||
pub fn get_day(timestamp: i32) -> i64 {
|
||
timestamp as i64 / 86400
|
||
}
|
||
|
||
/// Форматирование timestamp в полную дату и время (DD.MM.YYYY HH:MM)
|
||
pub fn format_datetime(timestamp: i32) -> String {
|
||
let secs = timestamp as i64;
|
||
|
||
// Время
|
||
let hours = ((secs % 86400) / 3600) as u32;
|
||
let minutes = ((secs % 3600) / 60) as u32;
|
||
let local_hours = (hours + 3) % 24; // MSK
|
||
|
||
// Дата
|
||
let days_since_epoch = secs / 86400;
|
||
let year = 1970 + (days_since_epoch / 365) as i32;
|
||
let day_of_year = days_since_epoch % 365;
|
||
|
||
let months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||
let mut month = 1;
|
||
let mut day = day_of_year as i32;
|
||
|
||
for (i, &m) in months.iter().enumerate() {
|
||
if day < m {
|
||
month = i + 1;
|
||
break;
|
||
}
|
||
day -= m;
|
||
}
|
||
|
||
format!("{:02}.{:02}.{} {:02}:{:02}", day + 1, month, year, local_hours, minutes)
|
||
}
|
||
|
||
/// Форматирование "был(а) онлайн" из timestamp
|
||
pub fn format_was_online(timestamp: i32) -> String {
|
||
use std::time::{SystemTime, UNIX_EPOCH};
|
||
|
||
let now = SystemTime::now()
|
||
.duration_since(UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs() as i32;
|
||
|
||
let diff = now - timestamp;
|
||
|
||
if diff < 60 {
|
||
"был(а) только что".to_string()
|
||
} else if diff < 3600 {
|
||
let mins = diff / 60;
|
||
format!("был(а) {} мин. назад", mins)
|
||
} else if diff < 86400 {
|
||
let hours = diff / 3600;
|
||
format!("был(а) {} ч. назад", hours)
|
||
} else {
|
||
// Показываем дату
|
||
let datetime = chrono::DateTime::from_timestamp(timestamp as i64, 0)
|
||
.map(|dt| dt.format("%d.%m %H:%M").to_string())
|
||
.unwrap_or_else(|| "давно".to_string());
|
||
format!("был(а) {}", datetime)
|
||
}
|
||
}
|