#include "irc_chan.h"
#include "irc_nm.h"
#include "log.h"
#include <stdlib.h>
#include <assert.h>
const char* irc_chan_name (struct irc_chan *chan)
{
return chan->info.channel;
}
/**
* :nm JOIN <channel>
*/
static void irc_chan_on_JOIN (const struct irc_line *line, void *arg)
{
struct irc_chan *chan = arg;
// us?
if (irc_prefix_cmp_nick(line->prefix, chan->net->conn->nickname) == 0) {
// twiddle state
chan->state.joining = false;
chan->state.joined = true;
log_info("joined channel: %s", chan->info.channel);
// invoke callback
IRC_CHAN_INVOKE_CALLBACK(chan, on_self_join);
}
}
/**
* :nm PRIVMSG <channel> <message>
*/
static void irc_chan_on_PRIVMSG (const struct irc_line *line, void *arg)
{
struct irc_chan *chan = arg;
// invoke callback (prefix, message)
IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, line->prefix, line->args[1]);
}
/**
* Core command handlers
*/
struct irc_cmd_handler _cmd_handlers[] = {
{ "JOIN", &irc_chan_on_JOIN },
{ "PRIVMSG", &irc_chan_on_PRIVMSG },
{ NULL, NULL }
};
err_t irc_chan_create (struct irc_chan **chan_ptr, struct irc_net *net, const struct irc_chan_info *info, struct error_info *err)
{
struct irc_chan *chan;
// allocate
if ((chan = calloc(1, sizeof(*chan))) == NULL)
return SET_ERROR(err, ERR_CALLOC);
// store
chan->net = net;
chan->info = *info;
// init
irc_cmd_init(&chan->handlers);
CHAIN_INIT(&chan->callbacks);
// add handlers
if ((ERROR_CODE(err) = irc_cmd_add(&chan->handlers, _cmd_handlers, chan)))
goto error;
// ok
*chan_ptr = chan;
return SUCCESS;
error:
// cleanup
irc_chan_destroy(chan);
return ERROR_CODE(err);
}
void irc_chan_destroy (struct irc_chan *chan)
{
// free command handlers
irc_cmd_free(&chan->handlers);
// free callbacks
chain_free(&chan->callbacks);
// free chan itself
free(chan);
}
err_t irc_chan_add_callbacks (struct irc_chan *chan, const struct irc_chan_callbacks *callbacks, void *arg)
{
return chain_add(&chan->callbacks, callbacks, arg);
}
err_t irc_chan_join (struct irc_chan *chan)
{
err_t err;
// XXX: error instead?
assert(!chan->state.joining && !chan->state.joined);
// send JOIN message on the appropriate connection
if ((err = irc_conn_JOIN(chan->net->conn, chan->info.channel)))
// XXX: error state?
return err;
// ok
chan->state.joining = true;
return SUCCESS;
}