use std::net::{Ipv4Addr, SocketAddrV4};
use std::num::NonZeroU64;
use bitflags::bitflags;
use time::OffsetDateTime;
use crate::str::{HexStr, HexString};
list!(
Channels,
"channels",
"List of channels, queries and their servers.",
"A channel.",
Channel {
["channel", "Channel or query name.", string] name: HexString => &HexStr,
["channelkey", "Channel key. (HexChat 2.9.6+)", string] key: Option<HexString> => Option<&HexStr>,
["chanmodes", "Available channel modes e.g. `\"beI,k,l\"`. (HexChat 2.12.2+)", string] modes: HexString => &HexStr,
["chantypes", "Available channel types e.g. `\"#!&\"`.", string] types: HexString => &HexStr,
["flags", "Info flags.", int] flags: ChannelFlags => ChannelFlags,
["id", "Unique server ID.", int] server_id: i32 => i32,
["lag", "Lag in milliseconds.", int] lag_ms: i32 => i32,
["maxmodes", "Maximum modes per line.", int] max_modes_per_line: u32 => u32,
["network", "Name of network.", string] network: HexString => &HexStr,
["nickprefixes", "Nickname prefixes e.g. `\"@+\"`.", string] nick_prefixes: HexString => &HexStr,
["nickmodes", "Nickname mode chars e.g. `\"ov\"`.", string] nick_modes: HexString => &HexStr,
["queue", "Number of bytes in the send-queue.", int] queue: u32 => u32,
["server", "Server name to which this channel belongs.", string] servname: HexString => &HexStr,
["type", "Channel type.", int] ty: ChannelType => ChannelType,
["users", "Number of users in this channel.", int] num_users: u32 => u32,
}
);
bitflags! {
pub struct ChannelFlags: i32 {
const CONNECTED = 1;
const CONNECTING = 2;
const MARKED_AWAY = 4;
const END_OF_MOTD = 8;
const HAS_WHOX = 16;
const HAS_IDMSG = 32;
const HIDE_JOIN_PARTS = 64;
const HIDE_JOIN_PARTS_UNSET = 128;
const BEEP_ON_MESSAGE = 256;
const BLINK_TRAY = 512;
const BLINK_TASKBAR = 1024;
const LOGGING = 2048;
const LOGGING_UNSET = 4096;
const SCROLLBACK = 8192;
const SCROLLBACK_UNSET = 16384;
const STRIP_COLORS = 32768;
const STRIP_COLORS_UNSET = 65536;
}
}
impl super::FromListElemField<i32> for ChannelFlags {
fn from_list_elem_field(field: i32) -> Self {
Self::from_bits_truncate(field)
}
}
#[non_exhaustive]
#[derive(Debug, Copy, Clone)]
pub enum ChannelType {
Server = 1,
Channel = 2,
Dialog = 3,
Notice = 4,
ServerNotice = 5,
}
impl super::FromListElemField<i32> for ChannelType {
fn from_list_elem_field(field: i32) -> Self {
match () {
_ if field == Self::Server as _ => Self::Server,
_ if field == Self::Channel as _ => Self::Channel,
_ if field == Self::Dialog as _ => Self::Dialog,
_ if field == Self::Notice as _ => Self::Notice,
_ if field == Self::ServerNotice as _ => Self::ServerNotice,
_ => panic!("Unexpected channel type: {}", field),
}
}
}
list!(
DccTransfers,
"dcc",
"List of DCC file transfers.",
"A DCC file transfer.",
DccTransfer {
[
custom,
"Socket of the remote user.",
|elem| SocketAddrV4::new(Ipv4Addr::from(elem.int(c"address32") as u32), elem.int(c"port") as u16)
] socket_addr: SocketAddrV4 => SocketAddrV4,
["cps", "Bytes per second (speed).", int] bytes_per_second: u32 => u32,
["destfile", "Destination full pathname.", string] dest_file: HexString => &HexStr,
["file", "Filename.", string] file_name: HexString => &HexStr,
["nick", "Nickname of person who the file is from/to.", string] nick: HexString => &HexStr,
[
custom,
"Bytes sent/received.",
|elem| (elem.int(c"poshigh") as u64) << 32 | (elem.int(c"pos") as u64)
] position: u64 => u64,
[
custom,
"Point at which this file was resumed.",
|elem| NonZeroU64::new((elem.int(c"resumehigh") as u64) << 32 | (elem.int(c"resume") as u64))
] resumed_at: Option<NonZeroU64> => Option<NonZeroU64>,
[
custom,
"File size in bytes.",
|elem| (elem.int(c"sizehigh") as u64) << 32 | (elem.int(c"size") as u64)
] size: u64 => u64
}
);
list!(
Ignores,
"ignore",
"List of ignores.",
"An ignored mask.",
Ignore {
["mask", "Ignore mask, e.g. `\"*!*@*.aol.com\"`.", string] mask: HexString => &HexStr,
["flags", "Info flags.", int] flags: IgnoreFlags => IgnoreFlags,
}
);
bitflags! {
pub struct IgnoreFlags: i32 {
#[allow(clippy::identity_op)]
const PRIVATE = 1 << 0;
const NOTICE = 1 << 1;
const CHANNEL = 1 << 2;
const CTCP = 1 << 3;
const INVITE = 1 << 4;
const UNIGNORE = 1 << 5;
const NO_SAVE = 1 << 6;
const DCC = 1 << 7;
}
}
impl super::FromListElemField<i32> for IgnoreFlags {
fn from_list_elem_field(field: i32) -> Self {
Self::from_bits_truncate(field)
}
}
list!(
Notifies,
"notify",
"List of people on notify in the current server [context](crate::PluginHandle::find_context).",
"A nick on notify.",
Notify {
["networks", "Networks to which this nick applies.", string] networks: super::SplitByCommas => impl Iterator<Item = &str>,
["nick", "Nickname.", string] nick: HexString => &HexStr,
["flags", "Info flags.", int] flags: NotifyFlags => NotifyFlags,
["on", "Time when user came online.", time] online: OffsetDateTime => OffsetDateTime,
["off", "Time when user went offline.", time] offline: OffsetDateTime => OffsetDateTime,
["seen", "Time when user the user was last verified still online.", time] seen: OffsetDateTime => OffsetDateTime,
}
);
bitflags! {
pub struct NotifyFlags: i32 {
#[allow(clippy::identity_op)]
const IS_ONLINE = 1 << 0;
}
}
impl super::FromListElemField<i32> for NotifyFlags {
fn from_list_elem_field(field: i32) -> Self {
Self::from_bits_truncate(field)
}
}
list!(
Users,
"users",
"List of users in the current [context](crate::PluginHandle::find_context).",
"A user.",
User {
["account", "Account name. (HexChat 2.9.6+)", string] account: Option<HexString> => Option<&HexStr>,
["away", "Away status.", int] is_away: bool => bool,
["lasttalk", "Last time the user was seen talking.", time] last_talk: OffsetDateTime => OffsetDateTime,
["nick", "Nickname.", string] nick: HexString => &HexStr,
["host", "Hostname e.g. `\"user@host\"`.", string] host: Option<HexString> => Option<&HexStr>,
["prefix", "Prefix character e.g. `'@'` or `'+'`.", string] prefix: Option<char> => Option<char>,
["realname", "Realname.", string] realname: Option<HexString> => Option<&HexStr>,
["selected", "Selected status in the user list, only works in the focused tab.", int] is_selected: bool => bool,
}
);