aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/user-guide/commands.xml27
-rw-r--r--irc.c1
-rw-r--r--irc.h1
-rw-r--r--irc_im.c54
-rw-r--r--irc_util.c12
-rw-r--r--protocols/bee.h4
-rw-r--r--protocols/bee_chat.c9
-rw-r--r--protocols/bee_user.c6
-rw-r--r--protocols/nogaim.h3
9 files changed, 98 insertions, 19 deletions
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index d671f6d0..32c3b24e 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -1403,6 +1403,33 @@
</description>
</bitlbee-setting>
+ <bitlbee-setting name="self_messages" type="string" scope="global">
+ <default>true</default>
+ <possible-values>true, false, prefix, prefix_notice</possible-values>
+
+ <description>
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ You can also set it to "false" to disable these messages completely.
+ </para>
+
+ <para>
+ 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.
+ </para>
+ </description>
+ </bitlbee-setting>
+
<bitlbee-setting name="server" type="string" scope="account">
<description>
<para>
diff --git a/irc.c b/irc.c
index 74e185a8..835bffa0 100644
--- a/irc.c
+++ b/irc.c
@@ -128,6 +128,7 @@ irc_t *irc_new(int fd)
s->flags |= SET_HIDDEN;
s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc);
s->flags |= SET_HIDDEN;
+ s = set_add(&b->set, "self_messages", "true", set_eval_self_messages, irc);
s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc);
s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc);
s = set_add(&b->set, "to_char", ": ", set_eval_to_char, irc);
diff --git a/irc.h b/irc.h
index f2df3b2e..23d97433 100644
--- a/irc.h
+++ b/irc.h
@@ -353,6 +353,7 @@ void irc_user_quit(irc_user_t *iu, const char *msg);
/* irc_util.c */
char *set_eval_timezone(struct set *set, char *value);
char *irc_format_timestamp(irc_t *irc, time_t msg_ts);
+char *set_eval_self_messages(struct set *set, char *value);
/* irc_im.c */
void bee_irc_channel_update(irc_t *irc, irc_channel_t *ic, irc_user_t *iu);
diff --git a/irc_im.c b/irc_im.c
index 2d569bbb..a66b72a2 100644
--- a/irc_im.c
+++ b/irc_im.c
@@ -200,14 +200,17 @@ void bee_irc_channel_update(irc_t *irc, irc_channel_t *ic, irc_user_t *iu)
}
}
-static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at)
+static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, guint32 flags, time_t sent_at)
{
irc_t *irc = bee->ui_data;
irc_user_t *iu = (irc_user_t *) bu->ui_data;
+ irc_user_t *src_iu = iu;
+ irc_user_t *dst_iu = irc->user;
const char *dst;
char *prefix = NULL;
char *wrapped, *ts = NULL;
char *msg = g_strdup(msg_);
+ char *message_type = "PRIVMSG";
GSList *l;
if (sent_at > 0 && set_getbool(&irc->b->set, "display_timestamps")) {
@@ -215,9 +218,44 @@ static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, t
}
dst = irc_user_msgdest(iu);
- if (dst != irc->user->nick) {
- /* if not messaging directly, call user by name */
- prefix = g_strdup_printf("%s%s%s", irc->user->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
+
+ if (flags & OPT_SELFMESSAGE) {
+ char *setting = set_getstr(&irc->b->set, "self_messages");
+
+ if (is_bool(setting)) {
+ if (bool2int(setting)) {
+ /* set to true, send it with src/dst flipped */
+
+ dst_iu = iu;
+ src_iu = irc->user;
+
+ if (dst == irc->user->nick) {
+ dst = dst_iu->nick;
+ }
+ } else {
+ /* set to false, skip the message completely */
+ goto cleanup;
+ }
+ } else if (g_strncasecmp(setting, "prefix", 6) == 0) {
+ /* third state, prefix, loosely imitates the znc privmsg_prefix module */
+
+ g_free(msg);
+ if (g_strncasecmp(msg_, "/me ", 4) == 0) {
+ msg = g_strdup_printf("/me -> %s", msg_ + 4);
+ } else {
+ msg = g_strdup_printf("-> %s", msg_);
+ }
+
+ if (g_strcasecmp(setting, "prefix_notice") == 0) {
+ message_type = "NOTICE";
+ }
+ }
+
+ }
+
+ if (dst != dst_iu->nick) {
+ /* if not messaging directly (control channel), call user by name */
+ prefix = g_strdup_printf("%s%s%s", dst_iu->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
} else {
prefix = ts;
ts = NULL; /* don't double-free */
@@ -248,7 +286,7 @@ static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, t
}
wrapped = word_wrap(msg, 425);
- irc_send_msg(iu, "PRIVMSG", dst, wrapped, prefix);
+ irc_send_msg(src_iu, message_type, dst, wrapped, prefix);
g_free(wrapped);
cleanup:
@@ -259,7 +297,7 @@ cleanup:
return TRUE;
}
-static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, uint32_t flags)
+static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, guint32 flags)
{
irc_t *irc = (irc_t *) bee->ui_data;
@@ -616,10 +654,10 @@ static gboolean bee_irc_chat_log(bee_t *bee, struct groupchat *c, const char *te
return TRUE;
}
-static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at)
+static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at)
{
irc_t *irc = bee->ui_data;
- irc_user_t *iu = bu->ui_data;
+ irc_user_t *iu = flags & OPT_SELFMESSAGE ? irc->user : bu->ui_data;
irc_channel_t *ic = c->ui_data;
char *wrapped, *ts = NULL;
diff --git a/irc_util.c b/irc_util.c
index 8c3886f6..86633cbe 100644
--- a/irc_util.c
+++ b/irc_util.c
@@ -118,3 +118,15 @@ char *irc_format_timestamp(irc_t *irc, time_t msg_ts)
msg.tm_hour, msg.tm_min, msg.tm_sec);
}
}
+
+
+char *set_eval_self_messages(set_t *set, char *value)
+{
+ if (is_bool(value) ||
+ g_strcasecmp(value, "prefix") == 0 ||
+ g_strcasecmp(value, "prefix_notice") == 0) {
+ return value;
+ } else {
+ return SET_INVALID;
+ }
+}
diff --git a/protocols/bee.h b/protocols/bee.h
index fc27d424..a9678a6e 100644
--- a/protocols/bee.h
+++ b/protocols/bee.h
@@ -104,7 +104,7 @@ typedef struct bee_ui_funcs {
/* State info is already updated, old is provided in case the UI needs a diff. */
gboolean (*user_status)(bee_t *bee, struct bee_user *bu, struct bee_user *old);
/* On every incoming message. sent_at = 0 means unknown. */
- gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at);
+ gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
/* Flags currently defined (OPT_TYPING/THINKING) in nogaim.h. */
gboolean (*user_typing)(bee_t *bee, bee_user_t *bu, guint32 flags);
/* CTCP-like stuff (buddy action) response */
@@ -117,7 +117,7 @@ typedef struct bee_ui_funcs {
gboolean (*chat_free)(bee_t *bee, struct groupchat *c);
/* System messages of any kind. */
gboolean (*chat_log)(bee_t *bee, struct groupchat *c, const char *text);
- gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at);
+ gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
gboolean (*chat_add_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu);
gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *reason);
gboolean (*chat_topic)(bee_t *bee, struct groupchat *c, const char *new_topic, bee_user_t *bu);
diff --git a/protocols/bee_chat.c b/protocols/bee_chat.c
index 6ea86c3a..2fcb0396 100644
--- a/protocols/bee_chat.c
+++ b/protocols/bee_chat.c
@@ -94,16 +94,15 @@ static gboolean handle_is_self(struct im_connection *ic, const char *handle)
(ic->acc->prpl->handle_cmp(ic->acc->user, handle) == 0);
}
-void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at)
+void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, guint32 flags, time_t sent_at)
{
struct im_connection *ic = c->ic;
bee_t *bee = ic->bee;
bee_user_t *bu;
- gboolean temp;
+ gboolean temp = FALSE;
char *s;
- /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
- if (handle_is_self(ic, who)) {
+ if (handle_is_self(ic, who) && !(flags & OPT_SELFMESSAGE)) {
return;
}
@@ -121,7 +120,7 @@ void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, uint32_t fla
}
if (bee->ui->chat_msg) {
- bee->ui->chat_msg(bee, c, bu, msg, sent_at);
+ bee->ui->chat_msg(bee, c, bu, msg, flags, sent_at);
}
if (temp) {
diff --git a/protocols/bee_user.c b/protocols/bee_user.c
index 2d63bfb4..ced92ee9 100644
--- a/protocols/bee_user.c
+++ b/protocols/bee_user.c
@@ -246,7 +246,7 @@ void imcb_buddy_times(struct im_connection *ic, const char *handle, time_t login
bu->idle_time = idle;
}
-void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, uint32_t flags, time_t sent_at)
+void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, guint32 flags, time_t sent_at)
{
bee_t *bee = ic->bee;
bee_user_t *bu;
@@ -264,7 +264,7 @@ void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *ms
}
if (bee->ui->user_msg && bu) {
- bee->ui->user_msg(bee, bu, msg, sent_at);
+ bee->ui->user_msg(bee, bu, msg, flags, sent_at);
} else {
imcb_log(ic, "Message from unknown handle %s:\n%s", handle, msg);
}
@@ -296,7 +296,7 @@ void imcb_notify_email(struct im_connection *ic, char *format, ...)
g_free(msg);
}
-void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags)
+void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags)
{
bee_user_t *bu;
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index 6e7343ba..548b22f9 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -69,6 +69,7 @@
#define OPT_NOOTR 0x00001000 /* protocol not suitable for OTR */
#define OPT_PONGS 0x00010000 /* Service sends us keep-alives */
#define OPT_PONGED 0x00020000 /* Received a keep-alive during last interval */
+#define OPT_SELFMESSAGE 0x00080000 /* A message sent by self from another location */
/* ok. now the fun begins. first we create a connection structure */
struct im_connection {
@@ -324,7 +325,7 @@ G_MODULE_EXPORT void imcb_rename_buddy(struct im_connection *ic, const char *han
G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick);
G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data);
-G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags);
+G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags);
G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle(struct im_connection *ic, const char *handle);
G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle);