1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-10 15:43:12 +02:00
Files
unrealircd/src/api-history-backend.c
T
Bram Matthys a8c191b291 Add new command: HISTORY #chan [lines]. This is meant for end-users
so they can fetch more history than the standard on-join history.

In the future we are also likely to implement IRCv3 CHATHISTORY
once that becomes an official specification. However, until it is
specified and until most major clients support it, several years
are likely to pass. It would be a shame to withhold channel
history to many end-users in the meantime when it takes so little
effort from us to provide an easy command.

See also
https://www.unrealircd.org/docs/Channel_history
And in particular the new section:
https://www.unrealircd.org/docs/Channel_history#Playback_frontends
which explains the relationship between on-join playback,
HISTORY and CHATHISTORY.
2020-02-02 11:57:51 +01:00

198 lines
4.6 KiB
C

/************************************************************************
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/api-history-backend.c
* (c) 2019- Bram Matthys and The UnrealIRCd team
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "unrealircd.h"
MODVAR HistoryBackend *historybackends = NULL; /**< List of registered history backends */
void history_backend_init(void)
{
}
/**
* Returns a history backend based on the given token name.
*
* @param name The name of the history backend.
* @return Returns the handle to the history backend,
* or NULL if not found.
*/
HistoryBackend *HistoryBackendFind(const char *name)
{
HistoryBackend *m;
for (m = historybackends; m; m = m->next)
{
if (!strcasecmp(name, m->name))
return m;
}
return NULL;
}
/**
* Adds a new history backend.
*
* @param module The module which provides this history backend.
* @param mreq The details of the request such as token name, access check handler, etc.
* @return Returns the handle to the new token if successful, otherwise NULL.
* The module's error code contains specific information about the
* error.
*/
HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mreq)
{
HistoryBackend *m;
int exists = 0;
if (!mreq->history_add || !mreq->history_request ||
!mreq->history_destroy || !mreq->history_set_limit)
{
if (module)
module->errorcode = MODERR_INVALID;
ircd_log(LOG_ERROR, "HistoryBackendAdd(): missing a handler for add/del/request/destroy/set_limit");
return NULL;
}
m = HistoryBackendFind(mreq->name);
if (m)
{
exists = 1;
if (m->unloaded)
{
m->unloaded = 0;
} else {
if (module)
module->errorcode = MODERR_EXISTS;
return NULL;
}
} else {
/* New history backend */
m = safe_alloc(sizeof(HistoryBackend));
safe_strdup(m->name, mreq->name);
}
/* Add or update the following fields: */
m->owner = module;
m->history_add = mreq->history_add;
m->history_request = mreq->history_request;
m->history_destroy = mreq->history_destroy;
m->history_set_limit = mreq->history_set_limit;
if (!exists)
AddListItem(m, historybackends);
if (module)
{
ModuleObject *mobj = safe_alloc(sizeof(ModuleObject));
mobj->type = MOBJ_HISTORY_BACKEND;
mobj->object.history_backend = m;
AddListItem(mobj, module->objects);
module->errorcode = MODERR_NOERROR;
}
return m;
}
void unload_history_backend_commit(HistoryBackend *m)
{
/* Destroy the object */
DelListItem(m, historybackends);
safe_free(m->name);
safe_free(m);
}
/**
* Removes the specified history backend.
*
* @param m The history backend to remove.
*/
void HistoryBackendDel(HistoryBackend *m)
{
if (m->owner)
{
ModuleObject *mobj;
for (mobj = m->owner->objects; mobj; mobj = mobj->next) {
if (mobj->type == MOBJ_HISTORY_BACKEND && mobj->object.history_backend == m)
{
DelListItem(mobj, m->owner->objects);
safe_free(mobj);
break;
}
}
m->owner = NULL;
}
if (loop.ircd_rehashing)
m->unloaded = 1;
else
unload_history_backend_commit(m);
}
void unload_all_unused_history_backends(void)
{
HistoryBackend *m, *m_next;
for (m = historybackends; m; m = m_next)
{
m_next = m->next;
if (m->unloaded)
unload_history_backend_commit(m);
}
}
int history_add(char *object, MessageTag *mtags, char *line)
{
HistoryBackend *hb;
for (hb = historybackends; hb; hb=hb->next)
hb->history_add(object, mtags, line);
return 1;
}
int history_request(Client *client, char *object, HistoryFilter *filter)
{
HistoryBackend *hb;
for (hb = historybackends; hb; hb=hb->next)
hb->history_request(client, object, filter);
return 1;
}
int history_destroy(char *object)
{
HistoryBackend *hb;
for (hb = historybackends; hb; hb=hb->next)
hb->history_destroy(object);
return 1;
}
int history_set_limit(char *object, int max_lines, long max_t)
{
HistoryBackend *hb;
for (hb = historybackends; hb; hb=hb->next)
hb->history_set_limit(object, max_lines, max_t);
return 1;
}