Fix bug #158 - Added plugin for setting topic (hub description).

Load plugin mod_topic, and it will provide 3 new user commands:

!topic - set new topic
!cleartopic - reset the topic (use default hub description)
!showtopic - show the current topic
This commit is contained in:
Jan Vidar Krey
2012-04-19 00:21:49 +02:00
parent df7bbc094f
commit 1dba731cc3
8 changed files with 303 additions and 4 deletions

View File

@@ -148,8 +148,11 @@ static enum command_parse_status command_extract_arguments(struct command_base*
{
int arg = 0;
int opt = 0;
int greedy = 0;
char arg_code;
char* token = NULL;
char* tmp = NULL;
size_t size = 0;
struct hub_command_arg_data* data = NULL;
enum command_parse_status status = cmd_status_ok;
@@ -160,7 +163,27 @@ static enum command_parse_status command_extract_arguments(struct command_base*
while (status == cmd_status_ok && (arg_code = command->args[arg++]))
{
token = list_get_first(tokens);
if (greedy)
{
size = 1;
for (tmp = (char*) list_get_first(tokens); tmp; tmp = (char*) list_get_next(tokens))
size += (strlen(tmp) + 1);
token = hub_malloc_zero(size);
while ((tmp = list_get_first(tokens)))
{
if (*token)
strcat(token, " ");
strcat(token, tmp);
list_remove(tokens, tmp);
hub_free(tmp);
}
}
else
{
token = list_get_first(tokens);
}
if (!token || !*token)
{
status = (arg_code == '?' ? cmd_status_ok : cmd_status_missing_args);
@@ -173,6 +196,10 @@ static enum command_parse_status command_extract_arguments(struct command_base*
opt = 1;
continue;
case '+':
greedy = 1;
continue;
case 'u':
data = hub_malloc(sizeof(*data));
data->type = type_user;

View File

@@ -128,12 +128,16 @@ extern struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd
* N = number (integer)
*
* Prefix an argument with ? to make it optional.
* NOTE; if an argument is optional then all following arguments must also be optional.
* Prefix with + to make the argument greedy, which causes it to grab the rest of the line ignoring boundaries (only supported for string types).
*
* NOTE: if an argument is optional then all following arguments must also be optional.
* NOTE: You can combine optional and greedy, example: "?+m" would match "", "a", "a b c", etc.
*
* Example:
* "nia" means "nick cid ip"
* "n?p" means "nick [password]" where password is optional.
*
* "?N?N" means two optional integers, this can also be expressed as "?NN".
* "?+m" means an optional string which may contain spaces that would otherwise be split into separate arguments.
*/
struct command_handle
{

View File

@@ -159,6 +159,58 @@ struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* pl
return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t);
}
static char* cbfunc_get_hub_name(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_NICK);
char* str = adc_msg_unescape(str_encoded);
hub_free(str_encoded);
return str;
}
static char* cbfunc_get_hub_description(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION);
char* str = adc_msg_unescape(str_encoded);
hub_free(str_encoded);
return str;
}
static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str)
{
struct hub_info* hub = plugin_get_hub(plugin);
struct adc_message* command;
char* new_str = adc_msg_escape(str ? str : hub->config->hub_name);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str);
// Broadcast hub name
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str);
route_to_all(hub, command);
adc_msg_free(command);
hub_free(new_str);
}
static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char* str)
{
struct hub_info* hub = plugin_get_hub(plugin);
struct adc_message* command;
char* new_str = adc_msg_escape(str ? str : hub->config->hub_description);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str);
// Broadcast hub description
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str);
route_to_all(hub, command);
adc_msg_free(command);
hub_free(new_str);
}
void plugin_register_callback_functions(struct plugin_handle* handle)
{
handle->hub.send_message = cbfunc_send_message;
@@ -168,6 +220,10 @@ void plugin_register_callback_functions(struct plugin_handle* handle)
handle->hub.command_del = cbfunc_command_del;
handle->hub.command_arg_reset = cbfunc_command_arg_reset;
handle->hub.command_arg_next = cbfunc_command_arg_next;
handle->hub.get_name = cbfunc_get_hub_name;
handle->hub.set_name = cbfunc_set_hub_name;
handle->hub.get_description = cbfunc_get_hub_description;
handle->hub.set_description = cbfunc_set_hub_description;
}
void plugin_unregister_callback_functions(struct plugin_handle* handle)

