1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-16 06:25:24 +00:00

Merge pull request #1250 from ailin-nemui/whox

better account tracking
This commit is contained in:
ailin-nemui 2021-04-01 21:27:51 +02:00 committed by GitHub
commit 437accdfa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 364 additions and 67 deletions

View File

@ -5,7 +5,7 @@
To compile Irssi you need:
- meson-0.49 build system with ninja-1.5 or greater
- glib-2.28 or greater
- glib-2.32 or greater
- openssl (for ssl support)
- perl-5.6 or greater (for Perl support)
- terminfo or ncurses (for text frontend)

View File

@ -40,7 +40,7 @@ make && sudo make install
### Requirements
- [glib-2.28](https://wiki.gnome.org/Projects/GLib) or greater
- [glib-2.32](https://wiki.gnome.org/Projects/GLib) or greater
- [openssl](https://www.openssl.org/)
- [perl-5.6](https://www.perl.org/) or greater (for perl support)
- terminfo or ncurses (for text frontend)

View File

@ -273,7 +273,7 @@ for try in 1 2; do
echo "*** trying without -lgmodule"
glib_modules=
fi
AM_PATH_GLIB_2_0(2.28.0,,, $glib_modules)
AM_PATH_GLIB_2_0(2.32.0,,, $glib_modules)
if test "$GLIB_LIBS"; then
if test $glib_modules = gmodule; then
AC_DEFINE(HAVE_GMODULE)

View File

@ -166,7 +166,7 @@ message('*** Or alternatively install your distribution\'s package')
message('*** On Debian: sudo apt-get install libglib2.0-dev')
message('*** On Redhat: dnf install glib2-devel')
if not require_glib_internal
glib_dep = dependency('glib-2.0', version : '>=2.28', required : not want_glib_internal, static : want_static_dependency)
glib_dep = dependency('glib-2.0', version : '>=2.32', required : not want_glib_internal, static : want_static_dependency)
else
glib_dep = dependency('', required : false)
endif

View File

@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
#define IRSSI_ABI_VERSION 34
#define IRSSI_ABI_VERSION 35
#define DEFAULT_SERVER_ADD_PORT 6667
#define DEFAULT_SERVER_ADD_TLS_PORT 6697

View File

@ -724,6 +724,7 @@ void fe_events_numeric_init(void)
signal_add("event 004", (SIGNAL_FUNC) event_received);
signal_add("event 005", (SIGNAL_FUNC) event_received);
signal_add("event 254", (SIGNAL_FUNC) event_received);
signal_add("event 354", (SIGNAL_FUNC) event_received);
signal_add("event 364", (SIGNAL_FUNC) event_received);
signal_add("event 365", (SIGNAL_FUNC) event_received);
signal_add("event 381", (SIGNAL_FUNC) event_received);
@ -814,6 +815,7 @@ void fe_events_numeric_deinit(void)
signal_remove("event 004", (SIGNAL_FUNC) event_received);
signal_remove("event 005", (SIGNAL_FUNC) event_received);
signal_remove("event 254", (SIGNAL_FUNC) event_received);
signal_remove("event 354", (SIGNAL_FUNC) event_received);
signal_remove("event 364", (SIGNAL_FUNC) event_received);
signal_remove("event 365", (SIGNAL_FUNC) event_received);
signal_remove("event 381", (SIGNAL_FUNC) event_received);

View File

@ -415,6 +415,7 @@ void fe_whois_init(void)
signal_add("event 319", (SIGNAL_FUNC) event_whois_channels);
signal_add("event 313", (SIGNAL_FUNC) event_whois_oper);
signal_add("event 330", (SIGNAL_FUNC) event_whois_auth);
signal_add("whois account", (SIGNAL_FUNC) event_whois_auth);
signal_add("event 377", (SIGNAL_FUNC) event_whois_usermode);
signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost);
signal_add("event 379", (SIGNAL_FUNC) event_whois_modes);
@ -438,6 +439,7 @@ void fe_whois_deinit(void)
signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels);
signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper);
signal_remove("event 330", (SIGNAL_FUNC) event_whois_auth);
signal_remove("whois account", (SIGNAL_FUNC) event_whois_auth);
signal_remove("event 377", (SIGNAL_FUNC) event_whois_usermode);
signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost);
signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes);

View File

