1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-12 17:34:46 +02:00

Expose more WHOWAS fields in JSON-RPC and change add_history() to take a reason

for the add, like: nick-change, quit, server terminating. Add logon time.

I also think i will move from user.get_whowas to a whowas.XXX since the
returned object is not a user object and getting more different each commit :D.
This commit is contained in:
Bram Matthys
2023-04-15 08:57:15 +02:00
parent e2320cb506
commit 2184f38e7e
10 changed files with 120 additions and 25 deletions
+2 -1
View File
@@ -417,7 +417,7 @@ extern void del_whowas_from_clist(WhoWas **, WhoWas *);
extern void add_whowas_to_list(WhoWas **, WhoWas *);
extern void del_whowas_from_list(WhoWas **, WhoWas *);
extern uint64_t hash_whowas_name(const char *name);
extern void create_whowas_entry(Client *client, WhoWas *e);
extern void create_whowas_entry(Client *client, WhoWas *e, WhoWasEvent event);
extern void free_whowas_fields(WhoWas *e);
extern int add_to_client_hash_table(const char *, Client *);
extern int del_from_client_hash_table(const char *, Client *);
@@ -1348,6 +1348,7 @@ extern void procio_post_rehash(int failure);
/* end of proc i/o */
extern int minimum_msec_since_last_run(struct timeval *tv_old, long minimum);
extern long get_connected_time(Client *client);
extern time_t get_creationtime(Client *client);
extern const char *StripControlCodes(const char *text);
extern const char *StripControlCodesEx(const char *text, char *output, size_t outputlen, int strip_flags);
extern MODVAR Module *Modules;
+3 -1
View File
@@ -859,7 +859,9 @@ typedef struct Whowas {
char *realname;
char *account;
long umodes;
time_t logoff;
time_t logon;
time_t logoff;
WhoWasEvent event;
struct Client *online; /* Pointer to new nickname for chasing or NULL */
struct Whowas *next; /* for hash table... */
struct Whowas *prev; /* for hash table... */
+10 -1
View File
@@ -35,6 +35,15 @@
#ifndef __whowas_include__
#define __whowas_include__
/* NOTE: Don't reorder values of these, as they are used in whowasdb */
typedef enum WhoWasEvent {
WHOWAS_EVENT_QUIT=0,
WHOWAS_EVENT_NICK_CHANGE=1,
WHOWAS_EVENT_SERVER_TERMINATING=2
} WhoWasEvent;
#define WHOWAS_LOWEST_EVENT 0
#define WHOWAS_HIGHEST_EVENT 2
/*
** add_history
** Add the currently defined name of the client to history.
@@ -42,7 +51,7 @@
** Client must be a fully registered user (specifically,
** the user structure must have been allocated).
*/
void add_history(Client *, int);
void add_history(Client *, int, WhoWasEvent);
/*
** off_history
+1 -1
View File
@@ -344,7 +344,7 @@ void remove_client_from_list(Client *client)
if (IsUser(client)) /* Only persons can have been added before */
{
add_history(client, 0);
add_history(client, 0, WHOWAS_EVENT_QUIT);
off_history(client); /* Remove all pointers to client */
}
+3 -3
View File
@@ -205,7 +205,7 @@ CMD_FUNC(cmd_nick_remote)
new_message(client, recv_mtags, &mtags);
RunHook(HOOKTYPE_REMOTE_NICKCHANGE, client, mtags, nick);
client->lastnick = lastnick ? lastnick : TStime();
add_history(client, 1);
add_history(client, 1, WHOWAS_EVENT_NICK_CHANGE);
sendto_server(client, 0, 0, mtags, ":%s NICK %s %lld",
client->id, nick, (long long)client->lastnick);
sendto_local_common_channels(client, client, 0, mtags, ":%s NICK :%s", client->name, nick);
@@ -433,8 +433,8 @@ CMD_FUNC(cmd_nick_local)
new_message(client, recv_mtags, &mtags);
RunHook(HOOKTYPE_LOCAL_NICKCHANGE, client, mtags, nick);
client->lastnick = TStime();
add_history(client, 1);
add_history(client, 1, WHOWAS_EVENT_NICK_CHANGE);
client->lastnick = TStime(); /* needs to be done AFTER add_history() */
sendto_server(client, 0, 0, mtags, ":%s NICK %s %lld",
client->id, nick, (long long)client->lastnick);
sendto_local_common_channels(client, client, 0, mtags, ":%s NICK :%s", client->name, nick);
+13
View File
@@ -708,6 +708,17 @@ RPC_CALL_FUNC(rpc_user_part)
extern WhoWas MODVAR WHOWAS[NICKNAMEHISTORYLENGTH];
const char *whowas_event_to_string(WhoWasEvent event)
{
if (event == WHOWAS_EVENT_QUIT)
return "quit";
if (event == WHOWAS_EVENT_NICK_CHANGE)
return "nick-change";
if (event == WHOWAS_EVENT_SERVER_TERMINATING)
return "server-terminating";
return "unknown";
}
void json_expand_whowas(json_t *j, const char *key, WhoWas *e, int detail)
{
json_t *child;
@@ -736,6 +747,8 @@ void json_expand_whowas(json_t *j, const char *key, WhoWas *e, int detail)
if (detail < 2)
return;
json_object_set_new(child, "event", json_string_unreal(whowas_event_to_string(e->event)));
json_object_set_new(child, "logon_time", json_timestamp(e->logon));
json_object_set_new(child, "logoff_time", json_timestamp(e->logoff));
/* client.user */
+5 -3
View File
@@ -66,6 +66,7 @@ CMD_FUNC(cmd_svsnick)
MessageTag *mtags = NULL;
char nickname[NICKLEN+1];
char oldnickname[NICKLEN+1];
time_t ts;
if (!IsSvsCmdOk(client) || parc < 4 || (strlen(parv[2]) > NICKLEN))
return; /* This looks like an error anyway -Studded */
@@ -96,7 +97,7 @@ CMD_FUNC(cmd_svsnick)
if (acptr != ocptr)
acptr->umodes &= ~UMODE_REGNICK;
acptr->lastnick = atol(parv[3]);
ts = atol(parv[3]);
/* no 'recv_mtags' here, we do not inherit from SVSNICK but generate a new NICK event */
new_message(acptr, NULL, &mtags);
@@ -104,9 +105,10 @@ CMD_FUNC(cmd_svsnick)
RunHook(HOOKTYPE_LOCAL_NICKCHANGE, acptr, mtags, nickname);
sendto_local_common_channels(acptr, acptr, 0, mtags, ":%s NICK :%s", acptr->name, nickname);
sendto_one(acptr, mtags, ":%s NICK :%s", acptr->name, nickname);
sendto_server(NULL, 0, 0, mtags, ":%s NICK %s :%lld", acptr->id, nickname, (long long)acptr->lastnick);
sendto_server(NULL, 0, 0, mtags, ":%s NICK %s :%lld", acptr->id, nickname, (long long)ts);
add_history(acptr, 1);
add_history(acptr, 1, WHOWAS_EVENT_NICK_CHANGE);
acptr->lastnick = ts; /* needs to be done AFTER add_history() */
del_from_client_hash_table(acptr->name, acptr);
unreal_log(ULOG_INFO, "nick", "FORCED_NICK_CHANGE", acptr,
+53 -12
View File
@@ -327,7 +327,7 @@ int write_whowasdb(void)
WhoWas *e = safe_alloc(sizeof(WhoWas));
int ret;
create_whowas_entry(client, e);
create_whowas_entry(client, e, WHOWAS_EVENT_SERVER_TERMINATING);
ret = write_whowas_entry(db, tmpfname, e);
free_whowas_fields(e);
safe_free(e);
@@ -364,13 +364,19 @@ int write_whowasdb(void)
int write_whowas_entry(UnrealDB *db, const char *tmpfname, WhoWas *e)
{
char logontime[64];
char logofftime[64];
char event[16];
snprintf(logontime, sizeof(logontime), "%lld", (long long)e->logon);
snprintf(logofftime, sizeof(logofftime), "%lld", (long long)e->logoff);
snprintf(event, sizeof(event), "%d", e->event);
W_SAFE(unrealdb_write_int32(db, MAGIC_WHOWASDB_START));
W_SAFE_PROPERTY(db, "nick", e->name);
W_SAFE_PROPERTY(db, "logontime", logontime);
W_SAFE_PROPERTY(db, "logofftime", logofftime);
W_SAFE_PROPERTY(db, "event", event);
W_SAFE_PROPERTY(db, "username", e->username);
W_SAFE_PROPERTY(db, "hostname", e->hostname);
W_SAFE_PROPERTY(db, "ip", e->ip);
@@ -393,7 +399,8 @@ int write_whowas_entry(UnrealDB *db, const char *tmpfname, WhoWas *e)
safe_free(hostname); \
safe_free(ip); \
safe_free(realname); \
logofftime = 0; \
logontime = logofftime = 0; \
event = 0; \
safe_free(server); \
safe_free(virthost); \
safe_free(account); \
@@ -424,7 +431,9 @@ int read_whowasdb(void)
char *hostname = NULL;
char *ip = NULL;
char *realname = NULL;
long long logontime = 0;
long long logofftime = 0;
int event = 0;
char *server = NULL;
char *virthost = NULL;
char *account = NULL;
@@ -482,7 +491,8 @@ int read_whowasdb(void)
// Variables
key = value = NULL;
nick = username = hostname = ip = realname = virthost = account = server = NULL;
logofftime = 0;
logontime = logofftime = 0;
event = 0;
R_SAFE(unrealdb_read_int32(db, &magic));
if (magic != MAGIC_WHOWASDB_START)
@@ -495,26 +505,55 @@ int read_whowasdb(void)
R_SAFE(unrealdb_read_str(db, &key));
R_SAFE(unrealdb_read_str(db, &value));
if (!strcmp(key, "nick"))
{
nick = value;
else if (!strcmp(key, "username"))
} else
if (!strcmp(key, "username"))
{
username = value;
else if (!strcmp(key, "hostname"))
} else
if (!strcmp(key, "hostname"))
{
hostname = value;
else if (!strcmp(key, "ip"))
} else
if (!strcmp(key, "ip"))
{
ip = value;
else if (!strcmp(key, "realname"))
} else
if (!strcmp(key, "realname"))
{
realname = value;
else if (!strcmp(key, "logofftime"))
} else
if (!strcmp(key, "logontime"))
{
logontime = atoll(value);
safe_free(value);
} else
if (!strcmp(key, "logofftime"))
{
logofftime = atoll(value);
safe_free(value);
} else if (!strcmp(key, "server"))
} else
if (!strcmp(key, "event"))
{
event = atoi(value);
if ((event < WHOWAS_LOWEST_EVENT) || (event > WHOWAS_HIGHEST_EVENT))
event = WHOWAS_EVENT_QUIT; /* safety */
safe_free(value);
} else
if (!strcmp(key, "server"))
{
server = value;
else if (!strcmp(key, "virthost"))
} else
if (!strcmp(key, "virthost"))
{
virthost = value;
else if (!strcmp(key, "account"))
} else
if (!strcmp(key, "account"))
{
account = value;
else if (!strcmp(key, "end"))
} else
if (!strcmp(key, "end"))
{
safe_free(key);
safe_free(value);
@@ -546,7 +585,9 @@ int read_whowasdb(void)
"[whowasdb] Adding '$nick'...",
log_data_string("nick", nick));
e->hashv = hash_whowas_name(nick);
e->logon = logontime;
e->logoff = logofftime;
e->event = event;
safe_strdup(e->name, nick);
safe_strdup(e->username, username);
safe_strdup(e->hostname, hostname);
+19
View File
@@ -737,6 +737,25 @@ int hide_idle_time(Client *client, Client *target)
}
}
/** Get creation time of a client.
* @param client The client to check (user, server, anything)
* @returns the time when the client first connected to IRC, or 0 for unknown.
*/
time_t get_creationtime(Client *client)
{
const char *str;
/* Shortcut for local clients */
if (client->local)
return client->local->creationtime;
/* Otherwise, hopefully available through this... */
str = moddata_client_get(client, "creationtime");
if (!BadPtr(str) && (*str != '0'))
return atoll(str);
return 0;
}
/** Get how long a client is connected to IRC.
* @param client The client to check
* @returns how long the client is connected to IRC (number of seconds)
+11 -3
View File
@@ -43,15 +43,21 @@ void free_whowas_fields(WhoWas *e)
safe_free(e->account);
safe_free(e->ip);
e->servername = NULL;
e->event = 0;
e->logon = 0;
e->logoff = 0;
/* Remove from lists and reset hashv */
if (e->online)
del_whowas_from_clist(&(e->online->user->whowas), e);
del_whowas_from_list(&WHOWASHASH[e->hashv], e);
e->hashv = -1;
}
void create_whowas_entry(Client *client, WhoWas *e)
void create_whowas_entry(Client *client, WhoWas *e, WhoWasEvent event)
{
e->hashv = hash_whowas_name(client->name);
e->logon = client->lastnick;
e->logoff = TStime();
e->umodes = client->umodes;
safe_strdup(e->name, client->name);
@@ -72,9 +78,11 @@ void create_whowas_entry(Client *client, WhoWas *e)
*/
/* strlcpy(e->servername, client->user->server,HOSTLEN); */
e->servername = client->user->server;
e->event = event;
}
void add_history(Client *client, int online)
void add_history(Client *client, int online, WhoWasEvent event)
{
WhoWas *new;
@@ -83,7 +91,7 @@ void add_history(Client *client, int online)
if (new->hashv != -1)
free_whowas_fields(new);
create_whowas_entry(client, new);
create_whowas_entry(client, new, event);
if (online)
{