View File

@@ -118,6 +118,11 @@ typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_ha
typedef size_t (*hfunc_command_arg_reset)(struct plugin_handle*, struct plugin_command*);
typedef struct plugin_command_arg_data* (*hfunc_command_arg_next)(struct plugin_handle*, struct plugin_command*, enum plugin_command_arg_type);
typedef char* (*hfunc_get_hub_name)(struct plugin_handle*);
typedef char* (*hfunc_get_hub_description)(struct plugin_handle*);
typedef void (*hfunc_set_hub_name)(struct plugin_handle*, const char*);
typedef void (*hfunc_set_hub_description)(struct plugin_handle*, const char*);
/**
* These are functions created and initialized by the hub and which can be used
* by plugins to access functionality internal to the hub.
@@ -131,6 +136,10 @@ struct plugin_hub_funcs
hfunc_command_del command_del;
hfunc_command_arg_reset command_arg_reset;
hfunc_command_arg_next command_arg_next;
hfunc_get_hub_name get_name;
hfunc_get_hub_description get_description;
hfunc_set_hub_name set_name;
hfunc_set_hub_description set_description;
};
struct plugin_handle

101
src/plugins/mod_topic.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "plugin_api/handle.h"
#include "plugin_api/command_api.h"
#include "util/memory.h"
#include "util/cbuffer.h"
struct topic_plugin_data
{
struct plugin_command_handle* topic;
struct plugin_command_handle* cleartopic;
struct plugin_command_handle* showtopic;
};
static int command_topic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_string);
plugin->hub.set_description(plugin, arg ? arg->data.string : NULL);
cbuf_append_format(buf, "*** %s: Topic set to \"%s\"", cmd->prefix, arg->data.string);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static int command_cleartopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
plugin->hub.set_description(plugin, NULL);
cbuf_append_format(buf, "*** %s: Topic cleared.", cmd->prefix);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static int command_showtopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
char* topic = plugin->hub.get_description(plugin);
cbuf_append_format(buf, "*** %s: Current topic is: \"%s\"", cmd->prefix, topic);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
hub_free(topic);
return 0;
}
int plugin_register(struct plugin_handle* plugin, const char* config)
{
struct topic_plugin_data* data = (struct topic_plugin_data*) hub_malloc(sizeof(struct topic_plugin_data));
data->topic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
data->cleartopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
data->showtopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
PLUGIN_INITIALIZE(plugin, "Topic plugin", "1.0", "Add commands for changing the hub topic (description)");
PLUGIN_COMMAND_INITIALIZE(data->topic, (void*) data, "topic", "+m", auth_cred_operator, command_topic_handler, "Set new topic");
PLUGIN_COMMAND_INITIALIZE(data->cleartopic, (void*) data, "cleartopic", "", auth_cred_operator, command_cleartopic_handler, "Clear the current topic");
PLUGIN_COMMAND_INITIALIZE(data->showtopic, (void*) data, "showtopic", "", auth_cred_guest, command_showtopic_handler, "Shows the current topic");
plugin->hub.command_add(plugin, data->topic);
plugin->hub.command_add(plugin, data->cleartopic);
plugin->hub.command_add(plugin, data->showtopic);
plugin->ptr = data;
return 0;
}
int plugin_unregister(struct plugin_handle* plugin)
{
struct topic_plugin_data* data = (struct topic_plugin_data*) plugin->ptr;
plugin->hub.command_del(plugin, data->topic);
plugin->hub.command_del(plugin, data->cleartopic);
plugin->hub.command_del(plugin, data->showtopic);
hub_free(data->topic);
hub_free(data->showtopic);
hub_free(data);
plugin->ptr = NULL;
return 0;
}