implement message subtype routing

v1
Tony Olagbaiye 6 years ago
parent 346a5fd71d
commit 44915eb1b6

@ -19,6 +19,8 @@ SRCS=slack.c \
slack-workspace.c \
api/slack-api-hello.c \
api/slack-api-error.c \
api/slack-api-message.c \
api/message/slack-api-message-unimplemented.c \
request/slack-request-channels-list.c \
request/slack-request-users-list.c
OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a

@ -0,0 +1,45 @@
#include <json.h>
#include <string.h>
#include "../../weechat-plugin.h"
#include "../../slack.h"
#include "../../slack-workspace.h"
#include "../../slack-api.h"
#include "../../slack-channel.h"
#include "../../slack-user.h"
#include "../slack-api-message.h"
static const char *subtype = "unimplemented";
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
{
if (!object)
{
weechat_printf(
workspace->buffer,
_("%s%s: error handling websocket %smessage.%s%s message: "
"unexpected response from server"),
weechat_prefix("error"), SLACK_PLUGIN_NAME,
weechat_color("chat_value"), subtype, weechat_color("reset"));
return 0;
}
return 1;
}
int slack_api_message_unimplemented(struct t_slack_workspace *workspace,
json_object *message)
{
json_object *subtype = json_object_object_get(message, "subtype");
if (!json_valid(subtype, workspace))
return 0;
weechat_printf(
workspace->buffer,
_("%s%s: got unhandled message of type: message.%s"),
weechat_prefix("error"), SLACK_PLUGIN_NAME,
json_object_get_string(subtype));
return 1;
}

@ -0,0 +1,8 @@
#ifndef _SLACK_API_MESSAGE_UNIMPLEMENTED_H_
#define _SLACK_API_MESSAGE_UNIMPLEMENTED_H_
int slack_api_message_unimplemented(
struct t_slack_workspace *workspace,
json_object *message);
#endif /*SLACK_API_MESSAGE_UNIMPLEMENTED_H*/

