degesch: implement auto-away

This commit is contained in:
Přemysl Eric Janouch 2015-11-22 23:04:51 +01:00
parent b746c014aa
commit 4d11be0b85
3 changed files with 103 additions and 3 deletions

2
NEWS
View File

@ -5,6 +5,8 @@
* degesch: added detection of pasting, so that it doesn't trigger other * degesch: added detection of pasting, so that it doesn't trigger other
keyboard shortcuts, such as for autocomplete keyboard shortcuts, such as for autocomplete
* degesch: added auto-away capability
* degesch: added an /oper command * degesch: added an /oper command
* degesch: libedit backend works again * degesch: libedit backend works again

View File

@ -24,7 +24,7 @@ This is the largest application within the project. It has most of the stuff
you'd expect of an IRC client, such as being able to set up multiple servers, you'd expect of an IRC client, such as being able to set up multiple servers,
a powerful configuration system, integrated help, text formatting, CTCP queries, a powerful configuration system, integrated help, text formatting, CTCP queries,
automatic splitting of overlong messages, autocomplete, logging to file, automatic splitting of overlong messages, autocomplete, logging to file,
command aliases and rudimentary support for Lua scripting. auto-away, command aliases and rudimentary support for Lua scripting.
kike kike
---- ----

102
degesch.c
View File