@ -50,22 +50,21 @@ loop:
#include <irssi/src/irc/core/irc-channels.h>
#include <irssi/src/irc/core/servers-redirect.h>
enum {
CHANNEL_QUERY_MODE,
CHANNEL_QUERY_WHO,
CHANNEL_QUERY_BMODE,
/* here are the WHOX commands we send. the full spec can be found on [1].
CHANNEL_QUERIES
};
(1) WHOX_CHANNEL_FULL_CMD for getting the user list when we join a channel. we request the fields
c (channel), u (user), h (host), n (nick), f (flags), d (hops), a (important, account!), and
r (the real name goes last because it os the only that can contain spaces.) we request all
those fields as they are also included in the "regular" WHO reply we would get without WHOX.
#define CHANNEL_IS_MODE_QUERY(a) ((a) != CHANNEL_QUERY_WHO)
(2) WHOX_USERACCOUNT_CMD for getting the account names of people that joined. this code is
obviously only used when we don't have extended-joins. we request n (nick) and a (account)
only, and we only send WHO nick with this command.
typedef struct {
int current_query_type; /* query type that is currently being asked */
GSList *current_queries; /* All channels that are currently being queried */
GSList *queries[CHANNEL_QUERIES]; /* All queries that need to be asked from server */
} SERVER_QUERY_REC;
[1] https://github.com/UndernetIRC/ircu2/blob/u2_10_12_branch/doc/readme.who
*/
#define WHOX_CHANNEL_FULL_CMD "WHO %s %%tcuhnfdar," WHOX_CHANNEL_FULL_ID
#define WHOX_USERACCOUNT_CMD "WHO %s %%tna," WHOX_USERACCOUNT_ID
static void sig_connected(IRC_SERVER_REC *server)
{
@ -76,7 +75,9 @@ static void sig_connected(IRC_SERVER_REC *server)
return;
rec = g_new0(SERVER_QUERY_REC, 1);
server->chanqueries = rec;
rec->accountqueries = g_hash_table_new_full(
(GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal, (GDestroyNotify) g_free, NULL);
server->chanqueries = rec;
}
static void sig_disconnected(IRC_SERVER_REC *server)
@ -91,6 +92,7 @@ static void sig_disconnected(IRC_SERVER_REC *server)
rec = server->chanqueries;
g_return_if_fail(rec != NULL);
g_hash_table_destroy(rec->accountqueries);
for (n = 0; n < CHANNEL_QUERIES; n++)
g_slist_free(rec->queries[n]);
g_slist_free(rec->current_queries);
@ -229,15 +231,19 @@ static void query_send(IRC_SERVER_REC *server, int query)
break;
case CHANNEL_QUERY_WHO:
cmd = g_strdup_printf("WHO %s", chanstr_commas);
if (server->isupport != NULL &&
g_hash_table_lookup(server->isupport, "whox") != NULL) {
cmd = g_strdup_printf(WHOX_CHANNEL_FULL_CMD, chanstr_commas);
} else {
cmd = g_strdup_printf("WHO %s", chanstr_commas);
}
server_redirect_event(server, "who",
server->one_endofwho ? 1 : count,
chanstr, -1,
"chanquery abort",
"event 315", "chanquery who end",
"event 352", "silent event who",
"", "chanquery abort", NULL);
server_redirect_event(server, "who", server->one_endofwho ? 1 : count, chanstr, -1,
"chanquery abort", /* failure signal */
"event 315", "chanquery who end", /* */
"event 352", "silent event who", /* */
"event 354", "silent event whox", /* */
"", "chanquery abort", NULL);
break;
case CHANNEL_QUERY_BMODE:
@ -395,6 +401,146 @@ static void channel_got_query(IRC_CHANNEL_REC *chanrec, int query_type)
query_check(chanrec->server);
}
void irc_channels_query_purge_accountquery(IRC_SERVER_REC *server, const char *nick)
{
GSList *tmp, *next, *prev;
REDIRECT_REC *redirect;
char *cmd, *target_cmd;
gboolean was_removed;
/* remove the marker */
was_removed = g_hash_table_remove(server->chanqueries->accountqueries, nick);
/* if it was removed we may have an outstanding query */
if (was_removed) {
target_cmd = g_strdup_printf(WHOX_USERACCOUNT_CMD "\r\n", nick);
/* remove queued WHO command */
prev = NULL;
for (tmp = server->cmdqueue; tmp != NULL; tmp = next) {
next = tmp->next->next;
cmd = tmp->data;
redirect = tmp->next->data;
if (g_strcmp0(cmd, target_cmd) == 0) {
if (prev != NULL)
prev->next = next;
else
server->cmdqueue = next;
/* remove the redirection */
g_slist_free_1(tmp->next);
if (redirect != NULL)
server_redirect_destroy(redirect);
/* remove the command */
g_slist_free_1(tmp);
g_free(cmd);
server->cmdcount--;
} else {
prev = tmp->next;
}
}
g_free(target_cmd);
}
}
static void query_useraccount_error(IRC_SERVER_REC *server, const char *cmd, const char *arg)
{
/* query failed, ignore it but remove the marker */
g_hash_table_remove(server->chanqueries->accountqueries, arg);
}
static void sig_event_join(IRC_SERVER_REC *server, const char *data, const char *nick,
const char *address)
{
char *params, *channel, *ptr, *account;
GSList *nicks, *tmp;
IRC_CHANNEL_REC *chanrec;
NICK_REC *nickrec;
g_return_if_fail(data != NULL);
if (i_slist_find_string(server->cap_active, CAP_EXTENDED_JOIN)) {
/* no need to chase accounts */
return;
}
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
/* You joined, do nothing */
return;
}
params = event_get_params(data, 3, &channel, NULL, NULL);
ptr = strchr(channel, 7); /* ^G does something weird.. */
if (ptr != NULL)
*ptr = '\0';
/* find channel */
chanrec = irc_channel_find(server, channel);
if (chanrec == NULL) {
g_free(params);
return;
}
g_free(params);
if (!chanrec->wholist) {
return;
}
/* find nick */
nickrec = nicklist_find(CHANNEL(chanrec), nick);
if (nickrec == NULL) {
return;
}
if (nickrec->account != NULL) {
return;
}
if (g_hash_table_contains(server->chanqueries->accountqueries, nick)) {
/* query already sent */
return;
}
account = NULL;
/* Check if user is already in some other channel, get the account from there */
nicks = nicklist_get_same(SERVER(server), nick);
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
NICK_REC *rec = tmp->next->data;
if (rec->account != NULL) {
account = rec->account;
break;
}
}
g_slist_free(nicks);
if (account != NULL) {
nicklist_set_account(CHANNEL(chanrec), nickrec, account);
return;
}
if (g_hash_table_size(chanrec->nicks) < settings_get_int("channel_max_who_sync") &&
server->isupport != NULL && g_hash_table_lookup(server->isupport, "whox") != NULL) {
char *cmd;
server_redirect_event(server, "who user", 1, nick, -1,
"chanquery useraccount abort", /* failure signal */
"event 354", "silent event whox useraccount", /* */
"", "event empty", /* */
NULL);
cmd = g_strdup_printf(WHOX_USERACCOUNT_CMD, nick);
g_hash_table_add(server->chanqueries->accountqueries, g_strdup(nick));
/* queue the command */
irc_send_cmd_full(server, cmd, FALSE, FALSE, FALSE);
g_free(cmd);
}
}
static void event_channel_mode(IRC_SERVER_REC *server, const char *data,
const char *nick)
{
@ -493,11 +639,14 @@ void channels_query_init(void)
signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined);
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
signal_add("event join", (SIGNAL_FUNC) sig_event_join);
signal_add("chanquery mode", (SIGNAL_FUNC) event_channel_mode);
signal_add("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
signal_add("chanquery ban end", (SIGNAL_FUNC) event_end_of_banlist);
signal_add("chanquery abort", (SIGNAL_FUNC) query_current_error);
signal_add("chanquery useraccount abort", (SIGNAL_FUNC) query_useraccount_error);
}
void channels_query_deinit(void)
@ -507,9 +656,12 @@ void channels_query_deinit(void)
signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined);
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
signal_remove("event join", (SIGNAL_FUNC) sig_event_join);
signal_remove("chanquery mode", (SIGNAL_FUNC) event_channel_mode);
signal_remove("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
signal_remove("chanquery ban end", (SIGNAL_FUNC) event_end_of_banlist);
signal_remove("chanquery abort", (SIGNAL_FUNC) query_current_error);
signal_remove("chanquery useraccount abort", (SIGNAL_FUNC) query_useraccount_error);
}

