1
0
mirror of https://github.com/irssi/irssi.git synced 2024-09-29 04:45:57 -04:00

better account tracking

This commit is contained in:
Ailin Nemui 2021-01-05 21:34:09 +01:00
parent bf1376e34e
commit dc87199100
6 changed files with 247 additions and 45 deletions

View File

@ -415,6 +415,7 @@ void fe_whois_init(void)
signal_add("event 319", (SIGNAL_FUNC) event_whois_channels); signal_add("event 319", (SIGNAL_FUNC) event_whois_channels);
signal_add("event 313", (SIGNAL_FUNC) event_whois_oper); signal_add("event 313", (SIGNAL_FUNC) event_whois_oper);
signal_add("event 330", (SIGNAL_FUNC) event_whois_auth); 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 377", (SIGNAL_FUNC) event_whois_usermode);
signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost); signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost);
signal_add("event 379", (SIGNAL_FUNC) event_whois_modes); 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 319", (SIGNAL_FUNC) event_whois_channels);
signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper); signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper);
signal_remove("event 330", (SIGNAL_FUNC) event_whois_auth); 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 377", (SIGNAL_FUNC) event_whois_usermode);
signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost); signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost);
signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes); signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes);

View File

@ -229,15 +229,19 @@ static void query_send(IRC_SERVER_REC *server, int query)
break; break;
case CHANNEL_QUERY_WHO: 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("WHO %s %%tcuhnfdar,743", chanstr_commas);
} else {
cmd = g_strdup_printf("WHO %s", chanstr_commas);
}
server_redirect_event(server, "who", server_redirect_event(server, "who", server->one_endofwho ? 1 : count, chanstr, -1,
server->one_endofwho ? 1 : count, "chanquery abort", /* failure signal */
chanstr, -1, "event 315", "chanquery who end", /* */
"chanquery abort", "event 352", "silent event who", /* */
"event 315", "chanquery who end", "event 354", "silent event whox", /* */
"event 352", "silent event who", "", "chanquery abort", NULL);
"", "chanquery abort", NULL);
break; break;
case CHANNEL_QUERY_BMODE: case CHANNEL_QUERY_BMODE:
@ -395,6 +399,87 @@ static void channel_got_query(IRC_CHANNEL_REC *chanrec, int query_type)
query_check(chanrec->server); query_check(chanrec->server);
} }
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;
}
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, NULL, /* failure signal */
"event 354", "silent event whox useraccount", /* */
"", "event empty", /* */
NULL);
cmd = g_strdup_printf("WHO %s %%tna,745", nick);
irc_send_cmd(server, cmd);
g_free(cmd);
}
}
static void event_channel_mode(IRC_SERVER_REC *server, const char *data, static void event_channel_mode(IRC_SERVER_REC *server, const char *data,
const char *nick) const char *nick)
{ {
@ -493,6 +578,8 @@ void channels_query_init(void)
signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined); signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined);
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); 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 mode", (SIGNAL_FUNC) event_channel_mode);
signal_add("chanquery who end", (SIGNAL_FUNC) event_end_of_who); signal_add("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
@ -507,6 +594,8 @@ void channels_query_deinit(void)
signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined); signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined);
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); 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 mode", (SIGNAL_FUNC) event_channel_mode);
signal_remove("chanquery who end", (SIGNAL_FUNC) event_end_of_who); signal_remove("chanquery who end", (SIGNAL_FUNC) event_end_of_who);

View File

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

View File