@ -1207,6 +1207,7 @@ struct server
int nick_counter; ///< Iterates "nicks" when registering int nick_counter; ///< Iterates "nicks" when registering
struct str irc_user_mode; ///< Our current user modes struct str irc_user_mode; ///< Our current user modes
char *irc_user_host; ///< Our current user@host char *irc_user_host; ///< Our current user@host
bool autoaway_active; ///< Autoaway is currently active
bool cap_echo_message; ///< Whether the server echos messages bool cap_echo_message; ///< Whether the server echos messages
@ -1480,6 +1481,7 @@ struct app_context
struct poller_timer flush_timer; ///< Flush all open files (e.g. logs) struct poller_timer flush_timer; ///< Flush all open files (e.g. logs)
struct poller_timer date_chg_tmr; ///< Print a date change struct poller_timer date_chg_tmr; ///< Print a date change
struct poller_timer autoaway_tmr; ///< Autoaway timer
struct poller poller; ///< Manages polled descriptors struct poller poller; ///< Manages polled descriptors
bool quitting; ///< User requested quitting bool quitting; ///< User requested quitting
@ -1863,6 +1865,16 @@ static struct config_schema g_config_behaviour[] =
.validate = config_validate_nonnegative, .validate = config_validate_nonnegative,
.default_ = "600" }, .default_ = "600" },
{ .name = "autoaway_message",
.comment = "Automated away message",
.type = CONFIG_ITEM_STRING,
.default_ = "\"I'm not here right now\"" },
{ .name = "autoaway_delay",
.comment = "Delay from the last keypress in seconds",
.type = CONFIG_ITEM_INTEGER,
.validate = config_validate_nonnegative,
.default_ = "1800" },
{ .name = "plugin_autoload", { .name = "plugin_autoload",
.comment = "Plugins to automatically load on start", .comment = "Plugins to automatically load on start",
.type = CONFIG_ITEM_STRING_ARRAY, .type = CONFIG_ITEM_STRING_ARRAY,
@ -6110,6 +6122,7 @@ irc_try_parse_welcome_for_userhost (struct server *s, const char *m)
static bool process_input_utf8 static bool process_input_utf8
(struct app_context *, struct buffer *, const char *, int); (struct app_context *, struct buffer *, const char *, int);
static void on_autoaway_timer (struct app_context *ctx);
static void static void
irc_on_registered (struct server *s, const char *nickname) irc_on_registered (struct server *s, const char *nickname)
@ -6124,6 +6137,10 @@ irc_on_registered (struct server *s, const char *nickname)
// XXX: we can also use WHOIS if it's not supported (optional by RFC 2812) // XXX: we can also use WHOIS if it's not supported (optional by RFC 2812)
irc_send (s, "USERHOST %s", s->irc_user->nickname); irc_send (s, "USERHOST %s", s->irc_user->nickname);
// A little hack that reinstates auto-away status when we get disconnected
if (s->autoaway_active)
on_autoaway_timer (s->ctx);
const char *command = get_config_string (s->config, "command"); const char *command = get_config_string (s->config, "command");
if (command) if (command)
{ {
@ -6486,6 +6503,24 @@ irc_handle_rpl_inviting (struct server *s, const struct irc_message *msg)
"You have invited #n to #S", nickname, channel_name); "You have invited #n to #S", nickname, channel_name);
} }
static void
irc_handle_rpl_nowaway (struct server *s, const struct irc_message *msg)
{
(void) msg;
if (s->irc_user)
s->irc_user->away = true;
}
static void
irc_handle_rpl_unaway (struct server *s, const struct irc_message *msg)
{
(void) msg;
if (s->irc_user)
s->irc_user->away = false;
}
static void static void
irc_handle_err_nicknameinuse (struct server *s, const struct irc_message *msg) irc_handle_err_nicknameinuse (struct server *s, const struct irc_message *msg)
{ {
@ -6707,6 +6742,10 @@ irc_process_numeric (struct server *s,
irc_handle_rpl_topicwhotime (s, msg); buffer = NULL; break; irc_handle_rpl_topicwhotime (s, msg); buffer = NULL; break;
case IRC_RPL_INVITING: case IRC_RPL_INVITING:
irc_handle_rpl_inviting (s, msg); buffer = NULL; break; irc_handle_rpl_inviting (s, msg); buffer = NULL; break;
case IRC_RPL_NOWAWAY:
irc_handle_rpl_nowaway (s, msg); break;
case IRC_RPL_UNAWAY:
irc_handle_rpl_unaway (s, msg); break;
case IRC_ERR_NICKNAMEINUSE: case IRC_ERR_NICKNAMEINUSE:
irc_handle_err_nicknameinuse (s, msg); buffer = NULL; break; irc_handle_err_nicknameinuse (s, msg); buffer = NULL; break;
@ -10979,11 +11018,61 @@ done:
ctx->in_bracketed_paste = false; ctx->in_bracketed_paste = false;
} }
static void
reset_autoaway (struct app_context *ctx)
{
// Stop the last one if it's been disabled altogether in the meantime
poller_timer_reset (&ctx->autoaway_tmr);
// Unset any automated statuses that are active right at this moment
struct str_map_iter iter;
str_map_iter_init (&iter, &ctx->servers);
struct server *s;
while ((s = str_map_iter_next (&iter)))
{
if (s->autoaway_active
&& s->irc_user
&& s->irc_user->away)
irc_send (s, "AWAY");
s->autoaway_active = false;
}
// And potentially start a new auto-away timer
int64_t delay = get_config_integer
(ctx->config.root, "behaviour.autoaway_delay");
if (delay)
poller_timer_set (&ctx->autoaway_tmr, delay * 1000);
}
static void
on_autoaway_timer (struct app_context *ctx)
{
// An empty message would unset any away status, so let's ignore that
const char *message = get_config_string
(ctx->config.root, "behaviour.autoaway_message");
if (!message || !*message)
return;
struct str_map_iter iter;
str_map_iter_init (&iter, &ctx->servers);
struct server *s;
while ((s = str_map_iter_next (&iter)))
{
// If the user has already been marked as away,
// don't override his current away status
if (s->irc_user
&& s->irc_user->away)
continue;
irc_send (s, "AWAY :%s", message);
s->autoaway_active = true;
}
}
static void static void
on_tty_readable (const struct pollfd *fd, struct app_context *ctx) on_tty_readable (const struct pollfd *fd, struct app_context *ctx)
{ {
(void) ctx;
if (fd->revents & ~(POLLIN | POLLHUP | POLLERR)) if (fd->revents & ~(POLLIN | POLLHUP | POLLERR))
print_debug ("fd %d: unexpected revents: %d", fd->fd, fd->revents); print_debug ("fd %d: unexpected revents: %d", fd->fd, fd->revents);
@ -10995,6 +11084,10 @@ on_tty_readable (const struct pollfd *fd, struct app_context *ctx)
// XXX: this may loop for a bit: stop the event or eat the input? // XXX: this may loop for a bit: stop the event or eat the input?
// (This prevents a segfault when the input has been stopped.) // (This prevents a segfault when the input has been stopped.)
input_on_readable (&ctx->input); input_on_readable (&ctx->input);
// User activity detected, stop current auto-away and start anew;
// since they might have just changed the settings, do this last
reset_autoaway (ctx);
} }
static void static void
@ -11059,6 +11152,10 @@ init_poller_events (struct app_context *ctx)
ctx->date_chg_tmr.dispatcher = (poller_timer_fn) on_date_change_timer; ctx->date_chg_tmr.dispatcher = (poller_timer_fn) on_date_change_timer;
ctx->date_chg_tmr.user_data = ctx; ctx->date_chg_tmr.user_data = ctx;
rearm_date_change_timer (ctx); rearm_date_change_timer (ctx);
poller_timer_init (&ctx->autoaway_tmr, &ctx->poller);
ctx->autoaway_tmr.dispatcher = (poller_timer_fn) on_autoaway_timer;
ctx->autoaway_tmr.user_data = ctx;
} }
// --- Main program ------------------------------------------------------------ // --- Main program ------------------------------------------------------------
@ -11146,6 +11243,7 @@ main (int argc, char *argv[])
refresh_prompt (&ctx); refresh_prompt (&ctx);
input_start (&ctx.input, argv[0]); input_start (&ctx.input, argv[0]);
toggle_bracketed_paste (true); toggle_bracketed_paste (true);
reset_autoaway (&ctx);
// Finally, we juice the configuration for some servers to create // Finally, we juice the configuration for some servers to create
load_plugins (&ctx); load_plugins (&ctx);