summaryrefslogtreecommitdiff
path: root/src/plugins/irc
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2023-05-05 20:38:38 +0200
committerSébastien Helleu <flashcode@flashtux.org>2023-05-14 15:32:39 +0200
commit176a10677137e887ed5e8299669bacbc4148d65a (patch)
treefd27d7d932c80eb3bec59a17ccbc9bd3a15a0eed /src/plugins/irc
parente8b5d73421f63e6e792c039e7a86754db8cfa78c (diff)
downloadweechat-176a10677137e887ed5e8299669bacbc4148d65a.zip
irc: add support of capability "draft/multiline" (closes #1923)
Diffstat (limited to 'src/plugins/irc')
-rw-r--r--src/plugins/irc/irc-batch.c197
-rw-r--r--src/plugins/irc/irc-batch.h6
-rw-r--r--src/plugins/irc/irc-channel.c1
-rw-r--r--src/plugins/irc/irc-command.c47
-rw-r--r--src/plugins/irc/irc-command.h4
-rw-r--r--src/plugins/irc/irc-message.c447
-rw-r--r--src/plugins/irc/irc-message.h11
-rw-r--r--src/plugins/irc/irc-protocol.c5
-rw-r--r--src/plugins/irc/irc-server.c59
-rw-r--r--src/plugins/irc/irc-server.h21
-rw-r--r--src/plugins/irc/irc.c3
11 files changed, 672 insertions, 129 deletions
diff --git a/src/plugins/irc/irc-batch.c b/src/plugins/irc/irc-batch.c
index 02f557d3e..87b51b474 100644
--- a/src/plugins/irc/irc-batch.c
+++ b/src/plugins/irc/irc-batch.c
@@ -30,7 +30,9 @@
#include "irc-batch.h"
#include "irc-message.h"
#include "irc-protocol.h"
+#include "irc-raw.h"
#include "irc-server.h"
+#include "irc-tag.h"
/*
@@ -59,6 +61,31 @@ irc_batch_search (struct t_irc_server *server, const char *reference)
}
/*
+ * Generates a random batch reference with `size` chars (the next one is the
+ * final '\0', so the string must be at least size + 1 bytes long).
+ */
+
+void
+irc_batch_generate_random_ref (char *string, int size)
+{
+ const char *chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789";
+
+ int i, length_chars;
+
+ if (!string || (size < 0))
+ return;
+
+ length_chars = strlen (chars);
+ for (i = 0; i < size; i++)
+ {
+ string[i] = chars[rand() % length_chars];
+ }
+ string[size] = '\0';
+}
+
+/*
* Adds a batch to list of batched events.
*/
@@ -199,6 +226,7 @@ irc_batch_process_messages (struct t_irc_server *server,
struct t_irc_batch *batch)
{
char **list_messages, *command, *channel, modifier_data[1024], *new_messages;
+ char *message;
int i, count_messages;
if (!batch || !batch->messages)
@@ -229,8 +257,12 @@ irc_batch_process_messages (struct t_irc_server *server,
{
for (i = 0; i < count_messages; i++)
{
+ message = weechat_string_replace (list_messages[i], "\r", "\n");
+ if (!message)
+ continue;
+
irc_message_parse (server,
- list_messages[i],
+ message,
NULL, /* tags */
NULL, /* message_without_tags */
NULL, /* nick */
@@ -246,9 +278,15 @@ irc_batch_process_messages (struct t_irc_server *server,
NULL, /* pos_arguments */
NULL, /* pos_channel */
NULL); /* pos_text */
+
+ /* add raw message */
+ irc_raw_print (server, IRC_RAW_FLAG_RECV, message);
+
/* call receive callback, ignoring batch tags */
- irc_protocol_recv_command (server, list_messages[i], command,
- channel, 1);
+ irc_protocol_recv_command (server, message, command, channel, 1);
+
+ if (message)
+ free (message);
if (command)
free (command);
if (channel)
@@ -318,6 +356,159 @@ irc_batch_end_batch (struct t_irc_server *server, const char *reference)
}
/*
+ * Processes multiline batch: convert multiple messages into a single one,
+ * that can include newline chars ("\r" that are converted later to "\n").
+ *
+ * Parameter "target" is the batch target (channel or nick name).
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+irc_batch_process_multiline (struct t_irc_server *server,
+ const char *messages, const char *target)
+{
+ char **result, **list_messages;
+ char *tags, *host, *command, *channel, *text;
+ int i, count_messages;
+ struct t_hashtable *hash_tags;
+
+ result = weechat_string_dyn_alloc (256);
+
+ list_messages = weechat_string_split (messages, "\n", NULL, 0, 0,
+ &count_messages);
+ if (!list_messages)
+ goto end;
+
+ hash_tags = weechat_hashtable_new (32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+
+ for (i = 0; i < count_messages; i++)
+ {
+ irc_message_parse (server,
+ list_messages[i],
+ &tags,
+ NULL, /* message_without_tags */
+ NULL, /* nick */
+ NULL, /* user */
+ &host,
+ &command,
+ &channel,
+ NULL, /* arguments */
+ &text,
+ NULL, /* params */
+ NULL, /* num_params */
+ NULL, /* pos_command */
+ NULL, /* pos_arguments */
+ NULL, /* pos_channel */
+ NULL); /* pos_text */
+ if (host
+ && command
+ && ((strcmp (command, "PRIVMSG") == 0)
+ || (strcmp (command, "NOTICE") == 0))
+ && channel
+ && (strcmp (channel, target) == 0))
+ {
+ if (hash_tags)
+ {
+ weechat_hashtable_remove_all (hash_tags);
+ if (tags && tags[0])
+ irc_tag_parse (tags, hash_tags, NULL);
+ }
+ if (*result[0])
+ {
+ if (!hash_tags
+ || !weechat_hashtable_has_key (hash_tags,
+ "draft/multiline-concat"))
+ {
+ weechat_string_dyn_concat (result, "\r", -1);
+ }
+ }
+ else
+ {
+ if (tags && tags[0])
+ {
+ weechat_string_dyn_concat (result, "@", -1);
+ weechat_string_dyn_concat (result, tags, -1);
+ weechat_string_dyn_concat (result, " ", -1);
+ }
+ weechat_string_dyn_concat (result, ":", -1);
+ weechat_string_dyn_concat (result, host, -1);
+ weechat_string_dyn_concat (result, " ", -1);
+ weechat_string_dyn_concat (result, command, -1);
+ weechat_string_dyn_concat (result, " ", -1);
+ weechat_string_dyn_concat (result, target, -1);
+ weechat_string_dyn_concat (result, " :", -1);
+ }
+ if (text)
+ weechat_string_dyn_concat (result, text, -1);
+ }
+ if (tags)
+ free (tags);
+ if (host)
+ free (host);
+ if (command)
+ free (command);
+ if (channel)
+ free (channel);
+ if (text)
+ free (text);
+ }
+
+end:
+ if (hash_tags)
+ weechat_hashtable_free (hash_tags);
+ if (list_messages)
+ weechat_string_free_split (list_messages);
+
+ return weechat_string_dyn_free (result, 0);
+}
+
+/*
+ * Callback for modifier "irc_batch".
+ */
+
+char *
+irc_batch_modifier_cb (const void *pointer, void *data,
+ const char *modifier, const char *modifier_data,
+ const char *string)
+{
+ struct t_irc_server *ptr_server;
+ char **items, *result;
+ int num_items;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) modifier;
+
+ result = NULL;
+
+ if (!modifier_data)
+ return NULL;
+
+ items = weechat_string_split (modifier_data, ",", NULL, 0, 3, &num_items);
+ if (!items)
+ return NULL;
+
+ if (items && (num_items > 1))
+ {
+ ptr_server = irc_server_search (items[0]);
+ if (ptr_server && (num_items > 2)
+ && (strcmp (items[1], "draft/multiline") == 0))
+ {
+ result = irc_batch_process_multiline (ptr_server, string, items[2]);
+ }
+ }
+ if (items)
+ weechat_string_free_split (items);
+
+ return (result) ? result : strdup (string);
+}
+
+/*
* Returns hdata for batch.
*/
diff --git a/src/plugins/irc/irc-batch.h b/src/plugins/irc/irc-batch.h
index bd8dec30c..04b718dad 100644
--- a/src/plugins/irc/irc-batch.h
+++ b/src/plugins/irc/irc-batch.h
@@ -39,6 +39,7 @@ struct t_irc_batch
struct t_irc_batch *next_batch; /* link to next batch */
};
+extern void irc_batch_generate_random_ref (char *string, int size);
extern struct t_irc_batch *irc_batch_search (struct t_irc_server *server,
const char *reference);
extern struct t_irc_batch *irc_batch_start_batch (struct t_irc_server *server,
@@ -54,6 +55,11 @@ extern void irc_batch_end_batch (struct t_irc_server *server,
extern void irc_batch_free (struct t_irc_server *server,
struct t_irc_batch *batch);
extern void irc_batch_free_all (struct t_irc_server *server);
+extern char *irc_batch_modifier_cb (const void *pointer, void *data,
+ const char *modifier,
+ const char *modifier_data,
+ const char *string);
+
extern struct t_hdata *irc_batch_hdata_batch_cb (const void *pointer,
void *data,
const char *hdata_name);
diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c
index fe5342973..d36e75ddb 100644
--- a/src/plugins/irc/irc-channel.c
+++ b/src/plugins/irc/irc-channel.c
@@ -330,6 +330,7 @@ irc_channel_create_buffer (struct t_irc_server *server,
if (buffer_created)
{
+ weechat_buffer_set (ptr_buffer, "input_multiline", "1");
if (!weechat_buffer_get_integer (ptr_buffer, "short_name_is_set"))
weechat_buffer_set (ptr_buffer, "short_name", channel_name);
}
diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c
index 8cc4e1c97..f176f0dd5 100644
--- a/src/plugins/irc/irc-command.c
+++ b/src/plugins/irc/irc-command.c
@@ -1105,27 +1105,38 @@ irc_command_me_channel (struct t_irc_server *server,
const char *arguments)
{
struct t_arraylist *list_messages;
- int i, list_size;
+ char **list_arguments;
+ int i, j, list_size, count_arguments;
- list_messages = irc_server_sendf (
- server,
- IRC_SERVER_SEND_OUTQ_PRIO_HIGH | IRC_SERVER_SEND_RETURN_LIST,
- NULL,
- "PRIVMSG %s :\01ACTION %s\01",
- channel->name,
- (arguments && arguments[0]) ? arguments : "");
- if (list_messages)
+ list_arguments = weechat_string_split ((arguments) ? arguments : "",
+ "\n", NULL, 0, 0, &count_arguments);
+ if (!list_arguments)
+ return;
+
+ for (i = 0; i < count_arguments; i++)
{
- list_size = weechat_arraylist_size (list_messages);
- for (i = 0; i < list_size; i++)
+ list_messages = irc_server_sendf (
+ server,
+ IRC_SERVER_SEND_OUTQ_PRIO_HIGH | IRC_SERVER_SEND_RETURN_LIST,
+ NULL,
+ "PRIVMSG %s :\01ACTION %s\01",
+ channel->name,
+ list_arguments[i]);
+ if (list_messages)
{
- irc_command_me_channel_display (
- server,
- channel,
- (const char *)weechat_arraylist_get (list_messages, i));
+ list_size = weechat_arraylist_size (list_messages);
+ for (j = 0; j < list_size; j++)
+ {
+ irc_command_me_channel_display (
+ server,
+ channel,
+ (const char *)weechat_arraylist_get (list_messages, j));
+ }
+ weechat_arraylist_free (list_messages);
}
- weechat_arraylist_free (list_messages);
}
+
+ weechat_string_free_split (list_arguments);
}
/*
@@ -6950,8 +6961,8 @@ irc_command_init ()
"\n"
"Capabilities supported by WeeChat are: "
"account-notify, away-notify, batch, cap-notify, chghost, "
- "extended-join, invite-notify, message-tags, multi-prefix, "
- "server-time, setname, userhost-in-names.\n"
+ "draft/multiline, extended-join, invite-notify, message-tags, "
+ "multi-prefix, server-time, setname, userhost-in-names.\n"
"\n"
"The capabilities to automatically enable on servers can be set "
"in option irc.server_default.capabilities (or by server in "
diff --git a/src/plugins/irc/irc-command.h b/src/plugins/irc/irc-command.h
index 7a57dfbb8..1de161d98 100644
--- a/src/plugins/irc/irc-command.h
+++ b/src/plugins/irc/irc-command.h
@@ -59,8 +59,8 @@ struct t_irc_channel;
*/
#define IRC_COMMAND_CAP_SUPPORTED \
"account-notify|away-notify|batch|cap-notify|chghost|" \
- "extended-join|invite-notify|message-tags|multi-prefix|" \
- "server-time|setname|userhost-in-names"
+ "draft/multiline|extended-join|invite-notify|message-tags|" \
+ "multi-prefix|server-time|setname|userhost-in-names"
/* list of supported CTCPs (for completion in command /ctcp) */
#define IRC_COMMAND_CTCP_SUPPORTED_COMPLETION \
diff --git a/src/plugins/irc/irc-message.c b/src/plugins/irc/irc-message.c
index e5b2360c1..bc5023727 100644
--- a/src/plugins/irc/irc-message.c
+++ b/src/plugins/irc/irc-message.c
@@ -26,6 +26,8 @@
#include "../weechat-plugin.h"
#include "irc.h"
+#include "irc-message.h"
+#include "irc-batch.h"
#include "irc-channel.h"
#include "irc-color.h"
#include "irc-config.h"
@@ -530,6 +532,112 @@ irc_message_parse_to_hashtable (struct t_irc_server *server,
}
/*
+ * Parses capability value.
+ *
+ * For example for this capability:
+ * draft/multiline=max-bytes=4096,max-lines=24
+ *
+ * The input value must be: "max-bytes=4096,max-lines=24"
+ * The output is a hashtable with following keys/values (as strings):
+ *
+ * "max-bytes": "4096"
+ * "max-lines": "24"
+ *
+ * Note: hashtable must be freed after use.
+ */
+
+struct t_hashtable *
+irc_message_parse_cap_value (const char *value)
+{
+ struct t_hashtable *hashtable;
+ char **items, *key;
+ const char *pos;
+ int i, count_items;
+
+ if (!value)
+ return NULL;
+
+ hashtable = weechat_hashtable_new (32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+ if (!hashtable)
+ return NULL;
+
+ items = weechat_string_split (value, ",", NULL, 0, 0, &count_items);
+ if (items)
+ {
+ for (i = 0; i < count_items; i++)
+ {
+ pos = strchr (items[i], '=');
+ if (pos)
+ {
+ key = weechat_strndup (items[i], pos - items[i]);
+ if (key)
+ {
+ weechat_hashtable_set (hashtable, key, pos + 1);
+ free (key);
+ }
+ }
+ else
+ {
+ weechat_hashtable_set (hashtable, items[i], NULL);
+ }
+ }
+ weechat_string_free_split (items);
+ }
+
+ return hashtable;
+}
+
+/*
+ * Parses "draft/multiline" cap value and extract:
+ * - max-bytes: maximum allowed total byte length of multiline batched content
+ * - max-lines: maximum allowed number of lines in a multiline batch content
+ */
+
+void
+irc_message_parse_cap_multiline_value (struct t_irc_server *server,
+ const char *value)
+{
+ struct t_hashtable *values;
+ const char *ptr_value;
+ char *error;
+ long number;
+
+ if (!server)
+ return;
+
+ server->multiline_max_bytes = IRC_SERVER_MULTILINE_DEFAULT_MAX_BYTES;
+ server->multiline_max_lines = IRC_SERVER_MULTILINE_DEFAULT_MAX_LINES;
+
+ if (!value)
+ return;
+
+ values = irc_message_parse_cap_value (value);
+ if (!values)
+ return;
+
+ ptr_value = (const char *)weechat_hashtable_get (values, "max-bytes");
+ if (ptr_value)
+ {
+ number = strtol (ptr_value, &error, 10);
+ if (error && !error[0])
+ server->multiline_max_bytes = number;
+ }
+
+ ptr_value = (const char *)weechat_hashtable_get (values, "max-lines");
+ if (ptr_value)
+ {
+ number = strtol (ptr_value, &error, 10);
+ if (error && !error[0])
+ server->multiline_max_lines = number;
+ }
+
+ weechat_hashtable_free (values);
+}
+
+/*
* Encodes/decodes an IRC message using a charset.
*
* Note: result must be freed after use.
@@ -762,24 +870,27 @@ irc_message_replace_vars (struct t_irc_server *server,
*/
void
-irc_message_split_add (struct t_hashtable *hashtable, int number,
+irc_message_split_add (struct t_irc_message_split_context *context,
const char *tags, const char *message,
const char *arguments)
{
char key[32], value[32], *buf;
int length;
+ if (!context)
+ return;
+
if (message)
{
length = ((tags) ? strlen (tags) : 0) + strlen (message) + 1;
buf = malloc (length);
if (buf)
{
- snprintf (key, sizeof (key), "msg%d", number);
+ snprintf (key, sizeof (key), "msg%d", context->number);
snprintf (buf, length, "%s%s",
(tags) ? tags : "",
message);
- weechat_hashtable_set (hashtable, key, buf);
+ weechat_hashtable_set (context->hashtable, key, buf);
if (weechat_irc_plugin->debug >= 2)
{
weechat_printf (NULL,
@@ -787,12 +898,13 @@ irc_message_split_add (struct t_hashtable *hashtable, int number,
key, buf, length - 1);
}
free (buf);
+ context->total_bytes += length;
}
}
if (arguments)
{
- snprintf (key, sizeof (key), "args%d", number);
- weechat_hashtable_set (hashtable, key, arguments);
+ snprintf (key, sizeof (key), "args%d", context->number);
+ weechat_hashtable_set (context->hashtable, key, arguments);
if (weechat_irc_plugin->debug >= 2)
{
weechat_printf (NULL,
@@ -800,8 +912,8 @@ irc_message_split_add (struct t_hashtable *hashtable, int number,
key, arguments);
}
}
- snprintf (value, sizeof (value), "%d", number);
- weechat_hashtable_set (hashtable, "count", value);
+ snprintf (value, sizeof (value), "%d", context->number);
+ weechat_hashtable_set (context->hashtable, "count", value);
}
/*
@@ -837,7 +949,7 @@ irc_message_split_add (struct t_hashtable *hashtable, int number,
*/
int
-irc_message_split_string (struct t_hashtable *hashtable,
+irc_message_split_string (struct t_irc_message_split_context *context,
const char *tags,
const char *host,
const char *command,
@@ -851,7 +963,9 @@ irc_message_split_string (struct t_hashtable *hashtable,
{
const char *pos, *pos_max, *pos_next, *pos_last_delim;
char message[8192], *dup_arguments;
- int number;
+
+ if (!context)
+ return 0;
max_length -= 2; /* by default: 512 - 2 = 510 bytes */
if (max_length_nick_user_host >= 0)
@@ -880,8 +994,6 @@ irc_message_split_string (struct t_hashtable *hashtable,
max_length);
}
- number = 1;
-
if (!arguments || !arguments[0])
{
snprintf (message, sizeof (message), "%s%s%s %s%s%s%s",
@@ -892,7 +1004,8 @@ irc_message_split_string (struct t_hashtable *hashtable,
(target && target[0]) ? " " : "",
(prefix) ? prefix : "",
(suffix) ? suffix : "");
- irc_message_split_add (hashtable, 1, tags, message, "");
+ irc_message_split_add (context, tags, message, "");
+ (context->number)++;
return 1;
}
@@ -924,9 +1037,8 @@ irc_message_split_string (struct t_hashtable *hashtable,
(prefix) ? prefix : "",
dup_arguments,
(suffix) ? suffix : "");
- irc_message_split_add (hashtable, number, tags, message,
- dup_arguments);
- number++;
+ irc_message_split_add (context, tags, message, dup_arguments);
+ (context->number)++;
free (dup_arguments);
}
arguments = (pos == pos_last_delim) ? pos + 1 : pos;
@@ -945,16 +1057,14 @@ irc_message_split_string (struct t_hashtable *hashtable,
*/
int
-irc_message_split_authenticate (struct t_hashtable *hashtable,
+irc_message_split_authenticate (struct t_irc_message_split_context *context,
const char *tags, const char *host,
const char *command, const char *arguments)
{
- int number, length;
+ int length;
char message[8192], *args;
const char *ptr_args;
- number = 1;
-
length = 0;
ptr_args = arguments;
while (ptr_args && ptr_args[0])
@@ -972,9 +1082,9 @@ irc_message_split_authenticate (struct t_hashtable *hashtable,
(host) ? " " : "",
command,
args);
- irc_message_split_add (hashtable, number, tags, message, args);
+ irc_message_split_add (context, tags, message, args);
free (args);
- number++;
+ (context->number)++;
ptr_args += length;
}
@@ -984,8 +1094,8 @@ irc_message_split_authenticate (struct t_hashtable *hashtable,
(host) ? host : "",
(host) ? " " : "",
command);
- irc_message_split_add (hashtable, number, tags, message, "+");
- number++;
+ irc_message_split_add (context, tags, message, "+");
+ (context->number)++;
}
return 1;
@@ -1001,20 +1111,18 @@ irc_message_split_authenticate (struct t_hashtable *hashtable,
*/
int
-irc_message_split_join (struct t_hashtable *hashtable,
+irc_message_split_join (struct t_irc_message_split_context *context,
const char *tags, const char *host,
const char *arguments,
int max_length)
{
- int number, channels_count, keys_count, length, length_no_channel;
+ int channels_count, keys_count, length, length_no_channel;
int length_to_add, index_channel;
char **channels, **keys, *pos, *str;
char msg_to_send[16384], keys_to_add[16384];
max_length -= 2; /* by default: 512 - 2 = 510 bytes */
- number = 1;
-
channels = NULL;
channels_count = 0;
keys = NULL;
@@ -1087,11 +1195,11 @@ irc_message_split_join (struct t_hashtable *hashtable,
else
{
strcat (msg_to_send, keys_to_add);
- irc_message_split_add (hashtable, number,
+ irc_message_split_add (context,
tags,
msg_to_send,
msg_to_send + length_no_channel + 1);
- number++;
+ (context->number)++;
snprintf (msg_to_send, sizeof (msg_to_send), "%s%sJOIN",
(host) ? host : "",
(host) ? " " : "");
@@ -1103,7 +1211,7 @@ irc_message_split_join (struct t_hashtable *hashtable,
if (length > length_no_channel)
{
strcat (msg_to_send, keys_to_add);
- irc_message_split_add (hashtable, number,
+ irc_message_split_add (context,
tags,
msg_to_send,
msg_to_send + length_no_channel + 1);
@@ -1118,25 +1226,78 @@ irc_message_split_join (struct t_hashtable *hashtable,
}
/*
+ * Starts batch for multiline message.
+ */
+
+void
+irc_message_start_batch (struct t_irc_message_split_context *context,
+ const char *target, const char *batch_ref)
+{
+ char msg_batch[4096], args_batch[4096];
+
+ snprintf (msg_batch, sizeof (msg_batch),
+ "BATCH +%s draft/multiline %s",
+ batch_ref,
+ target);
+ snprintf (args_batch, sizeof (args_batch),
+ "+%s draft/multiline %s",
+ batch_ref,
+ target);
+ irc_message_split_add (context, NULL, msg_batch, args_batch);
+ (context->number)++;
+}
+
+/*
+ * Ends batch for multiline message.
+ */
+
+void
+irc_message_end_batch (struct t_irc_message_split_context *context,
+ const char *batch_ref)
+{
+ char msg_batch[4096], args_batch[4096];
+
+ snprintf (msg_batch, sizeof (msg_batch),
+ "BATCH -%s",
+ batch_ref);
+ snprintf (args_batch, sizeof (args_batch),
+ "-%s",
+ batch_ref);
+ irc_message_split_add (context, NULL, msg_batch, args_batch);
+ (context->number)++;
+}
+
+/*
* Splits a PRIVMSG or NOTICE message, taking care of keeping the '\01' char
* used in CTCP messages.
*
+ * If multiline == 1, the message is split on newline chars ('\n') and is sent
+ * using BATCH command (to group messages together).
+ *
* Returns:
* 1: OK
* 0: error
*/
int
-irc_message_split_privmsg_notice (struct t_hashtable *hashtable,
- const char *tags, const char *host,
- const char *command, const char *target,
+irc_message_split_privmsg_notice (struct t_irc_message_split_context *context,
+ const char *tags,
+ const char *host,
+ const char *command,
+ const char *target,
const char *arguments,
int max_length_nick_user_host,
- int max_length)
+ int max_length,
+ int multiline,
+ int multiline_max_bytes,
+ int multiline_max_lines)
{
- char *arguments2, prefix[4096], suffix[2], *pos, saved_char;
+ char prefix[4096], suffix[2], *pos, saved_char, name[256];
+ char tags_multiline[4096], **list_lines, batch_ref[16 + 1];
+ char **multiline_args;
const char *ptr_args;
- int length, rc;
+ int i, length, length_tags, rc, count_lines, batch_lines;
+ int index_multiline_args;
/*
* message sent looks like:
@@ -1146,41 +1307,122 @@ irc_message_split_privmsg_notice (struct t_hashtable *hashtable,
* :nick!user@host.com PRIVMSG #channel :hello world!
*/
- arguments2 = strdup (arguments);
- if (!arguments2)
- return 0;
-
- ptr_args = arguments2;
+ rc = 1;
- /* for CTCP, prefix will be ":\01xxxx " and suffix "\01" */
- prefix[0] = '\0';
- suffix[0] = '\0';
- length = strlen (arguments2);
- if ((arguments2[0] == '\01')
- && (arguments2[length - 1] == '\01'))
+ if (multiline)
{
- pos = strchr (arguments2, ' ');
- if (pos)
+ index_multiline_args = 1;
+ multiline_args = weechat_string_dyn_alloc (256);
+ if (!multiline_args)
+ return 0;
+
+ irc_batch_generate_random_ref (batch_ref, sizeof (batch_ref) - 1);
+
+ /* start batch */
+ irc_message_start_batch (context, target, batch_ref);
+
+ /* add messages */
+ list_lines = weechat_string_split (arguments, "\n", NULL, 0, 0,
+ &count_lines);
+ if (list_lines)
{
- pos++;
- saved_char = pos[0];
- pos[0] = '\0';
- snprintf (prefix, sizeof (prefix), ":%s", arguments2);
- pos[0] = saved_char;
- arguments2[length - 1] = '\0';
- ptr_args = pos;
- suffix[0] = '\01';
- suffix[1] = '\0';
+ batch_lines = 0;
+ for (i = 0; i < count_lines; i++)
+ {
+ if (tags && tags[0])
+ {
+ snprintf (tags_multiline, sizeof (tags_multiline),
+ "@batch=%s;%s",
+ batch_ref,
+ tags + 1);
+ }
+ else
+ {
+ snprintf (tags_multiline, sizeof (tags_multiline),
+ "@batch=%s ",
+ batch_ref);
+ }
+ length_tags = strlen (tags_multiline);
+ rc &= irc_message_split_string (
+ context, tags_multiline, host, command, target, ":",
+ list_lines[i], "", ' ', max_length_nick_user_host,
+ max_length);
+ if (batch_lines > 0)
+ weechat_string_dyn_concat (multiline_args, "\n", -1);
+ weechat_string_dyn_concat (multiline_args,
+ list_lines[i], -1);
+ batch_lines++;
+ if ((i < count_lines - 1)
+ && ((batch_lines >= multiline_max_lines)
+ || (context->total_bytes + length_tags
+ + (int)strlen (list_lines[i + 1]) >= multiline_max_bytes)))
+ {
+ /* start new batch if we have reached max lines/bytes */
+ irc_message_end_batch (context, batch_ref);
+ snprintf (name, sizeof (name),
+ "multiline_args%d", index_multiline_args);
+ weechat_hashtable_set (context->hashtable, name,
+ *multiline_args);
+ weechat_string_dyn_copy (multiline_args, NULL);
+ index_multiline_args++;
+ irc_batch_generate_random_ref (batch_ref,
+ sizeof (batch_ref) - 1);
+ context->total_bytes = 0;
+ irc_message_start_batch (context, target, batch_ref);
+ batch_lines = 0;
+ }
+ }
+ weechat_string_free_split (list_lines);
}
- }
- if (!prefix[0])
- strcpy (prefix, ":");
- rc = irc_message_split_string (hashtable, tags, host, command, target,
- prefix, ptr_args, suffix,
- ' ', max_length_nick_user_host, max_length);
+ /* end batch */
+ irc_message_end_batch (context, batch_ref);
- free (arguments2);
+ snprintf (name, sizeof (name),
+ "multiline_args%d", index_multiline_args);
+ weechat_hashtable_set (context->hashtable, name, *multiline_args);
+ weechat_string_dyn_free (multiline_args, 1);
+ }
+ else
+ {
+ list_lines = weechat_string_split (arguments, "\n", NULL, 0, 0,
+ &count_lines);
+ if (list_lines)
+ {
+ for (i = 0; i < count_lines; i++)
+ {
+ /* for CTCP, prefix is ":\01xxxx " and suffix "\01" */
+ prefix[0] = '\0';
+ suffix[0] = '\0';
+ ptr_args = list_lines[i];
+ length = strlen (list_lines[i]);
+ if ((list_lines[i][0] == '\01')
+ && (list_lines[i][length - 1] == '\01'))
+ {
+ pos = strchr (list_lines[i], ' ');
+ if (pos)
+ {
+ pos++;
+ saved_char = pos[0];
+ pos[0] = '\0';
+ snprintf (prefix, sizeof (prefix), ":%s", list_lines[i]);
+ pos[0] = saved_char;
+ list_lines[i][length - 1] = '\0';
+ ptr_args = pos;
+ suffix[0] = '\01';
+ suffix[1] = '\0';
+ }
+ }
+ if (!prefix[0])
+ strcpy (prefix, ":");
+ rc = irc_message_split_string (context, tags, host, command, target,
+ prefix, ptr_args, suffix,
+ ' ', max_length_nick_user_host,
+ max_length);
+ }
+ weechat_string_free_split (list_lines);
+ }
+ }
return rc;
}
@@ -1194,7 +1436,7 @@ irc_message_split_privmsg_notice (struct t_hashtable *hashtable,
*/
int
-irc_message_split_005 (struct t_hashtable *hashtable,
+irc_message_split_005 (struct t_irc_message_split_context *context,
const char *tags, const char *host, const char *command,
const char *target, const char *arguments,
int max_length)
@@ -1218,7 +1460,7 @@ irc_message_split_005 (struct t_hashtable *hashtable,
pos[0] = '\0';
}
- return irc_message_split_string (hashtable, tags, host, command, target,
+ return irc_message_split_string (context, tags, host, command, target,
NULL, arguments, suffix, ' ', -1,
max_length);
}
@@ -1254,11 +1496,16 @@ irc_message_split_005 (struct t_hashtable *hashtable,
struct t_hashtable *
irc_message_split (struct t_irc_server *server, const char *message)
{
- struct t_hashtable *hashtable;
+ struct t_irc_message_split_context split_context;
char **argv, **argv_eol, *tags, *host, *command, *arguments, target[4096];
char *pos, monitor_action[3];
int split_ok, argc, index_args, max_length_nick, max_length_user;
int max_length_host, max_length_nick_user_host, split_msg_max_length;
+ int multiline, multiline_max_bytes, multiline_max_lines;
+
+ split_context.hashtable = NULL;
+ split_context.number = 1;
+ split_context.total_bytes = 0;
split_ok = 0;
tags = NULL;
@@ -1267,22 +1514,23 @@ irc_message_split (struct t_irc_server *server, const char *message)
arguments = NULL;
argv = NULL;
argv_eol = NULL;
+ multiline = 0;
if (server)
{
split_msg_max_length = IRC_SERVER_OPTION_INTEGER(
server, IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH);
-
- /*
- * split disabled? use a very high max_length so the message should
- * never be split
- */
+ /* if split disabled, use a high max_length to prevent any split */
if (split_msg_max_length == 0)
split_msg_max_length = INT_MAX - 16;
+ multiline_max_bytes = server->multiline_max_bytes;
+ multiline_max_lines = server->multiline_max_lines;
}
else
{
- split_msg_max_length = 512; /* max length by default */
+ split_msg_max_length = 512;
+ multiline_max_bytes = 0;
+ multiline_max_lines = 0;
}
/* debug message */
@@ -1292,11 +1540,11 @@ irc_message_split (struct t_irc_server *server, const char *message)
message, split_msg_max_length);
}
- hashtable = weechat_hashtable_new (32,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
- NULL, NULL);
- if (!hashtable)
+ split_context.hashtable = weechat_hashtable_new (32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+ if (!split_context.hashtable)
return NULL;
if (!message || !message[0])
@@ -1342,6 +1590,17 @@ irc_message_split (struct t_irc_server *server, const char *message)
index_args = 1;
}
+ multiline = (
+ ((weechat_strcasecmp (command, "privmsg") == 0)
+ || (weechat_strcasecmp (command, "notice") == 0))
+ && message
+ && strchr (message, '\n')
+ && (index_args + 1 <= argc - 1)
+ && (weechat_strncmp (argv[index_args + 1], "\01", 1) != 0)
+ && (weechat_strncmp (argv[index_args + 1], ":\01", 2) != 0)
+ && weechat_hashtable_has_key (server->cap_list, "batch")
+ && weechat_hashtable_has_key (server->cap_list, "draft/multiline"));
+
max_length_nick = (server && (server->nick_max_length > 0)) ?
server->nick_max_length : 16;
max_length_user = (server && (server->user_max_length > 0)) ?
@@ -1361,7 +1620,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
{
/* AUTHENTICATE UzXAmVffxuzFy77XWBGwABBQAgdinelBrKZaR3wE7nsIETuTVY= */
split_ok = irc_message_split_authenticate (
- hashtable, tags, host, command, arguments);
+ &split_context, tags, host, command, arguments);
}
else if ((weechat_strcasecmp (command, "ison") == 0)
|| (weechat_strcasecmp (command, "wallops") == 0))
@@ -1371,7 +1630,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
* WALLOPS :some text here
*/
split_ok = irc_message_split_string (
- hashtable, tags, host, command, NULL, ":",
+ &split_context, tags, host, command, NULL, ":",
(argv_eol[index_args][0] == ':') ?
argv_eol[index_args] + 1 : argv_eol[index_args],
NULL, ' ', max_length_nick_user_host, split_msg_max_length);
@@ -1388,14 +1647,14 @@ irc_message_split (struct t_irc_server *server, const char *message)
snprintf (monitor_action, sizeof (monitor_action),
"%c ", argv_eol[index_args][0]);
split_ok = irc_message_split_string (
- hashtable, tags, host, command, NULL, monitor_action,
+ &split_context, tags, host, command, NULL, monitor_action,
argv_eol[index_args] + 2, NULL, ',', max_length_nick_user_host,
split_msg_max_length);
}
else
{
split_ok = irc_message_split_string (
- hashtable, tags, host, command, NULL, ":",
+ &split_context, tags, host, command, NULL, ":",
(argv_eol[index_args][0] == ':') ?
argv_eol[index_args] + 1 : argv_eol[index_args],
NULL, ',', max_length_nick_user_host, split_msg_max_length);
@@ -1407,7 +1666,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
if ((int)strlen (message) > split_msg_max_length - 2)
{
/* split join if it's too long */
- split_ok = irc_message_split_join (hashtable, tags, host,
+ split_ok = irc_message_split_join (&split_context, tags, host,
arguments, split_msg_max_length);
}
}
@@ -1421,10 +1680,11 @@ irc_message_split (struct t_irc_server *server, const char *message)
if (index_args + 1 <= argc - 1)
{
split_ok = irc_message_split_privmsg_notice (
- hashtable, tags, host, command, argv[index_args],
+ &split_context, tags, host, command, argv[index_args],
(argv_eol[index_args + 1][0] == ':') ?
argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1],
- max_length_nick_user_host, split_msg_max_length);
+ max_length_nick_user_host, split_msg_max_length,
+ multiline, multiline_max_bytes, multiline_max_lines);
}
}
else if (weechat_strcasecmp (command, "005") == 0)
@@ -1433,7 +1693,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
if (index_args + 1 <= argc - 1)
{
split_ok = irc_message_split_005 (
- hashtable, tags, host, command, argv[index_args],
+ &split_context, tags, host, command, argv[index_args],
(argv_eol[index_args + 1][0] == ':') ?
argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1],
split_msg_max_length);
@@ -1452,7 +1712,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
snprintf (target, sizeof (target), "%s %s",
argv[index_args], argv[index_args + 1]);
split_ok = irc_message_split_string (
- hashtable, tags, host, command, target, ":",
+ &split_context, tags, host, command, target, ":",
(argv_eol[index_args + 2][0] == ':') ?
argv_eol[index_args + 2] + 1 : argv_eol[index_args + 2],
NULL, ' ', -1, split_msg_max_length);
@@ -1465,7 +1725,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
argv[index_args], argv[index_args + 1],
argv[index_args + 2]);
split_ok = irc_message_split_string (
- hashtable, tags, host, command, target, ":",
+ &split_context, tags, host, command, target, ":",
(argv_eol[index_args + 3][0] == ':') ?
argv_eol[index_args + 3] + 1 : argv_eol[index_args + 3],
NULL, ' ', -1, split_msg_max_length);
@@ -1476,10 +1736,11 @@ irc_message_split (struct t_irc_server *server, const char *message)
end:
if (!split_ok
- || (weechat_hashtable_get_integer (hashtable, "items_count") == 0))
+ || (weechat_hashtable_get_integer (split_context.hashtable,
+ "items_count") == 0))
{
- irc_message_split_add (hashtable,
- (message) ? 1 : 0,
+ split_context.number = (message) ? 1 : 0;
+ irc_message_split_add (&split_context,
tags,
message,
arguments);
@@ -1492,5 +1753,5 @@ end:
if (argv_eol)
weechat_string_free_split (argv_eol);
- return hashtable;
+ return split_context.hashtable;
}
diff --git a/src/plugins/irc/irc-message.h b/src/plugins/irc/irc-message.h
index 496c7c1f9..6583ff44a 100644
--- a/src/plugins/irc/irc-message.h
+++ b/src/plugins/irc/irc-message.h
@@ -20,6 +20,14 @@
#ifndef WEECHAT_PLUGIN_IRC_MESSAGE_H
#define WEECHAT_PLUGIN_IRC_MESSAGE_H
+struct t_irc_message_split_context
+{
+ struct t_hashtable *hashtable; /* hashtable with msgs/args/count */
+ int number; /* current msg index (starts to 1) */
+ long total_bytes; /* total bytes of messages split */
+ /* (+ 1 byte between each message) */
+};
+
struct t_irc_server;
struct t_irc_channel;
@@ -35,6 +43,9 @@ extern void irc_message_parse (struct t_irc_server *server, const char *message,
int *pos_channel, int *pos_text);
extern struct t_hashtable *irc_message_parse_to_hashtable (struct t_irc_server *server,
const char *message);
+extern struct t_hashtable *irc_message_parse_cap_value (const char *value);
+extern void irc_message_parse_cap_multiline_value (struct t_irc_server *server,
+ const char *value);
extern char *irc_message_convert_charset (const char *message,
int pos_start,
const char *modifier,
diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c
index 3ba8a45c1..d5c59b909 100644
--- a/src/plugins/irc/irc-protocol.c
+++ b/src/plugins/irc/irc-protocol.c
@@ -966,6 +966,11 @@ IRC_PROTOCOL_CALLBACK(cap)
{
weechat_hashtable_set (server->cap_ls,
str_name, pos_value + 1);
+ if (strcmp (str_name, "draft/multiline") == 0)
+ {
+ irc_message_parse_cap_multiline_value (
+ server, pos_value + 1);
+ }
free (str_name);
}
}
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index 50e45f6ea..b99831f6e 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -1681,6 +1681,8 @@ irc_server_alloc (const char *name)
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
+ new_server->multiline_max_bytes = IRC_SERVER_MULTILINE_DEFAULT_MAX_BYTES;
+ new_server->multiline_max_lines = IRC_SERVER_MULTILINE_DEFAULT_MAX_LINES;
new_server->isupport = NULL;
new_server->prefix_modes = NULL;
new_server->prefix_chars = NULL;
@@ -2749,11 +2751,14 @@ irc_server_outqueue_send (struct t_irc_server *server)
{
switch (priority)
{
- case 0:
+ case 0: /* immediate send */
+ anti_flood = 0;
+ break;
+ case 1: /* high priority */
anti_flood = IRC_SERVER_OPTION_INTEGER(
server, IRC_SERVER_OPTION_ANTI_FLOOD_PRIO_HIGH);
break;
- default:
+ default: /* low priority */
anti_flood = IRC_SERVER_OPTION_INTEGER(
server, IRC_SERVER_OPTION_ANTI_FLOOD_PRIO_LOW);
break;
@@ -2950,14 +2955,19 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags,
/* get queue from flags */
queue_msg = 0;
- if (flags & IRC_SERVER_SEND_OUTQ_PRIO_HIGH)
+ if (flags & IRC_SERVER_SEND_OUTQ_PRIO_IMMEDIATE)
queue_msg = 1;
- else if (flags & IRC_SERVER_SEND_OUTQ_PRIO_LOW)
+ else if (flags & IRC_SERVER_SEND_OUTQ_PRIO_HIGH)
queue_msg = 2;
+ else if (flags & IRC_SERVER_SEND_OUTQ_PRIO_LOW)
+ queue_msg = 3;
switch (queue_msg - 1)
{
case 0:
+ anti_flood = 0;
+ break;
+ case 1:
anti_flood = IRC_SERVER_OPTION_INTEGER(
server, IRC_SERVER_OPTION_ANTI_FLOOD_PRIO_HIGH);
break;
@@ -3090,7 +3100,7 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags,
char hash_key[32], *nick, *command, *channel, *new_msg;
char str_modifier[128];
const char *str_message, *str_args, *ptr_msg;
- int number;
+ int number, multiline;
struct t_hashtable *hashtable;
struct t_arraylist *list_messages;
@@ -3163,6 +3173,26 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags,
hashtable = irc_message_split (server, ptr_msg);
if (hashtable)
{
+ multiline = 0;
+ if (weechat_hashtable_has_key (hashtable, "multiline_args1"))
+ {
+ multiline = 1;
+ if (list_messages)
+ {
+ number = 1;
+ while (1)
+ {
+ snprintf (hash_key, sizeof (hash_key),
+ "multiline_args%d", number);
+ str_args = weechat_hashtable_get (hashtable, hash_key);
+ if (!str_args)
+ break;
+ weechat_arraylist_add (list_messages, strdup (str_args));
+ number++;
+ }
+ }
+ flags |= IRC_SERVER_SEND_OUTQ_PRIO_IMMEDIATE;
+ }
number = 1;
while (1)
{
@@ -3173,8 +3203,7 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags,
if (!irc_server_send_one_msg (server, flags, str_message,
nick, command, channel, tags))
break;
-
- if (list_messages)
+ if (!multiline && list_messages)
{
snprintf (hash_key, sizeof (hash_key), "args%d", number);
str_args = weechat_hashtable_get (hashtable, hash_key);
@@ -5620,6 +5649,8 @@ irc_server_disconnect (struct t_irc_server *server, int switch_address,
weechat_hashtable_remove_all (server->cap_ls);
server->checking_cap_list = 0;
weechat_hashtable_remove_all (server->cap_list);
+ server->multiline_max_bytes = IRC_SERVER_MULTILINE_DEFAULT_MAX_BYTES;
+ server->multiline_max_lines = IRC_SERVER_MULTILINE_DEFAULT_MAX_LINES;
server->is_away = 0;
server->away_time = 0;
server->lag = 0;
@@ -6286,6 +6317,8 @@ irc_server_hdata_server_cb (const void *pointer, void *data,
WEECHAT_HDATA_VAR(struct t_irc_server, cap_ls, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, checking_cap_list, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, cap_list, HASHTABLE, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, multiline_max_bytes, INTEGER, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, multiline_max_lines, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, isupport, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, prefix_modes, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, prefix_chars, STRING, 0, NULL, NULL);
@@ -6558,6 +6591,12 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "checking_cap_list", 0))
return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "multiline_max_bytes",
+ IRC_SERVER_MULTILINE_DEFAULT_MAX_BYTES))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "multiline_max_lines",
+ IRC_SERVER_MULTILINE_DEFAULT_MAX_LINES))
+ return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "is_away", 0))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "away_message", NULL))
@@ -6623,6 +6662,10 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_hashtable_add_to_infolist (server->cap_list, ptr_item, "cap_list"))
return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "multiline_max_bytes", server->multiline_max_bytes))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "multiline_max_lines", server->multiline_max_lines))
+ return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "is_away", server->is_away))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "away_message", server->away_message))
@@ -7042,6 +7085,8 @@ irc_server_print_log ()
weechat_log_printf (" cap_list. . . . . . . . . : 0x%lx (hashtable: '%s')",
ptr_server->cap_list,
weechat_hashtable_get_string (ptr_server->cap_list, "keys_values"));
+ weechat_log_printf (" multiline_max_bytes . . . : %d", ptr_server->multiline_max_bytes);
+ weechat_log_printf (" multiline_max_lines . . . : %d", ptr_server->multiline_max_lines);
weechat_log_printf (" isupport. . . . . . . . . : '%s'", ptr_server->isupport);
weechat_log_printf (" prefix_modes. . . . . . . : '%s'", ptr_server->prefix_modes);
weechat_log_printf (" prefix_chars. . . . . . . : '%s'", ptr_server->prefix_chars);
diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h
index f672a5288..2bee2b6d3 100644
--- a/src/plugins/irc/irc-server.h
+++ b/src/plugins/irc/irc-server.h
@@ -126,16 +126,21 @@ enum t_irc_server_option
#define IRC_SERVER_DEFAULT_NICKS "weechat1,weechat2,weechat3,weechat4,weechat5"
/* number of queues for sending messages */
-#define IRC_SERVER_NUM_OUTQUEUES_PRIO 2
+#define IRC_SERVER_NUM_OUTQUEUES_PRIO 3
/* flags for irc_server_sendf() */
-#define IRC_SERVER_SEND_OUTQ_PRIO_HIGH (1 << 0)
-#define IRC_SERVER_SEND_OUTQ_PRIO_LOW (1 << 1)
-#define IRC_SERVER_SEND_RETURN_LIST (1 << 2)
+#define IRC_SERVER_SEND_OUTQ_PRIO_IMMEDIATE (1 << 0)
+#define IRC_SERVER_SEND_OUTQ_PRIO_HIGH (1 << 1)
+#define IRC_SERVER_SEND_OUTQ_PRIO_LOW (1 << 2)
+#define IRC_SERVER_SEND_RETURN_LIST (1 << 3)
/* version strings */
#define IRC_SERVER_VERSION_CAP "302"
+/* multiline default limits */
+#define IRC_SERVER_MULTILINE_DEFAULT_MAX_BYTES 4096
+#define IRC_SERVER_MULTILINE_DEFAULT_MAX_LINES 24
+
/* casemapping (string comparisons for nicks/channels) */
enum t_irc_server_casemapping
{
@@ -232,6 +237,8 @@ struct t_irc_server
struct t_hashtable *cap_ls; /* list of supported capabilities */
int checking_cap_list; /* 1 if checking enabled capabilities */
struct t_hashtable *cap_list; /* list of enabled capabilities */
+ int multiline_max_bytes; /* max bytes for multiline batch */
+ int multiline_max_lines; /* max lines for multiline batch */
char *isupport; /* copy of message 005 (ISUPPORT) */
char *prefix_modes; /* prefix modes from msg 005 (eg "ohv") */
char *prefix_chars; /* prefix chars from msg 005 (eg "@%+") */
@@ -267,9 +274,11 @@ struct t_irc_server
time_t last_user_message; /* time of last user message (anti flood)*/
time_t last_away_check; /* time of last away check on server */
time_t last_data_purge; /* time of last purge (some hashtables) */
- struct t_irc_outqueue *outqueue[2]; /* queue for outgoing messages */
+ struct t_irc_outqueue *outqueue[IRC_SERVER_NUM_OUTQUEUES_PRIO];
+ /* queue for outgoing messages */
/* with 2 priorities (high/low) */
- struct t_irc_outqueue *last_outqueue[2]; /* last outgoing message */
+ struct t_irc_outqueue *last_outqueue[IRC_SERVER_NUM_OUTQUEUES_PRIO];
+ /* last outgoing message */
struct t_irc_redirect *redirects; /* command redirections */
struct t_irc_redirect *last_redirect; /* last command redirection */
struct t_irc_notify *notify_list; /* list of notify */
diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c
index f545dd603..3f7d7838a 100644
--- a/src/plugins/irc/irc.c
+++ b/src/plugins/irc/irc.c
@@ -26,6 +26,7 @@
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-bar-item.h"
+#include "irc-batch.h"
#include "irc-buffer.h"
#include "irc-channel.h"
#include "irc-color.h"
@@ -238,6 +239,8 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
&irc_tag_modifier_cb, NULL, NULL);
weechat_hook_modifier ("irc_tag_unescape_value",
&irc_tag_modifier_cb, NULL, NULL);
+ weechat_hook_modifier ("irc_batch",
+ &irc_batch_modifier_cb, NULL, NULL);
/* hook completions */
irc_completion_init ();