source: irc_util.c @ 129e282

Last change on this file since 129e282 was 345577b, checked in by dequis <dx@…>, at 2015-10-30T10:27:20Z

IRC self-message support (messages sent by yourself from other clients)

This adds an OPT_SELFMESSAGE flag that can be passed to imcb_buddy_msg()
or imcb_chat_msg() to indicate that the protocol knows that the message
being sent is a self message.

This needs to be explicit since the old behavior is to silently drop
these messages, which also removed server echoes.

This commit doesn't break API/ABI, the flags parameters that were added
are all internal (between protocols and UI code)

On the irc protocol side, the situation isn't very nice, since some
clients put these messages in the wrong window. Irssi, hexchat and mirc
get this wrong. Irssi 0.8.18 has a fix for it, and the others have
scripts to patch it.

But meanwhile, there's a "self_messages" global setting that lets users
disable this, or get them as normal messages / notices with a "->"
prefix, which loosely imitates the workaround used by the ZNC
"privmsg_prefix" module.

  • Property mode set to 100644
File size: 3.5 KB
RevLine 
[5ebff60]1/********************************************************************\
[21c87a7]2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Some stuff that doesn't belong anywhere else.                        */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
[6f10697]22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
[21c87a7]24*/
25
26#include "bitlbee.h"
27
[5ebff60]28char *set_eval_timezone(set_t *set, char *value)
[21c87a7]29{
30        char *s;
[5ebff60]31
32        if (strcmp(value, "local") == 0 ||
33            strcmp(value, "gmt") == 0 || strcmp(value, "utc") == 0) {
[21c87a7]34                return value;
[5ebff60]35        }
36
[21c87a7]37        /* Otherwise: +/- at the beginning optional, then one or more numbers,
38           possibly followed by a colon and more numbers. Don't bother bound-
39           checking them since users are free to shoot themselves in the foot. */
40        s = value;
[5ebff60]41        if (*s == '+' || *s == '-') {
42                s++;
43        }
44
[21c87a7]45        /* \d+ */
[5ebff60]46        if (!g_ascii_isdigit(*s)) {
[21c87a7]47                return SET_INVALID;
[5ebff60]48        }
49        while (*s && g_ascii_isdigit(*s)) {
50                s++;
51        }
52
[21c87a7]53        /* EOS? */
[5ebff60]54        if (*s == '\0') {
[21c87a7]55                return value;
[5ebff60]56        }
57
[21c87a7]58        /* Otherwise, colon */
[5ebff60]59        if (*s != ':') {
[21c87a7]60                return SET_INVALID;
[5ebff60]61        }
62        s++;
63
[21c87a7]64        /* \d+ */
[5ebff60]65        if (!g_ascii_isdigit(*s)) {
[21c87a7]66                return SET_INVALID;
[5ebff60]67        }
68        while (*s && g_ascii_isdigit(*s)) {
69                s++;
70        }
71
[21c87a7]72        /* EOS */
73        return *s == '\0' ? value : SET_INVALID;
74}
75
[5ebff60]76char *irc_format_timestamp(irc_t *irc, time_t msg_ts)
[21c87a7]77{
[5ebff60]78        time_t now_ts = time(NULL);
[21c87a7]79        struct tm now, msg;
80        char *set;
[5ebff60]81
[21c87a7]82        /* If the timestamp is <= 0 or less than a minute ago, discard it as
83           it doesn't seem to add to much useful info and/or might be noise. */
[5ebff60]84        if (msg_ts <= 0 || msg_ts > now_ts - 60) {
[21c87a7]85                return NULL;
86        }
[5ebff60]87
88        set = set_getstr(&irc->b->set, "timezone");
89        if (strcmp(set, "local") == 0) {
90                localtime_r(&now_ts, &now);
91                localtime_r(&msg_ts, &msg);
92        } else {
[21c87a7]93                int hr, min = 0, sign = 60;
[5ebff60]94
95                if (set[0] == '-') {
[21c87a7]96                        sign *= -1;
[5ebff60]97                        set++;
98                } else if (set[0] == '+') {
99                        set++;
[21c87a7]100                }
[5ebff60]101
102                if (sscanf(set, "%d:%d", &hr, &min) >= 1) {
103                        msg_ts += sign * (hr * 60 + min);
104                        now_ts += sign * (hr * 60 + min);
[21c87a7]105                }
[5ebff60]106
107                gmtime_r(&now_ts, &now);
108                gmtime_r(&msg_ts, &msg);
109        }
110
111        if (msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday) {
112                return g_strdup_printf("\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
113                                       msg.tm_hour, msg.tm_min, msg.tm_sec);
114        } else {
115                return g_strdup_printf("\x02[\x02\x02\x02%04d-%02d-%02d "
116                                       "%02d:%02d:%02d\x02]\x02 ",
117                                       msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday,
118                                       msg.tm_hour, msg.tm_min, msg.tm_sec);
[21c87a7]119        }
120}
[345577b]121
122
123char *set_eval_self_messages(set_t *set, char *value)
124{
125        if (is_bool(value) ||
126            g_strcasecmp(value, "prefix") == 0 ||
127            g_strcasecmp(value, "prefix_notice") == 0) {
128                return value;
129        } else {
130                return SET_INVALID;
131        }
132}
Note: See TracBrowser for help on using the repository browser.