forked from PsychoticNinja/irssi
Original patch by hondza <sedaj2@gmail.com>, from FS#833. I applied several needed style changes, and rebased to current HEAD. This implements the IRCv3.2 self-message extension partially (we can't announce its support through CAP yet). This is also the format used by the 'privmsg' znc module, and is already implemented by several other clients.
315 lines
9.7 KiB
C
315 lines
9.7 KiB
C
/*
|
|
fe-irc-messages.c : irssi
|
|
|
|
Copyright (C) 2001 Timo Sirainen
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "module.h"
|
|
#include "signals.h"
|
|
#include "levels.h"
|
|
#include "channels.h"
|
|
#include "ignore.h"
|
|
#include "settings.h"
|
|
|
|
#include "irc-servers.h"
|
|
#include "irc-channels.h"
|
|
#include "irc-queries.h"
|
|
|
|
#include "../core/module-formats.h"
|
|
#include "module-formats.h"
|
|
#include "printtext.h"
|
|
#include "fe-messages.h"
|
|
|
|
#include "fe-queries.h"
|
|
#include "window-items.h"
|
|
|
|
static const char *skip_target(IRC_SERVER_REC *server, const char *target)
|
|
{
|
|
int i = 0;
|
|
const char *val, *chars;
|
|
|
|
/* Quick check */
|
|
if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
|
|
return target;
|
|
|
|
/* Hack: for bahamut 1.4 which sends neither STATUSMSG nor
|
|
* WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */
|
|
val = g_hash_table_lookup(server->isupport, "STATUSMSG");
|
|
if (val == NULL && *target != '@')
|
|
return target;
|
|
chars = val ? val : "@+";
|
|
for(i = 0; target[i] != '\0'; i++) {
|
|
if (strchr(chars, target[i]) == NULL)
|
|
break;
|
|
};
|
|
|
|
if(ischannel(target[i]))
|
|
target += i;
|
|
|
|
return target;
|
|
}
|
|
|
|
static void sig_message_own_public(SERVER_REC *server, const char *msg,
|
|
const char *target, const char *origtarget)
|
|
{
|
|
const char *oldtarget;
|
|
char *nickmode;
|
|
|
|
if (!IS_IRC_SERVER(server))
|
|
return;
|
|
oldtarget = target;
|
|
target = skip_target(IRC_SERVER(server), target);
|
|
if (target != oldtarget) {
|
|
/* Hybrid 6 / Bahamut feature, send msg to all
|
|
ops / ops+voices in channel */
|
|
nickmode = channel_get_nickmode(channel_find(server, target),
|
|
server->nick);
|
|
|
|
printformat_module("fe-common/core", server, target,
|
|
MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
|
|
MSGLEVEL_NO_ACT,
|
|
TXT_OWN_MSG_CHANNEL,
|
|
server->nick, oldtarget, msg, nickmode);
|
|
g_free(nickmode);
|
|
signal_stop();
|
|
}
|
|
|
|
}
|
|
|
|
/* received msg to all ops in channel */
|
|
static void sig_message_irc_op_public(SERVER_REC *server, const char *msg,
|
|
const char *nick, const char *address,
|
|
const char *target)
|
|
{
|
|
char *nickmode, *optarget;
|
|
|
|
nickmode = channel_get_nickmode(channel_find(server, target),
|
|
nick);
|
|
|
|
optarget = g_strconcat("@", target, NULL);
|
|
printformat_module("fe-common/core", server, target,
|
|
MSGLEVEL_PUBLIC,
|
|
TXT_PUBMSG_CHANNEL,
|
|
nick, optarget, msg, nickmode);
|
|
g_free(nickmode);
|
|
g_free(optarget);
|
|
}
|
|
|
|
static void sig_message_own_wall(SERVER_REC *server, const char *msg,
|
|
const char *target)
|
|
{
|
|
char *nickmode, *optarget;
|
|
|
|
nickmode = channel_get_nickmode(channel_find(server, target),
|
|
server->nick);
|
|
|
|
optarget = g_strconcat("@", target, NULL);
|
|
printformat_module("fe-common/core", server, target,
|
|
MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
|
|
MSGLEVEL_NO_ACT,
|
|
TXT_OWN_MSG_CHANNEL,
|
|
server->nick, optarget, msg, nickmode);
|
|
g_free(nickmode);
|
|
g_free(optarget);
|
|
}
|
|
|
|
static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
|
|
const char *target)
|
|
{
|
|
void *item;
|
|
const char *oldtarget;
|
|
char *freemsg = NULL;
|
|
|
|
oldtarget = target;
|
|
target = skip_target(IRC_SERVER(server), target);
|
|
if (ischannel(*target))
|
|
item = irc_channel_find(server, target);
|
|
else
|
|
item = irc_query_find(server, target);
|
|
|
|
if (settings_get_bool("emphasis"))
|
|
msg = freemsg = expand_emphasis(item, msg);
|
|
|
|
printformat(server, target,
|
|
MSGLEVEL_ACTIONS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT |
|
|
(ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS),
|
|
item != NULL && oldtarget == target ? IRCTXT_OWN_ACTION : IRCTXT_OWN_ACTION_TARGET,
|
|
server->nick, msg, oldtarget);
|
|
g_free_not_null(freemsg);
|
|
}
|
|
|
|
static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
|
|
const char *nick, const char *address,
|
|
const char *target)
|
|
{
|
|
void *item;
|
|
const char *oldtarget;
|
|
char *freemsg = NULL;
|
|
int level;
|
|
int own = FALSE;
|
|
|
|
oldtarget = target;
|
|
target = skip_target(IRC_SERVER(server), target);
|
|
|
|
level = MSGLEVEL_ACTIONS |
|
|
(ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
|
|
|
|
if (ignore_check(SERVER(server), nick, address, target, msg, level))
|
|
return;
|
|
|
|
if (ignore_check(SERVER(server), nick, address, target, msg,
|
|
level | MSGLEVEL_NO_ACT))
|
|
level |= MSGLEVEL_NO_ACT;
|
|
|
|
if (ischannel(*target)) {
|
|
item = irc_channel_find(server, target);
|
|
} else {
|
|
own = (!strcmp(nick, server->nick));
|
|
item = privmsg_get_query(SERVER(server), own ? nick : target, FALSE, level);
|
|
}
|
|
|
|
if (settings_get_bool("emphasis"))
|
|
msg = freemsg = expand_emphasis(item, msg);
|
|
|
|
if (ischannel(*target)) {
|
|
/* channel action */
|
|
if (window_item_is_active(item) && target == oldtarget) {
|
|
/* message to active channel in window */
|
|
printformat(server, target, level,
|
|
IRCTXT_ACTION_PUBLIC, nick, msg);
|
|
} else {
|
|
/* message to not existing/active channel, or to @/+ */
|
|
printformat(server, target, level,
|
|
IRCTXT_ACTION_PUBLIC_CHANNEL,
|
|
nick, oldtarget, msg);
|
|
}
|
|
} else {
|
|
if (own) {
|
|
/* own action bounced */
|
|
printformat(server, target,
|
|
MSGLEVEL_ACTIONS | MSGLEVEL_MSGS,
|
|
item != NULL && oldtarget == target ? IRCTXT_OWN_ACTION : IRCTXT_OWN_ACTION_TARGET,
|
|
server->nick, msg, oldtarget);
|
|
} else {
|
|
/* private action */
|
|
printformat(server, nick, MSGLEVEL_ACTIONS | MSGLEVEL_MSGS,
|
|
item == NULL ? IRCTXT_ACTION_PRIVATE :
|
|
IRCTXT_ACTION_PRIVATE_QUERY,
|
|
nick, address == NULL ? "" : address, msg);
|
|
}
|
|
}
|
|
|
|
g_free_not_null(freemsg);
|
|
}
|
|
|
|
static void sig_message_own_notice(IRC_SERVER_REC *server, const char *msg,
|
|
const char *target)
|
|
{
|
|
printformat(server, skip_target(server, target), MSGLEVEL_NOTICES |
|
|
MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
|
|
IRCTXT_OWN_NOTICE, target, msg);
|
|
}
|
|
|
|
static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
|
|
const char *nick, const char *address,
|
|
const char *target)
|
|
{
|
|
const char *oldtarget;
|
|
int level = MSGLEVEL_NOTICES;
|
|
|
|
oldtarget = target;
|
|
target = skip_target(IRC_SERVER(server), target);
|
|
|
|
if (address == NULL || *address == '\0') {
|
|
/* notice from server */
|
|
if (!ignore_check(server, nick, "",
|
|
target, msg, MSGLEVEL_SNOTES)) {
|
|
printformat(server, target, MSGLEVEL_SNOTES,
|
|
IRCTXT_NOTICE_SERVER, nick, msg);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (ignore_check(server, nick, address,
|
|
ischannel(*target) ? target : NULL,
|
|
msg, level))
|
|
return;
|
|
|
|
if (ignore_check(server, nick, address,
|
|
ischannel(*target) ? target : NULL,
|
|
msg, level | MSGLEVEL_NO_ACT))
|
|
level |= MSGLEVEL_NO_ACT;
|
|
|
|
if (ischannel(*target)) {
|
|
/* notice in some channel */
|
|
printformat(server, target, level,
|
|
IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg);
|
|
} else {
|
|
/* private notice */
|
|
privmsg_get_query(SERVER(server), nick, FALSE,
|
|
MSGLEVEL_NOTICES);
|
|
printformat(server, nick, level,
|
|
IRCTXT_NOTICE_PRIVATE, nick, address, msg);
|
|
}
|
|
}
|
|
|
|
static void sig_message_own_ctcp(IRC_SERVER_REC *server, const char *cmd,
|
|
const char *data, const char *target)
|
|
{
|
|
printformat(server, skip_target(server, target), MSGLEVEL_CTCPS |
|
|
MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
|
|
IRCTXT_OWN_CTCP, target, cmd, data);
|
|
}
|
|
|
|
static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd,
|
|
const char *data, const char *nick,
|
|
const char *addr, const char *target)
|
|
{
|
|
const char *oldtarget;
|
|
|
|
oldtarget = target;
|
|
target = skip_target(server, target);
|
|
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
|
|
IRCTXT_CTCP_REQUESTED, nick, addr, cmd, data, oldtarget);
|
|
}
|
|
|
|
void fe_irc_messages_init(void)
|
|
{
|
|
signal_add_last("message own_public", (SIGNAL_FUNC) sig_message_own_public);
|
|
signal_add_last("message irc op_public", (SIGNAL_FUNC) sig_message_irc_op_public);
|
|
signal_add_last("message irc own_wall", (SIGNAL_FUNC) sig_message_own_wall);
|
|
signal_add_last("message irc own_action", (SIGNAL_FUNC) sig_message_own_action);
|
|
signal_add_last("message irc action", (SIGNAL_FUNC) sig_message_irc_action);
|
|
signal_add_last("message irc own_notice", (SIGNAL_FUNC) sig_message_own_notice);
|
|
signal_add_last("message irc notice", (SIGNAL_FUNC) sig_message_irc_notice);
|
|
signal_add_last("message irc own_ctcp", (SIGNAL_FUNC) sig_message_own_ctcp);
|
|
signal_add_last("message irc ctcp", (SIGNAL_FUNC) sig_message_irc_ctcp);
|
|
}
|
|
|
|
void fe_irc_messages_deinit(void)
|
|
{
|
|
signal_remove("message own_public", (SIGNAL_FUNC) sig_message_own_public);
|
|
signal_remove("message irc op_public", (SIGNAL_FUNC) sig_message_irc_op_public);
|
|
signal_remove("message irc own_wall", (SIGNAL_FUNC) sig_message_own_wall);
|
|
signal_remove("message irc own_action", (SIGNAL_FUNC) sig_message_own_action);
|
|
signal_remove("message irc action", (SIGNAL_FUNC) sig_message_irc_action);
|
|
signal_remove("message irc own_notice", (SIGNAL_FUNC) sig_message_own_notice);
|
|
signal_remove("message irc notice", (SIGNAL_FUNC) sig_message_irc_notice);
|
|
signal_remove("message irc own_ctcp", (SIGNAL_FUNC) sig_message_own_ctcp);
|
|
signal_remove("message irc ctcp", (SIGNAL_FUNC) sig_message_irc_ctcp);
|
|
}
|