mirror of
https://github.com/bqv/weechat-xmpp/
synced 2024-11-18 03:25:37 +00:00
typing notifications
This commit is contained in:
parent
22f22a0aee
commit
0c575b9dbc
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
# Prerequisites
|
||||
compile_commands.json
|
||||
cscope*
|
||||
.depend
|
||||
*.d
|
||||
|
11
Makefile
11
Makefile
@ -1,8 +1,10 @@
|
||||
CC=clang
|
||||
CXX=clang++
|
||||
CXX=g++
|
||||
RM=rm -f
|
||||
CFLAGS=-fsanitize=address -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c
|
||||
LDFLAGS=-shared -g -fsanitize=address
|
||||
SANCFLAGS=-fsanitize=address -fsanitize=leak
|
||||
SANLDFLAGS=-static-libasan -static-liblsan
|
||||
CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c
|
||||
LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS)
|
||||
LDLIBS=-lgnutls
|
||||
|
||||
SRCS=slack.c \
|
||||
@ -21,6 +23,7 @@ SRCS=slack.c \
|
||||
api/slack-api-hello.c \
|
||||
api/slack-api-error.c \
|
||||
api/slack-api-message.c \
|
||||
api/slack-api-user-typing.c \
|
||||
api/message/slack-api-message-unimplemented.c \
|
||||
request/slack-request-chat-postmessage.c \
|
||||
request/slack-request-channels-list.c \
|
||||
@ -30,7 +33,7 @@ OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a
|
||||
all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack
|
||||
|
||||
weechat-slack: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS)
|
||||
$(CXX) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS)
|
||||
|
||||
libwebsockets/lib/libwebsockets.a:
|
||||
cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG .
|
||||
|
@ -82,6 +82,7 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace,
|
||||
{
|
||||
struct t_slack_channel *ptr_channel;
|
||||
struct t_slack_user *ptr_user;
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
|
||||
ptr_channel = slack_channel_search(workspace, channel);
|
||||
if (!ptr_channel)
|
||||
@ -100,6 +101,14 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace,
|
||||
message);
|
||||
free(message);
|
||||
|
||||
ptr_typing = slack_channel_typing_search(ptr_channel,
|
||||
ptr_user->profile.display_name);
|
||||
if (ptr_typing)
|
||||
{
|
||||
slack_channel_typing_free(ptr_channel, ptr_typing);
|
||||
slack_channel_typing_cb(ptr_channel, NULL, 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
63
api/slack-api-user-typing.c
Normal file
63
api/slack-api-user-typing.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <json.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../slack-api.h"
|
||||
#include "slack-api-user-typing.h"
|
||||
|
||||
static const char *type = "user_typing";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error handling websocket %s%s%s message: "
|
||||
"unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
weechat_color("chat_value"), type, weechat_color("reset"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slack_api_user_typing_handle(struct t_slack_workspace *workspace,
|
||||
const char *channel, const char *user)
|
||||
{
|
||||
struct t_slack_channel *ptr_channel;
|
||||
struct t_slack_user *ptr_user;
|
||||
|
||||
ptr_channel = slack_channel_search(workspace, channel);
|
||||
if (!ptr_channel)
|
||||
return 1; /* silently ignore if channel hasn't been loaded yet */
|
||||
ptr_user = slack_user_search(workspace, user);
|
||||
if (!ptr_user)
|
||||
return 1; /* silently ignore if user hasn't been loaded yet */
|
||||
|
||||
slack_channel_add_typing(ptr_channel, ptr_user);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slack_api_user_typing(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *channel, *user;
|
||||
|
||||
channel = json_object_object_get(message, "channel");
|
||||
if (!json_valid(channel, workspace))
|
||||
return 0;
|
||||
|
||||
user = json_object_object_get(message, "user");
|
||||
if (!json_valid(user, workspace))
|
||||
return 0;
|
||||
|
||||
return slack_api_user_typing_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(user));
|
||||
}
|
7
api/slack-api-user-typing.h
Normal file
7
api/slack-api-user-typing.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _SLACK_API_USER_TYPING_H_
|
||||
#define _SLACK_API_USER_TYPING_H_
|
||||
|
||||
int slack_api_user_typing(struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_USER_TYPING_H*/
|
@ -245,6 +245,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
/* fallthrough */
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
request->client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
|
@ -165,6 +165,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
/* fallthrough */
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
request->client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
|
@ -251,6 +251,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
/* fallthrough */
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
request->client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
|
50
slack-api.c
50
slack-api.c
@ -10,6 +10,7 @@
|
||||
#include "api/slack-api-hello.h"
|
||||
#include "api/slack-api-error.h"
|
||||
#include "api/slack-api-message.h"
|
||||
#include "api/slack-api-user-typing.h"
|
||||
|
||||
struct stringcase
|
||||
{
|
||||
@ -22,6 +23,7 @@ static struct stringcase cases[] =
|
||||
{ { "hello", &slack_api_hello }
|
||||
, { "error", &slack_api_error }
|
||||
, { "message", &slack_api_message }
|
||||
, { "user_typing", &slack_api_user_typing }
|
||||
};
|
||||
|
||||
static int stringcase_cmp(const void *p1, const void *p2)
|
||||
@ -71,12 +73,53 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason,
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
(const char *)in);
|
||||
{
|
||||
int data_size;
|
||||
char *json_string;
|
||||
json_object *response, *type;
|
||||
struct t_json_chunk *new_chunk, *last_chunk, *chunk_ptr;
|
||||
|
||||
json_string = strdup((const char *)in);
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc(((int)len) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (workspace->json_chunks)
|
||||
{
|
||||
for (last_chunk = workspace->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
workspace->json_chunks = new_chunk;
|
||||
}
|
||||
|
||||
data_size = 0;
|
||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
data_size += strlen(chunk_ptr->data);
|
||||
}
|
||||
|
||||
json_string = malloc(data_size + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
strcat(json_string, chunk_ptr->data);
|
||||
}
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
if (response)
|
||||
{
|
||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr; workspace->json_chunks = chunk_ptr)
|
||||
{
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
free(workspace->json_chunks->data);
|
||||
free(workspace->json_chunks);
|
||||
}
|
||||
|
||||
type = json_object_object_get(response, "type");
|
||||
if (!type)
|
||||
{
|
||||
@ -115,6 +158,11 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason,
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(json_string);
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
@ -42,6 +44,67 @@ void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer,
|
||||
/* no workspace or channel found */
|
||||
}
|
||||
|
||||
char *slack_buffer_typing_bar_cb(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_bar_item *item,
|
||||
struct t_gui_window *window,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_hashtable *extra_info)
|
||||
{
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
struct t_slack_workspace *workspace;
|
||||
struct t_slack_channel *channel;
|
||||
char notification[256];
|
||||
unsigned typecount;
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) item;
|
||||
(void) window;
|
||||
(void) extra_info;
|
||||
|
||||
workspace = NULL;
|
||||
channel = NULL;
|
||||
|
||||
slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel);
|
||||
|
||||
if (!channel)
|
||||
return strdup("");
|
||||
|
||||
typecount = 0;
|
||||
|
||||
for (ptr_typing = channel->typings; ptr_typing;
|
||||
ptr_typing = ptr_typing->next_typing)
|
||||
{
|
||||
switch (++typecount)
|
||||
{
|
||||
case 1:
|
||||
strcpy(notification, ptr_typing->name);
|
||||
break;
|
||||
case 2:
|
||||
strcat(notification, ", ");
|
||||
strcat(notification, ptr_typing->name);
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
strcpy(notification, "Several people");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typecount)
|
||||
{
|
||||
strcat(notification, NG_(" is typing...",
|
||||
" are typing...",
|
||||
typecount));
|
||||
return strdup(notification);
|
||||
}
|
||||
else
|
||||
{
|
||||
return strdup("");
|
||||
}
|
||||
}
|
||||
|
||||
int slack_buffer_nickcmp_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *nick1,
|
||||
|
@ -5,6 +5,13 @@ void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer,
|
||||
struct t_slack_workspace **workspace,
|
||||
struct t_slack_channel **channel);
|
||||
|
||||
char *slack_buffer_typing_bar_cb(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_bar_item *item,
|
||||
struct t_gui_window *window,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_hashtable *extra_info);
|
||||
|
||||
int slack_buffer_nickcmp_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *nick1,
|
||||
|
153
slack-channel.c
153
slack-channel.c
@ -1,10 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-user.h"
|
||||
#include "slack-channel.h"
|
||||
#include "slack-input.h"
|
||||
#include "slack-buffer.h"
|
||||
@ -73,7 +75,7 @@ struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *works
|
||||
const char *name)
|
||||
{
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
int buffer_created, current_buffer_number;
|
||||
int buffer_created;
|
||||
const char *short_name, *localvar_channel;
|
||||
char buffer_name[256];
|
||||
|
||||
@ -89,9 +91,6 @@ struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *works
|
||||
}
|
||||
else
|
||||
{
|
||||
current_buffer_number = weechat_buffer_get_integer(
|
||||
weechat_current_buffer(), "number");
|
||||
|
||||
ptr_buffer = weechat_buffer_new(buffer_name,
|
||||
&slack_input_data_cb, NULL, NULL,
|
||||
&slack_buffer_close_cb, NULL, NULL);
|
||||
@ -181,6 +180,7 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
|
||||
{
|
||||
struct t_slack_channel *new_channel, *ptr_channel;
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
struct t_hook *typing_timer;
|
||||
char buffer_name[SLACK_CHANNEL_NAME_MAX_LEN + 2];
|
||||
|
||||
if (!workspace || !id || !name || !name[0])
|
||||
@ -202,6 +202,10 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
|
||||
if ((new_channel = malloc(sizeof(*new_channel))) == NULL)
|
||||
return NULL;
|
||||
|
||||
typing_timer = weechat_hook_timer(1 * 1000, 0, 0,
|
||||
&slack_channel_typing_cb,
|
||||
new_channel, NULL);
|
||||
|
||||
new_channel->type = type;
|
||||
new_channel->id = strdup(id);
|
||||
new_channel->name = strdup(name);
|
||||
@ -228,6 +232,9 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
|
||||
|
||||
new_channel->is_user_deleted = 0;
|
||||
|
||||
new_channel->typing_hook_timer = typing_timer;
|
||||
new_channel->typings = NULL;
|
||||
new_channel->last_typing = NULL;
|
||||
new_channel->members = NULL;
|
||||
new_channel->last_member = NULL;
|
||||
new_channel->buffer = ptr_buffer;
|
||||
@ -244,6 +251,137 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
|
||||
return new_channel;
|
||||
}
|
||||
|
||||
void slack_channel_typing_free(struct t_slack_channel *channel,
|
||||
struct t_slack_channel_typing *typing)
|
||||
{
|
||||
struct t_slack_channel_typing *new_typings;
|
||||
|
||||
if (!channel || !typing)
|
||||
return;
|
||||
|
||||
/* remove typing from typings list */
|
||||
if (channel->last_typing == typing)
|
||||
channel->last_typing = typing->prev_typing;
|
||||
if (typing->prev_typing)
|
||||
{
|
||||
(typing->prev_typing)->next_typing = typing->next_typing;
|
||||
new_typings = channel->typings;
|
||||
}
|
||||
else
|
||||
new_typings = typing->next_typing;
|
||||
|
||||
if (typing->next_typing)
|
||||
(typing->next_typing)->prev_typing = typing->prev_typing;
|
||||
|
||||
/* free typing data */
|
||||
if (typing->id)
|
||||
free(typing->id);
|
||||
if (typing->name)
|
||||
free(typing->name);
|
||||
|
||||
free(typing);
|
||||
|
||||
channel->typings = new_typings;
|
||||
}
|
||||
|
||||
void slack_channel_typing_free_all(struct t_slack_channel *channel)
|
||||
{
|
||||
while (channel->typings)
|
||||
slack_channel_typing_free(channel, channel->typings);
|
||||
}
|
||||
|
||||
int slack_channel_typing_cb(const void *pointer,
|
||||
void *data,
|
||||
int remaining_calls)
|
||||
{
|
||||
struct t_slack_channel_typing *ptr_typing, *next_typing;
|
||||
struct t_slack_channel *channel;
|
||||
unsigned typecount;
|
||||
time_t now;
|
||||
|
||||
(void) data;
|
||||
(void) remaining_calls;
|
||||
|
||||
if (!pointer)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
channel = (struct t_slack_channel *)pointer;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
typecount = 0;
|
||||
|
||||
for (ptr_typing = channel->typings; ptr_typing;
|
||||
ptr_typing = ptr_typing->next_typing)
|
||||
{
|
||||
next_typing = ptr_typing->next_typing;
|
||||
|
||||
while (ptr_typing && now - ptr_typing->ts > 5)
|
||||
{
|
||||
slack_channel_typing_free(channel, ptr_typing);
|
||||
ptr_typing = next_typing;
|
||||
if (ptr_typing)
|
||||
next_typing = ptr_typing->next_typing;
|
||||
}
|
||||
|
||||
if (!ptr_typing)
|
||||
break;
|
||||
|
||||
typecount++;
|
||||
}
|
||||
|
||||
weechat_buffer_set(channel->buffer,
|
||||
"localvar_set_typing",
|
||||
typecount > 0 ? "1" : "0");
|
||||
weechat_bar_item_update("slack_typing");
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
struct t_slack_channel_typing *slack_channel_typing_search(
|
||||
struct t_slack_channel *channel,
|
||||
const char *id)
|
||||
{
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
|
||||
if (!channel || !id)
|
||||
return NULL;
|
||||
|
||||
for (ptr_typing = channel->typings; ptr_typing;
|
||||
ptr_typing = ptr_typing->next_typing)
|
||||
{
|
||||
if (weechat_strcasecmp(ptr_typing->id, id) == 0)
|
||||
return ptr_typing;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void slack_channel_add_typing(struct t_slack_channel *channel,
|
||||
struct t_slack_user *user)
|
||||
{
|
||||
struct t_slack_channel_typing *new_typing;
|
||||
|
||||
new_typing = slack_channel_typing_search(channel, user->id);
|
||||
if (!new_typing)
|
||||
{
|
||||
new_typing = malloc(sizeof(*new_typing));
|
||||
new_typing->id = strdup(user->id);
|
||||
new_typing->name = strdup(user->profile.display_name);
|
||||
|
||||
new_typing->prev_typing = channel->last_typing;
|
||||
new_typing->next_typing = NULL;
|
||||
if (channel->last_typing)
|
||||
(channel->last_typing)->next_typing = new_typing;
|
||||
else
|
||||
channel->typings = new_typing;
|
||||
channel->last_typing = new_typing;
|
||||
}
|
||||
new_typing->ts = time(NULL);
|
||||
|
||||
slack_channel_typing_cb(channel, NULL, 0);
|
||||
}
|
||||
|
||||
void slack_channel_member_free(struct t_slack_channel *channel,
|
||||
struct t_slack_channel_member *member)
|
||||
{
|
||||
@ -303,7 +441,12 @@ void slack_channel_free(struct t_slack_workspace *workspace,
|
||||
if (channel->next_channel)
|
||||
(channel->next_channel)->prev_channel = channel->prev_channel;
|
||||
|
||||
/* free hooks */
|
||||
if (channel->typing_hook_timer)
|
||||
weechat_unhook(channel->typing_hook_timer);
|
||||
|
||||
/* free linked lists */
|
||||
slack_channel_typing_free_all(channel);
|
||||
slack_channel_member_free_all(channel);
|
||||
|
||||
/* free channel data */
|
||||
@ -324,7 +467,7 @@ void slack_channel_free(struct t_slack_workspace *workspace,
|
||||
if (channel->creator)
|
||||
free(channel->creator);
|
||||
if (channel->buffer_as_string)
|
||||
free (channel->buffer_as_string);
|
||||
free(channel->buffer_as_string);
|
||||
|
||||
free(channel);
|
||||
|
||||
|
@ -11,6 +11,16 @@ enum t_slack_channel_type
|
||||
SLACK_CHANNEL_TYPE_IM,
|
||||
};
|
||||
|
||||
struct t_slack_channel_typing
|
||||
{
|
||||
char *id;
|
||||
char *name;
|
||||
time_t ts;
|
||||
|
||||
struct t_slack_channel_typing *prev_typing;
|
||||
struct t_slack_channel_typing *next_typing;
|
||||
};
|
||||
|
||||
struct t_slack_channel_member
|
||||
{
|
||||
char *id;
|
||||
@ -61,6 +71,9 @@ struct t_slack_channel
|
||||
/* im */
|
||||
int is_user_deleted;
|
||||
|
||||
struct t_hook *typing_hook_timer;
|
||||
struct t_slack_channel_typing *typings;
|
||||
struct t_slack_channel_typing *last_typing;
|
||||
struct t_slack_channel_member *members;
|
||||
struct t_slack_channel_member *last_member;
|
||||
struct t_gui_buffer *buffer;
|
||||
@ -80,6 +93,22 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
|
||||
enum t_slack_channel_type type,
|
||||
const char *id, const char *name);
|
||||
|
||||
void slack_channel_typing_free(struct t_slack_channel *channel,
|
||||
struct t_slack_channel_typing *typing);
|
||||
|
||||
void slack_channel_typing_free_all(struct t_slack_channel *channel);
|
||||
|
||||
int slack_channel_typing_cb(const void *pointer,
|
||||
void *data,
|
||||
int remaining_calls);
|
||||
|
||||
struct t_slack_channel_typing *slack_channel_typing_search(
|
||||
struct t_slack_channel *channel,
|
||||
const char *id);
|
||||
|
||||
void slack_channel_add_typing(struct t_slack_channel *channel,
|
||||
struct t_slack_user *user);
|
||||
|
||||
void slack_channel_free_all(struct t_slack_workspace *workspace);
|
||||
|
||||
#endif /*SLACK_CHANNEL_H*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
@ -9,7 +10,7 @@
|
||||
#include "../slack-user.h"
|
||||
#include "../slack-message.h"
|
||||
|
||||
static const char format_regex[] = "<(.*?)>";
|
||||
static const char format_regex[] = "<([^>]*?)>";
|
||||
static const size_t max_groups = 2;
|
||||
|
||||
char *slack_message_translate_code(struct t_slack_workspace *workspace,
|
||||
@ -30,7 +31,12 @@ char *slack_message_translate_code(struct t_slack_workspace *workspace,
|
||||
case '@': /* user */
|
||||
user = slack_user_search(workspace, code+1);
|
||||
if (user)
|
||||
return strdup(user->profile.display_name);
|
||||
{
|
||||
size_t nicklen = snprintf(NULL, 0, "%s@%s%s", weechat_color("chat_nick"), user->profile.display_name, weechat_color("reset")) + 1;
|
||||
char *tag = malloc(nicklen);
|
||||
snprintf(tag, nicklen, "%s@%s%s", weechat_color("chat_nick"), user->profile.display_name, weechat_color("reset"));
|
||||
return tag;
|
||||
}
|
||||
else
|
||||
return strdup(code);
|
||||
case '!': /* special */
|
||||
@ -49,7 +55,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
regex_t reg;
|
||||
regmatch_t groups[max_groups];
|
||||
char msgbuf[100];
|
||||
char *decoded_text, *pos;
|
||||
char *decoded_text;
|
||||
const char *cursor;
|
||||
size_t offset;
|
||||
|
||||
@ -74,8 +80,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return strdup(text);
|
||||
}
|
||||
pos = decoded_text;
|
||||
pos[0] = '\0';
|
||||
decoded_text[0] = '\0';
|
||||
|
||||
for (cursor = text; regexec(®, cursor, max_groups, groups, 0) == 0; cursor += offset)
|
||||
{
|
||||
@ -85,6 +90,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
if (!copy)
|
||||
{
|
||||
regfree(®);
|
||||
free(decoded_text);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
@ -98,6 +104,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
{
|
||||
free(copy);
|
||||
regfree(®);
|
||||
free(decoded_text);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
@ -112,6 +119,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
free(match);
|
||||
free(copy);
|
||||
regfree(®);
|
||||
free(decoded_text);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
@ -120,18 +128,18 @@ char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
}
|
||||
free(copy);
|
||||
|
||||
pos = strncat(decoded_text, prematch,
|
||||
strncat(decoded_text, prematch,
|
||||
SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1);
|
||||
free(prematch);
|
||||
|
||||
char *replacement = slack_message_translate_code(workspace, match);
|
||||
free(match);
|
||||
|
||||
pos = strncat(decoded_text, replacement,
|
||||
strncat(decoded_text, replacement,
|
||||
SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1);
|
||||
free(replacement);
|
||||
}
|
||||
pos = strncat(decoded_text, cursor,
|
||||
strncat(decoded_text, cursor,
|
||||
SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1);
|
||||
|
||||
regfree(®);
|
||||
|
@ -228,6 +228,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
/* fallthrough */
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
|
@ -247,6 +247,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
/* fallthrough */
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
workspace->client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
|
@ -6,7 +6,7 @@ extern struct t_slack_workspace *last_slack_workspace;
|
||||
|
||||
enum t_slack_workspace_option
|
||||
{
|
||||
SLACK_WORKSPACE_OPTION_TOKEN = 0,
|
||||
SLACK_WORKSPACE_OPTION_TOKEN,
|
||||
SLACK_WORKSPACE_NUM_OPTIONS,
|
||||
};
|
||||
|
||||
|
18
slack.c
18
slack.c
@ -10,6 +10,7 @@
|
||||
#include "slack-command.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-api.h"
|
||||
#include "slack-buffer.h"
|
||||
|
||||
|
||||
WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME);
|
||||
@ -23,6 +24,8 @@ struct t_weechat_plugin *weechat_slack_plugin = NULL;
|
||||
|
||||
struct t_hook *slack_hook_timer = NULL;
|
||||
|
||||
struct t_gui_bar_item *slack_typing_bar_item = NULL;
|
||||
|
||||
void slack_lwsl_emit_weechat(int level, const char *line)
|
||||
{
|
||||
char buf[50];
|
||||
@ -60,6 +63,18 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[])
|
||||
&slack_workspace_timer_cb,
|
||||
NULL, NULL);
|
||||
|
||||
if (!weechat_bar_search("typing"))
|
||||
{
|
||||
weechat_bar_new("typing", "off", "400", "window", "${typing}",
|
||||
"bottom", "horizontal", "vertical",
|
||||
"1", "1", "default", "default", "default",
|
||||
"off", "slack_typing");
|
||||
}
|
||||
|
||||
slack_typing_bar_item = weechat_bar_item_new("slack_typing",
|
||||
&slack_buffer_typing_bar_cb,
|
||||
NULL, NULL);
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
@ -68,6 +83,9 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin)
|
||||
/* make C compiler happy */
|
||||
(void) plugin;
|
||||
|
||||
if (slack_typing_bar_item)
|
||||
weechat_bar_item_remove(slack_typing_bar_item);
|
||||
|
||||
if (slack_hook_timer)
|
||||
weechat_unhook(slack_hook_timer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user