@ -0,0 +1,166 @@
#include <json.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "../slack.h"
#include "../slack-workspace.h"
#include "../slack-api.h"
#include "../slack-channel.h"
#include "../slack-user.h"
#include "slack-api-message.h"
#include "message/slack-api-message-unimplemented.h"
static const char *type = "message";
struct stringcase
{
const char *string;
int (*func)(struct t_slack_workspace *workspace,
json_object *message);
};
static struct stringcase cases[] =
{ { "bot_message", &slack_api_message_unimplemented }
, { "channel_archive", &slack_api_message_unimplemented }
, { "channel_join", &slack_api_message_unimplemented }
, { "channel_leave", &slack_api_message_unimplemented }
, { "channel_name", &slack_api_message_unimplemented }
, { "channel_purpose", &slack_api_message_unimplemented }
, { "channel_topic", &slack_api_message_unimplemented }
, { "channel_unarchive", &slack_api_message_unimplemented }
, { "file_comment", &slack_api_message_unimplemented }
, { "file_mention", &slack_api_message_unimplemented }
, { "file_share", &slack_api_message_unimplemented }
, { "group_archive", &slack_api_message_unimplemented }
, { "group_join", &slack_api_message_unimplemented }
, { "group_leave", &slack_api_message_unimplemented }
, { "group_name", &slack_api_message_unimplemented }
, { "group_purpose", &slack_api_message_unimplemented }
, { "group_topic", &slack_api_message_unimplemented }
, { "group_unarchive", &slack_api_message_unimplemented }
, { "me_message", &slack_api_message_unimplemented }
, { "message_changed", &slack_api_message_unimplemented }
, { "message_deleted", &slack_api_message_unimplemented }
, { "message_replied", &slack_api_message_unimplemented }
, { "pinned_item", &slack_api_message_unimplemented }
, { "reply_broadcast", &slack_api_message_unimplemented }
, { "thread_broadcast", &slack_api_message_unimplemented }
, { "unpinned_item", &slack_api_message_unimplemented }
};
static int stringcase_cmp(const void *p1, const void *p2)
{
return strcasecmp(((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string);
}
void slack_api_message_init()
{
size_t case_count = sizeof(cases) / sizeof(cases[0]);
qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp);
}
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_message_message_handle(struct t_slack_workspace *workspace,
const char *channel, const char *user,
const char *text, const char *ts)
{
struct t_slack_channel *ptr_channel;
struct t_slack_user *ptr_user;
(void) ts;
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 */
weechat_printf(
workspace->buffer,
_("%s%s: message [%s]: <%s> %s"),
weechat_prefix("error"), SLACK_PLUGIN_NAME,
ptr_channel->name, ptr_user->profile.display_name, text);
return 1;
}
int slack_api_message_route_message(struct t_slack_workspace *workspace,
const char *subtype,
json_object *message)
{
struct stringcase key;
key.string = type;
size_t case_count = sizeof(cases) / sizeof(cases[0]);
void *entry_ptr = bsearch(&key, cases, case_count,
sizeof(struct stringcase), stringcase_cmp);
if (entry_ptr)
{
struct stringcase *entry = (struct stringcase *)entry_ptr;
return (*entry->func)(workspace, message);
}
else
{
weechat_printf(
workspace->buffer,
_("%s%s: got unhandled message of type: message.%s"),
weechat_prefix("error"), SLACK_PLUGIN_NAME,
subtype);
return 1;
}
}
int slack_api_message(struct t_slack_workspace *workspace,
json_object *message)
{
json_object *subtype, *channel, *user, *text, *ts;
subtype = json_object_object_get(message, "subtype");
if (!subtype)
{ /* normal message */
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;
text = json_object_object_get(message, "text");
if (!json_valid(text, workspace))
return 0;
ts = json_object_object_get(message, "ts");
if (!json_valid(ts, workspace))
return 0;
return slack_api_message_message_handle(workspace,
json_object_get_string(channel),
json_object_get_string(user),
json_object_get_string(text),
json_object_get_string(ts));
}
else
{ /* special message */
return slack_api_message_route_message(workspace,
json_object_get_string(subtype),
message);
}
}

@ -0,0 +1,9 @@
#ifndef _SLACK_API_MESSAGE_H_
#define _SLACK_API_MESSAGE_H_
int slack_api_message(struct t_slack_workspace *workspace,
json_object *message);
void slack_api_message_init();
#endif /*SLACK_API_MESSAGE_H*/

@ -22,7 +22,7 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work
workspace->buffer,
_("%s%s: error retrieving channels: unexpected response from server"),
weechat_prefix("error"), SLACK_PLUGIN_NAME);
__asm__("int3");
//__asm__("int3");
return 0;
}
@ -247,7 +247,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
}
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
request->client_wsi = NULL;
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
/* Does not doing this cause a leak?
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
break;
default:

@ -22,7 +22,7 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work
workspace->buffer,
_("%s%s: error retrieving users: unexpected response from server"),
weechat_prefix("error"), SLACK_PLUGIN_NAME);
__asm__("int3");
//__asm__("int3");
return 0;
}
@ -253,7 +253,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
}
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
request->client_wsi = NULL;
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
/* Does not doing this cause a leak?
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
break;
default:

@ -9,6 +9,7 @@
#include "slack-api.h"
#include "api/slack-api-hello.h"
#include "api/slack-api-error.h"
#include "api/slack-api-message.h"
struct stringcase
{
@ -18,8 +19,9 @@ struct stringcase
};
struct stringcase cases[] =
{ { "hello", slack_api_hello }
, { "error", slack_api_error }
{ { "hello", &slack_api_hello }
, { "error", &slack_api_error }
, { "message", &slack_api_message }
};
static int stringcase_cmp(const void *p1, const void *p2)
@ -80,6 +82,9 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason,
workspace->buffer,
_("%s%s: unexpected data received from websocket: closing"),
weechat_prefix("error"), SLACK_PLUGIN_NAME);
slack_workspace_disconnect(workspace, 0);
json_object_put(response);
free(json_string);
return -1;
@ -88,6 +93,18 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason,
if (!slack_api_route_message(workspace,
json_object_get_string(type), response))
{
weechat_printf(
workspace->buffer,
_("%s%s: error while handling message: %s"),
weechat_prefix("error"), SLACK_PLUGIN_NAME,
json_string);
weechat_printf(
workspace->buffer,
_("%s%s: closing connection."),
weechat_prefix("error"), SLACK_PLUGIN_NAME);
slack_workspace_disconnect(workspace, 0);
json_object_put(response);
free(json_string);
return -1;

@ -87,7 +87,7 @@ int slack_buffer_close_cb(const void *pointer, void *data,
if (!ptr_workspace->disconnected)
{
//slack_command_quit_workspace(ptr_workspace, NULL);
slack_workspace_disconnect(ptr_workspace, 0, 0);
slack_workspace_disconnect(ptr_workspace, 0);
}
ptr_workspace->buffer = NULL;

@ -181,6 +181,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;
char buffer_name[SLACK_CHANNEL_NAME_MAX_LEN + 2];
if (!workspace || !id || !name || !name[0])
return NULL;
@ -191,7 +192,10 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
return ptr_channel;
}
ptr_buffer = slack_channel_create_buffer(workspace, type, name);
buffer_name[0] = '#';
strncpy(&buffer_name[1], name, SLACK_CHANNEL_NAME_MAX_LEN + 1);
ptr_buffer = slack_channel_create_buffer(workspace, type, buffer_name);
if (!ptr_buffer)
return NULL;

@ -1,6 +1,8 @@
#ifndef _SLACK_CHANNEL_H_
#define _SLACK_CHANNEL_H_
#define SLACK_CHANNEL_NAME_MAX_LEN 22
enum t_slack_channel_type
{
SLACK_CHANNEL_TYPE_CHANNEL,

@ -135,7 +135,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
client_wsi = NULL;
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
/* Does not doing this cause a leak?
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
break;
default:

@ -230,7 +230,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
}
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
client_wsi = NULL;
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
/* Does not doing this cause a leak?
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
break;
default:

@ -249,7 +249,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
}
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
workspace->client_wsi = NULL;
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
/* Does not doing this cause a leak?
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
break;
default:
@ -548,9 +549,8 @@ void slack_workspace_free_all()
}
void slack_workspace_disconnect(struct t_slack_workspace *workspace,
int switch_address, int reconnect)
int reconnect)
{
(void) switch_address;
(void) reconnect;
struct t_slack_channel *ptr_channel;
@ -563,9 +563,11 @@ void slack_workspace_disconnect(struct t_slack_workspace *workspace,
* channel/private buffer
*/
slack_user_free_all(workspace);
weechat_nicklist_remove_all(workspace->buffer);
for (ptr_channel = workspace->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
weechat_nicklist_remove_all(ptr_channel->buffer);
weechat_printf(
ptr_channel->buffer,
_("%s%s: disconnected from workspace"),
@ -650,7 +652,7 @@ void slack_workspace_disconnect_all()
for (ptr_workspace = slack_workspaces; ptr_workspace;
ptr_workspace = ptr_workspace->next_workspace)
{
slack_workspace_disconnect(ptr_workspace, 0, 0);
slack_workspace_disconnect(ptr_workspace, 0);
}
}
@ -690,9 +692,44 @@ struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *wor
void slack_workspace_close_connection(struct t_slack_workspace *workspace)
{
struct t_slack_request *ptr_request;
workspace->is_connected = 0;
workspace->client_wsi = NULL;
workspace->context = NULL;
for (ptr_request = workspace->requests; ptr_request;
ptr_request = ptr_request->next_request)
{
if (ptr_request->context)
{
struct t_slack_request *new_requests;
lws_context_destroy(ptr_request->context);
ptr_request->context = NULL;
if (ptr_request->uri)
{
free(ptr_request->uri);
ptr_request->uri = NULL;
}
/* remove request from requests list */
if (workspace->last_request == ptr_request)
workspace->last_request = ptr_request->prev_request;
if (ptr_request->prev_request)
{
(ptr_request->prev_request)->next_request = ptr_request->next_request;
new_requests = workspace->requests;
}
else
new_requests = ptr_request->next_request;
if (ptr_request->next_request)
(ptr_request->next_request)->prev_request = ptr_request->prev_request;
workspace->requests = new_requests;
}
}
}
void slack_workspace_websocket_create(struct t_slack_workspace *workspace)

@ -61,7 +61,7 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace);
void slack_workspace_free(struct t_slack_workspace *workspace);
void slack_workspace_free_all();
void slack_workspace_disconnect(struct t_slack_workspace *workspace,
int switch_address, int reconnect);
int reconnect);
void slack_workspace_disconnect_all();
void slack_workspace_close_connection(struct t_slack_workspace *workspace);
int slack_workspace_connect(struct t_slack_workspace *workspace);

Loading…
Cancel
Save