Changeset 345577b


Ignore:
Timestamp:
2015-10-30T10:27:20Z (9 years ago)
Author:
dequis <dx@…>
Branches:
master
Children:
fb2338d
Parents:
0db6618
git-author:
dequis <dx@…> (13-09-15 04:17:14)
git-committer:
dequis <dx@…> (30-10-15 10:27:20)
Message:

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.

Files:
9 edited

Legend:

Unmodified
Added
Removed
  • doc/user-guide/commands.xml

    r0db6618 r345577b  
    14041404        </bitlbee-setting>
    14051405
     1406        <bitlbee-setting name="self_messages" type="string" scope="global">
     1407                <default>true</default>
     1408                <possible-values>true, false, prefix, prefix_notice</possible-values>
     1409
     1410                <description>
     1411                        <para>
     1412                                Change this setting to customize how (or whether) to show self-messages, which are messages sent by yourself from other locations (for example, mobile clients), for IM protocols that support it.
     1413                        </para>
     1414
     1415                        <para>
     1416                                When this is set to "true", it will send those messages in the "standard" way, which is a PRIVMSG with source and target fields swapped.
     1417                        </para>
     1418                       
     1419                        <para>
     1420                                Since this isn't very well supported by some clients (the messages might appear in the wrong window), you can set it to "prefix" to show them as a normal message prefixed with "-> ", or use "prefix_notice" which is the same thing but with a NOTICE instead.
     1421                        </para>
     1422
     1423                        <para>
     1424                                You can also set it to "false" to disable these messages completely.
     1425                        </para>
     1426
     1427                        <para>
     1428                                This setting only applies to private messages. Self messages in groupchats are always shown, since they haven't caused issues in any clients so far.
     1429                        </para>
     1430                </description>
     1431        </bitlbee-setting>
     1432
    14061433        <bitlbee-setting name="server" type="string" scope="account">
    14071434                <description>
  • irc.c

    r0db6618 r345577b  
    129129        s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc);
    130130        s->flags |= SET_HIDDEN;
     131        s = set_add(&b->set, "self_messages", "true", set_eval_self_messages, irc);
    131132        s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc);
    132133        s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc);
  • irc.h

    r0db6618 r345577b  
    354354char *set_eval_timezone(struct set *set, char *value);
    355355char *irc_format_timestamp(irc_t *irc, time_t msg_ts);
     356char *set_eval_self_messages(struct set *set, char *value);
    356357
    357358/* irc_im.c */
  • irc_im.c

    r0db6618 r345577b  
    201201}
    202202
    203 static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at)
     203static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, guint32 flags, time_t sent_at)
    204204{
    205205        irc_t *irc = bee->ui_data;
    206206        irc_user_t *iu = (irc_user_t *) bu->ui_data;
     207        irc_user_t *src_iu = iu;
     208        irc_user_t *dst_iu = irc->user;
    207209        const char *dst;
    208210        char *prefix = NULL;
    209211        char *wrapped, *ts = NULL;
    210212        char *msg = g_strdup(msg_);
     213        char *message_type = "PRIVMSG";
    211214        GSList *l;
    212215
     
    216219
    217220        dst = irc_user_msgdest(iu);
    218         if (dst != irc->user->nick) {
    219                 /* if not messaging directly, call user by name */
    220                 prefix = g_strdup_printf("%s%s%s", irc->user->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
     221
     222        if (flags & OPT_SELFMESSAGE) {
     223                char *setting = set_getstr(&irc->b->set, "self_messages");
     224
     225                if (is_bool(setting)) {
     226                        if (bool2int(setting)) {
     227                                /* set to true, send it with src/dst flipped */
     228                               
     229                                dst_iu = iu;
     230                                src_iu = irc->user;
     231
     232                                if (dst == irc->user->nick) {
     233                                        dst = dst_iu->nick;
     234                                }
     235                        } else {
     236                                /* set to false, skip the message completely */
     237                                goto cleanup;
     238                        }
     239                } else if (g_strncasecmp(setting, "prefix", 6) == 0) {
     240                        /* third state, prefix, loosely imitates the znc privmsg_prefix module */
     241
     242                        g_free(msg);
     243                        if (g_strncasecmp(msg_, "/me ", 4) == 0) {
     244                                msg = g_strdup_printf("/me -> %s", msg_ + 4);
     245                        } else {
     246                                msg = g_strdup_printf("-> %s", msg_);
     247                        }
     248
     249                        if (g_strcasecmp(setting, "prefix_notice") == 0) {
     250                                message_type = "NOTICE";
     251                        }
     252                }
     253
     254        }
     255
     256        if (dst != dst_iu->nick) {
     257                /* if not messaging directly (control channel), call user by name */
     258                prefix = g_strdup_printf("%s%s%s", dst_iu->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
    221259        } else {
    222260                prefix = ts;
     
    249287
    250288        wrapped = word_wrap(msg, 425);
    251         irc_send_msg(iu, "PRIVMSG", dst, wrapped, prefix);
     289        irc_send_msg(src_iu, message_type, dst, wrapped, prefix);
    252290        g_free(wrapped);
    253291
     
    260298}
    261299
    262 static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, uint32_t flags)
     300static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, guint32 flags)
    263301{
    264302        irc_t *irc = (irc_t *) bee->ui_data;
     
    617655}
    618656
    619 static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at)
     657static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at)
    620658{
    621659        irc_t *irc = bee->ui_data;
    622         irc_user_t *iu = bu->ui_data;
     660        irc_user_t *iu = flags & OPT_SELFMESSAGE ? irc->user : bu->ui_data;
    623661        irc_channel_t *ic = c->ui_data;
    624662        char *wrapped, *ts = NULL;
  • irc_util.c

    r0db6618 r345577b  
    119119        }
    120120}
     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}
  • protocols/bee.h

    r0db6618 r345577b  
    105105        gboolean (*user_status)(bee_t *bee, struct bee_user *bu, struct bee_user *old);
    106106        /* On every incoming message. sent_at = 0 means unknown. */
    107         gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at);
     107        gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
    108108        /* Flags currently defined (OPT_TYPING/THINKING) in nogaim.h. */
    109109        gboolean (*user_typing)(bee_t *bee, bee_user_t *bu, guint32 flags);
     
    118118        /* System messages of any kind. */
    119119        gboolean (*chat_log)(bee_t *bee, struct groupchat *c, const char *text);
    120         gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at);
     120        gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
    121121        gboolean (*chat_add_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu);
    122122        gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *reason);
  • protocols/bee_chat.c

    r0db6618 r345577b  
    9595}
    9696
    97 void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at)
     97void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, guint32 flags, time_t sent_at)
    9898{
    9999        struct im_connection *ic = c->ic;
    100100        bee_t *bee = ic->bee;
    101101        bee_user_t *bu;
    102         gboolean temp;
     102        gboolean temp = FALSE;
    103103        char *s;
    104104
    105         /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
    106         if (handle_is_self(ic, who)) {
     105        if (handle_is_self(ic, who) && !(flags & OPT_SELFMESSAGE)) {
    107106                return;
    108107        }
     
    122121
    123122        if (bee->ui->chat_msg) {
    124                 bee->ui->chat_msg(bee, c, bu, msg, sent_at);
     123                bee->ui->chat_msg(bee, c, bu, msg, flags, sent_at);
    125124        }
    126125
  • protocols/bee_user.c

    r0db6618 r345577b  
    247247}
    248248
    249 void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, uint32_t flags, time_t sent_at)
     249void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, guint32 flags, time_t sent_at)
    250250{
    251251        bee_t *bee = ic->bee;
     
    265265
    266266        if (bee->ui->user_msg && bu) {
    267                 bee->ui->user_msg(bee, bu, msg, sent_at);
     267                bee->ui->user_msg(bee, bu, msg, flags, sent_at);
    268268        } else {
    269269                imcb_log(ic, "Message from unknown handle %s:\n%s", handle, msg);
     
    297297}
    298298
    299 void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags)
     299void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags)
    300300{
    301301        bee_user_t *bu;
  • protocols/nogaim.h

    r0db6618 r345577b  
    7070#define OPT_PONGS       0x00010000 /* Service sends us keep-alives */
    7171#define OPT_PONGED      0x00020000 /* Received a keep-alive during last interval */
     72#define OPT_SELFMESSAGE 0x00080000 /* A message sent by self from another location */
    7273
    7374/* ok. now the fun begins. first we create a connection structure */
     
    325326G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data);
    326327
    327 G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags);
     328G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags);
    328329G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle(struct im_connection *ic, const char *handle);
    329330G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle);
Note: See TracChangeset for help on using the changeset viewer.