degesch: naively implement a few user commands
/mode, /topic, /kick, /kickban, /ban, /invite It's all a bit messy and needs some rewriting.
This commit is contained in:
parent
f2ab9f3937
commit
310b9c31d3
193
degesch.c
193
degesch.c
@ -4741,6 +4741,25 @@ cut_word (char **s)
|
||||
return start;
|
||||
}
|
||||
|
||||
static char *
|
||||
maybe_cut_word (char **s, bool (*validator) (void *, char *), void *user_data)
|
||||
{
|
||||
char *start = *s;
|
||||
size_t word_len = strcspn (*s, WORD_BREAKING_CHARS);
|
||||
|
||||
char *word = xstrndup (start, word_len);
|
||||
bool ok = validator (user_data, word);
|
||||
free (word);
|
||||
|
||||
if (!ok)
|
||||
return NULL;
|
||||
|
||||
char *end = start + word_len;
|
||||
*s = end + strspn (end, WORD_BREAKING_CHARS);
|
||||
*end = '\0';
|
||||
return start;
|
||||
}
|
||||
|
||||
static bool
|
||||
try_handle_buffer_goto (struct app_context *ctx, const char *word)
|
||||
{
|
||||
@ -4790,6 +4809,25 @@ server_command_check (struct app_context *ctx, const char *action,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_channel_name (void *user_data, char *word)
|
||||
{
|
||||
struct server *s = user_data;
|
||||
return irc_is_channel (s, word);
|
||||
}
|
||||
|
||||
static char *
|
||||
try_get_channel (struct app_context *ctx, char **arguments)
|
||||
{
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = maybe_cut_word (arguments, validate_channel_name, s);
|
||||
if (channel_name)
|
||||
return channel_name;
|
||||
if (ctx->current_buffer->type == BUFFER_CHANNEL)
|
||||
return ctx->current_buffer->channel->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
show_buffers_list (struct app_context *ctx)
|
||||
{
|
||||
@ -5261,6 +5299,131 @@ handle_command_cycle (struct app_context *ctx, char *arguments)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_mode (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "mode", true))
|
||||
return true;
|
||||
|
||||
// FIXME: allow usernames as well, not only channels
|
||||
// FIXME: +channels collide with setting modes
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = try_get_channel (ctx, &arguments);
|
||||
if (!channel_name)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"%s: %s", "Can't set mode",
|
||||
"no channel name given and this buffer is not a channel");
|
||||
else if (*arguments)
|
||||
irc_send (s, "MODE %s %s", channel_name, arguments);
|
||||
else
|
||||
irc_send (s, "MODE %s", channel_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_topic (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "topic", true))
|
||||
return true;
|
||||
|
||||
// FIXME: currently the topic can't start with a channel name
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = try_get_channel (ctx, &arguments);
|
||||
if (!channel_name)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"%s: %s", "Can't change topic",
|
||||
"no channel name given and this buffer is not a channel");
|
||||
else if (*arguments)
|
||||
// FIXME: there's no way to unset the topic
|
||||
irc_send (s, "TOPIC %s :%s", channel_name, arguments);
|
||||
else
|
||||
irc_send (s, "TOPIC %s", channel_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_kick (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "kick", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = try_get_channel (ctx, &arguments);
|
||||
if (!channel_name)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"%s: %s", "Can't kick",
|
||||
"no channel name given and this buffer is not a channel");
|
||||
else if (*arguments)
|
||||
// FIXME: the reason should be one argument
|
||||
irc_send (s, "KICK %s %s", channel_name, arguments);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_kickban (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "kickban", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = try_get_channel (ctx, &arguments);
|
||||
if (!channel_name)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"%s: %s", "Can't kickban",
|
||||
"no channel name given and this buffer is not a channel");
|
||||
else if (*arguments)
|
||||
{
|
||||
// FIXME: don't include the reason
|
||||
irc_send (s, "MODE %s +b %s", channel_name, arguments);
|
||||
// FIXME: the reason should be one argument
|
||||
irc_send (s, "KICK %s %s", channel_name, arguments);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_ban (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "ban", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = try_get_channel (ctx, &arguments);
|
||||
if (!channel_name)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"%s: %s", "Can't ban",
|
||||
"no channel name given and this buffer is not a channel");
|
||||
else if (*arguments)
|
||||
irc_send (s, "MODE %s +b %s", channel_name, arguments);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_invite (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "invite", true))
|
||||
return true;
|
||||
|
||||
// XXX: the order of arguments should probably be reverse
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
char *channel_name = try_get_channel (ctx, &arguments);
|
||||
if (!channel_name)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"%s: %s", "Can't invite",
|
||||
"no channel name given and this buffer is not a channel");
|
||||
else if (*arguments)
|
||||
irc_send (s, "INVITE %s %s", arguments, channel_name);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_command_connect (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
@ -5410,18 +5573,30 @@ g_command_handlers[] =
|
||||
"[<channel>[,<channel>...]]",
|
||||
handle_command_join },
|
||||
{ "part", "Leave channels",
|
||||
"[<channel>[,<channel>...]] [reason]",
|
||||
"[<channel>[,<channel>...]] [<reason>]",
|
||||
handle_command_part },
|
||||
{ "cycle", "Rejoin channels",
|
||||
"[<channel>[,<channel>...]] [reason]",
|
||||
"[<channel>[,<channel>...]] [<reason>]",
|
||||
handle_command_cycle },
|
||||
|
||||
NOT_IMPLEMENTED (mode)
|
||||
NOT_IMPLEMENTED (topic)
|
||||
NOT_IMPLEMENTED (kick)
|
||||
NOT_IMPLEMENTED (kickban)
|
||||
NOT_IMPLEMENTED (ban)
|
||||
NOT_IMPLEMENTED (invite)
|
||||
{ "mode", "Change mode",
|
||||
"[<channel>] [<mode>...]",
|
||||
handle_command_mode },
|
||||
{ "topic", "Change topic",
|
||||
"[<channel>] [<topic>]",
|
||||
handle_command_topic },
|
||||
{ "kick", "Kick user from channel",
|
||||
"[<channel>] <user> [<reason>]",
|
||||
handle_command_kick },
|
||||
{ "kickban", "Kick and ban user from channel",
|
||||
"[<channel>] <user> [<reason>]",
|
||||
handle_command_kickban },
|
||||
{ "ban", "Ban user from channel",
|
||||
"[<channel>] <mask>",
|
||||
handle_command_ban },
|
||||
{ "invite", "Invite user to channel",
|
||||
"[<channel>] <user>",
|
||||
handle_command_invite },
|
||||
|
||||
{ "connect", "Connect to the server",
|
||||
"[server]",
|
||||
@ -5430,7 +5605,7 @@ g_command_handlers[] =
|
||||
"[reason]",
|
||||
handle_command_disconnect },
|
||||
{ "list", "List channels and their topic",
|
||||
"[<channel>[,<channel>...]] [server]",
|
||||
"[<channel>[,<channel>...]] [<server>]",
|
||||
handle_command_list },
|
||||
NOT_IMPLEMENTED (names)
|
||||
NOT_IMPLEMENTED (who)
|
||||
|
Loading…
Reference in New Issue
Block a user