1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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 <https://www.gnu.org/licenses/>.
#[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<Option<CommandHookHandle>>,
cmd_cwmsg: Cell<Option<CommandHookHandle>>,
print_hooks: Cell<Vec<PrintHookHandle>>,
}
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);
|