Add some more code from pidgin-icq

This commit is contained in:
2021-04-10 14:28:20 +01:00
parent 6237b9421d
commit 77a257892a
2 changed files with 257 additions and 0 deletions

136
src/chat_info.rs Normal file
View File

@@ -0,0 +1,136 @@
// This is a copy of https://github.com/Flared/purple-icq/blob/master/src/chat_info.rs
use super::purple;
use lazy_static::lazy_static;
use std::ffi::CString;
lazy_static! {
pub static ref SN: CString = CString::new("sn").unwrap();
pub static ref SN_NAME: CString = CString::new("Chat ID").unwrap();
pub static ref STAMP: CString = CString::new("stamp").unwrap();
pub static ref TITLE: CString = CString::new("title").unwrap();
pub static ref GROUP: CString = CString::new("group").unwrap();
pub static ref STATE: CString = CString::new("state").unwrap();
}
#[derive(Debug, Clone)]
pub struct MemberRole(String);
#[derive(Debug, Clone, Default)]
pub struct PartialChatInfo {
pub sn: String,
pub title: String,
pub group: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct ChatInfo {
pub stamp: Option<String>,
pub group: Option<String>,
pub sn: String,
pub title: String,
pub about: Option<String>,
pub members_version: String,
pub info_version: String,
pub members: Vec<ChatMember>,
}
#[derive(Debug, Clone)]
pub struct ChatMember {
pub sn: String,
pub friendly_name: Option<String>,
pub role: MemberRole,
pub last_seen: Option<u64>,
pub first_name: Option<String>,
pub last_name: Option<String>,
}
#[derive(Debug, Clone)]
pub struct ChatInfoVersion {
pub members_version: String,
pub info_version: String,
}
impl MemberRole {
pub fn as_flags(&self) -> purple::PurpleConvChatBuddyFlags {
match self.0.as_str() {
"admin" => purple::PurpleConvChatBuddyFlags::PURPLE_CBFLAGS_OP,
"readonly" => purple::PurpleConvChatBuddyFlags::PURPLE_CBFLAGS_NONE,
_ => purple::PurpleConvChatBuddyFlags::PURPLE_CBFLAGS_VOICE,
}
}
}
impl PartialChatInfo {
pub fn from_hashtable(table: &purple::StrHashTable) -> Option<Self> {
Some(Self {
group: table.lookup(&GROUP).map(Into::into),
sn: table.lookup(&SN)?.into(),
title: table.lookup(&TITLE)?.into(),
})
}
pub fn as_hashtable(&self) -> purple::StrHashTable {
let mut table = purple::StrHashTable::default();
table.insert(&SN, &self.sn);
if let Some(group) = &self.group {
table.insert(&GROUP, &group);
}
table.insert(&TITLE, &self.title);
table
}
}
impl ChatInfo {
pub fn as_partial(&self) -> PartialChatInfo {
PartialChatInfo {
sn: self.sn.clone(),
title: self.title.clone(),
group: self.group.clone(),
}
}
pub fn need_update(&self, new_version: &ChatInfoVersion) -> bool {
self.members_version < new_version.members_version
|| self.info_version < new_version.info_version
}
}
/*
impl From<icq::client::GetChatInfoResponseData> for ChatInfo {
fn from(info: icq::client::GetChatInfoResponseData) -> Self {
Self {
sn: info.sn,
stamp: Some(info.stamp),
title: info.name,
members_version: info.members_version,
info_version: info.info_version,
about: info.about,
members: info
.members
.into_iter()
.map(|m| ChatMember {
sn: m.sn,
role: MemberRole(m.role),
last_seen: m.user_state.last_seen.and_then(|t| match t {
0 => None,
t => Some(t),
}),
friendly_name: m.friendly,
first_name: m.anketa.first_name,
last_name: m.anketa.last_name,
})
.collect(),
..Default::default()
}
}
}
impl From<icq::client::events::HistDlgStateMChatState> for ChatInfoVersion {
fn from(info: icq::client::events::HistDlgStateMChatState) -> Self {
Self {
members_version: info.members_version,
info_version: info.info_version,
}
}
}
*/

121
src/logging.rs Normal file
View File

@@ -0,0 +1,121 @@
// This is a copy of https://github.com/Flared/purple-icq/blob/master/src/logging.rs
//use crate::messages::{FdSender, SystemMessage};
use crate::purple;
use std::cell::RefCell;
use std::sync::Mutex;
std::thread_local! {
pub static LOGGER: RefCell<Option<Box<dyn log::Log>>> = RefCell::new(None);
}
lazy_static::lazy_static! {
static ref PURPLE_BUFFER: Mutex<Vec<(String, log::Level, String)>> = Default::default();
}
static TLS_LOGGER: ThreadLocalLogger = ThreadLocalLogger;
pub struct ThreadLocalLogger;
impl log::Log for ThreadLocalLogger {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
true
}
fn log(&self, record: &log::Record) {
LOGGER.with(|cell| {
if let Some(ref logger) = cell.borrow().as_ref() {
logger.log(record);
}
})
}
fn flush(&self) {
LOGGER.with(|cell| {
if let Some(ref logger) = cell.borrow().as_ref() {
logger.flush()
}
})
}
}
pub struct PurpleDebugLogger;
impl log::Log for PurpleDebugLogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() < log::Level::Debug
}
fn log(&self, record: &log::Record) {
let purple_level = match record.level() {
log::Level::Error => purple::PurpleDebugLevel::PURPLE_DEBUG_ERROR,
log::Level::Warn => purple::PurpleDebugLevel::PURPLE_DEBUG_WARNING,
log::Level::Info => purple::PurpleDebugLevel::PURPLE_DEBUG_INFO,
_ => purple::PurpleDebugLevel::PURPLE_DEBUG_MISC,
};
let target = if !record.target().is_empty() {
record.target()
} else {
record.module_path().unwrap_or_default()
};
let line = format!("[{}] {}\n", target, record.args());
purple::debug(purple_level, "", &line);
}
fn flush(&self) {
let buffer = {
match PURPLE_BUFFER.lock() {
Ok(mut buffer) => buffer.split_off(0),
Err(_) => return,
}
};
for (target, level, message) in buffer {
log::log!(target: &target, level, "{}", message);
}
}
}
/*
pub struct RemoteLogger(pub FdSender<SystemMessage>);
impl log::Log for RemoteLogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() < log::Level::Debug
}
fn log(&self, record: &log::Record) {
let target = if !record.target().is_empty() {
record.target()
} else {
record.module_path().unwrap_or_default()
};
if let Ok(mut buffer) = PURPLE_BUFFER.lock() {
buffer.push((target.into(), record.level(), record.args().to_string()));
}
}
fn flush(&self) {
self.0.clone().try_send(SystemMessage::FlushLogs);
}
}
*/
pub fn init(level: log::LevelFilter) -> Result<(), log::SetLoggerError> {
log::set_logger(&TLS_LOGGER).map(|()| log::set_max_level(level))
}
pub fn set_thread_logger<T>(logger: T)
where
T: log::Log + 'static,
{
LOGGER.with(|cell| *cell.borrow_mut() = Some(Box::new(logger)))
}
pub fn flush() {
LOGGER.with(|cell| {
if let Some(ref logger) = cell.borrow().as_ref() {
logger.flush();
}
})
}