void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu ) { GSList *l; if( ic == NULL ) { for( l = irc->channels; l; l = l->next ) { ic = l->data; /* TODO: Just add a type flag or so.. */ if( ic->f == irc->default_channel->f && ( ic->flags & IRC_CHANNEL_JOINED ) ) bee_irc_channel_update( irc, ic, iu ); } return; } if( iu == NULL ) { for( l = irc->users; l; l = l->next ) { iu = l->data; if( iu->bu ) bee_irc_channel_update( irc, ic, l->data ); } return; } if( !irc_channel_wants_user( ic, iu ) ) { irc_channel_del_user( ic, iu, IRC_CDU_PART, NULL ); } else { struct irc_control_channel *icc = ic->data; int mode = 0; if( !( iu->bu->flags & BEE_USER_ONLINE ) ) mode = icc->modes[0]; else if( iu->bu->flags & BEE_USER_AWAY ) mode = icc->modes[1]; else mode = icc->modes[2]; if( !mode ) irc_channel_del_user( ic, iu, IRC_CDU_PART, NULL ); else { irc_channel_add_user( ic, iu ); irc_channel_user_set_mode( ic, iu, mode ); } } }
static gboolean bee_irc_user_status(bee_t *bee, bee_user_t *bu, bee_user_t *old) { irc_t *irc = bee->ui_data; irc_user_t *iu = bu->ui_data; /* Do this outside the if below since away state can change without the online state changing. */ iu->flags &= ~IRC_USER_AWAY; if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) { iu->flags |= IRC_USER_AWAY; } if ((bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE)) { if (bu->flags & BEE_USER_ONLINE) { if (g_hash_table_lookup(irc->watches, iu->key)) { irc_send_num(irc, 600, "%s %s %s %d :%s", iu->nick, iu->user, iu->host, (int) time(NULL), "logged online"); } } else { if (g_hash_table_lookup(irc->watches, iu->key)) { irc_send_num(irc, 601, "%s %s %s %d :%s", iu->nick, iu->user, iu->host, (int) time(NULL), "logged offline"); } /* Send a QUIT since those will also show up in any query windows the user may have, plus it's only one QUIT instead of possibly many (in case of multiple control chans). If there's a channel that shows offline people, a JOIN will follow. */ if (set_getbool(&bee->set, "offline_user_quits")) { irc_user_quit(iu, "Leaving..."); } } } /* Reset this one since the info may have changed. */ iu->away_reply_timeout = 0; bee_irc_channel_update(irc, NULL, iu); /* If away-notify enabled, send status updates when: * Away or Online state changes * Status changes (e.g. "Away" to "Mobile") * Status message changes */ if ((irc->caps & CAP_AWAY_NOTIFY) && ((bu->flags & BEE_USER_AWAY) != (old->flags & BEE_USER_AWAY) || (bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE) || (g_strcmp0(bu->status, old->status) != 0) || (g_strcmp0(bu->status_msg, old->status_msg) != 0))) { irc_send_away_notify(iu); } return TRUE; }
static gboolean bee_irc_user_status( bee_t *bee, bee_user_t *bu, bee_user_t *old ) { irc_t *irc = bee->ui_data; irc_user_t *iu = bu->ui_data; /* Do this outside the if below since away state can change without the online state changing. */ iu->flags &= ~IRC_USER_AWAY; if( bu->flags & BEE_USER_AWAY || !( bu->flags & BEE_USER_ONLINE ) ) iu->flags |= IRC_USER_AWAY; if( ( bu->flags & BEE_USER_ONLINE ) != ( old->flags & BEE_USER_ONLINE ) ) { if( bu->flags & BEE_USER_ONLINE ) { if( g_hash_table_lookup( irc->watches, iu->key ) ) irc_send_num( irc, 600, "%s %s %s %d :%s", iu->nick, iu->user, iu->host, (int) time( NULL ), "logged online" ); } else { if( g_hash_table_lookup( irc->watches, iu->key ) ) irc_send_num( irc, 601, "%s %s %s %d :%s", iu->nick, iu->user, iu->host, (int) time( NULL ), "logged offline" ); /* Send a QUIT since those will also show up in any query windows the user may have, plus it's only one QUIT instead of possibly many (in case of multiple control chans). If there's a channel that shows offline people, a JOIN will follow. */ if( set_getbool( &bee->set, "offline_user_quits" ) ) irc_user_quit( iu, "Leaving..." ); } } /* Reset this one since the info may have changed. */ iu->away_reply_timeout = 0; bee_irc_channel_update( irc, NULL, iu ); return TRUE; }
static void irc_cmd_join( irc_t *irc, char **cmd ) { char *comma, *s = cmd[1]; while( s ) { irc_channel_t *ic; if( ( comma = strchr( s, ',' ) ) ) *comma = '\0'; if( ( ic = irc_channel_by_name( irc, s ) ) == NULL && ( ic = irc_channel_new( irc, s ) ) ) { if( strcmp( set_getstr( &ic->set, "type" ), "control" ) != 0 ) { /* Autoconfiguration is for control channels only ATM. */ } else if( bee_group_by_name( ic->irc->b, ic->name + 1, FALSE ) ) { set_setstr( &ic->set, "group", ic->name + 1 ); set_setstr( &ic->set, "fill_by", "group" ); } else if( set_setstr( &ic->set, "protocol", ic->name + 1 ) ) { set_setstr( &ic->set, "fill_by", "protocol" ); } else if( set_setstr( &ic->set, "account", ic->name + 1 ) ) { set_setstr( &ic->set, "fill_by", "account" ); } else { /* The set commands above will run this already, but if we didn't hit any, we have to fill the channel with the default population. */ bee_irc_channel_update( ic->irc, ic, NULL ); } } else if( ic == NULL ) { irc_send_num( irc, 479, "%s :Invalid channel name", s ); goto next; } if( ic->flags & IRC_CHANNEL_JOINED ) /* Dude, you're already there... RFC doesn't have any reply for that though? */ goto next; if( ic->f->join && !ic->f->join( ic ) ) /* The story is: FALSE either means the handler showed an error message, or is doing some work before the join should be confirmed. (In the latter case, the caller should take care of that confirmation.) TRUE means all's good, let the user join the channel right away. */ goto next; irc_channel_add_user( ic, irc->user ); next: if( comma ) { s = comma + 1; *comma = ','; } else break; } }