@ -29,6 +29,34 @@
#include <irssi/src/irc/core/modes.h> #include <irssi/src/irc/core/modes.h>
#include <irssi/src/core/servers.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 */ /* Add new nick to list */
NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick, NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
int op, int halfop, int voice, int send_massjoin, 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 = g_new0(NICK_REC, 1);
rec->nick = g_strdup(nick); 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; rec->send_massjoin = send_massjoin;
nicklist_set_modes(channel, rec, op, halfop, voice, prefixes, FALSE);
if (prefixes != NULL) {
g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
}
nicklist_insert(CHANNEL(channel), rec); nicklist_insert(CHANNEL(channel), rec);
return rec; return rec;
@ -154,11 +176,14 @@ static void event_names_list(IRC_SERVER_REC *server, const char *data)
if (host != NULL) if (host != NULL)
*host++ = '\0'; *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, rec = irc_nicklist_insert(chanrec, ptr, op, halfop,
voice, FALSE, prefixes); voice, FALSE, prefixes);
if (host != NULL) if (host != NULL)
nicklist_set_host(CHANNEL(chanrec), rec, host); 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); 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; CHANNEL_REC *chanrec;
NICK_REC *nickrec; 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 */ /* update host, realname, hopcount */
chanrec = channel_find(server, channel); chanrec = channel_find(server, channel);
nickrec = chanrec == NULL ? NULL : nickrec = chanrec == NULL ? NULL :
@ -223,15 +238,88 @@ static void event_who(SERVER_REC *server, const char *data)
nicklist_set_host(chanrec, nickrec, str); nicklist_set_host(chanrec, nickrec, str);
g_free(str); g_free(str);
} }
if (nickrec->realname == NULL) if (nickrec->realname == NULL) {
nickrec->realname = g_strdup(realname); 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); sscanf(hops, "%d", &nickrec->hops);
} }
nicklist_update_flags(server, nick, nicklist_update_flags(server, nick,
strchr(stat, 'G') != NULL, /* gone */ strchr(stat, 'G') != NULL, /* gone */
strchr(stat, '*') != NULL); /* ircop */ 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_743(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, "743") != 0) {
g_free(params);
return;
}
fill_who(server, channel, user, host, nick, stat, hops, account, realname);
g_free(params);
}
static void event_whox_745(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, "745") != 0) {
g_free(params);
return;
}
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); g_free(params);
} }
@ -510,7 +598,10 @@ void irc_nicklist_init(void)
{ {
signal_add_first("event nick", (SIGNAL_FUNC) event_nick); signal_add_first("event nick", (SIGNAL_FUNC) event_nick);
signal_add_first("event 352", (SIGNAL_FUNC) event_who); signal_add_first("event 352", (SIGNAL_FUNC) event_who);
signal_add_first("event 354", (SIGNAL_FUNC) event_whox_743);
signal_add("silent event who", (SIGNAL_FUNC) event_who); signal_add("silent event who", (SIGNAL_FUNC) event_who);
signal_add("silent event whox", (SIGNAL_FUNC) event_whox_743);
signal_add("silent event whox useraccount", (SIGNAL_FUNC) event_whox_745);
signal_add("silent event whois", (SIGNAL_FUNC) event_whois); signal_add("silent event whois", (SIGNAL_FUNC) event_whois);
signal_add_first("event 311", (SIGNAL_FUNC) event_whois); signal_add_first("event 311", (SIGNAL_FUNC) event_whois);
signal_add_first("whois away", (SIGNAL_FUNC) event_whois_away); signal_add_first("whois away", (SIGNAL_FUNC) event_whois_away);
@ -534,7 +625,10 @@ void irc_nicklist_deinit(void)
{ {
signal_remove("event nick", (SIGNAL_FUNC) event_nick); signal_remove("event nick", (SIGNAL_FUNC) event_nick);
signal_remove("event 352", (SIGNAL_FUNC) event_who); signal_remove("event 352", (SIGNAL_FUNC) event_who);
signal_remove("event 354", (SIGNAL_FUNC) event_whox_743);
signal_remove("silent event who", (SIGNAL_FUNC) event_who); signal_remove("silent event who", (SIGNAL_FUNC) event_who);
signal_remove("silent event whox", (SIGNAL_FUNC) event_whox_743);
signal_remove("silent event whox useraccount", (SIGNAL_FUNC) event_whox_745);
signal_remove("silent event whois", (SIGNAL_FUNC) event_whois); signal_remove("silent event whois", (SIGNAL_FUNC) event_whois);
signal_remove("event 311", (SIGNAL_FUNC) event_whois); signal_remove("event 311", (SIGNAL_FUNC) event_whois);
signal_remove("whois away", (SIGNAL_FUNC) event_whois_away); signal_remove("whois away", (SIGNAL_FUNC) event_whois_away);

View File

@ -39,12 +39,15 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
IRC_CHANNEL_REC *chanrec; IRC_CHANNEL_REC *chanrec;
NICK_REC *nickrec; NICK_REC *nickrec;
GSList *nicks, *tmp; GSList *nicks, *tmp;
gboolean send_massjoin;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
if (g_ascii_strcasecmp(nick, server->nick) == 0) { if (g_ascii_strcasecmp(nick, server->nick) == 0) {
/* You joined, no need to do anything here */ /* You joined, do not massjoin */
return; send_massjoin = FALSE;
} else {
send_massjoin = TRUE;
} }
params = event_get_params(data, 3, &channel, &account, &realname); 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 */ /* 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) { if (*account != '\0' && g_strcmp0(nickrec->account, account) != 0) {
nicklist_set_account(CHANNEL(chanrec), nickrec, account); nicklist_set_account(CHANNEL(chanrec), nickrec, account);
} }
nicklist_set_host(CHANNEL(chanrec), nickrec, address); nicklist_set_host(CHANNEL(chanrec), nickrec, address);
if (chanrec->massjoins == 0) { if (send_massjoin && chanrec->massjoins == 0) {
/* no nicks waiting in massjoin queue */ /* no nicks waiting in massjoin queue */
chanrec->massjoin_start = time(NULL); chanrec->massjoin_start = time(NULL);
chanrec->last_massjoins = 0; chanrec->last_massjoins = 0;
@ -104,7 +107,9 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
nickrec->realname = g_strdup(realname); nickrec->realname = g_strdup(realname);
} }
chanrec->massjoins++; if (send_massjoin) {
chanrec->massjoins++;
}
g_free(params); g_free(params);
} }

View File

@ -671,7 +671,16 @@ void servers_redirect_init(void)
NULL, NULL,
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, server_redirect_register("list", FALSE, 0,
"event 321", 1, /* Begins the LIST */ "event 321", 1, /* Begins the LIST */
NULL, NULL,