diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-07 18:41:45 +0000 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-07 18:41:45 +0000 |
commit | c32f492758759c04d8b6239a7862648c9d32c4d8 (patch) | |
tree | 628612ec0d2c431519a0a3741df7e4c6609db7f1 | |
parent | 1c2eaa3c99a2e7fbe264b06e559f3d709b9a080d (diff) | |
parent | 0e99548ba9c6ec9c78367e05b676dab90b5261a4 (diff) |
Merging in improved away/status message code.
-rw-r--r-- | account.c | 30 | ||||
-rw-r--r-- | account.h | 16 | ||||
-rw-r--r-- | doc/user-guide/commands.xml | 32 | ||||
-rw-r--r-- | doc/user-guide/misc.xml | 22 | ||||
-rw-r--r-- | irc.c | 23 | ||||
-rw-r--r-- | irc_commands.c | 9 | ||||
-rw-r--r-- | protocols/jabber/jabber.c | 20 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 2 | ||||
-rw-r--r-- | protocols/jabber/jabber_util.c | 9 | ||||
-rw-r--r-- | protocols/jabber/presence.c | 17 | ||||
-rw-r--r-- | protocols/msn/msn.c | 18 | ||||
-rw-r--r-- | protocols/msn/msn.h | 1 | ||||
-rw-r--r-- | protocols/msn/ns.c | 14 | ||||
-rw-r--r-- | protocols/msn/tables.c | 37 | ||||
-rw-r--r-- | protocols/nogaim.c | 98 | ||||
-rw-r--r-- | protocols/nogaim.h | 7 | ||||
-rw-r--r-- | protocols/oscar/oscar.c | 39 | ||||
-rw-r--r-- | protocols/yahoo/libyahoo2.c | 17 | ||||
-rw-r--r-- | protocols/yahoo/yahoo.c | 41 |
19 files changed, 253 insertions, 199 deletions
@@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* Account management functions */ @@ -68,7 +68,16 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) if( prpl->init ) prpl->init( a ); - return( a ); + s = set_add( &a->set, "away", NULL, set_eval_account, a ); + s->flags |= SET_NULL_OK; + + if( a->flags & ACC_FLAG_STATUS_MESSAGE ) + { + s = set_add( &a->set, "status", NULL, set_eval_account, a ); + s->flags |= SET_NULL_OK; + } + + return a; } char *set_eval_account( set_t *set, char *value ) @@ -122,6 +131,21 @@ char *set_eval_account( set_t *set, char *value ) acc->auto_connect = bool2int( value ); return value; } + else if( strcmp( set->key, "away" ) == 0 || + strcmp( set->key, "status" ) == 0 ) + { + if( acc->ic && acc->ic->flags & OPT_LOGGED_IN ) + { + /* If we're currently on-line, set the var now already + (bit of a hack) and send an update. */ + g_free( set->value ); + set->value = g_strdup( value ); + + imc_away_send_update( acc->ic ); + } + + return value; + } return SET_INVALID; } @@ -266,7 +290,7 @@ int account_reconnect_delay_parse( char *value, struct account_reconnect_delay * /* A whole day seems like a sane "maximum maximum". */ p->max = 86400; - /* Format: /[0-9]+([*+][0-9]+(<[0-9+]))/ */ + /* Format: /[0-9]+([*+][0-9]+(<[0-9+])?)?/ */ while( *value && isdigit( *value ) ) p->start = p->start * 10 + *value++ - '0'; @@ -36,6 +36,7 @@ typedef struct account int auto_connect; int auto_reconnect_delay; int reconnect; + int flags; set_t *set; GHashTable *nicks; @@ -55,8 +56,17 @@ char *set_eval_account( set_t *set, char *value ); char *set_eval_account_reconnect_delay( set_t *set, char *value ); int account_reconnect_delay( account_t *a ); -#define ACC_SET_NOSAVE 0x01 -#define ACC_SET_OFFLINE_ONLY 0x02 -#define ACC_SET_ONLINE_ONLY 0x04 +typedef enum +{ + ACC_SET_NOSAVE = 0x01, /* Don't save this setting (i.e. stored elsewhere). */ + ACC_SET_OFFLINE_ONLY = 0x02, /* Allow changes only if the acct is offline. */ + ACC_SET_ONLINE_ONLY = 0x04, /* Allow changes only if the acct is online. */ +} account_set_flag_t; + +typedef enum +{ + ACC_FLAG_AWAY_MESSAGE = 0x01, /* Supports away messages instead of just states. */ + ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */ +} account_flag_t; #endif diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index af566de4..a7d06cf1 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -435,6 +435,22 @@ </description> </bitlbee-setting> + <bitlbee-setting name="away" type="string" scope="both"> + <description> + <para> + To mark yourself as away, it is recommended to just use <emphasis>/away</emphasis>, like on normal IRC networks. If you want to mark yourself as away on only one IM network, you can use this per-account setting. + </para> + + <para> + You can set it to any value and BitlBee will try to map it to the most appropriate away state for every open IM connection, or set it as a free-form away message where possible. + </para> + + <para> + Any per-account away setting will override globally set away states. To un-set the setting, use <emphasis>set -del away</emphasis>. + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="away_devoice" type="boolean" scope="global"> <default>true</default> @@ -746,6 +762,22 @@ </description> </bitlbee-setting> + <bitlbee-setting name="status" type="string" scope="both"> + <description> + <para> + Certain protocols (like Jabber/XMPP) support status messages, similar to away messages. They can be used to indicate things like your location or activity, without showing up as away/busy. + </para> + + <para> + This setting can be used to set such a message. It will be available as a per-account setting for protocols that support it, and also as a global setting (which will then automatically be used for all protocols that support it). + </para> + + <para> + Away states set using <emphasis>/away</emphasis> or the <emphasis>away</emphasis> setting will override this setting. To un-set the setting, use <emphasis>set -del status</emphasis>. + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="strip_html" type="boolean" scope="global"> <default>true</default> diff --git a/doc/user-guide/misc.xml b/doc/user-guide/misc.xml index 68b44e95..a926775a 100644 --- a/doc/user-guide/misc.xml +++ b/doc/user-guide/misc.xml @@ -85,31 +85,35 @@ Some protocols (like Jabber) also support named groupchats. BitlBee now supports <title>Away states</title> <para> -As you might've expected, you can just use the <emphasis>/away</emphasis> command in your IRC client to set an away-state. BitlBee supports most away-states supported by the protocols. +To mark yourself as away, you can just use the <emphasis>/away</emphasis> command in your IRC client. BitlBee supports most away-states supported by the protocols. </para> <para> -Not all away states are supported by all protocols, and some protocols have different names for them. BitlBee will try to pick the best available alias from this list for every connection: +Away states have different names accross different protocols. BitlBee will try to pick the best available option for every connection: </para> <simplelist> - <member>Away from computer, Away, Extended away</member> - <member>NA, N/A, Not available</member> - <member>Busy, Do not disturb, DND, Occupied</member> - <member>Be right back, BRB</member> - <member>On the phone, Phone, On phone</member> - <member>Out to lunch, Lunch, Food</member> + <member>Away</member> + <member>NA</member> + <member>Busy, DND</member> + <member>BRB</member> + <member>Phone</member> + <member>Lunch, Food</member> <member>Invisible, Hidden</member> </simplelist> <para> -So <emphasis>/away Food</emphasis> will set your state to "Out to lunch" on your MSN connection, and for most other connections the default, "Away" or "Away from computer" will be chosen. +So <emphasis>/away Food</emphasis> will set your state to "Out to lunch" on your MSN connection, and for most other connections the default, "Away" will be chosen. </para> <para> You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Most IM-protocols can also show this additional information to your buddies. </para> +<para> +If you want to set an away state for only one of your connections, you can use the per-account <emphasis>away</emphasis> setting. See <emphasis>help set away</emphasis>. +</para> + </sect1> </chapter> @@ -77,6 +77,25 @@ static char *set_eval_charset( set_t *set, char *value ) return value; } +static char *set_eval_away_status( set_t *set, char *value ) +{ + irc_t *irc = set->data; + account_t *a; + + g_free( set->value ); + set->value = g_strdup( value ); + + for( a = irc->accounts; a; a = a->next ) + { + struct im_connection *ic = a->ic; + + if( ic && ic->flags & OPT_LOGGED_IN ) + imc_away_send_update( ic ); + } + + return value; +} + irc_t *irc_new( int fd ) { irc_t *irc; @@ -142,6 +161,8 @@ irc_t *irc_new( int fd ) irc_connection_list = g_slist_append( irc_connection_list, irc ); + s = set_add( &irc->set, "away", NULL, set_eval_away_status, irc ); + s->flags |= SET_NULL_OK; s = set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); s = set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc ); @@ -162,6 +183,8 @@ irc_t *irc_new( int fd ) s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); + s = set_add( &irc->set, "status", NULL, set_eval_away_status, irc ); + s->flags |= SET_NULL_OK; s = set_add( &irc->set, "strip_html", "true", NULL, irc ); s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); diff --git a/irc_commands.c b/irc_commands.c index 74334ee9..750bbcf5 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -447,7 +447,6 @@ static void irc_cmd_away( irc_t *irc, char **cmd ) { user_t *u = user_find( irc, irc->nick ); char *away = cmd[1]; - account_t *a; if( !u ) return; @@ -474,13 +473,7 @@ static void irc_cmd_away( irc_t *irc, char **cmd ) irc_reply( irc, 305, ":Welcome back" ); } - for( a = irc->accounts; a; a = a->next ) - { - struct im_connection *ic = a->ic; - - if( ic && ic->flags & OPT_LOGGED_IN ) - imc_set_away( ic, u->away ); - } + set_setstr( &irc->set, "away", u->away ); } static void irc_cmd_whois( irc_t *irc, char **cmd ) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b8e88c26..eca7d2d3 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -79,6 +79,8 @@ static void jabber_init( account_t *acc ) s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; + + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE; } static void jabber_generate_id_hash( struct jabber_data *jd ); @@ -363,10 +365,11 @@ static void jabber_get_info( struct im_connection *ic, char *who ) while( bud ) { - imcb_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", - bud->full_jid, bud->priority, - bud->away_state ? bud->away_state->full_name : "(none)", - bud->away_message ? : "(none)" ); + imcb_log( ic, "Buddy %s (%d) information:", bud->full_jid, bud->priority ); + if( bud->away_state ) + imcb_log( ic, "Away state: %s", bud->away_state->full_name ); + imcb_log( ic, "Status message: %s", bud->away_message ? : "(none)" ); + bud = bud->next; } @@ -376,11 +379,12 @@ static void jabber_get_info( struct im_connection *ic, char *who ) static void jabber_set_away( struct im_connection *ic, char *state_txt, char *message ) { struct jabber_data *jd = ic->proto_data; - struct jabber_away_state *state; - /* Save all this info. We need it, for example, when changing the priority setting. */ - state = (void *) jabber_away_state_by_name( state_txt ); - jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */ + /* state_txt == NULL -> Not away. + Unknown state -> fall back to the first defined away state. */ + jd->away_state = state_txt ? jabber_away_state_by_name( state_txt ) + ? : jabber_away_state_list : NULL; + g_free( jd->away_message ); jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 1180d2b9..7bb66e0e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -83,7 +83,7 @@ struct jabber_data /* After changing one of these two (or the priority setting), call presence_send_update() to inform the server about the changes. */ - struct jabber_away_state *away_state; + const struct jabber_away_state *away_state; char *away_message; md5_state_t cached_id_prefix; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 19a73b6a..185d3878 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -227,10 +227,9 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node * const struct jabber_away_state jabber_away_state_list[] = { { "away", "Away" }, - { "chat", "Free for Chat" }, + { "chat", "Free for Chat" }, /* WTF actually uses this? */ { "dnd", "Do not Disturb" }, { "xa", "Extended Away" }, - { "", "Online" }, { "", NULL } }; @@ -238,6 +237,9 @@ const struct jabber_away_state *jabber_away_state_by_code( char *code ) { int i; + if( code == NULL ) + return NULL; + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 ) return jabber_away_state_list + i; @@ -249,6 +251,9 @@ const struct jabber_away_state *jabber_away_state_by_name( char *name ) { int i; + if( name == NULL ) + return NULL; + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 ) return jabber_away_state_list + i; diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 939bc888..28aaea1b 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -189,13 +189,12 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { int is_away = 0; - if( send_presence->away_state && !( *send_presence->away_state->code == 0 || - strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) + if( send_presence->away_state && + strcmp( send_presence->away_state->code, "chat" ) != 0 ) is_away = OPT_AWAY; imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, - ( is_away && send_presence->away_state ) ? - send_presence->away_state->full_name : NULL, + is_away ? send_presence->away_state->full_name : NULL, send_presence->away_message ); } @@ -208,17 +207,15 @@ int presence_send_update( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; struct xt_node *node, *cap; - char *show = jd->away_state->code; - char *status = jd->away_message; struct groupchat *c; int st; node = jabber_make_packet( "presence", NULL, NULL, NULL ); xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) ); - if( show && *show ) - xt_add_child( node, xt_new_node( "show", show, NULL ) ); - if( status ) - xt_add_child( node, xt_new_node( "status", status, NULL ) ); + if( jd->away_state ) + xt_add_child( node, xt_new_node( "show", jd->away_state->code, NULL ) ); + if( jd->away_message ) + xt_add_child( node, xt_new_node( "status", jd->away_message, NULL ) ); /* This makes the packet slightly bigger, but clients interested in capabilities can now cache the discovery info. This reduces the diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 046b2772..e12fb3a9 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -138,8 +138,9 @@ static GList *msn_away_states( struct im_connection *ic ) int i; if( l == NULL ) - for( i = 0; msn_away_state_list[i].number > -1; i ++ ) - l = g_list_append( l, (void*) msn_away_state_list[i].name ); + for( i = 0; *msn_away_state_list[i].code; i ++ ) + if( *msn_away_state_list[i].name ) + l = g_list_append( l, (void*) msn_away_state_list[i].name ); return l; } @@ -148,17 +149,14 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) { char buf[1024]; struct msn_data *md = ic->proto_data; - const struct msn_away_state *st; - if( strcmp( state, GAIM_AWAY_CUSTOM ) == 0 ) - st = msn_away_state_by_name( "Away" ); + if( state ) + md->away_state = msn_away_state_by_name( state ) ? : + msn_away_state_list + 1; else - st = msn_away_state_by_name( state ); + md->away_state = msn_away_state_list; - if( !st ) st = msn_away_state_list; - md->away_state = st; - - g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, st->code ); + g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code ); msn_write( ic, buf, strlen( buf ) ); } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 7c849acf..333ae7f0 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -96,7 +96,6 @@ struct msn_switchboard struct msn_away_state { - int number; char code[4]; char name[16]; }; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 30a35e4e..d05d8e0d 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -419,11 +419,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( !st ) { /* FIXME: Warn/Bomb about unknown away state? */ - st = msn_away_state_list; + st = msn_away_state_list + 1; } - imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | - ( st->number ? OPT_AWAY : 0 ), st->name, NULL ); + imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | + ( st != msn_away_state_list ? OPT_AWAY : 0 ), + st->name, NULL ); } else if( strcmp( cmd[0], "FLN" ) == 0 ) { @@ -448,11 +449,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( !st ) { /* FIXME: Warn/Bomb about unknown away state? */ - st = msn_away_state_list; + st = msn_away_state_list + 1; } - imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | - ( st->number ? OPT_AWAY : 0 ), st->name, NULL ); + imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | + ( st != msn_away_state_list ? OPT_AWAY : 0 ), + st->name, NULL ); } else if( strcmp( cmd[0], "RNG" ) == 0 ) { diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index 5ba9ea73..42b12aa9 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -28,48 +28,37 @@ const struct msn_away_state msn_away_state_list[] = { - { 0, "NLN", "Available" }, - { 1, "BSY", "Busy" }, - { 3, "IDL", "Idle" }, - { 5, "BRB", "Be Right Back" }, - { 7, "AWY", "Away" }, - { 9, "PHN", "On the Phone" }, - { 11, "LUN", "Out to Lunch" }, - { 13, "HDN", "Hidden" }, - { -1, "", "" } + { "NLN", "" }, + { "AWY", "Away" }, + { "BSY", "Busy" }, + { "IDL", "Idle" }, + { "BRB", "Be Right Back" }, + { "PHN", "On the Phone" }, + { "LUN", "Out to Lunch" }, + { "HDN", "Hidden" }, + { "", "" } }; -const struct msn_away_state *msn_away_state_by_number( int number ) -{ - int i; - - for( i = 0; msn_away_state_list[i].number > -1; i ++ ) - if( msn_away_state_list[i].number == number ) - return( msn_away_state_list + i ); - - return( NULL ); -} - const struct msn_away_state *msn_away_state_by_code( char *code ) { int i; - for( i = 0; msn_away_state_list[i].number > -1; i ++ ) + for( i = 0; *msn_away_state_list[i].code; i ++ ) if( g_strcasecmp( msn_away_state_list[i].code, code ) == 0 ) return( msn_away_state_list + i ); - return( NULL ); + return NULL; } const struct msn_away_state *msn_away_state_by_name( char *name ) { int i; - for( i = 0; msn_away_state_list[i].number > -1; i ++ ) + for( i = 0; *msn_away_state_list[i].code; i ++ ) if( g_strcasecmp( msn_away_state_list[i].name, name ) == 0 ) return( msn_away_state_list + i ); - return( NULL ); + return NULL; } const struct msn_status_code msn_status_code_list[] = diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 21f7dcb1..3d2cff5c 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2006 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -267,9 +267,8 @@ void imcb_connected( struct im_connection *ic ) ic->keepalive = b_timeout_add( 60000, send_keepalive, ic ); ic->flags |= OPT_LOGGED_IN; - /* Also necessary when we're not away, at least for some of the - protocols. */ - imc_set_away( ic, u->away ); + /* Necessary to send initial presence status, even if we're not away. */ + imc_away_send_update( ic ); /* Apparently we're connected successfully, so reset the exponential backoff timer. */ @@ -1069,51 +1068,30 @@ int imc_chat_msg( struct groupchat *c, char *msg, int flags ) return 1; } -static char *imc_away_alias_find( GList *gcm, char *away ); +static char *imc_away_state_find( GList *gcm, char *away, char **message ); -int imc_set_away( struct im_connection *ic, char *away ) +int imc_away_send_update( struct im_connection *ic ) { - GList *m, *ms; - char *s; - - if( !away ) away = ""; - ms = m = ic->acc->prpl->away_states( ic ); - - while( m ) - { - if( *away ) - { - if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 ) - break; - } - else - { - if( g_strcasecmp( m->data, "Available" ) == 0 ) - break; - if( g_strcasecmp( m->data, "Online" ) == 0 ) - break; - } - m = m->next; - } + char *away, *msg; - if( m ) + away = set_getstr( &ic->acc->set, "away" ) ? + : set_getstr( &ic->irc->set, "away" ); + if( away && *away ) { - ic->acc->prpl->set_away( ic, m->data, *away ? away : NULL ); + GList *m = ic->acc->prpl->away_states( ic ); + msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL; + away = imc_away_state_find( m, away, &msg ) ? : m->data; } - else + else if( ic->acc->flags & ACC_FLAG_STATUS_MESSAGE ) { - s = imc_away_alias_find( ms, away ); - if( s ) - { - ic->acc->prpl->set_away( ic, s, away ); - if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "Setting away state to %s", s ); - } - else - ic->acc->prpl->set_away( ic, GAIM_AWAY_CUSTOM, away ); + away = NULL; + msg = set_getstr( &ic->acc->set, "status" ) ? + : set_getstr( &ic->irc->set, "status" ); } - return( 1 ); + ic->acc->prpl->set_away( ic, away, msg ); + + return 1; } static char *imc_away_alias_list[8][5] = @@ -1128,16 +1106,33 @@ static char *imc_away_alias_list[8][5] = { NULL } }; -static char *imc_away_alias_find( GList *gcm, char *away ) +static char *imc_away_state_find( GList *gcm, char *away, char **message ) { GList *m; int i, j; + for( m = gcm; m; m = m->next ) + if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 ) + { + /* At least the Yahoo! module works better if message + contains no data unless it adds something to what + we have in state already. */ + if( strlen( m->data ) == strlen( away ) ) + *message = NULL; + + return m->data; + } + for( i = 0; *imc_away_alias_list[i]; i ++ ) { + int keep_message; + for( j = 0; imc_away_alias_list[i][j]; j ++ ) if( g_strncasecmp( away, imc_away_alias_list[i][j], strlen( imc_away_alias_list[i][j] ) ) == 0 ) + { + keep_message = strlen( away ) != strlen( imc_away_alias_list[i][j] ); break; + } if( !imc_away_alias_list[i][j] ) /* If we reach the end, this row */ continue; /* is not what we want. Next! */ @@ -1145,17 +1140,22 @@ static char *imc_away_alias_find( GList *gcm, char *away ) /* Now find an entry in this row which exists in gcm */ for( j = 0; imc_away_alias_list[i][j]; j ++ ) { - m = gcm; - while( m ) - { + for( m = gcm; m; m = m->next ) if( g_strcasecmp( imc_away_alias_list[i][j], m->data ) == 0 ) - return( imc_away_alias_list[i][j] ); - m = m->next; - } + { + if( !keep_message ) + *message = NULL; + + return imc_away_alias_list[i][j]; + } } + + /* No need to look further, apparently this state doesn't + have any good alias for this protocol. */ + break; } - return( NULL ); + return NULL; } void imc_add_allow( struct im_connection *ic, char *handle ) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index dc6154e2..4fc32281 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -48,7 +48,6 @@ #define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */ #define WEBSITE "http://www.bitlbee.org/" -#define GAIM_AWAY_CUSTOM "Custom" /* Sharing flags between all kinds of things. I just hope I won't hit any limits before 32-bit machines become extinct. ;-) */ @@ -217,8 +216,8 @@ struct prpl { void (* chat_topic) (struct groupchat *, char *topic); /* You can tell what away states your protocol supports, so that - * BitlBee will try to map the IRC away reasons to them, or use - * GAIM_AWAY_CUSTOM when calling skype_set_away(). */ + * BitlBee will try to map the IRC away reasons to them. If your + * protocol doesn't have any, just return one generic "Away". */ GList *(* away_states)(struct im_connection *ic); /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* @@ -314,7 +313,7 @@ G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topi G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); /* Actions, or whatever. */ -int imc_set_away( struct im_connection *ic, char *away ); +int imc_away_send_update( struct im_connection *ic ); int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); int imc_chat_msg( struct groupchat *c, char *msg, int flags ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 1118c26d..f0e65f9a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -379,6 +379,8 @@ static void oscar_init(account_t *acc) s = set_add( &acc->set, "web_aware", "false", set_eval_bool, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; } + + acc->flags |= ACC_FLAG_AWAY_MESSAGE; } static void oscar_login(account_t *acc) { @@ -1951,6 +1953,8 @@ static void oscar_get_away(struct im_connection *g, char *who) { static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message) { + if (state == NULL) + state = ""; if (!g_strcasecmp(state, _("Visible"))) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); @@ -1958,7 +1962,9 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, } else if (!g_strcasecmp(state, _("Invisible"))) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE); return; - } /* else... */ + } else if (message == NULL) { + message = state; + } if (od->rights.maxawaymsglen == 0) imcb_error(ic, "oscar_set_away_aim called before locate rights received"); @@ -2001,7 +2007,7 @@ static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, no_message = TRUE; } - if (!g_strcasecmp(state, "Online")) { + if (state == NULL) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); } else if (!g_strcasecmp(state, "Away")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY); @@ -2026,7 +2032,7 @@ static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, } else if (!g_strcasecmp(state, "Invisible")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE); ic->away = g_strdup(msg); - } else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) { + } else { if (no_message) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); } else { @@ -2275,20 +2281,21 @@ static void oscar_rem_deny(struct im_connection *ic, char *who) { static GList *oscar_away_states(struct im_connection *ic) { struct oscar_data *od = ic->proto_data; - GList *m = NULL; - - if (!od->icq) - return g_list_append(m, GAIM_AWAY_CUSTOM); - m = g_list_append(m, "Online"); - m = g_list_append(m, "Away"); - m = g_list_append(m, "Do Not Disturb"); - m = g_list_append(m, "Not Available"); - m = g_list_append(m, "Occupied"); - m = g_list_append(m, "Free For Chat"); - m = g_list_append(m, "Invisible"); - - return m; + if (od->icq) { + static GList *m = NULL; + m = g_list_append(m, "Away"); + m = g_list_append(m, "Do Not Disturb"); + m = g_list_append(m, "Not Available"); + m = g_list_append(m, "Occupied"); + m = g_list_append(m, "Free For Chat"); + m = g_list_append(m, "Invisible"); + return m; + } else { + static GList *m = NULL; + m = g_list_append(m, "Away"); + return m; + } } static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 836670f7..721f4b7c 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -4098,14 +4098,8 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) return; yd = yid->yd; - old_status = yd->current_status; - - if (msg && strncmp(msg,"Invisible",9)) { - yd->current_status = YAHOO_STATUS_CUSTOM; - } else { - yd->current_status = state; - } + yd->current_status = state; /* Thank you libpurple :) */ if (yd->current_status == YAHOO_STATUS_INVISIBLE) { @@ -4120,15 +4114,8 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, yd->current_status, yd->session_id); snprintf(s, sizeof(s), "%d", yd->current_status); yahoo_packet_hash(pkt, 10, s); - - if (yd->current_status == YAHOO_STATUS_CUSTOM) { - yahoo_packet_hash(pkt, 19, msg); - } else { - yahoo_packet_hash(pkt, 19, ""); - } - + yahoo_packet_hash(pkt, 19, msg && state == YAHOO_STATUS_CUSTOM ? msg : ""); yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); - yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index ac57d4b6..a47de966 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -129,6 +129,8 @@ static char *byahoo_strip( const char *in ) static void byahoo_init( account_t *acc ) { set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); + + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE; } static void byahoo_login( account_t *acc ) @@ -196,29 +198,12 @@ static int byahoo_send_typing( struct im_connection *ic, char *who, int typing ) static void byahoo_set_away( struct im_connection *ic, char *state, char *msg ) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - char *away; - - away = NULL; - if( state && msg && g_strcasecmp( state, msg ) != 0 ) - { - yd->current_status = YAHOO_STATUS_CUSTOM; - away = ""; - } - else if( state ) + if( state && msg == NULL ) { - /* Set msg to NULL since (if it isn't NULL already) it's equal - to state. msg must be empty if we want to use an existing - away state. */ - msg = NULL; - - away = ""; - if( g_strcasecmp( state, "Available" ) == 0 ) - { - yd->current_status = YAHOO_STATUS_AVAILABLE; - away = NULL; - } - else if( g_strcasecmp( state, "Be Right Back" ) == 0 ) + /* Use these states only if msg doesn't contain additional + info since away messages are only supported with CUSTOM. */ + if( g_strcasecmp( state, "Be Right Back" ) == 0 ) yd->current_status = YAHOO_STATUS_BRB; else if( g_strcasecmp( state, "Busy" ) == 0 ) yd->current_status = YAHOO_STATUS_BUSY; @@ -238,17 +223,15 @@ static void byahoo_set_away( struct im_connection *ic, char *state, char *msg ) yd->current_status = YAHOO_STATUS_STEPPEDOUT; else if( g_strcasecmp( state, "Invisible" ) == 0 ) yd->current_status = YAHOO_STATUS_INVISIBLE; - else if( g_strcasecmp( state, GAIM_AWAY_CUSTOM ) == 0 ) - { - yd->current_status = YAHOO_STATUS_AVAILABLE; - - away = NULL; - } + else + yd->current_status = YAHOO_STATUS_CUSTOM; } + else if( state ) + yd->current_status = YAHOO_STATUS_CUSTOM; else yd->current_status = YAHOO_STATUS_AVAILABLE; - yahoo_set_away( yd->y2_id, yd->current_status, msg, away != NULL ? 2 : 0 ); + yahoo_set_away( yd->y2_id, yd->current_status, msg, state ? 2 : 0 ); } static GList *byahoo_away_states( struct im_connection *ic ) @@ -257,7 +240,6 @@ static GList *byahoo_away_states( struct im_connection *ic ) if( m == NULL ) { - m = g_list_append( m, "Available" ); m = g_list_append( m, "Be Right Back" ); m = g_list_append( m, "Busy" ); m = g_list_append( m, "Not At Home" ); @@ -268,7 +250,6 @@ static GList *byahoo_away_states( struct im_connection *ic ) m = g_list_append( m, "Out To Lunch" ); m = g_list_append( m, "Stepped Out" ); m = g_list_append( m, "Invisible" ); - m = g_list_append( m, GAIM_AWAY_CUSTOM ); } return m; |