Add away-notify client capability.

This commit is contained in:
Keith Buck 2012-02-14 14:15:44 +00:00
parent e5520caf0a
commit c5bbc60375
6 changed files with 64 additions and 0 deletions

43
doc/away-notify.txt Normal file
View file

@ -0,0 +1,43 @@
away-notify client capability specification
----------------------------------------------
Copyright (c) 2012 Keith Buck <mr_flea@esper.net>.
Unlimited redistribution and modification of this document is allowed
provided that the above copyright notice and this permission notice
remains in tact.
The away-notify client capability allows a client to specify that it
would like to be notified when users are marked/unmarked as away. This
capability is referred to as 'away-notify' at capability negotiation
time.
This capability is designed to replace polling of WHO as a more
efficient method of tracking the away state of users in a channel. The
away-notify capability both conserves bandwidth as WHO requests are
not continually sent and allows the client to be notified immediately
upon a user setting or removing their away state (as opposed to when
WHO is next polled).
When this capability is enabled, clients will be sent an AWAY message
when a user sharing a channel with them sets or removes their away
state, as well as when a user joins and has an away message set.
(Note that AWAY will not be sent for joining users with no away
message set.)
The format of the AWAY message is as follows:
:nick!user@host AWAY [:message]
If the message is present, the user (specified by the nick!user@host
mask) is going away. If the message is not present, the user is
removing their away message/state.
To fully track the away state of users, clients should:
1) Enable the away-notify capability at negotiation time.
2) Execute WHO when joining a channel to capture the current away
state of all users in that channel.
3) Update state appropriately upon receiving an AWAY message.

View file

@ -444,6 +444,7 @@ struct ListClient
#define CLICAP_SASL 0x0002
#define CLICAP_ACCOUNT_NOTIFY 0x0004
#define CLICAP_EXTENDED_JOIN 0x0008
#define CLICAP_AWAY_NOTIFY 0x0010
/*
* flags macros.

View file

@ -84,6 +84,9 @@ m_away(struct Client *client_p, struct Client *source_p, int parc, const char *p
sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
":%s AWAY", use_id(source_p));
free_away(source_p);
sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY",
source_p->name, source_p->username, source_p->host);
}
if(MyConnect(source_p))
sendto_one_numeric(source_p, RPL_UNAWAY, form_str(RPL_UNAWAY));
@ -102,5 +105,9 @@ m_away(struct Client *client_p, struct Client *source_p, int parc, const char *p
if(MyConnect(source_p))
sendto_one_numeric(source_p, RPL_NOWAWAY, form_str(RPL_NOWAWAY));
sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s",
source_p->name, source_p->username, source_p->host,
source_p->user->away);
return 0;
}

View file

@ -72,6 +72,7 @@ static struct clicap
_CLICAP("sasl", CLICAP_SASL, 0, 0),
_CLICAP("account-notify", CLICAP_ACCOUNT_NOTIFY, 0, 0),
_CLICAP("extended-join", CLICAP_EXTENDED_JOIN, 0, 0),
_CLICAP("away-notify", CLICAP_AWAY_NOTIFY, 0, 0),
};
#define CLICAP_LIST_LEN (sizeof(clicap_list) / sizeof(struct clicap))

View file

@ -136,6 +136,12 @@ send_channel_join(struct Channel *chptr, struct Client *client_p)
client_p->name, client_p->username, client_p->host, chptr->chname,
EmptyString(client_p->user->suser) ? "*" : client_p->user->suser,
client_p->info);
/* Send away message to away-notify enabled clients. */
if (client_p->user->away)
sendto_channel_local_with_capability_butone(client_p, ALL_MEMBERS, CLICAP_AWAY_NOTIFY, NOCAPS, chptr,
":%s!%s@%s AWAY :%s", client_p->name, client_p->username,
client_p->host, client_p->user->away);
}
/* find_channel_membership()

View file

@ -1468,6 +1468,12 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
*modeval = '\0';
}
/* Resend away message to away-notify enabled clients. */
if (target_p->user->away)
sendto_common_channels_local_butone(target_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s",
target_p->name, target_p->username, target_p->host,
target_p->user->away);
if(MyClient(target_p) && changed_case)
sendto_one(target_p, ":%s!%s@%s NICK %s",
target_p->name, target_p->username, target_p->host, nick);