View File

@ -11,6 +11,20 @@
#define IS_IRC_CHANNEL(channel) \
(IRC_CHANNEL(channel) ? TRUE : FALSE)
enum {
CHANNEL_QUERY_MODE,
CHANNEL_QUERY_WHO,
CHANNEL_QUERY_BMODE,
CHANNEL_QUERIES
};
/* arbitrary 3-digit identifiers so we can find our WHOX responses */
#define WHOX_CHANNEL_FULL_ID "743"
#define WHOX_USERACCOUNT_ID "745"
#define CHANNEL_IS_MODE_QUERY(a) ((a) != CHANNEL_QUERY_WHO)
#define STRUCT_SERVER_REC IRC_SERVER_REC
struct _IRC_CHANNEL_REC {
#include <irssi/src/core/channel-rec.h>
@ -22,6 +36,16 @@ struct _IRC_CHANNEL_REC {
int last_massjoins; /* Massjoins when last checked in timeout function */
};
typedef struct _SERVER_QUERY_REC {
int current_query_type; /* query type that is currently being asked */
GSList *current_queries; /* All channels that are currently being queried */
GSList *queries[CHANNEL_QUERIES]; /* All queries that need to be asked from server */
GHashTable *accountqueries; /* Per-nick account queries */
} SERVER_QUERY_REC;
void irc_channels_query_purge_accountquery(IRC_SERVER_REC *server, const char *nick);
void irc_channels_init(void);
void irc_channels_deinit(void);

View File

@ -438,15 +438,18 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
query = get_redirect_nicklist(query, &free_nick);
str = g_strconcat(qserver, " ", query, NULL);
server_redirect_event(server, "whois", 1, str, TRUE,
NULL,
"event 318", "whois end",
"event 402", event_402,
"event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
"event 313", "whois oper",
"event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
"event 311", "whois event",
"", "whois default event", NULL);
server_redirect_event(
server, "whois", 1, str, TRUE, /* */
NULL, /* */
"event 318", "whois end", /* */
"event 402", event_402, /* */
"event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
"event 313", "whois oper", /* */
"event 330", "whois account", /* */
"event 401",
(settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
"event 311", "whois event", /* */
"", "whois default event", NULL);
g_free(str);
server->whois_found = FALSE;

View File

@ -29,6 +29,34 @@
#include <irssi/src/irc/core/modes.h>
#include <irssi/src/core/servers.h>
static void nicklist_set_modes(IRC_CHANNEL_REC *channel, NICK_REC *rec, gboolean op,
gboolean halfop, gboolean voice, const char *prefixes,
gboolean send_changed)
{
gboolean changed = FALSE;
if (rec->op != op) {
rec->op = op;
changed = TRUE;
}
if (rec->halfop != halfop) {
rec->halfop = halfop;
changed = TRUE;
}
if (rec->voice != voice) {
rec->voice = voice;
changed = TRUE;
}
if (prefixes != NULL && g_strcmp0(rec->prefixes, prefixes) != 0) {
g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
changed = TRUE;
}
if (changed && send_changed) {
signal_emit("nicklist changed", 3, channel, rec, rec->nick);
}
}
/* Add new nick to list */
NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
int op, int halfop, int voice, int send_massjoin,
@ -42,14 +70,8 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
rec = g_new0(NICK_REC, 1);
rec->nick = g_strdup(nick);
if (op) rec->op = TRUE;
if (halfop) rec->halfop = TRUE;
if (voice) rec->voice = TRUE;
rec->send_massjoin = send_massjoin;
if (prefixes != NULL) {
g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
}
nicklist_set_modes(channel, rec, op, halfop, voice, prefixes, FALSE);
nicklist_insert(CHANNEL(channel), rec);
return rec;
@ -154,11 +176,14 @@ static void event_names_list(IRC_SERVER_REC *server, const char *data)
if (host != NULL)
*host++ = '\0';
if (nicklist_find((CHANNEL_REC *) chanrec, ptr) == NULL) {
rec = nicklist_find((CHANNEL_REC *) chanrec, ptr);
if (rec == NULL) {
rec = irc_nicklist_insert(chanrec, ptr, op, halfop,
voice, FALSE, prefixes);
if (host != NULL)
nicklist_set_host(CHANNEL(chanrec), rec, host);
} else {
nicklist_set_modes(chanrec, rec, op, halfop, voice, prefixes, TRUE);
}
}
@ -196,23 +221,13 @@ static void event_end_of_names(IRC_SERVER_REC *server, const char *data)
g_free(params);
}
static void event_who(SERVER_REC *server, const char *data)
static void fill_who(SERVER_REC *server, const char *channel, const char *user, const char *host,
const char *nick, const char *stat, const char *hops, const char *account,
const char *realname)
{
char *params, *nick, *channel, *user, *host, *stat, *realname, *hops;
CHANNEL_REC *chanrec;
NICK_REC *nickrec;
g_return_if_fail(data != NULL);
params = event_get_params(data, 8, NULL, &channel, &user, &host,
NULL, &nick, &stat, &realname);
/* get hop count */
hops = realname;
while (*realname != '\0' && *realname != ' ') realname++;
if (*realname == ' ')
*realname++ = '\0';
/* update host, realname, hopcount */
chanrec = channel_find(server, channel);
nickrec = chanrec == NULL ? NULL :
@ -223,15 +238,89 @@ static void event_who(SERVER_REC *server, const char *data)
nicklist_set_host(chanrec, nickrec, str);
g_free(str);
}
if (nickrec->realname == NULL)
if (nickrec->realname == NULL) {
nickrec->realname = g_strdup(realname);
}
if (nickrec->account == NULL && account != NULL) {
nicklist_set_account(chanrec, nickrec,
strcmp(account, "0") == 0 ? "*" : account);
}
sscanf(hops, "%d", &nickrec->hops);
}
nicklist_update_flags(server, nick,
strchr(stat, 'G') != NULL, /* gone */
strchr(stat, '*') != NULL); /* ircop */
}
static void event_who(SERVER_REC *server, const char *data)
{
char *params, *nick, *channel, *user, *host, *stat, *realname, *hops;
g_return_if_fail(data != NULL);
params =
event_get_params(data, 8, NULL, &channel, &user, &host, NULL, &nick, &stat, &realname);
/* get hop count */
hops = realname;
while (*realname != '\0' && *realname != ' ')
realname++;
if (*realname == ' ')
*realname++ = '\0';
fill_who(server, channel, user, host, nick, stat, hops, NULL, realname);
g_free(params);
}
static void event_whox_channel_full(SERVER_REC *server, const char *data)
{
char *params, *id, *nick, *channel, *user, *host, *stat, *hops, *account, *realname;
g_return_if_fail(data != NULL);
params = event_get_params(data, 10, NULL, &id, &channel, &user, &host, &nick, &stat, &hops,
&account, &realname);
if (g_strcmp0(id, WHOX_CHANNEL_FULL_ID) != 0) {
g_free(params);
return;
}
fill_who(server, channel, user, host, nick, stat, hops, account, realname);
g_free(params);
}
static void event_whox_useraccount(IRC_SERVER_REC *server, const char *data)
{
char *params, *id, *nick, *account;
GSList *nicks, *tmp;
g_return_if_fail(data != NULL);
params = event_get_params(data, 4, NULL, &id, &nick, &account);
if (g_strcmp0(id, WHOX_USERACCOUNT_ID) != 0) {
g_free(params);
return;
}
g_hash_table_remove(server->chanqueries->accountqueries, nick);
if (strcmp(account, "0") == 0) {
account = "*";
}
nicks = nicklist_get_same(SERVER(server), nick);
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
NICK_REC *rec = tmp->next->data;
if (rec->account == NULL || g_strcmp0(rec->account, account) != 0) {
nicklist_set_account(CHANNEL(tmp->data), rec, account);
}
}
g_slist_free(nicks);
g_free(params);
}
@ -415,7 +504,9 @@ static void event_nick(IRC_SERVER_REC *server, const char *data,
server_change_nick(SERVER(server), nick);
}
nicklist_rename(SERVER(server), orignick, nick);
/* invalidate any outstanding accountqueries for the old nick */
irc_channels_query_purge_accountquery(server, orignick);
nicklist_rename(SERVER(server), orignick, nick);
g_free(params);
}
@ -510,7 +601,10 @@ void irc_nicklist_init(void)
{
signal_add_first("event nick", (SIGNAL_FUNC) event_nick);
signal_add_first("event 352", (SIGNAL_FUNC) event_who);
signal_add_first("event 354", (SIGNAL_FUNC) event_whox_channel_full);
signal_add("silent event who", (SIGNAL_FUNC) event_who);
signal_add("silent event whox", (SIGNAL_FUNC) event_whox_channel_full);
signal_add("silent event whox useraccount", (SIGNAL_FUNC) event_whox_useraccount);
signal_add("silent event whois", (SIGNAL_FUNC) event_whois);
signal_add_first("event 311", (SIGNAL_FUNC) event_whois);
signal_add_first("whois away", (SIGNAL_FUNC) event_whois_away);
@ -534,7 +628,10 @@ void irc_nicklist_deinit(void)
{
signal_remove("event nick", (SIGNAL_FUNC) event_nick);
signal_remove("event 352", (SIGNAL_FUNC) event_who);
signal_remove("event 354", (SIGNAL_FUNC) event_whox_channel_full);
signal_remove("silent event who", (SIGNAL_FUNC) event_who);
signal_remove("silent event whox", (SIGNAL_FUNC) event_whox_channel_full);
signal_remove("silent event whox useraccount", (SIGNAL_FUNC) event_whox_useraccount);
signal_remove("silent event whois", (SIGNAL_FUNC) event_whois);
signal_remove("event 311", (SIGNAL_FUNC) event_whois);
signal_remove("whois away", (SIGNAL_FUNC) event_whois_away);

View File

@ -136,7 +136,7 @@ struct _IRC_SERVER_REC {
GSList *rejoin_channels; /* try to join to these channels after a while -
channels go here if they're "temporarily unavailable"
because of netsplits */
void *chanqueries;
struct _SERVER_QUERY_REC *chanqueries;
GHashTable *isupport;
struct modes_type modes[256]; /* Stores the modes sent by a server in an isupport reply */

View File

@ -39,12 +39,15 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
IRC_CHANNEL_REC *chanrec;
NICK_REC *nickrec;
GSList *nicks, *tmp;
gboolean send_massjoin;
g_return_if_fail(data != NULL);
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
/* You joined, no need to do anything here */
return;
/* You joined, do not massjoin */
send_massjoin = FALSE;
} else {
send_massjoin = TRUE;
}
params = event_get_params(data, 3, &channel, &account, &realname);
@ -68,14 +71,14 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
}
/* add user to nicklist */
nickrec = irc_nicklist_insert(chanrec, nick, FALSE, FALSE, FALSE, TRUE, NULL);
nickrec = irc_nicklist_insert(chanrec, nick, FALSE, FALSE, FALSE, send_massjoin, NULL);
if (*account != '\0' && g_strcmp0(nickrec->account, account) != 0) {
nicklist_set_account(CHANNEL(chanrec), nickrec, account);
}
nicklist_set_host(CHANNEL(chanrec), nickrec, address);
if (chanrec->massjoins == 0) {
if (send_massjoin && chanrec->massjoins == 0) {
/* no nicks waiting in massjoin queue */
chanrec->massjoin_start = time(NULL);
chanrec->last_massjoins = 0;
@ -104,7 +107,9 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
nickrec->realname = g_strdup(realname);
}
chanrec->massjoins++;
if (send_massjoin) {
chanrec->massjoins++;
}
g_free(params);
}
@ -217,6 +222,9 @@ static void event_quit(IRC_SERVER_REC *server, const char *data,
nicklist_remove(CHANNEL(channel), nickrec);
}
g_slist_free(nicks);
/* invalidate any outstanding accountqueries for the nick */
irc_channels_query_purge_accountquery(server, nick);
}
static void event_kick(IRC_SERVER_REC *server, const char *data)

View File

@ -442,7 +442,7 @@ static void redirect_abort(IRC_SERVER_REC *server, REDIRECT_REC *rec)
g_free(str);
if (rec->failure_signal != NULL)
signal_emit(rec->failure_signal, 1, server);
signal_emit(rec->failure_signal, 3, server, rec->cmd->name, rec->arg);
} else if (rec->last_signal != NULL) {
/* emit the last signal */
signal_emit(rec->last_signal, 1, server);
@ -697,7 +697,16 @@ void servers_redirect_init(void)
NULL,
NULL);
/* LIST */
/* WHO user */
server_redirect_register("who user", FALSE, 0, /* */
"event 352", 5, /* An element of the WHO */
"event 354", -1, /* WHOX element */
NULL, /* */
"event 315", 1, /* End of WHO */
NULL, /* */
NULL);
/* LIST */
server_redirect_register("list", FALSE, 0,
"event 321", 1, /* Begins the LIST */
NULL,