/* Global data */
server_t *servers;
channel_t *channels;
+user_t *users;
message_t *messages;
int history;
fprintf(chan->log, "(%04d-%02d-%02d %02d:%02d:%02d) %s%s %s\n",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
- msg->from ?: "***",
- msg->from ? ":" : "",
+ msg->from ? msg->from->name : "***",
+ msg->from ? ":" : "",
msg->text);
fflush(chan->log);
}
}
}
-void chat_recv(channel_t *channel, const char *from, const char *text)
+void chat_recv(channel_t *channel, user_t *from, const char *text)
{
append(&msg_buf, NULL, sizeof(message_t));
messages = (message_t*)msg_buf.data;
message_t *msg = &messages[history];
msg->channel = channel;
msg->when = time(NULL);
- msg->from = strcopy(from);
+ msg->from = from;
msg->text = strcopy(text);
history++;
return (*last = server);
}
+user_t *add_user(const char *name, server_t *server)
+{
+ user_t *user = NULL;
+ user_t **last = &users;
+ debug("adding %s user \"%s\"", server->name, name);
+ switch (server->protocol) {
+ case IRC:
+ user = irc_user();
+ break;
+ case XMPP:
+ user = xmpp_user();
+ break;
+ }
+ user->name = strcopy(name);
+ user->server = server;
+ while (*last)
+ last = &(*last)->next;
+ return (*last = user);
+}
+
channel_t *add_channel(const char *name, server_t *server)
{
channel_t *channel = NULL;
return NULL;
}
+user_t *find_user(const char *name)
+{
+ for (user_t *cur = users; cur; cur = cur->next) {
+ if (match(cur->name, name))
+ return cur;
+ }
+ return NULL;
+}
+
channel_t *find_channel(const char *name)
{
for (channel_t *cur = channels; cur; cur = cur->next) {
typedef struct server_t server_t;
typedef struct channel_t channel_t;
+typedef struct user_t user_t;
typedef enum {
IRC,
channel_t *next;
} channel_t;
+typedef struct user_t {
+ server_t *server;
+ char *name;
+ char *full;
+ user_t *next;
+} user_t;
+
typedef struct {
- channel_t *channel;
stamp_t when;
- char *from;
+ channel_t *channel;
+ user_t *from;
char *text;
} message_t;
/* Global Data */
extern server_t *servers;
extern channel_t *channels;
+extern user_t *users;
extern message_t *messages;
extern int history;
void chat_init(void);
void chat_config(const char *group, const char *name,
const char *key, const char *value);
-void chat_recv(channel_t *channel, const char *from, const char *text);
+void chat_recv(channel_t *channel, user_t *from, const char *text);
void chat_send(channel_t *channel, const char *text);
void chat_exit(void);
server_t *add_server(const char *name, protocol_t protocol);
channel_t *add_channel(const char *name, server_t *server);
+user_t *add_user(const char *name, server_t *server);
server_t *find_server(const char *name);
channel_t *find_channel(const char *name);
+user_t *find_user(const char *name);
/* Protocol functions */
extern void irc_init(void);
extern server_t *irc_server(void);
+extern user_t *irc_user(void);
extern channel_t *irc_channel(void);
extern void irc_config(server_t *server, channel_t *channel,
const char *group, const char *name,
extern void xmpp_init(void);
extern server_t *xmpp_server(void);
+extern user_t *xmpp_user(void);
extern channel_t *xmpp_channel(void);
extern void xmpp_config(server_t *server, channel_t *channel,
const char *group, const char *name,
IRC_DEAD,
} irc_state_t;
+typedef struct {
+ user_t user;
+
+ const char *nick;
+} irc_user_t;
+
typedef struct {
channel_t channel;
const char *auth;
const char *pass;
+ irc_user_t myself;
irc_channel_t system;
net_t net;
irc_state_t state;
return chan;
}
+static irc_user_t *find_nick(irc_server_t *srv, const char *from, int create)
+{
+ irc_user_t *usr;
+
+ /* Find existing channels */
+ for (user_t *cur = users; cur; cur = cur->next) {
+ if (cur->server != &srv->server)
+ continue;
+ usr = (irc_user_t *)cur;
+ if (match(usr->nick, from))
+ return usr;
+ }
+
+ /* Create a new channel */
+ usr = (irc_user_t *)add_user(from, &srv->server);
+ usr->nick = strcopy(from);
+ return usr;
+}
+
static void join_channel(irc_server_t *srv, irc_channel_t *chan)
{
chan_notice(chan, "Joining Channel: %s", chan->channel.name);
/* Receive messages */
if (srv->state == IRC_READY) {
irc_channel_t *chan;
+ irc_user_t *usr;
if (match(cmd, "PING")) {
net_print(&srv->net, "PING %s\n", msg);
}
}
if (match(cmd, "PRIVMSG") && dst[0] == '#') {
chan = find_dest(srv, dst, 1);
- chat_recv(&chan->channel, from, msg);
+ usr = find_nick(srv, from, 1);
+ chat_recv(&chan->channel, &usr->user, msg);
}
if (match(cmd, "PRIVMSG") && dst[0] != '#') {
chan = find_dest(srv, from, 1);
- chat_recv(&chan->channel, from, msg);
+ usr = find_nick(srv, from, 1);
+ chat_recv(&chan->channel, &usr->user, msg);
}
}
return new0(irc_server_t);
}
+user_t *irc_user(void)
+{
+ return new0(irc_user_t);
+}
+
channel_t *irc_channel(void)
{
return new0(irc_channel_t);
}
else {
net_print(&srv->net, "PRIVMSG %s :%s\n", chan->dest, text);
- chat_recv(channel, srv->nick, text);
+ chat_recv(channel, &srv->myself.user, text);
}
}
}
if (focus->filter && msg->from)
snprintf(buf, sizeof(buf), "%02d:%02d [%s] %s: ",
tm->tm_hour, tm->tm_min,
- msg->channel->name, msg->from);
+ msg->channel->name,
+ msg->from->full ?: msg->from->name);
else if (focus->filter)
snprintf(buf, sizeof(buf), "%02d:%02d [%s] *** ",
tm->tm_hour, tm->tm_min, msg->channel->name);
else if (msg->from)
snprintf(buf, sizeof(buf), "%02d:%02d %s: ",
- tm->tm_hour, tm->tm_min, msg->from);
+ tm->tm_hour, tm->tm_min,
+ msg->from->full ?: msg->from->name);
else
snprintf(buf, sizeof(buf), "%02d:%02d *** ",
tm->tm_hour, tm->tm_min);
const char *chan = focus->filter ? msg->channel->name : NULL;
- const char *from = msg->from;
+ const char *from = msg->from ? msg->from->name : NULL;
int attr, word = 0;
while (*hdr) {
if (word==0) attr = color_date;
XMPP_IN_PRESENCE,
} xmpp_state_t;
+typedef struct {
+ user_t user;
+ char jid[JID_LEN];
+} xmpp_user_t;
+
typedef struct {
channel_t channel;
char dest[JID_LEN];
typedef struct {
server_t server;
+ xmpp_user_t myself;
xmpp_channel_t system;
int connect;
return chan;
}
+static xmpp_user_t *find_jid(xmpp_server_t *srv, const char *jid, int create)
+{
+ xmpp_user_t *usr;
+
+ /* Find existing channels */
+ for (user_t *cur = users; cur; cur = cur->next) {
+ if (cur->server != &srv->server)
+ continue;
+ usr = (xmpp_user_t *)cur;
+ if (match(usr->jid, jid))
+ return usr;
+ }
+
+ /* Create a new channel */
+ usr = (xmpp_user_t *)add_user(jid, &srv->server);
+ strncpy(usr->jid, jid, JID_LEN);
+ return usr;
+}
+
static const char *find_attr(const char **attrs, const char *name)
{
for (int i = 0; attrs[i] && attrs[i+1]; i += 2)
}
if (srv->state == XMPP_IN_VCARD) {
if (end && chan && data) {
+ xmpp_user_t *usr = NULL;
chan_notice(chan, "%-12s -- %s", end, data);
+ if (srv->msg_from)
+ usr = find_jid(srv, srv->msg_from, 1);
+ if (usr && match(end, "FN"))
+ strset(&usr->user.full, data);
}
if (match(end, "vCard")) {
srv->state = XMPP_IN_IQ;
srv->msg_chan->channel.name,
srv->msg_jid, srv->msg_from);
if (srv->body) {
- chat_recv(&chan->channel, srv->msg_from, srv->body);
+ xmpp_user_t *usr = NULL;
+ if (srv->msg_from)
+ usr = find_jid(srv, srv->msg_from, 1);
+ chat_recv(&chan->channel, &usr->user, srv->body);
message_t *msg = &messages[history-1];
msg->when = srv->stamp ?: msg->when;
}
return new0(xmpp_server_t);
}
+user_t *xmpp_user(void)
+{
+ return new0(xmpp_user_t);
+}
+
channel_t *xmpp_channel(void)
{
return new0(xmpp_channel_t);
"<body>%s</body>"
"</message>",
srv->id++, srv->jid, chan->dest, text);
- chat_recv(channel, srv->nick, text);
+ chat_recv(channel, &srv->myself.user, text);
}
}
}