degesch: implement auto-away
This commit is contained in:
parent
b746c014aa
commit
4d11be0b85
2
NEWS
2
NEWS
|
@ -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
|
||||||
|
|
|
@ -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
102
degesch.c
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue