[FEATURE] /quote bip backlog [n]
/quote bip backlog triggers a log replay. With the optional argument n in hours, you can request a backlog of a few hours.
This commit is contained in:
parent
26eb9c28d7
commit
fe251f72b5
11
src/bip.c
11
src/bip.c
@ -1988,6 +1988,8 @@ void adm_bip_help(struct link_client *ic, int admin, const char *subhelp)
|
||||
bip_notify(ic, "/BIP ON_CONNECT_SEND # Clears on_connect_send");
|
||||
bip_notify(ic, "/BIP AWAY_NICK <nick> # Set away nick");
|
||||
bip_notify(ic, "/BIP AWAY_NICK # clear away nick");
|
||||
bip_notify(ic, "/BIP BACKLOG [n] # backlog text of the n last "
|
||||
"hours");
|
||||
} else if (admin && strcasecmp(subhelp, "RELOAD") == 0) {
|
||||
bip_notify(ic, "/BIP RELOAD (admin only) :");
|
||||
bip_notify(ic, " Reloads bip configuration file and apply "
|
||||
@ -2237,6 +2239,15 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
|
||||
bip_notify(ic, "-- AWAY_NICK command needs zero or one"
|
||||
" argument");
|
||||
}
|
||||
} else if (irc_line_elem_case_equals(line, privmsg + 1, "BACKLOG")) {
|
||||
if (irc_line_count(line) == privmsg + 2) {
|
||||
irc_cli_backlog(ic, 0);
|
||||
} else if (irc_line_count(line) == privmsg + 3) {
|
||||
int hours = atoi(irc_line_elem(line, privmsg + 2));
|
||||
irc_cli_backlog(ic, hours);
|
||||
} else {
|
||||
bip_notify(ic, "-- BACKLOG takes 0 or one argument");
|
||||
}
|
||||
} else if (admin && irc_line_elem_case_equals(line, privmsg + 1,
|
||||
"ADD_CONN")) {
|
||||
if (irc_line_count(line) != privmsg + 4) {
|
||||
|
24
src/irc.c
24
src/irc.c
@ -650,7 +650,7 @@ static void irc_cli_make_join(struct link_client *ic)
|
||||
}
|
||||
}
|
||||
|
||||
static void irc_cli_backlog(struct link_client *ic)
|
||||
void irc_cli_backlog(struct link_client *ic, int hours)
|
||||
{
|
||||
struct user *user;
|
||||
|
||||
@ -664,17 +664,25 @@ static void irc_cli_backlog(struct link_client *ic)
|
||||
return;
|
||||
}
|
||||
|
||||
if (hours != 0) {
|
||||
/* have some limit */
|
||||
if (hours > 24 * 366)
|
||||
hours = 24 * 366;
|
||||
}
|
||||
|
||||
list_t *backlogl;
|
||||
char *bl;
|
||||
list_t *bllines;
|
||||
|
||||
backlogl = log_backlogs(LINK(ic)->log);
|
||||
while ((bl = list_remove_first(backlogl))) {
|
||||
list_t *bllines;
|
||||
bllines = backlog_lines_from_last_mark(LINK(ic)->log, bl,
|
||||
LINK(ic)->l_server->nick);
|
||||
mylog(LOG_INFO, "backlogging: %s", bl);
|
||||
write_lines(CONN(ic), bllines);
|
||||
list_free(bllines);
|
||||
bllines = backlog_lines(LINK(ic)->log, bl,
|
||||
LINK(ic)->l_server->nick, hours);
|
||||
if (bllines) {
|
||||
mylog(LOG_INFO, "backlogging: %s", bl);
|
||||
write_lines(CONN(ic), bllines);
|
||||
list_free(bllines);
|
||||
}
|
||||
free(bl);
|
||||
}
|
||||
list_free(backlogl);
|
||||
@ -787,7 +795,7 @@ static int irc_cli_startup(bip_t *bip, struct link_client *ic,
|
||||
}
|
||||
|
||||
irc_cli_make_join(ic);
|
||||
irc_cli_backlog(ic);
|
||||
irc_cli_backlog(ic, 0);
|
||||
|
||||
log_client_connected(LINK(ic)->log);
|
||||
free(init_nick);
|
||||
|
@ -263,6 +263,7 @@ struct link *irc_link_new();
|
||||
void link_kill(bip_t *bip, struct link *);
|
||||
void unbind_from_link(struct link_client *ic);
|
||||
char *nick_from_ircmask(const char *mask);
|
||||
void irc_cli_backlog(struct link_client *ic, int hours);
|
||||
#define BIP_FAKEMASK "!bip@bip.bip.bip"
|
||||
|
||||
#endif
|
||||
|
91
src/log.c
91
src/log.c
@ -16,6 +16,7 @@
|
||||
#include "irc.h"
|
||||
#include "util.h"
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern int errno;
|
||||
extern int log_level;
|
||||
@ -292,7 +293,6 @@ static int log_add_file(log_t *logdata, const char *destination,
|
||||
store->name = bip_strdup(destination);
|
||||
store->skip_advance = 0;
|
||||
hash_insert(&logdata->logfgs, destination, store);
|
||||
list_it_init(&store->file_group, &store->file_it);
|
||||
}
|
||||
|
||||
if (!conf_log && logdata->user->backlog) {
|
||||
@ -302,6 +302,8 @@ static int log_add_file(log_t *logdata, const char *destination,
|
||||
|
||||
if (lf) {
|
||||
list_add_last(&store->file_group, lf);
|
||||
if (list_it_item(&store->file_it) == NULL)
|
||||
list_it_init_last(&store->file_group, &store->file_it);
|
||||
store->file_offset = lf->len;
|
||||
}
|
||||
return 1;
|
||||
@ -912,8 +914,20 @@ char *log_beautify(log_t *logdata, const char *buf, const char *storename,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static time_t compute_time(const char *buf)
|
||||
{
|
||||
struct tm tm;
|
||||
int err;
|
||||
err = sscanf(buf, "%2d-%2d-%4d %2d:%2d:%2d", &tm.tm_mday, &tm.tm_mon,
|
||||
&tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
|
||||
if (err != 6)
|
||||
return (time_t)-1;
|
||||
tm.tm_year -= 1900;
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
||||
static int log_backread_file(log_t *log, logstore_t *store, logfile_t *lf,
|
||||
list_t *res, const char *dest)
|
||||
list_t *res, const char *dest, time_t start)
|
||||
{
|
||||
char *buf, *logbr;
|
||||
int close = 0;
|
||||
@ -931,7 +945,7 @@ static int log_backread_file(log_t *log, logstore_t *store, logfile_t *lf,
|
||||
close = 1;
|
||||
}
|
||||
|
||||
if (list_get_first(&store->file_group) == lf) {
|
||||
if (!start && list_it_item(&store->file_it) == lf) {
|
||||
mylog(LOG_DEBUG, "Seeking %s to %d", lf->filename,
|
||||
store->file_offset);
|
||||
if (fseek(lf->file, store->file_offset, SEEK_SET)) {
|
||||
@ -968,6 +982,15 @@ static int log_backread_file(log_t *log, logstore_t *store, logfile_t *lf,
|
||||
if (buf[0] == 0 || buf[0] == '\n')
|
||||
continue;
|
||||
|
||||
if (start != 0) {
|
||||
time_t linetime = compute_time(buf);
|
||||
/* parse error, don't backlog */
|
||||
if (linetime == (time_t)-1)
|
||||
continue;
|
||||
/* too old line, don't backlog */
|
||||
if (linetime < start)
|
||||
continue;
|
||||
}
|
||||
logbr = log_beautify(log, buf, store->name, dest);
|
||||
if (logbr)
|
||||
list_add_last(res, logbr);
|
||||
@ -1010,14 +1033,15 @@ static list_t *log_backread(log_t *log, const char *storename, const char *dest)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterator_t file_it;
|
||||
list_iterator_t file_it = store->file_it;
|
||||
logfile_t *logf;
|
||||
|
||||
ret = list_new(NULL);
|
||||
for (list_it_init(&store->file_group, &file_it);
|
||||
for (file_it = store->file_it;
|
||||
(logf = list_it_item(&file_it));
|
||||
list_it_next(&file_it)) {
|
||||
if (!log_backread_file(log, store, logf, ret, dest)) {
|
||||
if (!log_backread_file(log, store, logf, ret, dest,
|
||||
(time_t)0)) {
|
||||
log_reinit(store);
|
||||
return ret;
|
||||
}
|
||||
@ -1213,29 +1237,26 @@ int log_parse_date(char *strdate, int *year, int *month, int *mday, int *hour,
|
||||
return ret;
|
||||
}
|
||||
|
||||
logfile_t *logstore_get_file_at(logstore_t *store, time_t at)
|
||||
void logstore_get_file_at(logstore_t *store, time_t at, list_iterator_t *li)
|
||||
{
|
||||
list_iterator_t li;
|
||||
|
||||
for (list_it_init(&store->file_group, &li); list_it_item(&li);
|
||||
list_it_next(&li)) {
|
||||
logfile_t *lf = list_it_item(&li);
|
||||
for (list_it_init(&store->file_group, li); list_it_item(li);
|
||||
list_it_next(li)) {
|
||||
logfile_t *lf = list_it_item(li);
|
||||
|
||||
if (mktime(&lf->last_log) > at)
|
||||
return lf;
|
||||
return;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
list_t *backlog_hours(log_t *log, const char *storename, int hours)
|
||||
static list_t *log_backread_hours(log_t *log, const char *storename,
|
||||
const char *dest, int hours)
|
||||
{
|
||||
time_t blstarttime, linetime;
|
||||
time_t blstarttime;
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
logstore_t *store;
|
||||
logfile_t *lf;
|
||||
const char *line;
|
||||
logfile_t *logf;
|
||||
list_t *ret;
|
||||
list_iterator_t file_it;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
if (tv.tv_sec <= 3600 * 24 * hours)
|
||||
@ -1243,36 +1264,38 @@ list_t *backlog_hours(log_t *log, const char *storename, int hours)
|
||||
blstarttime = tv.tv_sec - 3600 * 24 * hours;
|
||||
|
||||
store = hash_get(&log->logfgs, storename);
|
||||
lf = logstore_get_file_at(store, blstarttime);
|
||||
|
||||
foreach_logline(lf, line) {
|
||||
log_parse_date(line, &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
|
||||
&tm.tm_hour, &tm.tm_min, &tm.tm_sec);
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
linetime = mktime(&tm);
|
||||
if (linetime > blstarttime) {
|
||||
ret = list_new(NULL);
|
||||
for (logstore_get_file_at(store, blstarttime, &file_it);
|
||||
(logf = list_it_item(&file_it));
|
||||
list_it_next(&file_it)) {
|
||||
if (!log_backread_file(log, store, logf, ret, dest,
|
||||
blstarttime)) {
|
||||
log_reinit(store);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
list_t *backlog_lines_from_last_mark(log_t *log, const char *bl,
|
||||
const char *cli_nick)
|
||||
list_t *backlog_lines(log_t *log, const char *bl, const char *cli_nick,
|
||||
int hours)
|
||||
{
|
||||
list_t *ret;
|
||||
struct line l;
|
||||
const char *dest;
|
||||
|
||||
ret = list_new(NULL);
|
||||
ret = NULL;
|
||||
if (ischannel(*bl))
|
||||
dest = bl;
|
||||
else
|
||||
dest = cli_nick;
|
||||
|
||||
if (log_has_backlog(log, bl)) {
|
||||
ret = log_backread(log, bl, dest);
|
||||
if (hours == 0)
|
||||
ret = log_backread(log, bl, dest);
|
||||
else
|
||||
ret = log_backread_hours(log, bl, dest, hours);
|
||||
/*
|
||||
* This exception is cosmetic, but you want it.
|
||||
* Most of the time, you get backlog from your own nick for
|
||||
|
@ -103,5 +103,6 @@ int check_dir(char *filename, int is_fatal);
|
||||
void log_reset_store(log_t *log, const char *storename);
|
||||
|
||||
list_t *log_backlogs(log_t *log);
|
||||
list_t *backlog_lines_from_last_mark(log_t *log, const char *bl, const char *);
|
||||
list_t *backlog_lines(log_t *log, const char *bl, const char *cli_nick,
|
||||
int hours);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user