From d6a17fdd92b690e2584d743c153b45ba4d684d30 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Fri, 14 May 2021 00:50:37 -0300 Subject: [Project] CW2 Plugin for Hexchat A nice Content Warning plugin for Hexchat! --- src/lib.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 src/lib.rs (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..fd67b88 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,146 @@ +// CW2 - Hexchat Plugin for Content Warnings +// Copyright (C) 2021 Soni L. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#[macro_use] +extern crate hexchat_plugin; + +mod parsing; + +mod hexchat_plugin_ext; + +use std::cell::Cell; + +use hexchat_plugin::Plugin as HexchatPlugin; +use hexchat_plugin::PluginHandle as Ph; +use hexchat_plugin::CommandHookHandle; +use hexchat_plugin::PrintHookHandle; + +use hexchat_plugin_ext::PhExt; + +#[derive(Default)] +struct Cw2Plugin { + cmd_cw: Cell>, + cmd_cwmsg: Cell>, + print_hooks: Cell>, +} + +const PLUG_NAME: &'static str = "CW2"; +const PLUG_VER: &'static str = "1.0.0"; +const PLUG_DESC: &'static str = "Adds support for content warnings."; + +const CMD_CW: &'static str = "CW"; +const CMD_CW_HELP: &'static str = "Sends a content warned msg. \ + Example usage: /cw [thing] message"; +const CMD_CW_EPARSE: &'static str = "Error parsing CW. \ + Example usage: /cw [thing] message"; +const CMD_CW_ENOARG: &'static str = "This command requires more arguments. \ + Example usage: /cw [thing] message"; + +const CMD_CWMSG: &'static str = "CWMSG"; +const CMD_CWMSG_HELP: &'static str = "Sends a content warned msg to an user. \ + Example usage: /cwmsg user [thing] message"; +const CMD_CWMSG_EPARSE: &'static str = "Error parsing CW. \ + Example usage: /cwmsg user [thing] message"; +const CMD_CWMSG_ENOARG: &'static str = "This command requires more arguments. \ + Example usage: /cwmsg user [thing] message"; + +impl HexchatPlugin for Cw2Plugin { + fn init(&self, ph: &mut Ph, _: Option<&str>) -> bool { + ph.register(PLUG_NAME, PLUG_VER, PLUG_DESC); + + ph.make_command(CMD_CW, |ph, arg, arg_eol| { + if arg.len() < 2 { + ph.print(CMD_CW_ENOARG); + return hexchat_plugin::EAT_ALL + } + if let Some(message) = parsing::try_to_cw2(arg_eol[1]) { + ph.ensure_valid_context(|ph| { + ph.command(&format!("say {}", message)); + }); + } else { + ph.print(CMD_CW_EPARSE); + } + hexchat_plugin::EAT_ALL + }).set_help(CMD_CW_HELP).build_into(&self.cmd_cw); + + ph.make_command(CMD_CWMSG, |ph, arg, arg_eol| { + if arg.len() < 3 { + ph.print(CMD_CWMSG_ENOARG); + return hexchat_plugin::EAT_ALL + } + let user = arg_eol[1]; + if let Some(message) = parsing::try_to_cw2(arg_eol[2]) { + ph.ensure_valid_context(|ph| { + ph.command(&format!("msg {} {}", user, message)); + }); + } else { + ph.print(CMD_CWMSG_EPARSE); + } + hexchat_plugin::EAT_ALL + }).set_help(CMD_CWMSG_HELP).build_into(&self.cmd_cwmsg); + + let mut hooks = Vec::new(); + let to_hook = [ + ("Channel Message", 2,), + ("Channel Msg Hilight", 2,), + ("Channel Notice", 3,), + ("Private Message", 2,), + ("Private Message to Dialog", 2,), + ("Notice", 2,), + ("Your Message", 2,), + ("Notice Send", 2,), + ("Message Send", 2,), + ]; + for &(msg, idx) in &to_hook { + let h = ph.make_print_attrs(msg, move |ph, arg, attrs| { + if arg.len() < idx { + return hexchat_plugin::EAT_NONE + } + // hexchat uses 1-indexed arg + // but hexchat_plugin uses 0-indexed + // (ah well) + let x = arg[idx-1]; + if let Some((reason, content)) = parsing::try_parse_cw2(x) { + let mut newargs = Vec::new(); + newargs.extend(arg.iter().map(|x| String::from(*x))); + // NOTE: must not start with "[CW ", as that'd cause an + // infinite loop! + newargs[idx-1] = format!("[Content Hidden: {}]", reason); + ph.print(&format!("\x0326*\t[Content Hidden: {}]\x03\x08{}\x08 \x0324(Copy and paste this line to expand)\x03", reason, content)); + ph.ensure_valid_context(|ph| { + let iter = newargs.iter().map(|x| &**x); + // TODO ideally we'd avoid recursion but eh it's fine + // .-. + // (we guess as long as the above isn't "[CW {}]", + // this is probably fine.) + ph.emit_print_attrs(attrs, msg, iter); + }); + hexchat_plugin::EAT_ALL + } else { + hexchat_plugin::EAT_NONE + } + }).set_priority(i32::MAX).build(); + hooks.push(h); + } + self.print_hooks.set(hooks); + + ph.print("CW2 plugin loaded!"); + + true + } +} + +hexchat_plugin!(Cw2Plugin); -- cgit 1.4.1