mirror of https://github.com/bqv/weechat-xmpp
cleanup
parent
ae0ada316e
commit
a97d77f332
@ -1,155 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../weechat-plugin.h"
|
||||
#include "../../slack.h"
|
||||
#include "../../slack-workspace.h"
|
||||
#include "../../slack-message.h"
|
||||
#include "../../slack-api.h"
|
||||
#include "../../slack-channel.h"
|
||||
#include "../../slack-user.h"
|
||||
#include "../slack-api-message.h"
|
||||
#include "slack-api-message-bot-message.h"
|
||||
|
||||
static const char *subtype = "bot_message";
|
||||
|
||||
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_bot_message_handle(struct t_slack_workspace *workspace,
|
||||
const char *channel, const char *bot_id,
|
||||
const char *username, const char *text,
|
||||
const char *ts)
|
||||
{
|
||||
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)
|
||||
return 1; /* silently ignore if channel hasn't been loaded yet */
|
||||
ptr_user = slack_user_bot_search(workspace, bot_id);
|
||||
if (!ptr_user)
|
||||
return 1; /* silently ignore if bot user hasn't been loaded yet */
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message,slack_bot_message",
|
||||
_("%s%s"),
|
||||
slack_user_as_prefix(workspace, ptr_user, username),
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_slackbot_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;
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
|
||||
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 slackbot user hasn't been loaded yet */
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message,slack_slackbot_message",
|
||||
_("%s%s"),
|
||||
slack_user_as_prefix(workspace, ptr_user, user),
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_bot_message(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *channel, *bot_id, *username, *user, *text, *ts;
|
||||
channel = json_object_object_get(message, "channel");
|
||||
if (!json_valid(channel, workspace))
|
||||
return 0;
|
||||
|
||||
username = json_object_object_get(message, "username");
|
||||
if (!json_valid(username, 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;
|
||||
|
||||
if (strcmp("slackbot", json_object_get_string(username)) == 0)
|
||||
{
|
||||
user = json_object_object_get(message, "user");
|
||||
if (!json_valid(user, workspace))
|
||||
return 0;
|
||||
|
||||
return slack_api_message_slackbot_message_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(user),
|
||||
json_object_get_string(text),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
else
|
||||
{
|
||||
bot_id = json_object_object_get(message, "bot_id");
|
||||
if (!json_valid(bot_id, workspace))
|
||||
return 0;
|
||||
|
||||
return slack_api_message_bot_message_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(bot_id),
|
||||
json_object_get_string(username),
|
||||
json_object_get_string(text),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_MESSAGE_BOT_MESSAGE_H_
|
||||
#define _SLACK_API_MESSAGE_BOT_MESSAGE_H_
|
||||
|
||||
int slack_api_message_bot_message(
|
||||
struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_MESSAGE_BOT_MESSAGE_H*/
|
@ -1,102 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../weechat-plugin.h"
|
||||
#include "../../slack.h"
|
||||
#include "../../slack-workspace.h"
|
||||
#include "../../slack-message.h"
|
||||
#include "../../slack-api.h"
|
||||
#include "../../slack-channel.h"
|
||||
#include "../../slack-user.h"
|
||||
#include "../slack-api-message.h"
|
||||
#include "slack-api-message-me-message.h"
|
||||
|
||||
static const char *subtype = "me_message";
|
||||
|
||||
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_me_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;
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
|
||||
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 */
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message,slack_me_message",
|
||||
_("%s%s%s%s%s%s"),
|
||||
weechat_prefix("action"),
|
||||
slack_user_get_colour(ptr_user),
|
||||
ptr_user->profile.display_name,
|
||||
weechat_color("reset"),
|
||||
message[0] ? " " : "",
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_me_message(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *channel, *user, *text, *ts;
|
||||
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_me_message_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(user),
|
||||
json_object_get_string(text),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_MESSAGE_ME_MESSAGE_H_
|
||||
#define _SLACK_API_MESSAGE_ME_MESSAGE_H_
|
||||
|
||||
int slack_api_message_me_message(
|
||||
struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_MESSAGE_ME_MESSAGE_H*/
|
@ -1,104 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../weechat-plugin.h"
|
||||
#include "../../slack.h"
|
||||
#include "../../slack-workspace.h"
|
||||
#include "../../slack-message.h"
|
||||
#include "../../slack-api.h"
|
||||
#include "../../slack-channel.h"
|
||||
#include "../../slack-user.h"
|
||||
#include "../slack-api-message.h"
|
||||
#include "slack-api-message-message-changed.h"
|
||||
|
||||
static const char *subtype = "message_changed";
|
||||
|
||||
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_message_changed_handle(struct t_slack_workspace *workspace,
|
||||
json_object *root, const char *user,
|
||||
const char *text, const char *ts)
|
||||
{
|
||||
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)
|
||||
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
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message,slack_thread_broadcast",
|
||||
_("%s%s"),
|
||||
slack_user_as_prefix(workspace, ptr_user, NULL),
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_message_changed(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *channel, *oldmsg, *user, *text, *ts;
|
||||
channel = json_object_object_get(message, "channel");
|
||||
if (!json_valid(channel, workspace))
|
||||
return 0;
|
||||
|
||||
oldmsg = json_object_object_get(message, "message");
|
||||
if (!json_valid(oldmsg, workspace))
|
||||
return 0;
|
||||
|
||||
user = json_object_object_get(oldmsg, "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_changed_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(user),
|
||||
json_object_get_string(text),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_MESSAGE_MESSAGE_CHANGED_H_
|
||||
#define _SLACK_API_MESSAGE_MESSAGE_CHANGED_H_
|
||||
|
||||
int slack_api_message_message_changed(
|
||||
struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_MESSAGE_MESSAGE_CHANGED_H*/
|
@ -1,98 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../weechat-plugin.h"
|
||||
#include "../../slack.h"
|
||||
#include "../../slack-workspace.h"
|
||||
#include "../../slack-message.h"
|
||||
#include "../../slack-api.h"
|
||||
#include "../../slack-channel.h"
|
||||
#include "../../slack-user.h"
|
||||
#include "../slack-api-message.h"
|
||||
#include "slack-api-message-slackbot-response.h"
|
||||
|
||||
static const char *subtype = "slackbot_response";
|
||||
|
||||
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_slackbot_response_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;
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
|
||||
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 slackbot user hasn't been loaded yet */
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message,slack_slackbot_response",
|
||||
_("%s%s"),
|
||||
slack_user_as_prefix(workspace, ptr_user, "slackbot"),
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_slackbot_response(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *channel, *user, *text, *ts;
|
||||
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_slackbot_response_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(user),
|
||||
json_object_get_string(text),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_
|
||||
#define _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_
|
||||
|
||||
int slack_api_message_slackbot_response(
|
||||
struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H*/
|
@ -1,99 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../weechat-plugin.h"
|
||||
#include "../../slack.h"
|
||||
#include "../../slack-workspace.h"
|
||||
#include "../../slack-message.h"
|
||||
#include "../../slack-api.h"
|
||||
#include "../../slack-channel.h"
|
||||
#include "../../slack-user.h"
|
||||
#include "../slack-api-message.h"
|
||||
#include "slack-api-message-thread-broadcast.h"
|
||||
|
||||
static const char *subtype = "thread_broadcast";
|
||||
|
||||
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_thread_broadcast_handle(struct t_slack_workspace *workspace,
|
||||
json_object *root, const char *user,
|
||||
const char *text, const char *ts)
|
||||
{
|
||||
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)
|
||||
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
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message,slack_thread_broadcast",
|
||||
_("%s%s"),
|
||||
slack_user_as_prefix(workspace, ptr_user, NULL),
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_thread_broadcast(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *root, *user, *text, *ts;
|
||||
root = json_object_object_get(message, "root");
|
||||
if (!json_valid(root, 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_thread_broadcast_handle(workspace,
|
||||
root, json_object_get_string(user),
|
||||
json_object_get_string(text),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_MESSAGE_THREAD_BROADCAST_H_
|
||||
#define _SLACK_API_MESSAGE_THREAD_BROADCAST_H_
|
||||
|
||||
int slack_api_message_thread_broadcast(
|
||||
struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_MESSAGE_THREAD_BROADCAST_H*/
|
@ -1,50 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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 "slack-api-message-unimplemented.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;
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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*/
|
@ -1,63 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-api.h"
|
||||
#include "slack-api-error.h"
|
||||
|
||||
static const char *type = "error";
|
||||
|
||||
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_error_handle(struct t_slack_workspace *workspace,
|
||||
int code, const char *msg)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error %d: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
code, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int slack_api_error(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
json_object *error, *code, *msg;
|
||||
|
||||
error = json_object_object_get(message, "error");
|
||||
if (!json_valid(error, workspace))
|
||||
return 0;
|
||||
|
||||
code = json_object_object_get(error, "code");
|
||||
if (!json_valid(code, workspace))
|
||||
return 0;
|
||||
|
||||
msg = json_object_object_get(error, "msg");
|
||||
if (!json_valid(msg, workspace))
|
||||
return 0;
|
||||
|
||||
return slack_api_error_handle(workspace,
|
||||
json_object_get_int(code),
|
||||
json_object_get_string(msg));
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_ERROR_H_
|
||||
#define _SLACK_API_ERROR_H_
|
||||
|
||||
int slack_api_error(struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_ERROR_H*/
|
@ -1,54 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <json.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-api.h"
|
||||
#include "slack-api-hello.h"
|
||||
#include "../request/slack-request-channels-list.h"
|
||||
#include "../request/slack-request-users-list.h"
|
||||
#include "../request/slack-request-emoji-list.h"
|
||||
|
||||
int slack_api_hello_handle(struct t_slack_workspace *workspace)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: connected!"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
||||
|
||||
request = slack_request_users_list(workspace,
|
||||
weechat_config_string(
|
||||
workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
"");
|
||||
if (request)
|
||||
slack_workspace_register_request(workspace, request);
|
||||
|
||||
request = slack_request_channels_list(workspace,
|
||||
weechat_config_string(
|
||||
workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
"");
|
||||
if (request)
|
||||
slack_workspace_register_request(workspace, request);
|
||||
|
||||
request = slack_request_emoji_list(workspace,
|
||||
weechat_config_string(
|
||||
workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]));
|
||||
if (request)
|
||||
slack_workspace_register_request(workspace, request);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slack_api_hello(struct t_slack_workspace *workspace,
|
||||
json_object *message)
|
||||
{
|
||||
(void) message;
|
||||
|
||||
return slack_api_hello_handle(workspace);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_API_HELLO_H_
|
||||
#define _SLACK_API_HELLO_H_
|
||||
|
||||
int slack_api_hello(struct t_slack_workspace *workspace,
|
||||
json_object *message);
|
||||
|
||||
#endif /*SLACK_API_HELLO_H*/
|
@ -1,240 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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-message.h"
|
||||
#include "slack-api-message.h"
|
||||
#include "message/slack-api-message-unimplemented.h"
|
||||
#include "message/slack-api-message-bot-message.h"
|
||||
#include "message/slack-api-message-me-message.h"
|
||||
#include "message/slack-api-message-slackbot-response.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_bot_message }
|
||||
, { "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_me_message }
|
||||
, { "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 }
|
||||
, { "slackbot_response", &slack_api_message_slackbot_response }
|
||||
, { "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;
|
||||
struct t_slack_channel_typing *ptr_typing;
|
||||
|
||||
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 */
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message",
|
||||
_("%s%s"),
|
||||
slack_user_as_prefix(workspace, ptr_user, NULL),
|
||||
message);
|
||||
slack_channel_member_speaking_add(ptr_channel, ptr_user->profile.display_name,
|
||||
weechat_string_has_highlight(
|
||||
message,
|
||||
ptr_user->profile.display_name));
|
||||
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;
|
||||
}
|
||||
|
||||
int slack_api_message_attachment_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;
|
||||
|
||||
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 */
|
||||
|
||||
char *message = slack_message_decode(workspace, text);
|
||||
weechat_printf_date_tags(
|
||||
ptr_channel->buffer,
|
||||
(time_t)atof(ts),
|
||||
"slack_message",
|
||||
_("%s%s"),
|
||||
"++\t",
|
||||
message);
|
||||
free(message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slack_api_message_route_message(struct t_slack_workspace *workspace,
|
||||
const char *subtype,
|
||||
json_object *message)
|
||||
{
|
||||
struct stringcase key;
|
||||
key.string = subtype;
|
||||
|
||||
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;
|
||||
json_object *attachments, *attachment, *fallback;
|
||||
int i, rc;
|
||||
|
||||
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;
|
||||
|
||||
rc = 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));
|
||||
attachments = json_object_object_get(message, "attachments");
|
||||
if (json_valid(attachments, workspace))
|
||||
{
|
||||
for (i = json_object_array_length(attachments); i > 0; i--)
|
||||
{
|
||||
attachment = json_object_array_get_idx(attachments, i - 1);
|
||||
if (!json_valid(attachment, workspace))
|
||||
continue;
|
||||
|
||||
fallback = json_object_object_get(attachment, "fallback");
|
||||
if (!json_valid(fallback, workspace))
|
||||
continue;
|
||||
|
||||
slack_api_message_attachment_handle(workspace,
|
||||
json_object_get_string(channel),
|
||||
json_object_get_string(user),
|
||||
json_object_get_string(fallback),
|
||||
json_object_get_string(ts));
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{ /* special message */
|
||||
return slack_api_message_route_message(workspace,
|
||||
json_object_get_string(subtype),
|
||||
message);
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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*/
|
@ -1,67 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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));
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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*/
|
@ -1,272 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../request/slack-request-bots-info.h"
|
||||
|
||||
static const char *const endpoint = "/api/bots.info?"
|
||||
"token=%s&bot=%s";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error retrieving bot info: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) retrieving bot info... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
char cursor[64];
|
||||
json_object *response, *ok, *error, *members, *metadata;
|
||||
json_object *user, *id, *name, *profile, *display_name, *next_cursor;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
// TODO: this
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to retrieve users: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_bots_info(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *cursor)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token, cursor);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_BOTS_INFO_H_
|
||||
#define _SLACK_REQUEST_BOTS_INFO_H_
|
||||
|
||||
struct t_slack_request *slack_request_bots_info(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *cursor);
|
||||
|
||||
#endif /*SLACK_REQUEST_BOTS_INFO_H*/
|
@ -1,431 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../request/slack-request-channels-list.h"
|
||||
|
||||
static const char *const endpoint = "/api/channels.list?"
|
||||
"token=%s&cursor=%s&"
|
||||
"exclude_archived=false&exclude_members=true&limit=20";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error retrieving channels: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) retrieving channels... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
char cursor[64];
|
||||
json_object *response, *ok, *error, *channels, *metadata;
|
||||
json_object *channel, *id, *name, *created;
|
||||
json_object *is_general, *name_normalized, *is_shared, *is_org_shared, *is_member;
|
||||
json_object *topic, *purpose, *is_archived;
|
||||
json_object *sub_value, *sub_creator, *sub_last_set;
|
||||
json_object *creator, *next_cursor;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
channels = json_object_object_get(response, "channels");
|
||||
if (!json_valid(channels, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = json_object_array_length(channels); i > 0; i--)
|
||||
{
|
||||
struct t_slack_channel *new_channel;
|
||||
|
||||
channel = json_object_array_get_idx(channels, i - 1);
|
||||
if (!json_valid(channel, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
id = json_object_object_get(channel, "id");
|
||||
if (!json_valid(id, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
name = json_object_object_get(channel, "name");
|
||||
if (!json_valid(name, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
new_channel = slack_channel_new(
|
||||
request->workspace,
|
||||
SLACK_CHANNEL_TYPE_CHANNEL,
|
||||
json_object_get_string(id),
|
||||
json_object_get_string(name));
|
||||
|
||||
created = json_object_object_get(channel, "created");
|
||||
if (json_valid(created, request->workspace))
|
||||
{
|
||||
new_channel->created = json_object_get_int(created);
|
||||
}
|
||||
|
||||
is_general = json_object_object_get(channel, "is_general");
|
||||
if (json_valid(is_general, request->workspace))
|
||||
{
|
||||
new_channel->is_general = json_object_get_boolean(is_general);
|
||||
}
|
||||
|
||||
name_normalized = json_object_object_get(channel, "name_normalized");
|
||||
if (json_valid(name_normalized, request->workspace))
|
||||
{
|
||||
new_channel->name_normalized = strdup(
|
||||
json_object_get_string(name_normalized));
|
||||
}
|
||||
|
||||
is_shared = json_object_object_get(channel, "is_shared");
|
||||
if (json_valid(is_shared, request->workspace))
|
||||
{
|
||||
new_channel->is_shared = json_object_get_boolean(is_shared);
|
||||
}
|
||||
|
||||
is_org_shared = json_object_object_get(channel, "is_org_shared");
|
||||
if (json_valid(is_org_shared, request->workspace))
|
||||
{
|
||||
new_channel->is_org_shared = json_object_get_boolean(is_org_shared);
|
||||
}
|
||||
|
||||
is_member = json_object_object_get(channel, "is_member");
|
||||
if (json_valid(is_member, request->workspace))
|
||||
{
|
||||
new_channel->is_member = json_object_get_boolean(is_member);
|
||||
}
|
||||
|
||||
topic = json_object_object_get(channel, "topic");
|
||||
if (json_valid(topic, request->workspace))
|
||||
{
|
||||
sub_value = json_object_object_get(topic, "value");
|
||||
|
||||
sub_creator = json_object_object_get(topic, "creator");
|
||||
|
||||
sub_last_set = json_object_object_get(topic, "last_set");
|
||||
|
||||
slack_channel_update_topic(new_channel,
|
||||
json_valid(sub_value, request->workspace) ?
|
||||
json_object_get_string(sub_value) :
|
||||
NULL,
|
||||
json_valid(sub_creator, request->workspace) ?
|
||||
json_object_get_string(sub_creator) :
|
||||
NULL,
|
||||
json_valid(sub_last_set, request->workspace) ?
|
||||
json_object_get_int(sub_last_set) :
|
||||
0);
|
||||
}
|
||||
|
||||
purpose = json_object_object_get(channel, "purpose");
|
||||
if (json_valid(purpose, request->workspace))
|
||||
{
|
||||
sub_value = json_object_object_get(topic, "value");
|
||||
|
||||
sub_creator = json_object_object_get(topic, "creator");
|
||||
|
||||
sub_last_set = json_object_object_get(topic, "last_set");
|
||||
|
||||
slack_channel_update_purpose(new_channel,
|
||||
json_valid(sub_value, request->workspace) ?
|
||||
json_object_get_string(sub_value) :
|
||||
NULL,
|
||||
json_valid(sub_creator, request->workspace) ?
|
||||
json_object_get_string(sub_creator) :
|
||||
NULL,
|
||||
json_valid(sub_last_set, request->workspace) ?
|
||||
json_object_get_int(sub_last_set) :
|
||||
0);
|
||||
}
|
||||
|
||||
is_archived = json_object_object_get(response, "is_archived");
|
||||
if (json_valid(is_archived, request->workspace))
|
||||
{
|
||||
new_channel->is_archived = json_object_get_boolean(is_archived);
|
||||
}
|
||||
|
||||
creator = json_object_object_get(response, "creator");
|
||||
if (json_valid(creator, request->workspace))
|
||||
{
|
||||
new_channel->creator = strdup(json_object_get_string(creator));
|
||||
}
|
||||
}
|
||||
|
||||
metadata = json_object_object_get(response, "response_metadata");
|
||||
if (!json_valid(metadata, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_cursor = json_object_object_get(metadata, "next_cursor");
|
||||
if (!json_valid(next_cursor, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor));
|
||||
|
||||
if (cursor[0])
|
||||
{
|
||||
struct t_slack_request *next_request;
|
||||
|
||||
next_request = slack_request_channels_list(request->workspace,
|
||||
weechat_config_string(
|
||||
request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
cursor);
|
||||
if (next_request)
|
||||
slack_workspace_register_request(request->workspace, next_request);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to retrieve channels: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_channels_list(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *cursor)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token, cursor);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_CHANNELS_LIST_H_
|
||||
#define _SLACK_REQUEST_CHANNELS_LIST_H_
|
||||
|
||||
struct t_slack_request *slack_request_channels_list(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *cursor);
|
||||
|
||||
#endif /*SLACK_REQUEST_CHANNELS_LIST_H*/
|
@ -1,270 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../request/slack-request-chat-memessage.h"
|
||||
|
||||
static const char *const endpoint = "/api/chat.meMessage?"
|
||||
"token=%s&channel=%s&text=%s&";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error sending me-message: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) sending me-message... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
json_object *response, *ok, *error;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
/* wait for websocket to catch up */
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to send me-message: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_chat_memessage(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *channel,
|
||||
const char *text)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token, channel, text) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token, channel, text);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_CHAT_MEMESSAGE_H_
|
||||
#define _SLACK_REQUEST_CHAT_MEMESSAGE_H_
|
||||
|
||||
struct t_slack_request *slack_request_chat_memessage(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *channel,
|
||||
const char *text);
|
||||
|
||||
#endif /*SLACK_REQUEST_CHAT_MEMESSAGE_H*/
|
@ -1,271 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../request/slack-request-chat-postmessage.h"
|
||||
|
||||
static const char *const endpoint = "/api/chat.postMessage?"
|
||||
"token=%s&channel=%s&text=%s&"
|
||||
"as_user=true&link_names=true&mrkdwn=false&parse=full";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error posting message: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) posting message... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
json_object *response, *ok, *error;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
/* wait for websocket to catch up */
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to post message: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_chat_postmessage(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *channel,
|
||||
const char *text)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token, channel, text) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token, channel, text);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_CHAT_POSTMESSAGE_H_
|
||||
#define _SLACK_REQUEST_CHAT_POSTMESSAGE_H_
|
||||
|
||||
struct t_slack_request *slack_request_chat_postmessage(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *channel,
|
||||
const char *text);
|
||||
|
||||
#endif /*SLACK_REQUEST_CHAT_POSTMESSAGE_H*/
|
@ -1,330 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../request/slack-request-conversations-members.h"
|
||||
|
||||
static const char *const endpoint = "/api/conversations.members?"
|
||||
"token=%s&channel=%s&cursor=%s&limit=100";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error retrieving members: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
struct t_slack_channel *channel;
|
||||
const char *channelid;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) retrieving members... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
char cursor[64];
|
||||
json_object *response, *ok, *error, *members;
|
||||
json_object *user, *metadata, *next_cursor;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
channelid = (const char *)request->pointer;
|
||||
channel = slack_channel_search(request->workspace, channelid);
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
members = json_object_object_get(response, "members");
|
||||
if (!json_valid(members, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = json_object_array_length(members); i > 0; i--)
|
||||
{
|
||||
user = json_object_array_get_idx(members, i - 1);
|
||||
if (!json_valid(user, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
slack_channel_add_member(request->workspace,
|
||||
channel,
|
||||
json_object_get_string(user));
|
||||
}
|
||||
|
||||
metadata = json_object_object_get(response, "response_metadata");
|
||||
if (!json_valid(metadata, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_cursor = json_object_object_get(metadata, "next_cursor");
|
||||
if (!json_valid(next_cursor, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor));
|
||||
|
||||
if (cursor[0])
|
||||
{
|
||||
struct t_slack_request *next_request;
|
||||
|
||||
next_request = slack_request_conversations_members(request->workspace,
|
||||
weechat_config_string(
|
||||
request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
channelid,
|
||||
cursor);
|
||||
if (next_request)
|
||||
slack_workspace_register_request(request->workspace, next_request);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to retrieve users: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_conversations_members(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *channel,
|
||||
const char *cursor)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
request->pointer = channel;
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token, channel, cursor) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token, channel, cursor);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_
|
||||
#define _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_
|
||||
|
||||
struct t_slack_request *slack_request_conversations_members(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *channel,
|
||||
const char *cursor);
|
||||
|
||||
#endif /*SLACK_REQUEST_CONVERSATIONS_MEMBERS_H*/
|
@ -1,287 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../request/slack-request-emoji-list.h"
|
||||
|
||||
static const char *const endpoint = "/api/emoji.list?"
|
||||
"token=%s";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error retrieving emoji: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) retrieving emoji... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
json_object *response, *ok, *error, *emoji;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
emoji = json_object_object_get(response, "emoji");
|
||||
if (!json_valid(emoji, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
json_object_object_foreach(emoji, key, val)
|
||||
{
|
||||
if (!json_valid(val, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
slack_workspace_add_emoji(
|
||||
request->workspace,
|
||||
key, json_object_get_string(val));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to retrieve emoji: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_emoji_list(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_EMOJI_LIST_H_
|
||||
#define _SLACK_REQUEST_EMOJI_LIST_H_
|
||||
|
||||
struct t_slack_request *slack_request_emoji_list(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token);
|
||||
|
||||
#endif /*SLACK_REQUEST_EMOJI_LIST_H*/
|
@ -1,375 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../slack-request.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../request/slack-request-conversations-members.h"
|
||||
#include "../request/slack-request-users-list.h"
|
||||
|
||||
static const char *const endpoint = "/api/users.list?"
|
||||
"token=%s&cursor=%s&"
|
||||
"exclude_archived=false&exclude_members=true&limit=20";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error retrieving users: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
//__asm__("int3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_request *request = (struct t_slack_request *)user;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
in ? (char *)in : "(null)");
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) reconnecting..."),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) retrieving users... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (request->json_chunks)
|
||||
{
|
||||
for (last_chunk = request->json_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->json_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
char cursor[64];
|
||||
json_object *response, *ok, *error, *members;
|
||||
json_object *user, *id, *name;
|
||||
json_object *profile, *display_name, *bot_id;
|
||||
json_object *metadata, *next_cursor;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (request->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = request->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = request->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(request->json_chunks->data);
|
||||
free(request->json_chunks);
|
||||
request->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
members = json_object_object_get(response, "members");
|
||||
if (!json_valid(members, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = json_object_array_length(members); i > 0; i--)
|
||||
{
|
||||
struct t_slack_user *new_user;
|
||||
|
||||
user = json_object_array_get_idx(members, i - 1);
|
||||
if (!json_valid(user, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
id = json_object_object_get(user, "id");
|
||||
if (!json_valid(id, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
name = json_object_object_get(user, "name");
|
||||
if (!json_valid(name, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profile = json_object_object_get(user, "profile");
|
||||
if (!json_valid(profile, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
display_name = json_object_object_get(profile, "display_name");
|
||||
if (!json_valid(display_name, request->workspace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
new_user = slack_user_new(request->workspace,
|
||||
json_object_get_string(id),
|
||||
json_object_get_string(display_name)[0] ?
|
||||
json_object_get_string(display_name) :
|
||||
json_object_get_string(name));
|
||||
|
||||
bot_id = json_object_object_get(profile, "bot_id");
|
||||
if (json_valid(bot_id, request->workspace))
|
||||
{
|
||||
new_user->profile.bot_id = strdup(json_object_get_string(bot_id));
|
||||
}
|
||||
}
|
||||
|
||||
metadata = json_object_object_get(response, "response_metadata");
|
||||
if (!json_valid(metadata, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_cursor = json_object_object_get(metadata, "next_cursor");
|
||||
if (!json_valid(next_cursor, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor));
|
||||
|
||||
if (cursor[0])
|
||||
{
|
||||
struct t_slack_request *next_request;
|
||||
|
||||
next_request = slack_request_users_list(request->workspace,
|
||||
weechat_config_string(
|
||||
request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
cursor);
|
||||
if (next_request)
|
||||
slack_workspace_register_request(request->workspace, next_request);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct t_slack_request *next_request;
|
||||
struct t_slack_channel *ptr_channel;
|
||||
|
||||
for (ptr_channel = request->workspace->channels; ptr_channel;
|
||||
ptr_channel = ptr_channel->next_channel)
|
||||
{
|
||||
next_request = slack_request_conversations_members(request->workspace,
|
||||
weechat_config_string(
|
||||
request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
ptr_channel->id,
|
||||
cursor);
|
||||
if (next_request)
|
||||
slack_workspace_register_request(request->workspace, next_request);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, request->workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
request->workspace->buffer,
|
||||
_("%s%s: (%d) failed to retrieve users: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_users_list(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *cursor)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
struct lws_context_creation_info ctxinfo;
|
||||
struct lws_client_connect_info ccinfo;
|
||||
|
||||
request = slack_request_alloc(workspace);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1;
|
||||
request->uri = malloc(urilen);
|
||||
snprintf(request->uri, urilen, endpoint, token, cursor);
|
||||
|
||||
memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */
|
||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
ctxinfo.protocols = protocols;
|
||||
|
||||
request->context = lws_create_context(&ctxinfo);
|
||||
if (!request->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: (%d) contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx);
|
||||
}
|
||||
|
||||
memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */
|
||||
ccinfo.context = request->context;
|
||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||
ccinfo.port = 443;
|
||||
ccinfo.address = "slack.com";
|
||||
ccinfo.path = request->uri;
|
||||
ccinfo.host = ccinfo.address;
|
||||
ccinfo.origin = ccinfo.address;
|
||||
ccinfo.method = "GET";
|
||||
ccinfo.protocol = protocols[0].name;
|
||||
ccinfo.pwsi = &request->client_wsi;
|
||||
ccinfo.userdata = request;
|
||||
|
||||
lws_client_connect_via_info(&ccinfo);
|
||||
|
||||
return request;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_USERS_LIST_H_
|
||||
#define _SLACK_REQUEST_USERS_LIST_H_
|
||||
|
||||
struct t_slack_request *slack_request_users_list(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *token, const char *cursor);
|
||||
|
||||
#endif /*SLACK_REQUEST_USERS_LIST_H*/
|
@ -1,164 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-channel.h"
|
||||
#include "slack-buffer.h"
|
||||
|
||||
void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer,
|
||||
struct t_slack_workspace **workspace,
|
||||
struct t_slack_channel **channel)
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
struct t_slack_channel *ptr_channel;
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
/* look for a workspace or channel using this buffer */
|
||||
for (ptr_workspace = slack_workspaces; ptr_workspace;
|
||||
ptr_workspace = ptr_workspace->next_workspace)
|
||||
{
|
||||
if (ptr_workspace->buffer == buffer)
|
||||
{
|
||||
if (workspace)
|
||||
*workspace = ptr_workspace;
|
||||
return;
|
||||
}
|
||||
|
||||
for (ptr_channel = ptr_workspace->channels; ptr_channel;
|
||||
ptr_channel = ptr_channel->next_channel)
|
||||
{
|
||||
if (ptr_channel->buffer == buffer)
|
||||
{
|
||||
if (workspace)
|
||||
*workspace = ptr_workspace;
|
||||
if (channel)
|
||||
*channel = ptr_channel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
const char *nick2)
|
||||
{
|
||||
struct t_slack_workspace *workspace;
|
||||
|
||||
(void) data;
|
||||
|
||||
if (pointer)
|
||||
workspace = (struct t_slack_workspace *)pointer;
|
||||
else
|
||||
slack_buffer_get_workspace_and_channel(buffer, &workspace, NULL);
|
||||
|
||||
if (workspace)
|
||||
{
|
||||
return weechat_strcasecmp(nick1, nick2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return weechat_strcasecmp(nick1, nick2);
|
||||
}
|
||||
}
|
||||
|
||||
int slack_buffer_close_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer)
|
||||
{
|
||||
struct t_weechat_plugin *buffer_plugin = NULL;
|
||||
struct t_slack_workspace *ptr_workspace = NULL;
|
||||
struct t_slack_channel *ptr_channel = NULL;
|
||||
|
||||
buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin");
|
||||
if (buffer_plugin == weechat_slack_plugin)
|
||||
slack_buffer_get_workspace_and_channel(buffer,
|
||||
&ptr_workspace, &ptr_channel);
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) buffer;
|
||||
|
||||
if (ptr_workspace)
|
||||
{
|
||||
if (!ptr_workspace->disconnected)
|
||||
{
|
||||
//slack_command_quit_workspace(ptr_workspace, NULL);
|
||||
slack_workspace_disconnect(ptr_workspace, 0);
|
||||
}
|
||||
|
||||
ptr_workspace->buffer = NULL;
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_BUFFER_H_
|
||||
#define _SLACK_BUFFER_H_
|
||||
|
||||
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,
|
||||
const char *nick2);
|
||||
|
||||
int slack_buffer_close_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer);
|
||||
|
||||
#endif /*SLACK_BUFFER_H*/
|
@ -1,642 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#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"
|
||||
|
||||
struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace,
|
||||
const char *id)
|
||||
{
|
||||
struct t_slack_channel *ptr_channel;
|
||||
|
||||
if (!workspace || !id)
|
||||
return NULL;
|
||||
|
||||
for (ptr_channel = workspace->channels; ptr_channel;
|
||||
ptr_channel = ptr_channel->next_channel)
|
||||
{
|
||||
if (weechat_strcasecmp(ptr_channel->id, id) == 0)
|
||||
return ptr_channel;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct t_gui_buffer *slack_channel_search_buffer(struct t_slack_workspace *workspace,
|
||||
enum t_slack_channel_type type,
|
||||
const char *name)
|
||||
{
|
||||
struct t_hdata *hdata_buffer;
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
const char *ptr_type, *ptr_workspace_name, *ptr_channel_name;
|
||||
|
||||
hdata_buffer = weechat_hdata_get("buffer");
|
||||
ptr_buffer = weechat_hdata_get_list(hdata_buffer, "gui_buffers");
|
||||
|
||||
while (ptr_buffer)
|
||||
{
|
||||
if (weechat_buffer_get_pointer(ptr_buffer, "plugin") == weechat_slack_plugin)
|
||||
{
|
||||
ptr_type = weechat_buffer_get_string(ptr_buffer, "localvar_type");
|
||||
ptr_workspace_name = weechat_buffer_get_string(ptr_buffer,
|
||||
"localvar_server");
|
||||
ptr_channel_name = weechat_buffer_get_string(ptr_buffer,
|
||||
"localvar_channel");
|
||||
if (ptr_type && ptr_type[0]
|
||||
&& ptr_workspace_name && ptr_workspace_name[0]
|
||||
&& ptr_channel_name && ptr_channel_name[0]
|
||||
&& ( (( (type == SLACK_CHANNEL_TYPE_CHANNEL)
|
||||
|| (type == SLACK_CHANNEL_TYPE_GROUP))
|
||||
&& (strcmp(ptr_type, "channel") == 0))
|
||||
|| (( (type == SLACK_CHANNEL_TYPE_MPIM)
|
||||
|| (type == SLACK_CHANNEL_TYPE_IM))
|
||||
&& (strcmp(ptr_type, "private") == 0)))
|
||||
&& (strcmp(ptr_workspace_name, workspace->domain) == 0)
|
||||
&& (weechat_strcasecmp(ptr_channel_name, name) == 0))
|
||||
{
|
||||
return ptr_buffer;
|
||||
}
|
||||
}
|
||||
ptr_buffer = weechat_hdata_move(hdata_buffer, ptr_buffer, 1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *workspace,
|
||||
enum t_slack_channel_type type,
|
||||
const char *name)
|
||||
{
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
int buffer_created;
|
||||
const char *short_name, *localvar_channel;
|
||||
char buffer_name[256];
|
||||
|
||||
buffer_created = 0;
|
||||
|
||||
snprintf(buffer_name, sizeof(buffer_name),
|
||||
"%s.%s", workspace->domain, name);
|
||||
|
||||
ptr_buffer = slack_channel_search_buffer(workspace, type, name);
|
||||
if (ptr_buffer)
|
||||
{
|
||||
weechat_nicklist_remove_all(ptr_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr_buffer = weechat_buffer_new(buffer_name,
|
||||
&slack_input_data_cb, NULL, NULL,
|
||||
&slack_buffer_close_cb, NULL, NULL);
|
||||
if (!ptr_buffer)
|
||||
return NULL;
|
||||
|
||||
buffer_created = 1;
|
||||
}
|
||||
|
||||
if (buffer_created)
|
||||
{
|
||||
if (!weechat_buffer_get_integer(ptr_buffer, "short_name_is_set"))
|
||||
weechat_buffer_set(ptr_buffer, "short_name", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
short_name = weechat_buffer_get_string (ptr_buffer, "short_name");
|
||||
localvar_channel = weechat_buffer_get_string (ptr_buffer,
|
||||
"localvar_channel");
|
||||
|
||||
if (!short_name ||
|
||||
(localvar_channel && (strcmp(localvar_channel, short_name) == 0)))
|
||||
{
|
||||
weechat_buffer_set (ptr_buffer, "short_name", name);
|
||||
}
|
||||
}
|
||||
|
||||
weechat_buffer_set(ptr_buffer, "name", buffer_name);
|
||||
weechat_buffer_set(ptr_buffer, "localvar_set_type",
|
||||
(type == SLACK_CHANNEL_TYPE_IM ||
|
||||
type == SLACK_CHANNEL_TYPE_MPIM) ? "private" : "channel");
|
||||
weechat_buffer_set(ptr_buffer, "localvar_set_nick", workspace->nick);
|
||||
weechat_buffer_set(ptr_buffer, "localvar_set_server", workspace->domain);
|
||||
weechat_buffer_set(ptr_buffer, "localvar_set_channel", name);
|
||||
|
||||
if (buffer_created)
|
||||
{
|
||||
(void) weechat_hook_signal_send ("logger_backlog",
|
||||
WEECHAT_HOOK_SIGNAL_POINTER,
|
||||
ptr_buffer);
|
||||
weechat_buffer_set(ptr_buffer, "input_get_unknown_commands", "1");
|
||||
if (type != SLACK_CHANNEL_TYPE_IM)
|
||||
{
|
||||
weechat_buffer_set(ptr_buffer, "nicklist", "1");
|
||||
weechat_buffer_set(ptr_buffer, "nicklist_display_groups", "0");
|
||||
weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback",
|
||||
&slack_buffer_nickcmp_cb);
|
||||
weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback_pointer",
|
||||
workspace);
|
||||
}
|
||||
|
||||
weechat_buffer_set(ptr_buffer, "highlight_words_add",
|
||||
workspace->nick);
|
||||
weechat_buffer_set(ptr_buffer, "highlight_tags_restrict",
|
||||
"slack_message");
|
||||
}
|
||||
|
||||
return ptr_buffer;
|
||||
}
|
||||
|
||||
void slack_channel_add_nicklist_groups(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel)
|
||||
{
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
char str_group[32];
|
||||
|
||||
if (channel && channel->type == SLACK_CHANNEL_TYPE_MPIM)
|
||||
return;
|
||||
if (channel && channel->type == SLACK_CHANNEL_TYPE_IM)
|
||||
return;
|
||||
|
||||
ptr_buffer = channel ? channel->buffer : workspace->buffer;
|
||||
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s",
|
||||
000, "+");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s",
|
||||
999, "...");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
}
|
||||
|
||||
struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
|
||||
enum t_slack_channel_type type,
|
||||
const char *id, const char *name)
|
||||
{
|
||||
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])
|
||||
return NULL;
|
||||
|
||||
ptr_channel = slack_channel_search(workspace, id);
|
||||
if (ptr_channel)
|
||||
{
|
||||
return ptr_channel;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
new_channel->created = 0;
|
||||
|
||||
new_channel->is_general = 0;
|
||||
new_channel->name_normalized = NULL;
|
||||
new_channel->is_shared = 0;
|
||||
new_channel->is_org_shared = 0;
|
||||
new_channel->is_member = 0;
|
||||
|
||||
new_channel->topic.value = NULL;
|
||||
new_channel->topic.creator = NULL;
|
||||
new_channel->topic.last_set = 0;
|
||||
new_channel->purpose.value = NULL;
|
||||
new_channel->purpose.creator = NULL;
|
||||
new_channel->purpose.last_set = 0;
|
||||
new_channel->is_archived = 0;
|
||||
|
||||
new_channel->creator = NULL;
|
||||
new_channel->last_read = 0.0;
|
||||
new_channel->unread_count = 0;
|
||||
new_channel->unread_count_display = 0;
|
||||
|
||||
new_channel->is_user_deleted = 0;
|
||||
|
||||
new_channel->typing_hook_timer = typing_timer;
|
||||
new_channel->members_speaking[0] = NULL;
|
||||
new_channel->members_speaking[1] = NULL;
|
||||
new_channel->typings = NULL;
|
||||
new_channel->last_typing = NULL;
|
||||
new_channel->members = NULL;
|
||||
new_channel->last_member = NULL;
|
||||
new_channel->buffer = ptr_buffer;
|
||||
new_channel->buffer_as_string = NULL;
|
||||
|
||||
new_channel->prev_channel = workspace->last_channel;
|
||||
new_channel->next_channel = NULL;
|
||||
if (workspace->last_channel)
|
||||
(workspace->last_channel)->next_channel = new_channel;
|
||||
else
|
||||
workspace->channels = new_channel;
|
||||
workspace->last_channel = new_channel;
|
||||
|
||||
return new_channel;
|
||||
}
|
||||
|
||||
void slack_channel_member_speaking_add_to_list(struct t_slack_channel *channel,
|
||||
const char *nick,
|
||||
int highlight)
|
||||
{
|
||||
int size, to_remove, i;
|
||||
struct t_weelist_item *ptr_item;
|
||||
|
||||
/* create list if it does not exist */
|
||||
if (!channel->members_speaking[highlight])
|
||||
channel->members_speaking[highlight] = weechat_list_new();
|
||||
|
||||
/* remove item if it was already in list */
|
||||
ptr_item = weechat_list_casesearch(channel->members_speaking[highlight], nick);
|
||||
if (ptr_item)
|
||||
weechat_list_remove(channel->members_speaking[highlight], ptr_item);
|
||||
|
||||
/* add nick in list */
|
||||
weechat_list_add(channel->members_speaking[highlight], nick,
|
||||
WEECHAT_LIST_POS_END, NULL);
|
||||
|
||||
/* reduce list size if it's too big */
|
||||
size = weechat_list_size(channel->members_speaking[highlight]);
|
||||
if (size > SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT)
|
||||
{
|
||||
to_remove = size - SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT;
|
||||
for (i = 0; i < to_remove; i++)
|
||||
{
|
||||
weechat_list_remove(
|
||||
channel->members_speaking[highlight],
|
||||
weechat_list_get(channel->members_speaking[highlight], 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void slack_channel_member_speaking_add(struct t_slack_channel *channel,
|
||||
const char *nick, int highlight)
|
||||
{
|
||||
if (highlight < 0)
|
||||
highlight = 0;
|
||||
if (highlight > 1)
|
||||
highlight = 1;
|
||||
if (highlight)
|
||||
slack_channel_member_speaking_add_to_list(channel, nick, 1);
|
||||
|
||||
slack_channel_member_speaking_add_to_list(channel, nick, 0);
|
||||
}
|
||||
|
||||
void slack_channel_member_speaking_rename(struct t_slack_channel *channel,
|
||||
const char *old_nick,
|
||||
const char *new_nick)
|
||||
{
|
||||
struct t_weelist_item *ptr_item;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (channel->members_speaking[i])
|
||||
{
|
||||
ptr_item = weechat_list_search(channel->members_speaking[i], old_nick);
|
||||
if (ptr_item)
|
||||
weechat_list_set(ptr_item, new_nick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
const char *nick)
|
||||
{
|
||||
struct t_weelist_item *ptr_item;
|
||||
int i, j, list_size;
|
||||
|
||||
(void) workspace;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (channel->members_speaking[i])
|
||||
{
|
||||
list_size = weechat_list_size(channel->members_speaking[i]);
|
||||
for (j = 0; j < list_size; j++)
|
||||
{
|
||||
ptr_item = weechat_list_get (channel->members_speaking[i], j);
|
||||
if (ptr_item && (strcasecmp(weechat_list_string(ptr_item), nick) == 0))
|
||||
weechat_list_set(ptr_item, nick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
const char *localvar;
|
||||
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++;
|
||||
}
|
||||
|
||||
localvar = weechat_buffer_get_string(channel->buffer, "localvar_typing");
|
||||
if (!localvar || strncmp(localvar, typecount > 0 ? "1" : "0", 1) != 0)
|
||||
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)
|
||||
{
|
||||
struct t_slack_channel_member *new_members;
|
||||
|
||||
if (!channel || !member)
|
||||
return;
|
||||
|
||||
/* remove member from members list */
|
||||
if (channel->last_member == member)
|
||||
channel->last_member = member->prev_member;
|
||||
if (member->prev_member)
|
||||
{
|
||||
(member->prev_member)->next_member = member->next_member;
|
||||
new_members = channel->members;
|
||||
}
|
||||
else
|
||||
new_members = member->next_member;
|
||||
|
||||
if (member->next_member)
|
||||
(member->next_member)->prev_member = member->prev_member;
|
||||
|
||||
/* free member data */
|
||||
if (member->id)
|
||||
free(member->id);
|
||||
|
||||
free(member);
|
||||
|
||||
channel->members = new_members;
|
||||
}
|
||||
|
||||
void slack_channel_member_free_all(struct t_slack_channel *channel)
|
||||
{
|
||||
while (channel->members)
|
||||
slack_channel_member_free(channel, channel->members);
|
||||
}
|
||||
|
||||
void slack_channel_free(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel)
|
||||
{
|
||||
struct t_slack_channel *new_channels;
|
||||
|
||||
if (!workspace || !channel)
|
||||
return;
|
||||
|
||||
/* remove channel from channels list */
|
||||
if (workspace->last_channel == channel)
|
||||
workspace->last_channel = channel->prev_channel;
|
||||
if (channel->prev_channel)
|
||||
{
|
||||
(channel->prev_channel)->next_channel = channel->next_channel;
|
||||
new_channels = workspace->channels;
|
||||
}
|
||||
else
|
||||
new_channels = channel->next_channel;
|
||||
|
||||
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 */
|
||||
if (channel->id)
|
||||
free(channel->id);
|
||||
if (channel->name)
|
||||
free(channel->name);
|
||||
if (channel->name_normalized)
|
||||
free(channel->name_normalized);
|
||||
if (channel->topic.value)
|
||||
free(channel->topic.value);
|
||||
if (channel->topic.creator)
|
||||
free(channel->topic.creator);
|
||||
if (channel->purpose.value)
|
||||
free(channel->purpose.value);
|
||||
if (channel->purpose.creator)
|
||||
free(channel->purpose.creator);
|
||||
if (channel->creator)
|
||||
free(channel->creator);
|
||||
if (channel->members_speaking[0])
|
||||
weechat_list_free(channel->members_speaking[0]);
|
||||
if (channel->members_speaking[1])
|
||||
weechat_list_free(channel->members_speaking[1]);
|
||||
if (channel->buffer_as_string)
|
||||
free(channel->buffer_as_string);
|
||||
|
||||
free(channel);
|
||||
|
||||
workspace->channels = new_channels;
|
||||
}
|
||||
|
||||
void slack_channel_free_all(struct t_slack_workspace *workspace)
|
||||
{
|
||||
while (workspace->channels)
|
||||
slack_channel_free(workspace, workspace->channels);
|
||||
}
|
||||
|
||||
void slack_channel_update_topic(struct t_slack_channel *channel,
|
||||
const char* topic,
|
||||
const char* creator,
|
||||
int last_set)
|
||||
{
|
||||
if (channel->topic.value)
|
||||
free(channel->topic.value);
|
||||
if (channel->topic.creator)
|
||||
free(channel->topic.creator);
|
||||
channel->topic.value = (topic) ? strdup(topic) : NULL;
|
||||
channel->topic.creator = (creator) ? strdup(creator) : NULL;
|
||||
channel->topic.last_set = last_set;
|
||||
|
||||
if (channel->topic.value)
|
||||
weechat_buffer_set(channel->buffer, "title", topic);
|
||||
else
|
||||
weechat_buffer_set(channel->buffer, "title", "");
|
||||
}
|
||||
|
||||
void slack_channel_update_purpose(struct t_slack_channel *channel,
|
||||
const char* purpose,
|
||||
const char* creator,
|
||||
int last_set)
|
||||
{
|
||||
if (channel->purpose.value)
|
||||
free(channel->purpose.value);
|
||||
if (channel->purpose.creator)
|
||||
free(channel->purpose.creator);
|
||||
channel->purpose.value = (purpose) ? strdup(purpose) : NULL;
|
||||
channel->purpose.creator = (creator) ? strdup(creator) : NULL;
|
||||
channel->purpose.last_set = last_set;
|
||||
}
|
||||
|
||||
struct t_slack_channel_member *slack_channel_add_member(
|
||||
struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
const char *id)
|
||||
{
|
||||
struct t_slack_channel_member *member;
|
||||
struct t_slack_user *user;
|
||||
|
||||
member = malloc(sizeof(struct t_slack_channel_member));
|
||||
member->id = strdup(id);
|
||||
|
||||
member->prev_member = channel->last_member;
|
||||
member->next_member = NULL;
|
||||
if (channel->last_member)
|
||||
(channel->last_member)->next_member = member;
|
||||
else
|
||||
channel->members = member;
|
||||
channel->last_member = member;
|
||||
|
||||
user = slack_user_search(workspace, id);
|
||||
if (user)
|
||||
slack_user_nicklist_add(workspace, channel, user);
|
||||
|
||||
return member;
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_CHANNEL_H_
|
||||
#define _SLACK_CHANNEL_H_
|
||||
|
||||
#define SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT 128
|
||||
|
||||
#define SLACK_CHANNEL_NAME_MAX_LEN 22
|
||||
|
||||
enum t_slack_channel_type
|
||||
{
|
||||
SLACK_CHANNEL_TYPE_CHANNEL,
|
||||
SLACK_CHANNEL_TYPE_GROUP,
|
||||
SLACK_CHANNEL_TYPE_MPIM,
|
||||
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;
|
||||
|
||||
struct t_slack_channel_member *prev_member;
|
||||
struct t_slack_channel_member *next_member;
|
||||
};
|
||||
|
||||
struct t_slack_channel_topic
|
||||
{
|
||||
char *value;
|
||||
char *creator;
|
||||
time_t last_set;
|
||||
};
|
||||
|
||||
struct t_slack_channel_purpose
|
||||
{
|
||||
char *value;
|
||||
char *creator;
|
||||
time_t last_set;
|
||||
};
|
||||
|
||||
struct t_slack_channel
|
||||
{
|
||||
enum t_slack_channel_type type;
|
||||
char *id;
|
||||
char *name;
|
||||
time_t created;
|
||||
|
||||
/* channel */
|
||||
int is_general;
|
||||
char *name_normalized;
|
||||
int is_shared;
|
||||
int is_org_shared;
|
||||
int is_member;
|
||||
|
||||
/* group */
|
||||
struct t_slack_channel_topic topic;
|
||||
struct t_slack_channel_purpose purpose;
|
||||
int is_archived;
|
||||
|
||||
/* mpim */
|
||||
char *creator;
|
||||
double last_read;
|
||||
int unread_count;
|
||||
int unread_count_display;
|
||||
|
||||
/* im */
|
||||
int is_user_deleted;
|
||||
|
||||
struct t_hook *typing_hook_timer;
|
||||
struct t_weelist *members_speaking[2];
|
||||
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;
|
||||
char *buffer_as_string;
|
||||
|
||||
struct t_slack_channel *prev_channel;
|
||||
struct t_slack_channel *next_channel;
|
||||
};
|
||||
|
||||
struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace,
|
||||
const char *id);
|
||||
|
||||
void slack_channel_add_nicklist_groups(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel);
|
||||
|
||||
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_member_speaking_add(struct t_slack_channel *channel,
|
||||
const char *nick, int highlight);
|
||||
|
||||
void slack_channel_member_speaking_rename(struct t_slack_channel *channel,
|
||||
const char *old_nick,
|
||||
const char *new_nick);
|
||||
|
||||
void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
const char *nick);
|
||||
|
||||
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);
|
||||
|
||||
void slack_channel_update_topic(struct t_slack_channel *channel,
|
||||
const char* title,
|
||||
const char* creator,
|
||||
int last_set);
|
||||
|
||||
void slack_channel_update_purpose(struct t_slack_channel *channel,
|
||||
const char* purpose,
|
||||
const char* creator,
|
||||
int last_set);
|
||||
|
||||
struct t_slack_channel_member *slack_channel_add_member(
|
||||
struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
const char *id);
|
||||
|
||||
#endif /*SLACK_CHANNEL_H*/
|
@ -1,162 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-config.h"
|
||||
#include "slack-emoji.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-channel.h"
|
||||
#include "slack-user.h"
|
||||
#include "slack-buffer.h"
|
||||
#include "slack-completion.h"
|
||||
|
||||
void slack_completion_channel_nicks_add_speakers(struct t_gui_completion *completion,
|
||||
struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
int highlight)
|
||||
{
|
||||
struct t_slack_user *user;
|
||||
const char *member;
|
||||
int list_size, i;
|
||||
|
||||
if (channel->members_speaking[highlight])
|
||||
{
|
||||
list_size = weechat_list_size(channel->members_speaking[highlight]);
|
||||
for (i = 0; i < list_size; i++)
|
||||
{
|
||||
member = weechat_list_string (
|
||||
weechat_list_get(channel->members_speaking[highlight], i));
|
||||
if (member)
|
||||
{
|
||||
user = slack_user_search(workspace, member);
|
||||
if (user)
|
||||
weechat_hook_completion_list_add(completion,
|
||||
user->profile.display_name,
|
||||
1, WEECHAT_LIST_POS_BEGINNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int slack_completion_channel_nicks_cb(const void *pointer, void *data,
|
||||
const char *completion_item,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_gui_completion *completion)
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
struct t_slack_channel *ptr_channel;
|
||||
struct t_slack_channel_member *ptr_member;
|
||||
struct t_slack_user *ptr_user;
|
||||
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) completion_item;
|
||||
|
||||
ptr_workspace = NULL;
|
||||
ptr_channel = NULL;
|
||||
slack_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel);
|
||||
|
||||
if (ptr_channel)
|
||||
{
|
||||
switch (ptr_channel->type)
|
||||
{
|
||||
case SLACK_CHANNEL_TYPE_CHANNEL:
|
||||
case SLACK_CHANNEL_TYPE_GROUP:
|
||||
case SLACK_CHANNEL_TYPE_MPIM:
|
||||
case SLACK_CHANNEL_TYPE_IM:
|
||||
for (ptr_member = ptr_channel->members; ptr_member;
|
||||
ptr_member = ptr_member->next_member)
|
||||
{
|
||||
ptr_user = slack_user_search(ptr_workspace, ptr_member->id);
|
||||
if (ptr_user)
|
||||
weechat_hook_completion_list_add(completion,
|
||||
ptr_user->profile.display_name,
|
||||
1, WEECHAT_LIST_POS_SORT);
|
||||
}
|
||||
/* add recent speakers on channel */
|
||||
if (weechat_config_integer(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS)
|
||||
{
|
||||
slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 0);
|
||||
}
|
||||
/* add members whose make highlights on me recently on this channel */
|
||||
if (weechat_config_integer(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS)
|
||||
{
|
||||
slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 1);
|
||||
}
|
||||
/* add self member at the end */
|
||||
weechat_hook_completion_list_add(completion,
|
||||
ptr_workspace->nick,
|
||||
1, WEECHAT_LIST_POS_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
int slack_completion_workspaces_cb(const void *pointer, void *data,
|
||||
const char *completion_item,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_gui_completion *completion)
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) completion_item;
|
||||
(void) buffer;
|
||||
|
||||
for (ptr_workspace = slack_workspaces; ptr_workspace;
|
||||
ptr_workspace = ptr_workspace->next_workspace)
|
||||
{
|
||||
weechat_hook_completion_list_add(completion, ptr_workspace->domain,
|
||||
0, WEECHAT_LIST_POS_SORT);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
void slack_completion_init()
|
||||
{
|
||||
struct t_config_option *option;
|
||||
const char *default_template;
|
||||
|
||||
|
||||
weechat_hook_completion ("nick",
|
||||
N_("nicks of current Slack channel"),
|
||||
&slack_completion_channel_nicks_cb,
|
||||
NULL, NULL);
|
||||
|
||||
weechat_hook_completion("slack_workspace",
|
||||
N_("slack workspaces"),
|
||||
&slack_completion_workspaces_cb,
|
||||
NULL, NULL);
|
||||
|
||||
weechat_hook_completion("slack_emoji",
|
||||
N_("slack emoji"),
|
||||
&slack_emoji_complete_by_name_cb,
|
||||
NULL, NULL);
|
||||
|
||||
option = weechat_config_get("weechat.completion.default_template");
|
||||
default_template = weechat_config_string(option);
|
||||
if (!weechat_strcasestr(default_template, "%(slack_emoji)"))
|
||||
{
|
||||
size_t length = snprintf(NULL, 0, "%s|%s",
|
||||
default_template,
|
||||
"%(slack_emoji)") + 1;
|
||||
char *new_template = malloc(length);
|
||||
snprintf(new_template, length, "%s|%s",
|
||||
default_template,
|
||||
"%(slack_emoji)");
|
||||
weechat_config_option_set(option, new_template, 1);
|
||||
free(new_template);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_COMPLETION_H_
|
||||
#define _SLACK_COMPLETION_H_
|
||||
|
||||
void slack_completion_init();
|
||||
|
||||
#endif /*SLACK_COMPLETION_H*/
|
@ -1,289 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-channel.h"
|
||||
#include "slack-buffer.h"
|
||||
#include "slack-emoji.h"
|
||||
|
||||
#include "slack-emoji.inc"
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
static int emoji_byname_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
return strcasecmp(((struct t_slack_emoji_by_name *)p1)->name,
|
||||
((struct t_slack_emoji_by_name *)p2)->name);
|
||||
}
|
||||
|
||||
static int emoji_bytext_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
return strcasecmp(((struct t_slack_emoji_by_text *)p1)->text,
|
||||
((struct t_slack_emoji_by_text *)p2)->text);
|
||||
}
|
||||
|
||||
static size_t modified_wagner_fischer(const char *src, const char *targ)
|
||||
{
|
||||
size_t len = strlen(targ) + 1;
|
||||
size_t above[len], below[len];
|
||||
for (size_t *k = above, c = 0; k < above + len; ++k, ++c) *k = c;
|
||||
|
||||
const char *src_at = src, *targ_at;
|
||||
for (size_t j = 1; j < strlen(src) + 1; ++j)
|
||||
{
|
||||
*below = j;
|
||||
targ_at = targ;
|
||||
for (size_t *d = above, *a = above + 1, *l = below, *c = below + 1;
|
||||
c < below + len; ++d, ++a, ++l, ++c)
|
||||
{
|
||||
/* |-------------replace-----------| |isrt| |delt| */
|
||||
*c = MIN( *src_at == *targ_at ? *d : *d + 1, MIN( *a + 0, *l + 1 ) );
|
||||
++targ_at;
|
||||
}
|
||||
for (size_t *a = above, *b = below; a < above + len; ++a, ++b) *a = *b;
|
||||
++src_at;
|
||||
}
|
||||
|
||||
return above[len-1];
|
||||
}
|
||||
|
||||
static size_t longest_common_substring(const char *X, const char *Y)
|
||||
{
|
||||
const size_t n = strlen(X);
|
||||
const size_t m = strlen(Y);
|
||||
size_t i, j, result = 0;
|
||||
size_t **L;
|
||||
|
||||
L = malloc(sizeof(size_t *) * (n + 1));
|
||||
L[0] = malloc(sizeof(size_t) * (m + 1) * (n + 1));
|
||||
|
||||
for (i = 0; i <= n; i++)
|
||||
L[i] = (*L + (m + 1) * i);
|
||||
|
||||
/* Following steps build L[n+1][m+1] in bottom up fashion. Note
|
||||
that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */
|
||||
for (i = 0; i <= n; i++)
|
||||
{
|
||||
for (j = 0; j <= m; j++)
|
||||
{
|
||||
if (i == 0 || j == 0)
|
||||
{
|
||||
L[i][j] = 0;
|
||||
}
|
||||
else if (X[i-1] == Y[j-1])
|
||||
{
|
||||
L[i][j] = L[i - 1][j - 1] + 1;
|
||||
if (result < L[i][j])
|
||||
result = L[i][j];
|
||||
}
|
||||
else
|
||||
{
|
||||
L[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* result now contains length of LCS for X[0..n-1] and Y[0..m-1] */
|
||||
free(L[0]);
|
||||
free(L);
|
||||
return result;
|
||||
}
|
||||
|
||||
int slack_emoji_complete_by_name_cb(const void *pointer, void *data,
|
||||
const char *completion_item,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_gui_completion *completion)
|
||||
{
|
||||
struct t_slack_workspace_emoji *ptr_emoji;
|
||||
struct t_slack_workspace *workspace;
|
||||
struct t_slack_channel *channel;
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) completion_item;
|
||||
|
||||
workspace = NULL;
|
||||
slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel);
|
||||
|
||||
size_t i, emoji_count = sizeof(slack_emoji_by_name)
|
||||
/ sizeof(struct t_slack_emoji_by_name);
|
||||
|
||||
if (workspace)
|
||||
{
|
||||
for (ptr_emoji = workspace->emoji; ptr_emoji;
|
||||
ptr_emoji = ptr_emoji->next_emoji)
|
||||
weechat_hook_completion_list_add(completion,
|
||||
ptr_emoji->name,
|
||||
0, WEECHAT_LIST_POS_END);
|
||||
|
||||
for (i = 0; i < emoji_count; i++)
|
||||
weechat_hook_completion_list_add(completion,
|
||||
slack_emoji_by_name[i].name,
|
||||
0, WEECHAT_LIST_POS_END);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
int slack_emoji_input_complete_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *command)
|
||||
{
|
||||
struct t_slack_emoji_by_name *closest_emoji;
|
||||
int input_pos, input_length, start, end;
|
||||
char *new_string, *word, *new_pos;
|
||||
const char *input_string;
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) command;
|
||||
|
||||
input_string = weechat_buffer_get_string(buffer, "input");
|
||||
input_length = strlen(input_string);
|
||||
input_pos = weechat_buffer_get_integer(buffer, "input_pos");
|
||||
for (start = input_pos; start > 0 && input_string[start] != ':'; start--)
|
||||
if (input_string[start] == ' ') { break; }
|
||||
for (end = input_pos; end < input_length && input_string[end] != ' '; end++)
|
||||
if (input_string[end] == ':') { end++; break; }
|
||||
|
||||
if (input_string[start] != ':')
|
||||
return WEECHAT_RC_OK;
|
||||
else
|
||||
word = strndup(&input_string[start], end - start);
|
||||
|
||||
size_t emoji_count = sizeof(slack_emoji_by_name)
|
||||
/ sizeof(struct t_slack_emoji_by_name);
|
||||
closest_emoji = malloc(sizeof(slack_emoji_by_name));
|
||||
memcpy(closest_emoji, slack_emoji_by_name,
|
||||
sizeof(slack_emoji_by_name));
|
||||
|
||||
int edit_dist_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct t_slack_emoji_by_name *e1 = p1;
|
||||
const struct t_slack_emoji_by_name *e2 = p2;
|
||||
size_t d1 = modified_wagner_fischer(e1->name, word);
|
||||
size_t d2 = modified_wagner_fischer(e2->name, word);
|
||||
if (d1 == d2)
|
||||
{
|
||||
size_t l1 = longest_common_substring(e1->name, word);
|
||||
size_t l2 = longest_common_substring(e2->name, word);
|
||||
return (l1 < l2) - (l1 > l2);
|
||||
}
|
||||
return (d1 > d2) - (d1 < d2);
|
||||
};
|
||||
qsort(closest_emoji, emoji_count,
|
||||
sizeof(struct t_slack_emoji_by_name),
|
||||
edit_dist_cmp);
|
||||
|
||||
size_t new_length = snprintf(NULL, 0, "%.*s%s%s",
|
||||
start, input_string,
|
||||
closest_emoji[0].name,
|
||||
&input_string[end]) + 1;
|
||||
new_string = malloc(new_length);
|
||||
snprintf(new_string, new_length, "%.*s%s%s",
|
||||
start, input_string,
|
||||
closest_emoji[0].name,
|
||||
&input_string[end]);
|
||||
weechat_buffer_set(buffer, "input", new_string);
|
||||
|
||||
size_t new_pos_len = snprintf(NULL, 0, "%lu",
|
||||
(unsigned long)(start +
|
||||
strlen(closest_emoji[0].name) - 1));
|
||||
new_pos = malloc(new_pos_len);
|
||||
snprintf(new_pos, new_pos_len, "%lu",
|
||||
(unsigned long)(start +
|
||||
strlen(closest_emoji[0].name) - 1));
|
||||
weechat_buffer_set(buffer, "input_pos", new_pos);
|
||||
|
||||
free(new_pos);
|
||||
free(new_string);
|
||||
free(closest_emoji);
|
||||
free(word);
|
||||
return WEECHAT_RC_OK_EAT;
|
||||
}
|
||||
|
||||
int slack_emoji_input_replace_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *command)
|
||||
{
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) buffer;
|
||||
(void) command;
|
||||
|
||||
/* TBI */
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
const char *slack_emoji_get_unicode_by_name(const char *name)
|
||||
{
|
||||
struct t_slack_emoji_by_name *result;
|
||||
struct t_slack_emoji_by_name key;
|
||||
key.name = name;
|
||||
|
||||
size_t emoji_count = sizeof(slack_emoji_by_name)
|
||||
/ sizeof(struct t_slack_emoji_by_name);
|
||||
result = (struct t_slack_emoji_by_name *)bsearch(
|
||||
&key, slack_emoji_by_name, emoji_count,
|
||||
sizeof(struct t_slack_emoji_by_name),
|
||||
emoji_byname_cmp);
|
||||
|
||||
return result->unicode;
|
||||
}
|
||||
|
||||
const char *slack_emoji_get_unicode_by_text(const char *text)
|
||||
{
|
||||
struct t_slack_emoji_by_text *result;
|
||||
struct t_slack_emoji_by_text key;
|
||||
key.text = text;
|
||||
|
||||
size_t emoji_count = sizeof(slack_emoji_by_text)
|
||||
/ sizeof(struct t_slack_emoji_by_text);
|
||||
result = (struct t_slack_emoji_by_text *)bsearch(
|
||||
&key, slack_emoji_by_text, emoji_count,
|
||||
sizeof(struct t_slack_emoji_by_text),
|
||||
emoji_bytext_cmp);
|
||||
|
||||
return result->unicode;
|
||||
}
|
||||
|
||||
const char *slack_emoji_get_text_by_name(const char *name)
|
||||
{
|
||||
struct t_slack_emoji_by_name *result;
|
||||
struct t_slack_emoji_by_name key;
|
||||
key.name = name;
|
||||
|
||||
size_t emoji_count = sizeof(slack_emoji_by_name)
|
||||
/ sizeof(struct t_slack_emoji_by_name);
|
||||
result = (struct t_slack_emoji_by_name *)bsearch(
|
||||
&key, slack_emoji_by_name, emoji_count,
|
||||
sizeof(struct t_slack_emoji_by_name),
|
||||
emoji_byname_cmp);
|
||||
|
||||
return result->text_to;
|
||||
}
|
||||
|
||||
const char *slack_emoji_get_name_by_text(const char *text)
|
||||
{
|
||||
struct t_slack_emoji_by_text *result;
|
||||
struct t_slack_emoji_by_text key;
|
||||
key.text = text;
|
||||
|
||||
size_t emoji_count = sizeof(slack_emoji_by_text)
|
||||
/ sizeof(struct t_slack_emoji_by_text);
|
||||
result = (struct t_slack_emoji_by_text *)bsearch(
|
||||
&key, slack_emoji_by_text, emoji_count,
|
||||
sizeof(struct t_slack_emoji_by_text),
|
||||
emoji_bytext_cmp);
|
||||
|
||||
return result->name_to;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_EMOJI_H_
|
||||
#define _SLACK_EMOJI_H_
|
||||
|
||||
int slack_emoji_complete_by_name_cb(const void *pointer, void *data,
|
||||
const char *completion_item,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_gui_completion *completion);
|
||||
|
||||
int slack_emoji_input_complete_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *command);
|
||||
|
||||
int slack_emoji_input_replace_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *command);
|
||||
|
||||
const char *slack_emoji_get_unicode_by_name(const char *name);
|
||||
|
||||
const char *slack_emoji_get_unicode_by_text(const char *text);
|
||||
|
||||
const char *slack_emoji_get_text_by_name(const char *name);
|
||||
|
||||
const char *slack_emoji_get_name_by_text(const char *text);
|
||||
|
||||
#endif /*SLACK_EMOJI_H*/
|
File diff suppressed because it is too large
Load Diff
@ -1,77 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-channel.h"
|
||||
#include "slack-buffer.h"
|
||||
#include "slack-request.h"
|
||||
#include "slack-message.h"
|
||||
#include "slack-input.h"
|
||||
#include "request/slack-request-chat-postmessage.h"
|
||||
|
||||
int slack_input_data(struct t_gui_buffer *buffer, const char *input_data)
|
||||
{
|
||||
struct t_slack_workspace *workspace = NULL;
|
||||
struct t_slack_channel *channel = NULL;
|
||||
struct t_slack_request *request;
|
||||
char *text;
|
||||
|
||||
slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel);
|
||||
|
||||
if (!workspace)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
if (channel)
|
||||
{
|
||||
if (!workspace->is_connected)
|
||||
{
|
||||
weechat_printf(buffer,
|
||||
_("%s%s: you are not connected to server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
text = malloc(SLACK_MESSAGE_MAX_LENGTH);
|
||||
if (!text)
|
||||
{
|
||||
weechat_printf(buffer,
|
||||
_("%s%s: error allocating string"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return WEECHAT_RC_ERROR;
|
||||
}
|
||||
lws_urlencode(text, input_data, SLACK_MESSAGE_MAX_LENGTH);
|
||||
|
||||
request = slack_request_chat_postmessage(workspace,
|
||||
weechat_config_string(
|
||||
workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]),
|
||||
channel->id, text);
|
||||
if (request)
|
||||
slack_workspace_register_request(workspace, request);
|
||||
|
||||
free(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(buffer,
|
||||
_("%s%s: this buffer is not a channel!"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
int slack_input_data_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *input_data)
|
||||
{
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
|
||||
return slack_input_data(buffer, input_data);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_INPUT_H_
|
||||
#define _SLACK_INPUT_H_
|
||||
|
||||
int slack_input_data_cb(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *input_data);
|
||||
|
||||
#endif /*SLACK_INPUT_H*/
|
@ -1,249 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "../slack.h"
|
||||
#include "../slack-workspace.h"
|
||||
#include "../slack-channel.h"
|
||||
#include "../slack-user.h"
|
||||
#include "../slack-message.h"
|
||||
|
||||
static const char format_regex[] = "<([^>]*?)>";
|
||||
static const size_t max_groups = 2;
|
||||
|
||||
char *slack_message_translate_code(struct t_slack_workspace *workspace,
|
||||
const char *code)
|
||||
{
|
||||
struct t_slack_channel *channel;
|
||||
struct t_slack_user *user;
|
||||
size_t resultlen;
|
||||
char *identifier, *alttext, *result, *symbol, *prefix;
|
||||
|
||||
identifier = strdup(code);
|
||||
alttext = strchr(identifier, '|');
|
||||
if (alttext)
|
||||
*alttext++ = '\0';
|
||||
|
||||
switch (identifier[0])
|
||||
{
|
||||
case '#': /* channel */
|
||||
if (alttext)
|
||||
{
|
||||
prefix = "#";
|
||||
symbol = strdup(alttext);
|
||||
}
|
||||
else
|
||||
{
|
||||
channel = slack_channel_search(workspace, identifier+1);
|
||||
if (channel)
|
||||
{
|
||||
prefix = "#";
|
||||
symbol = strdup(channel->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = "Channel:";
|
||||
symbol = strdup(identifier+1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '@': /* user */
|
||||
if (alttext)
|
||||
{
|
||||
prefix = "@";
|
||||
symbol = strdup(alttext);
|
||||
}
|
||||
else
|
||||
{
|
||||
user = slack_user_search(workspace, identifier+1);
|
||||
if (user)
|
||||
{
|
||||
prefix = "@";
|
||||
symbol = strdup(user->profile.display_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = "User:";
|
||||
symbol = strdup(identifier+1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '!': /* special */
|
||||
if (alttext)
|
||||
{
|
||||
prefix = "@";
|
||||
symbol = strdup(alttext);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = "@";
|
||||
symbol = strdup(identifier+1);
|
||||
}
|
||||
break;
|
||||
default: /* url */
|
||||
prefix = "";
|
||||
symbol = strdup(code);
|
||||
break;
|
||||
}
|
||||
|
||||
free(identifier);
|
||||
resultlen = snprintf(NULL, 0, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")) + 1;
|
||||
result = malloc(resultlen);
|
||||
snprintf(result, resultlen, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset"));
|
||||
free(symbol);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void slack_message_htmldecode(char *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; i < n; i++, j++)
|
||||
switch (src[i])
|
||||
{
|
||||
case '\0':
|
||||
dest[j] = '\0';
|
||||
return;
|
||||
case '&':
|
||||
if (src[i+1] == 'g' &&
|
||||
src[i+2] == 't' &&
|
||||
src[i+3] == ';')
|
||||
{
|
||||
dest[j] = '>';
|
||||
i += 3;
|
||||
break;
|
||||
}
|
||||
else if (src[i+1] == 'l' &&
|
||||
src[i+2] == 't' &&
|
||||
src[i+3] == ';')
|
||||
{
|
||||
dest[j] = '<';
|
||||
i += 3;
|
||||
break;
|
||||
}
|
||||
else if (src[i+1] == 'a' &&
|
||||
src[i+2] == 'm' &&
|
||||
src[i+3] == 'p' &&
|
||||
src[i+4] == ';')
|
||||
{
|
||||
dest[j] = '&';
|
||||
i += 4;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
dest[j] = src[i];
|
||||
break;
|
||||
}
|
||||
dest[j-1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
const char *text)
|
||||
{
|
||||
int rc;
|
||||
regex_t reg;
|
||||
regmatch_t groups[max_groups];
|
||||
char msgbuf[100];
|
||||
char *decoded_text;
|
||||
const char *cursor;
|
||||
size_t offset;
|
||||
|
||||
if ((rc = regcomp(®, format_regex, REG_EXTENDED)))
|
||||
{
|
||||
regerror(rc, ®, msgbuf, sizeof(msgbuf));
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error compiling message formatting regex: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
msgbuf);
|
||||
return strdup(text);
|
||||
}
|
||||
|
||||
decoded_text = malloc(SLACK_MESSAGE_MAX_LENGTH);
|
||||
if (!decoded_text)
|
||||
{
|
||||
regfree(®);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return strdup(text);
|
||||
}
|
||||
decoded_text[0] = '\0';
|
||||
|
||||
for (cursor = text; regexec(®, cursor, max_groups, groups, 0) == 0; cursor += offset)
|
||||
{
|
||||
offset = groups[0].rm_eo;
|
||||
|
||||
char *copy = strdup(cursor);
|
||||
if (!copy)
|
||||
{
|
||||
regfree(®);
|
||||
free(decoded_text);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return strdup(text);
|
||||
}
|
||||
copy[groups[1].rm_eo] = '\0';
|
||||
|
||||
char *match = strdup(copy + groups[1].rm_so);
|
||||
if (!match)
|
||||
{
|
||||
free(copy);
|
||||
regfree(®);
|
||||
free(decoded_text);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return strdup(text);
|
||||
}
|
||||
copy[groups[0].rm_so] = '\0';
|
||||
|
||||
char *prematch = strdup(copy);
|
||||
if (!prematch)
|
||||
{
|
||||
free(match);
|
||||
free(copy);
|
||||
regfree(®);
|
||||
free(decoded_text);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error allocating space for message"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return strdup(text);
|
||||
}
|
||||
free(copy);
|
||||
|
||||
strncat(decoded_text, prematch,
|
||||
SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1);
|
||||
free(prematch);
|
||||
|
||||
char *replacement = slack_message_translate_code(workspace, match);
|
||||
free(match);
|
||||
|
||||
strncat(decoded_text, replacement,
|
||||
SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1);
|
||||
free(replacement);
|
||||
}
|
||||
strncat(decoded_text, cursor,
|
||||
SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1);
|
||||
|
||||
slack_message_htmldecode(decoded_text, decoded_text,
|
||||
SLACK_MESSAGE_MAX_LENGTH);
|
||||
|
||||
regfree(®);
|
||||
return decoded_text;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_MESSAGE_H_
|
||||
#define _SLACK_MESSAGE_H_
|
||||
|
||||
#define SLACK_MESSAGE_MAX_LENGTH 40000
|
||||
|
||||
char *slack_message_decode(struct t_slack_workspace *workspace,
|
||||
const char *text);
|
||||
|
||||
#endif /*SLACK_MESSAGE_H*/
|
@ -1,245 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-oauth.h"
|
||||
|
||||
static void (*weechat_callback)(char *token);
|
||||
|
||||
static const char *const endpoint = "/api/oauth.access?"
|
||||
"client_id=%s&client_secret=%s&code=%s";
|
||||
static char *uri;
|
||||
|
||||
static int n = 0;
|
||||
static struct lws *client_wsi = NULL;
|
||||
static struct lws_context *context = NULL;
|
||||
|
||||
static struct t_hook *slack_oauth_hook_timer = NULL;
|
||||
|
||||
static inline int json_valid(json_object *object)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error retrieving token: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
in ? (char *)in : "(null)");
|
||||
client_wsi = NULL;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: retrieving token... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
char *json_string = weechat_strndup(in, (int)len);
|
||||
json_object *response, *ok, *error, *token;
|
||||
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
token = json_object_object_get(response, "access_token");
|
||||
if (!json_valid(token))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: retrieved token: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
json_object_get_string(token));
|
||||
|
||||
weechat_callback(strdup(json_object_get_string(token)));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: failed to retrieve token: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
int slack_oauth_timer_cb(const void *pointer, void *data, int remaining_calls)
|
||||
{
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) remaining_calls;
|
||||
|
||||
if (n >= 0 && client_wsi)
|
||||
{
|
||||
n = lws_service(context, 0);
|
||||
}
|
||||
else if (context)
|
||||
{
|
||||
lws_context_destroy(context);
|
||||
context = NULL;
|
||||
free(uri);
|
||||
|
||||
if (slack_oauth_hook_timer)
|
||||
weechat_unhook(slack_oauth_hook_timer);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
void slack_oauth_request_token(char *code, void (*callback)(char *token))
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_client_connect_info i;
|
||||
|
||||
if (client_wsi)
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error: a registration is already in progress"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code) + 1;
|
||||
uri = malloc(urilen);
|
||||
snprintf(uri, urilen, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
info.protocols = protocols;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context)
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
||||
}
|
||||
|
||||
memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
|
||||
i.context = context;
|
||||
i.ssl_connection = LCCSCF_USE_SSL;
|
||||
i.port = 443;
|
||||
i.address = "slack.com";
|
||||
i.path = uri;
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.method = "GET";
|
||||
i.protocol = protocols[0].name;
|
||||
i.pwsi = &client_wsi;
|
||||
|
||||
lws_client_connect_via_info(&i);
|
||||
|
||||
slack_oauth_hook_timer = weechat_hook_timer(1 * 1000, 0, 0,
|
||||
&slack_oauth_timer_cb,
|
||||
NULL, NULL);
|
||||
|
||||
weechat_callback = callback;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_OAUTH_H_
|
||||
#define _SLACK_OAUTH_H_
|
||||
|
||||
extern void slack_oauth_request_token(char *code, void (*callback)(char *token));
|
||||
|
||||
#endif /*SLACK_OAUTH_H*/
|
@ -1,27 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-request.h"
|
||||
|
||||
struct t_slack_request *slack_request_alloc(
|
||||
struct t_slack_workspace *workspace)
|
||||
{
|
||||
struct t_slack_request *request;
|
||||
|
||||
request = malloc(sizeof(struct t_slack_request));
|
||||
memset(request, 0, sizeof(struct t_slack_request));
|
||||
|
||||
request->workspace = workspace;
|
||||
request->idx = workspace->idx++;
|
||||
|
||||
return request;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_REQUEST_H_
|
||||
#define _SLACK_REQUEST_H_
|
||||
|
||||
struct t_slack_request
|
||||
{
|
||||
struct t_slack_workspace *workspace;
|
||||
|
||||
int idx;
|
||||
|
||||
const void *pointer;
|
||||
void *data;
|
||||
|
||||
char *uri;
|
||||
struct lws *client_wsi;
|
||||
struct lws_context *context;
|
||||
struct t_json_chunk *json_chunks;
|
||||
|
||||
struct t_slack_request *prev_request;
|
||||
struct t_slack_request *next_request;
|
||||
};
|
||||
|
||||
struct t_slack_request *slack_request_alloc(
|
||||
struct t_slack_workspace *workspace);
|
||||
|
||||
#endif /*SLACK_REQUEST_H*/
|
@ -1,348 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-teaminfo.h"
|
||||
|
||||
static void (*weechat_callback)(struct t_slack_teaminfo *slack_teaminfo);
|
||||
|
||||
static const char *const endpoint = "/api/team.info?"
|
||||
"token=%s";
|
||||
static char *uri;
|
||||
|
||||
static int n = 0;
|
||||
static struct lws *client_wsi = NULL;
|
||||
static struct lws_context *context = NULL;
|
||||
|
||||
static struct t_hook *slack_teaminfo_hook_timer = NULL;
|
||||
|
||||
struct t_json_chunk
|
||||
{
|
||||
char *data;
|
||||
struct t_json_chunk *next;
|
||||
};
|
||||
|
||||
static struct t_json_chunk *slack_teaminfo_chunks = NULL;
|
||||
static struct t_slack_teaminfo slack_teaminfo;
|
||||
|
||||
static inline int json_valid(json_object *object)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error retrieving workspace info: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
in ? (char *)in : "(null)");
|
||||
client_wsi = NULL;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: retrieving workspace details... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 1);
|
||||
new_chunk->data[0] = '\0';
|
||||
new_chunk->next = NULL;
|
||||
|
||||
strncat(new_chunk->data, in, (int)len);
|
||||
|
||||
if (slack_teaminfo_chunks)
|
||||
{
|
||||
for (last_chunk = slack_teaminfo_chunks; last_chunk->next;
|
||||
last_chunk = last_chunk->next);
|
||||
last_chunk->next = new_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
slack_teaminfo_chunks = new_chunk;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
json_object *response, *ok, *error, *team;
|
||||
json_object *id, *name, *domain, *email_domain;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (slack_teaminfo_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = slack_teaminfo_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = slack_teaminfo_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(slack_teaminfo_chunks->data);
|
||||
free(slack_teaminfo_chunks);
|
||||
slack_teaminfo_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
team = json_object_object_get(response, "team");
|
||||
if (!json_valid(team))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
id = json_object_object_get(team, "id");
|
||||
if (!json_valid(id))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = json_object_object_get(team, "name");
|
||||
if (!json_valid(name))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
domain = json_object_object_get(team, "domain");
|
||||
if (!json_valid(domain))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
email_domain = json_object_object_get(team, "email_domain");
|
||||
if (!json_valid(email_domain))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: retrieved workspace details for %s@%s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
json_object_get_string(name), json_object_get_string(domain));
|
||||
|
||||
slack_teaminfo.id = json_object_get_string(id);
|
||||
slack_teaminfo.name = json_object_get_string(name);
|
||||
slack_teaminfo.domain = json_object_get_string(domain);
|
||||
slack_teaminfo.email_domain = json_object_get_string(email_domain);
|
||||
|
||||
weechat_callback(&slack_teaminfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: failed to retrieve workspace details: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
}
|
||||
/* fallthrough */
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
client_wsi = NULL;
|
||||
/* Does not doing this cause a leak?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
int slack_teaminfo_timer_cb(const void *pointer, void *data, int remaining_calls)
|
||||
{
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) remaining_calls;
|
||||
|
||||
if (n >= 0 && client_wsi)
|
||||
{
|
||||
n = lws_service(context, 0);
|
||||
}
|
||||
else if (context)
|
||||
{
|
||||
lws_context_destroy(context);
|
||||
context = NULL;
|
||||
free(uri);
|
||||
|
||||
if (slack_teaminfo_hook_timer)
|
||||
weechat_unhook(slack_teaminfo_hook_timer);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
void slack_teaminfo_fetch(char *token, void (*callback)(struct t_slack_teaminfo *slack_teaminfo))
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_client_connect_info i;
|
||||
|
||||
if (client_wsi)
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error: a registration is already in progress"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
slack_teaminfo.token = strdup(token);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token) + 1;
|
||||
uri = malloc(urilen);
|
||||
snprintf(uri, urilen, endpoint, token);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
info.protocols = protocols;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context)
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
NULL,
|
||||
_("%s%s: contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
||||
}
|
||||
|
||||
memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
|
||||
i.context = context;
|
||||
i.ssl_connection = LCCSCF_USE_SSL;
|
||||
i.port = 443;
|
||||
i.address = "slack.com";
|
||||
i.path = uri;
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.method = "GET";
|
||||
i.protocol = protocols[0].name;
|
||||
i.pwsi = &client_wsi;
|
||||
|
||||
lws_client_connect_via_info(&i);
|
||||
|
||||
slack_teaminfo_hook_timer = weechat_hook_timer(1 * 1000, 0, 0,
|
||||
&slack_teaminfo_timer_cb,
|
||||
NULL, NULL);
|
||||
|
||||
weechat_callback = callback;
|
||||
}
|
||||
|
||||
void free_teaminfo(struct t_slack_teaminfo *teaminfo)
|
||||
{
|
||||
free(teaminfo->token);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_TEAMINFO_H_
|
||||
#define _SLACK_TEAMINFO_H_
|
||||
|
||||
struct t_slack_teaminfo
|
||||
{
|
||||
const char *id;
|
||||
const char *name;
|
||||
const char *domain;
|
||||
const char *email_domain;
|
||||
char *token;
|
||||
};
|
||||
|
||||
extern void slack_teaminfo_fetch(char *token, void (*callback)(struct t_slack_teaminfo *slack_teaminfo));
|
||||
extern void free_teaminfo(struct t_slack_teaminfo *teaminfo);
|
||||
|
||||
#endif /*SLACK_TEAMINFO_H*/
|
@ -1,241 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-user.h"
|
||||
#include "slack-channel.h"
|
||||
|
||||
const char *slack_user_get_colour(struct t_slack_user *user)
|
||||
{
|
||||
return weechat_info_get("nick_color", user->profile.display_name);
|
||||
}
|
||||
|
||||
const char *slack_user_get_colour_for_nicklist(struct t_slack_user *user)
|
||||
{
|
||||
return weechat_info_get("nick_color_name", user->profile.display_name);
|
||||
}
|
||||
|
||||
const char *slack_user_as_prefix(struct t_slack_workspace *workspace,
|
||||
struct t_slack_user *user,
|
||||
const char *name)
|
||||
{
|
||||
static char result[256];
|
||||
|
||||
(void) workspace;
|
||||
|
||||
snprintf(result, sizeof(result), "%s%s\t",
|
||||
slack_user_get_colour(user),
|
||||
name ? name : user->profile.display_name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct t_slack_user *slack_user_bot_search(struct t_slack_workspace *workspace,
|
||||
const char *bot_id)
|
||||
{
|
||||
struct t_slack_user *ptr_user;
|
||||
|
||||
if (!workspace || !bot_id)
|
||||
return NULL;
|
||||
|
||||
for (ptr_user = workspace->users; ptr_user;
|
||||
ptr_user = ptr_user->next_user)
|
||||
{
|
||||
if (ptr_user->profile.bot_id &&
|
||||
weechat_strcasecmp(ptr_user->profile.bot_id, bot_id) == 0)
|
||||
return ptr_user;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace,
|
||||
const char *id)
|
||||
{
|
||||
struct t_slack_user *ptr_user;
|
||||
|
||||
if (!workspace || !id)
|
||||
return NULL;
|
||||
|
||||
for (ptr_user = workspace->users; ptr_user;
|
||||
ptr_user = ptr_user->next_user)
|
||||
{
|
||||
if (weechat_strcasecmp(ptr_user->id, id) == 0)
|
||||
return ptr_user;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void slack_user_nicklist_add(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
struct t_slack_user *user)
|
||||
{
|
||||
struct t_gui_nick_group *ptr_group;
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
|
||||
ptr_buffer = channel ? channel->buffer : workspace->buffer;
|
||||
|
||||
ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL,
|
||||
user->is_away ?
|
||||
"+" : "...");
|
||||
weechat_nicklist_add_nick(ptr_buffer, ptr_group,
|
||||
user->profile.display_name,
|
||||
user->is_away ?
|
||||
"weechat.color.nicklist_away" :
|
||||
slack_user_get_colour_for_nicklist(user),
|
||||
user->is_away ? "+" : "",
|
||||
"bar_fg",
|
||||
1);
|
||||
}
|
||||
|
||||
struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace,
|
||||
const char *id, const char *display_name)
|
||||
{
|
||||
struct t_slack_user *new_user, *ptr_user;
|
||||
|
||||
if (!workspace || !id || !display_name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!display_name[0] && strcmp("USLACKBOT", id) == 0)
|
||||
return NULL;
|
||||
|
||||
if (!workspace->users)
|
||||
slack_channel_add_nicklist_groups(workspace, NULL);
|
||||
|
||||
ptr_user = slack_user_search(workspace, id);
|
||||
if (ptr_user)
|
||||
{
|
||||
slack_user_nicklist_add(workspace, NULL, ptr_user);
|
||||
return ptr_user;
|
||||
}
|
||||
|
||||
if ((new_user = malloc(sizeof(*new_user))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_user->prev_user = workspace->last_user;
|
||||
new_user->next_user = NULL;
|
||||
if (workspace->last_user)
|
||||
(workspace->last_user)->next_user = new_user;
|
||||
else
|
||||
workspace->users = new_user;
|
||||
workspace->last_user = new_user;
|
||||
|
||||
new_user->id = strdup(id);
|
||||
new_user->name = NULL;
|
||||
new_user->team_id = NULL;
|
||||
new_user->real_name = NULL;
|
||||
new_user->colour = NULL;
|
||||
new_user->deleted = 0;
|
||||
|
||||
new_user->tz = NULL;
|
||||
new_user->tz_label = NULL;
|
||||
new_user->tz_offset = 0;
|
||||
new_user->locale = NULL;
|
||||
|
||||
new_user->profile.avatar_hash = NULL;
|
||||
new_user->profile.status_text = NULL;
|
||||
new_user->profile.status_emoji = NULL;
|
||||
new_user->profile.real_name = NULL;
|
||||
new_user->profile.display_name = display_name[0] ?
|
||||
strdup(display_name) :
|
||||
strdup("slackbot");
|
||||
new_user->profile.real_name_normalized = NULL;
|
||||
new_user->profile.email = NULL;
|
||||
new_user->profile.team = NULL;
|
||||
new_user->profile.bot_id = NULL;
|
||||
new_user->updated = 0;
|
||||
new_user->is_away = 0;
|
||||
|
||||
new_user->is_admin = 0;
|
||||
new_user->is_owner = 0;
|
||||
new_user->is_primary_owner = 0;
|
||||
new_user->is_restricted = 0;
|
||||
new_user->is_ultra_restricted = 0;
|
||||
new_user->is_bot = 0;
|
||||
new_user->is_stranger = 0;
|
||||
new_user->is_app_user = 0;
|
||||
new_user->has_2fa = 0;
|
||||
|
||||
slack_user_nicklist_add(workspace, NULL, new_user);
|
||||
|
||||
return new_user;
|
||||
}
|
||||
|
||||
void slack_user_free(struct t_slack_workspace *workspace,
|
||||
struct t_slack_user *user)
|
||||
{
|
||||
struct t_slack_user *new_users;
|
||||
|
||||
if (!workspace || !user)
|
||||
return;
|
||||
|
||||
/* remove user from users list */
|
||||
if (workspace->last_user == user)
|
||||
workspace->last_user = user->prev_user;
|
||||
if (user->prev_user)
|
||||
{
|
||||
(user->prev_user)->next_user = user->next_user;
|
||||
new_users = workspace->users;
|
||||
}
|
||||
else
|
||||
new_users = user->next_user;
|
||||
|
||||
if (user->next_user)
|
||||
(user->next_user)->prev_user = user->prev_user;
|
||||
|
||||
/* free user data */
|
||||
if (user->id)
|
||||
free(user->id);
|
||||
if (user->name)
|
||||
free(user->name);
|
||||
if (user->team_id)
|
||||
free(user->team_id);
|
||||
if (user->real_name)
|
||||
free(user->real_name);
|
||||
if (user->colour)
|
||||
free(user->colour);
|
||||
if (user->tz)
|
||||
free(user->tz);
|
||||
if (user->tz_label)
|
||||
free(user->tz_label);
|
||||
if (user->locale)
|
||||
free(user->locale);
|
||||
if (user->profile.avatar_hash)
|
||||
free(user->profile.avatar_hash);
|
||||
if (user->profile.status_text)
|
||||
free(user->profile.status_text);
|
||||
if (user->profile.status_emoji)
|
||||
free(user->profile.status_emoji);
|
||||
if (user->profile.real_name)
|
||||
free(user->profile.real_name);
|
||||
if (user->profile.display_name)
|
||||
free(user->profile.display_name);
|
||||
if (user->profile.real_name_normalized)
|
||||
free(user->profile.real_name_normalized);
|
||||
if (user->profile.email)
|
||||
free(user->profile.email);
|
||||
if (user->profile.team)
|
||||
free(user->profile.team);
|
||||
|
||||
free(user);
|
||||
|
||||
workspace->users = new_users;
|
||||
}
|
||||
|
||||
void slack_user_free_all(struct t_slack_workspace *workspace)
|
||||
{
|
||||
while (workspace->users)
|
||||
slack_user_free(workspace, workspace->users);
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_USER_H_
|
||||
#define _SLACK_USER_H_
|
||||
|
||||
struct t_slack_user_profile
|
||||
{
|
||||
char *avatar_hash;
|
||||
char *status_text;
|
||||
char *status_emoji;
|
||||
char *real_name;
|
||||
char *display_name;
|
||||
char *real_name_normalized;
|
||||
char *email;
|
||||
char *team;
|
||||
char *bot_id;
|
||||
};
|
||||
|
||||
struct t_slack_user
|
||||
{
|
||||
char *id;
|
||||
char *name;
|
||||
char *team_id;
|
||||
char *real_name;
|
||||
char *colour;
|
||||
|
||||
int deleted;
|
||||
char *tz;
|
||||
char *tz_label;
|
||||
int tz_offset;
|
||||
char *locale;
|
||||
|
||||
struct t_slack_user_profile profile;
|
||||
int updated;
|
||||
int is_away;
|
||||
|
||||
int is_admin;
|
||||
int is_owner;
|
||||
int is_primary_owner;
|
||||
int is_restricted;
|
||||
int is_ultra_restricted;
|
||||
int is_bot;
|
||||
int is_stranger;
|
||||
int is_app_user;
|
||||
int has_2fa;
|
||||
|
||||
struct t_slack_user *prev_user;
|
||||
struct t_slack_user *next_user;
|
||||
};
|
||||
|
||||
const char *slack_user_get_colour(struct t_slack_user *user);
|
||||
|
||||
const char *slack_user_as_prefix(struct t_slack_workspace *workspace,
|
||||
struct t_slack_user *user,
|
||||
const char *name);
|
||||
|
||||
struct t_slack_user *slack_user_bot_search(struct t_slack_workspace *workspace,
|
||||
const char *bot_id);
|
||||
|
||||
struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace,
|
||||
const char *id);
|
||||
|
||||
struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace,
|
||||
const char *id, const char *display_name);
|
||||
|
||||
void slack_user_free_all(struct t_slack_workspace *workspace);
|
||||
|
||||
void slack_user_nicklist_add(struct t_slack_workspace *workspace,
|
||||
struct t_slack_channel *channel,
|
||||
struct t_slack_user *user);
|
||||
|
||||
#endif /*SLACK_USER_H*/
|
@ -1,972 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "weechat-plugin.h"
|
||||
#include "slack.h"
|
||||
#include "slack-config.h"
|
||||
#include "slack-input.h"
|
||||
#include "slack-workspace.h"
|
||||
#include "slack-api.h"
|
||||
#include "slack-request.h"
|
||||
#include "slack-user.h"
|
||||
#include "slack-channel.h"
|
||||
#include "slack-buffer.h"
|
||||
|
||||
struct t_slack_workspace *slack_workspaces = NULL;
|
||||
struct t_slack_workspace *last_slack_workspace = NULL;
|
||||
|
||||
char *slack_workspace_options[SLACK_WORKSPACE_NUM_OPTIONS][2] =
|
||||
{ { "token", "" },
|
||||
};
|
||||
|
||||
static const char *const endpoint = "/api/rtm.connect?"
|
||||
"token=%s&batch_presence_aware=true&presence_sub=false&";
|
||||
|
||||
static inline int json_valid(json_object *object, struct t_slack_workspace *workspace)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error requesting websocket: unexpected response from server"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct t_slack_workspace *workspace = (struct t_slack_workspace *)user;
|
||||
int status;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error connecting to slack: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
in ? (char *)in : "(null)");
|
||||
workspace->client_wsi = NULL;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
status = lws_http_client_http_response(wsi);
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: requesting a websocket... (%d)"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
status);
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
{
|
||||
struct t_json_chunk *new_chunk, *last_chunk;
|
||||
|
||||
new_chunk = malloc(sizeof(*new_chunk));
|
||||
new_chunk->data = malloc((1024 * sizeof(char)) + 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;
|
||||
}
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
{
|
||||
int chunk_count, i;
|
||||
char *json_string;
|
||||
json_object *response, *ok, *error, *self, *team, *url;
|
||||
json_object *id, *name, *domain;
|
||||
struct t_json_chunk *chunk_ptr;
|
||||
|
||||
chunk_count = 0;
|
||||
if (workspace->json_chunks)
|
||||
{
|
||||
chunk_count++;
|
||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr->next;
|
||||
chunk_ptr = chunk_ptr->next)
|
||||
{
|
||||
chunk_count++;
|
||||
}
|
||||
}
|
||||
|
||||
json_string = malloc((1024 * sizeof(char) * chunk_count) + 1);
|
||||
json_string[0] = '\0';
|
||||
|
||||
chunk_ptr = workspace->json_chunks;
|
||||
for (i = 0; i < chunk_count; i++)
|
||||
{
|
||||
strncat(json_string, chunk_ptr->data, 1024);
|
||||
chunk_ptr = chunk_ptr->next;
|
||||
|
||||
free(workspace->json_chunks->data);
|
||||
free(workspace->json_chunks);
|
||||
workspace->json_chunks = chunk_ptr;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: got response: %s"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
||||
json_string);
|
||||
|
||||
response = json_tokener_parse(json_string);
|
||||
ok = json_object_object_get(response, "ok");
|
||||
if (!json_valid(ok, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(json_object_get_boolean(ok))
|
||||
{
|
||||
self = json_object_object_get(response, "self");
|
||||
if (!json_valid(self, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = json_object_object_get(self, "id");
|
||||
if (!json_valid(id, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
workspace->user = strdup(json_object_get_string(id));
|
||||
|
||||
name = json_object_object_get(self, "name");
|
||||
if (!json_valid(name, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
workspace->nick = strdup(json_object_get_string(name));
|
||||
}
|
||||
|
||||
team = json_object_object_get(response, "team");
|
||||
if (!json_valid(team, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
domain = json_object_object_get(team, "domain");
|
||||
if (!json_valid(domain, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
id = json_object_object_get(team, "id");
|
||||
if (!json_valid(id, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
workspace->id = strdup(json_object_get_string(id));
|
||||
|
||||
name = json_object_object_get(team, "name");
|
||||
if (!json_valid(name, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
workspace->name = strdup(json_object_get_string(name));
|
||||
}
|
||||
|
||||
url = json_object_object_get(response, "url");
|
||||
if (!json_valid(url, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
workspace->ws_url = strdup(json_object_get_string(url));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = json_object_object_get(response, "error");
|
||||
if (!json_valid(error, workspace))
|
||||
{
|
||||
json_object_put(response);
|
||||
free(json_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: failed to request websocket: %s"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
||||
json_object_get_string(error));
|
||||
}
|
||||
|
||||
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?
|
||||
lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct t_slack_workspace *slack_workspace_search(const char *workspace_domain)
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
|
||||
if (!workspace_domain)
|
||||
return NULL;
|
||||
|
||||
for (ptr_workspace = slack_workspaces; ptr_workspace;
|
||||
ptr_workspace = ptr_workspace->next_workspace)
|
||||
{
|
||||
if (strcmp(ptr_workspace->domain, workspace_domain) == 0)
|
||||
return ptr_workspace;
|
||||
}
|
||||
|
||||
/* workspace not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_domain)
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
|
||||
if (!workspace_domain)
|
||||
return NULL;
|
||||
|
||||
for (ptr_workspace = slack_workspaces; ptr_workspace;
|
||||
ptr_workspace = ptr_workspace->next_workspace)
|
||||
{
|
||||
if (weechat_strcasecmp (ptr_workspace->domain, workspace_domain) == 0)
|
||||
return ptr_workspace;
|
||||
}
|
||||
|
||||
/* workspace not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int slack_workspace_search_option(const char *option_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!option_name)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++)
|
||||
{
|
||||
if (weechat_strcasecmp(slack_workspace_options[i][0], option_name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
/* workspace option not found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct t_slack_workspace *slack_workspace_alloc(const char *domain)
|
||||
{
|
||||
struct t_slack_workspace *new_workspace;
|
||||
int i, length;
|
||||
char *option_name;
|
||||
|
||||
if (slack_workspace_casesearch(domain))
|
||||
return NULL;
|
||||
|
||||
/* alloc memory for new workspace */
|
||||
new_workspace = malloc(sizeof(*new_workspace));
|
||||
if (!new_workspace)
|
||||
{
|
||||
weechat_printf(NULL,
|
||||
_("%s%s: error when allocating new workspace"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add new workspace to queue */
|
||||
new_workspace->prev_workspace = last_slack_workspace;
|
||||
new_workspace->next_workspace = NULL;
|
||||
if (last_slack_workspace)
|
||||
last_slack_workspace->next_workspace = new_workspace;
|
||||
else
|
||||
slack_workspaces = new_workspace;
|
||||
last_slack_workspace = new_workspace;
|
||||
|
||||
/* set properties */
|
||||
new_workspace->id = NULL;
|
||||
new_workspace->name = NULL;
|
||||
|
||||
/* set name */
|
||||
new_workspace->domain = strdup(domain);
|
||||
|
||||
/* internal vars */
|
||||
new_workspace->reloading_from_config = 0;
|
||||
new_workspace->reloaded_from_config = 0;
|
||||
|
||||
new_workspace->is_connected = 0;
|
||||
new_workspace->disconnected = 0;
|
||||
|
||||
new_workspace->idx = 0;
|
||||
new_workspace->uri = NULL;
|
||||
new_workspace->ws_url = NULL;
|
||||
new_workspace->client_wsi = NULL;
|
||||
new_workspace->context = NULL;
|
||||
new_workspace->json_chunks = NULL;
|
||||
new_workspace->requests = NULL;
|
||||
new_workspace->last_request = NULL;
|
||||
|
||||
new_workspace->user = NULL;
|
||||
new_workspace->nick = NULL;
|
||||
|
||||
new_workspace->buffer = NULL;
|
||||
new_workspace->buffer_as_string = NULL;
|
||||
new_workspace->users = NULL;
|
||||
new_workspace->last_user = NULL;
|
||||
new_workspace->channels = NULL;
|
||||
new_workspace->last_channel = NULL;
|
||||
new_workspace->emoji = NULL;
|
||||
new_workspace->last_emoji = NULL;
|
||||
|
||||
/* create options with null value */
|
||||
for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++)
|
||||
{
|
||||
length = strlen(new_workspace->domain) + 1 +
|
||||
strlen(slack_workspace_options[i][0]) +
|
||||
512 + /* inherited option name(slack.workspace_default.xxx) */
|
||||
1;
|
||||
option_name = malloc(length);
|
||||
if (option_name)
|
||||
{
|
||||
snprintf(option_name, length, "%s.%s << slack.workspace_default.%s",
|
||||
new_workspace->domain,
|
||||
slack_workspace_options[i][0],
|
||||
slack_workspace_options[i][0]);
|
||||
new_workspace->options[i] = slack_config_workspace_new_option(
|
||||
slack_config_file,
|
||||
slack_config_section_workspace,
|
||||
i,
|
||||
option_name,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
&slack_config_workspace_check_value_cb,
|
||||
slack_workspace_options[i][0],
|
||||
NULL,
|
||||
&slack_config_workspace_change_cb,
|
||||
slack_workspace_options[i][0],
|
||||
NULL);
|
||||
slack_config_workspace_change_cb(slack_workspace_options[i][0], NULL,
|
||||
new_workspace->options[i]);
|
||||
free(option_name);
|
||||
}
|
||||
}
|
||||
|
||||
return new_workspace;
|
||||
}
|
||||
|
||||
void slack_workspace_free_data(struct t_slack_workspace *workspace)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!workspace)
|
||||
return;
|
||||
|
||||
/* free linked lists */
|
||||
/*
|
||||
for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++)
|
||||
{
|
||||
slack_workspace_outqueue_free_all(workspace, i);
|
||||
}
|
||||
slack_redirect_free_all(workspace);
|
||||
slack_notify_free_all(workspace);
|
||||
*/
|
||||
slack_channel_free_all(workspace);
|
||||
slack_user_free_all(workspace);
|
||||
|
||||
/* free hashtables */
|
||||
/*
|
||||
weechat_hashtable_free(workspace->join_manual);
|
||||
weechat_hashtable_free(workspace->join_channel_key);
|
||||
weechat_hashtable_free(workspace->join_noswitch);
|
||||
*/
|
||||
|
||||
/* free workspace data */
|
||||
for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++)
|
||||
{
|
||||
if (workspace->options[i])
|
||||
weechat_config_option_free(workspace->options[i]);
|
||||
}
|
||||
if (workspace->id)
|
||||
free(workspace->id);
|
||||
if (workspace->name)
|
||||
free(workspace->name);
|
||||
if (workspace->domain)
|
||||
free(workspace->domain);
|
||||
|
||||
if (workspace->uri)
|
||||
free(workspace->uri);
|
||||
if (workspace->ws_url)
|
||||
free(workspace->ws_url);
|
||||
if (workspace->context)
|
||||
lws_context_destroy(workspace->context);
|
||||
while (workspace->json_chunks)
|
||||
{
|
||||
struct t_json_chunk *chunk_ptr = workspace->json_chunks->next;
|
||||
|
||||
free(workspace->json_chunks->data);
|
||||
free(workspace->json_chunks);
|
||||
workspace->json_chunks = chunk_ptr;
|
||||
}
|
||||
while (workspace->requests)
|
||||
{
|
||||
struct t_slack_request *request_ptr = workspace->requests->next_request;
|
||||
|
||||
workspace->requests->client_wsi = NULL;
|
||||
if (workspace->requests->context)
|
||||
{
|
||||
lws_context_destroy(workspace->requests->context);
|
||||
workspace->requests->context = NULL;
|
||||
if (workspace->requests->uri)
|
||||
{
|
||||
free(workspace->requests->uri);
|
||||
workspace->requests->uri = NULL;
|
||||
}
|
||||
}
|
||||
free(workspace->requests);
|
||||
workspace->requests = request_ptr;
|
||||
}
|
||||
|
||||
if (workspace->user)
|
||||
free(workspace->user);
|
||||
if (workspace->nick)
|
||||
free(workspace->nick);
|
||||
|
||||
if (workspace->buffer_as_string)
|
||||
free(workspace->buffer_as_string);
|
||||
|
||||
slack_channel_free_all(workspace);
|
||||
slack_user_free_all(workspace);
|
||||
}
|
||||
|
||||
void slack_workspace_free(struct t_slack_workspace *workspace)
|
||||
{
|
||||
struct t_slack_workspace *new_slack_workspaces;
|
||||
|
||||
if (!workspace)
|
||||
return;
|
||||
|
||||
/*
|
||||
* close workspace buffer (and all channels/privates)
|
||||
* (only if we are not in a /upgrade, because during upgrade we want to
|
||||
* keep connections and closing workspace buffer would disconnect from workspace)
|
||||
*/
|
||||
if (workspace->buffer)
|
||||
weechat_buffer_close(workspace->buffer);
|
||||
|
||||
/* remove workspace from queue */
|
||||
if (last_slack_workspace == workspace)
|
||||
last_slack_workspace = workspace->prev_workspace;
|
||||
if (workspace->prev_workspace)
|
||||
{
|
||||
(workspace->prev_workspace)->next_workspace = workspace->next_workspace;
|
||||
new_slack_workspaces = slack_workspaces;
|
||||
}
|
||||
else
|
||||
new_slack_workspaces = workspace->next_workspace;
|
||||
|
||||
if (workspace->next_workspace)
|
||||
(workspace->next_workspace)->prev_workspace = workspace->prev_workspace;
|
||||
|
||||
slack_workspace_free_data(workspace);
|
||||
free(workspace);
|
||||
slack_workspaces = new_slack_workspaces;
|
||||
}
|
||||
|
||||
void slack_workspace_free_all()
|
||||
{
|
||||
/* for each workspace in memory, remove it */
|
||||
while (slack_workspaces)
|
||||
{
|
||||
slack_workspace_free(slack_workspaces);
|
||||
}
|
||||
}
|
||||
|
||||
void slack_workspace_disconnect(struct t_slack_workspace *workspace,
|
||||
int reconnect)
|
||||
{
|
||||
(void) reconnect;
|
||||
|
||||
struct t_slack_channel *ptr_channel;
|
||||
(void) ptr_channel;
|
||||
|
||||
if (workspace->is_connected)
|
||||
{
|
||||
/*
|
||||
* remove all nicks and write disconnection message on each
|
||||
* 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"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
||||
}
|
||||
/* remove away status on workspace buffer */
|
||||
//weechat_buffer_set(workspace->buffer, "localvar_del_away", "");
|
||||
}
|
||||
|
||||
slack_workspace_close_connection(workspace);
|
||||
|
||||
if (workspace->buffer)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: disconnected from workspace"),
|
||||
weechat_prefix ("network"), SLACK_PLUGIN_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
workspace->current_retry = 0;
|
||||
|
||||
if (switch_address)
|
||||
slack_workspace_switch_address(workspace, 0);
|
||||
else
|
||||
slack_workspace_set_index_current_address(workspace, 0);
|
||||
|
||||
if (workspace->nick_modes)
|
||||
{
|
||||
free (workspace->nick_modes);
|
||||
workspace->nick_modes = NULL;
|
||||
weechat_bar_item_update ("input_prompt");
|
||||
weechat_bar_item_update ("slack_nick_modes");
|
||||
}
|
||||
workspace->cap_away_notify = 0;
|
||||
workspace->cap_account_notify = 0;
|
||||
workspace->cap_extended_join = 0;
|
||||
workspace->is_away = 0;
|
||||
workspace->away_time = 0;
|
||||
workspace->lag = 0;
|
||||
workspace->lag_displayed = -1;
|
||||
workspace->lag_check_time.tv_sec = 0;
|
||||
workspace->lag_check_time.tv_usec = 0;
|
||||
workspace->lag_next_check = time (NULL) +
|
||||
weechat_config_integer (slack_config_network_lag_check);
|
||||
workspace->lag_last_refresh = 0;
|
||||
slack_workspace_set_lag (workspace);
|
||||
workspace->monitor = 0;
|
||||
workspace->monitor_time = 0;
|
||||
|
||||
if (reconnect
|
||||
&& IRC_SERVER_OPTION_BOOLEAN(workspace, IRC_SERVER_OPTION_AUTORECONNECT))
|
||||
slack_workspace_reconnect_schedule(workspace);
|
||||
else
|
||||
{
|
||||
workspace->reconnect_delay = 0;
|
||||
workspace->reconnect_start = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* discard current nick if no reconnection asked */
|
||||
/*
|
||||
if (!reconnect && workspace->nick)
|
||||
slack_workspace_set_nick(workspace, NULL);
|
||||
|
||||
slack_workspace_set_buffer_title(workspace);
|
||||
|
||||
workspace->disconnected = 1;
|
||||
*/
|
||||
|
||||
/* send signal "slack_workspace_disconnected" with workspace name */
|
||||
/*
|
||||
(void) weechat_hook_signal_send("slack_workspace_disconnected",
|
||||
WEECHAT_HOOK_SIGNAL_STRING, workspace->name);
|
||||
*/
|
||||
}
|
||||
|
||||
void slack_workspace_disconnect_all()
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
|
||||
for (ptr_workspace = slack_workspaces; ptr_workspace;
|
||||
ptr_workspace = ptr_workspace->next_workspace)
|
||||
{
|
||||
slack_workspace_disconnect(ptr_workspace, 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *workspace)
|
||||
{
|
||||
char buffer_name[256], charset_modifier[256];
|
||||
|
||||
snprintf(buffer_name, sizeof(buffer_name),
|
||||
"workspace.%s", workspace->domain);
|
||||
workspace->buffer = weechat_buffer_new(buffer_name,
|
||||
&slack_input_data_cb, NULL, NULL,
|
||||
&slack_buffer_close_cb, NULL, NULL);
|
||||
if (!workspace->buffer)
|
||||
return NULL;
|
||||
|
||||
if (!weechat_buffer_get_integer(workspace->buffer, "short_name_is_set"))
|
||||
weechat_buffer_set(workspace->buffer, "short_name", workspace->domain);
|
||||
weechat_buffer_set(workspace->buffer, "localvar_set_type", "server");
|
||||
weechat_buffer_set(workspace->buffer, "localvar_set_server", workspace->domain);
|
||||
weechat_buffer_set(workspace->buffer, "localvar_set_channel", workspace->domain);
|
||||
snprintf(charset_modifier, sizeof (charset_modifier),
|
||||
"workspace.%s", workspace->domain);
|
||||
weechat_buffer_set(workspace->buffer, "localvar_set_charset_modifier",
|
||||
charset_modifier);
|
||||
weechat_buffer_set(workspace->buffer, "title",
|
||||
(workspace->name) ? workspace->name : "");
|
||||
|
||||
weechat_buffer_set(workspace->buffer, "nicklist", "1");
|
||||
weechat_buffer_set(workspace->buffer, "nicklist_display_groups", "0");
|
||||
weechat_buffer_set_pointer(workspace->buffer, "nicklist_callback",
|
||||
&slack_buffer_nickcmp_cb);
|
||||
weechat_buffer_set_pointer(workspace->buffer, "nicklist_callback_pointer",
|
||||
workspace);
|
||||
|
||||
return workspace->buffer;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_client_connect_info i;
|
||||
const char *token;
|
||||
|
||||
if (workspace->client_wsi)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error: a websocket already exists"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
token = weechat_config_string(workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]);
|
||||
|
||||
size_t urilen = snprintf(NULL, 0, endpoint, token) + 1;
|
||||
workspace->uri = malloc(urilen);
|
||||
snprintf(workspace->uri, urilen, endpoint, token);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
info.protocols = protocols;
|
||||
|
||||
workspace->context = lws_create_context(&info);
|
||||
if (!workspace->context)
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: error connecting to slack: lws init failed"),
|
||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
workspace->buffer,
|
||||
_("%s%s: contacting slack.com:443"),
|
||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
||||
}
|
||||
|
||||
memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
|
||||
i.context = workspace->context;
|
||||
i.ssl_connection = LCCSCF_USE_SSL;
|
||||
i.port = 443;
|
||||
i.address = "slack.com";
|
||||
i.path = workspace->uri;
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.method = "GET";
|
||||
i.protocol = protocols[0].name;
|
||||
i.pwsi = &workspace->client_wsi;
|
||||
i.userdata = workspace;
|
||||
|
||||
lws_client_connect_via_info(&i);
|
||||
|
||||
workspace->is_connected = 1;
|
||||
}
|
||||
|
||||
int slack_workspace_connect(struct t_slack_workspace *workspace)
|
||||
{
|
||||
workspace->disconnected = 0;
|
||||
|
||||
if (!workspace->buffer)
|
||||
{
|
||||
if (!slack_workspace_create_buffer(workspace))
|
||||
return 0;
|
||||
weechat_buffer_set(workspace->buffer, "display", "auto");
|
||||
}
|
||||
|
||||
slack_workspace_close_connection(workspace);
|
||||
|
||||
slack_workspace_websocket_create(workspace);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls)
|
||||
{
|
||||
struct t_slack_workspace *ptr_workspace;
|
||||
struct t_slack_request *ptr_request;
|
||||
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) remaining_calls;
|
||||
|
||||
for (ptr_workspace = slack_workspaces; ptr_workspace;
|
||||
ptr_workspace = ptr_workspace->next_workspace)
|
||||
{
|
||||
if (!ptr_workspace->is_connected)
|
||||
continue;
|
||||
|
||||
for (ptr_request = ptr_workspace->requests; ptr_request;
|
||||
ptr_request = ptr_request->next_request)
|
||||
{
|
||||
if (ptr_request->client_wsi)
|
||||
{
|
||||
lws_service(ptr_request->context, 0);
|
||||
}
|
||||
else 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;
|
||||
}
|
||||
ptr_request->pointer = NULL;
|
||||
if (ptr_request->data)
|
||||
{
|
||||
free(ptr_request->data);
|
||||
ptr_request->data = NULL;
|
||||
}
|
||||
|
||||
/* remove request from requests list */
|
||||
if (ptr_workspace->last_request == ptr_request)
|
||||
ptr_workspace->last_request = ptr_request->prev_request;
|
||||
if (ptr_request->prev_request)
|
||||
{
|
||||
(ptr_request->prev_request)->next_request = ptr_request->next_request;
|
||||
new_requests = ptr_workspace->requests;
|
||||
}
|
||||
else
|
||||
new_requests = ptr_request->next_request;
|
||||
|
||||
if (ptr_request->next_request)
|
||||
(ptr_request->next_request)->prev_request = ptr_request->prev_request;
|
||||
|
||||
ptr_workspace->requests = new_requests;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr_workspace->client_wsi)
|
||||
{
|
||||
lws_service(ptr_workspace->context, 0);
|
||||
}
|
||||
else if (ptr_workspace->context)
|
||||
{
|
||||
lws_context_destroy(ptr_workspace->context);
|
||||
ptr_workspace->context = NULL;
|
||||
if (ptr_workspace->uri)
|
||||
{
|
||||
free(ptr_workspace->uri);
|
||||
ptr_workspace->uri = NULL;
|
||||
}
|
||||
if (ptr_workspace->ws_url)
|
||||
{
|
||||
slack_api_connect(ptr_workspace);
|
||||
free(ptr_workspace->ws_url);
|
||||
ptr_workspace->ws_url = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
void slack_workspace_register_request(struct t_slack_workspace *workspace,
|
||||
struct t_slack_request *request)
|
||||
{
|
||||
request->prev_request = workspace->last_request;
|
||||
request->next_request = NULL;
|
||||
if (workspace->last_request)
|
||||
(workspace->last_request)->next_request = request;
|
||||
else
|
||||
workspace->requests = request;
|
||||
workspace->last_request = request;
|
||||
}
|
||||
|
||||
struct t_slack_workspace_emoji *slack_workspace_emoji_search(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *name)
|
||||
{
|
||||
struct t_slack_workspace_emoji *ptr_emoji;
|
||||
|
||||
if (!workspace || !name)
|
||||
return NULL;
|
||||
|
||||
for (ptr_emoji = workspace->emoji; ptr_emoji;
|
||||
ptr_emoji = ptr_emoji->next_emoji)
|
||||
{
|
||||
if (weechat_strcasecmp(ptr_emoji->name, name) == 0)
|
||||
return ptr_emoji;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct t_slack_workspace_emoji *slack_workspace_add_emoji(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *name, const char *url)
|
||||
{
|
||||
struct t_slack_workspace_emoji *ptr_emoji, *new_emoji;
|
||||
char shortname[SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN + 1];
|
||||
|
||||
(void) url;
|
||||
|
||||
if (!workspace || !name || !name[0])
|
||||
return NULL;
|
||||
|
||||
snprintf(shortname, SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN + 1,
|
||||
":%s:", name);
|
||||
|
||||
ptr_emoji = slack_workspace_emoji_search(workspace, shortname);
|
||||
if (ptr_emoji)
|
||||
{
|
||||
return ptr_emoji;
|
||||
}
|
||||
|
||||
if ((new_emoji = malloc(sizeof(*new_emoji))) == NULL)
|
||||
return NULL;
|
||||
|
||||
new_emoji->name = strdup(shortname);
|
||||
new_emoji->url = strdup(url);
|
||||
|
||||
new_emoji->prev_emoji = workspace->last_emoji;
|
||||
new_emoji->next_emoji = NULL;
|
||||
if (workspace->last_emoji)
|
||||
(workspace->last_emoji)->next_emoji = new_emoji;
|
||||
else
|
||||
workspace->emoji = new_emoji;
|
||||
workspace->last_emoji = new_emoji;
|
||||
|
||||
return new_emoji;
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef _SLACK_WORKSPACE_H_
|
||||
#define _SLACK_WORKSPACE_H_
|
||||
|
||||
#define SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN 1 + 100 + 1
|
||||
|
||||
extern struct t_slack_workspace *slack_workspaces;
|
||||
extern struct t_slack_workspace *last_slack_workspace;
|
||||
|
||||
struct t_slack_workspace_emoji
|
||||
{
|
||||
char *name;
|
||||
char *url;
|
||||
|
||||
struct t_slack_workspace_emoji *prev_emoji;
|
||||
struct t_slack_workspace_emoji *next_emoji;
|
||||
};
|
||||
|
||||
enum t_slack_workspace_option
|
||||
{
|
||||
SLACK_WORKSPACE_OPTION_TOKEN,
|
||||
SLACK_WORKSPACE_NUM_OPTIONS,
|
||||
};
|
||||
|
||||
struct t_json_chunk
|
||||
{
|
||||
char *data;
|
||||
struct t_json_chunk *next;
|
||||
};
|
||||
|
||||
struct t_slack_workspace
|
||||
{
|
||||
char *id;
|
||||
char *name;
|
||||
char *domain;
|
||||
struct t_config_option *options[SLACK_WORKSPACE_NUM_OPTIONS];
|
||||
|
||||
int reloading_from_config;
|
||||
int reloaded_from_config;
|
||||
|
||||
int is_connected;
|
||||
int disconnected;
|
||||
|
||||
int idx;
|
||||
char *uri;
|
||||
char *ws_url;
|
||||
struct lws *client_wsi;
|
||||
struct lws_context *context;
|
||||
struct t_json_chunk *json_chunks;
|
||||
struct t_slack_request *requests;
|
||||
struct t_slack_request *last_request;
|
||||
|
||||
char *user;
|
||||
char *nick;
|
||||
|
||||
struct t_gui_buffer *buffer;
|
||||
char *buffer_as_string;
|
||||
struct t_slack_user *users;
|
||||
struct t_slack_user *last_user;
|
||||
struct t_slack_channel *channels;
|
||||
struct t_slack_channel *last_channel;
|
||||
struct t_slack_workspace_emoji *emoji;
|
||||
struct t_slack_workspace_emoji *last_emoji;
|
||||
struct t_slack_workspace *prev_workspace;
|
||||
struct t_slack_workspace *next_workspace;
|
||||
};
|
||||
|
||||
extern char *slack_workspace_options[][2];
|
||||
|
||||
struct t_slack_workspace *slack_workspace_search(const char *workspace_domain);
|
||||
struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_domain);
|
||||
int slack_workspace_search_option(const char *option_name);
|
||||
struct t_slack_workspace *slack_workspace_alloc(const char *domain);
|
||||
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 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);
|
||||
int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls);
|
||||
void slack_workspace_register_request(struct t_slack_workspace *workspace,
|
||||
struct t_slack_request *request);
|
||||
struct t_slack_workspace_emoji *slack_workspace_emoji_search(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *name);
|
||||
struct t_slack_workspace_emoji *slack_workspace_add_emoji(
|
||||
struct t_slack_workspace *workspace,
|
||||
const char *name, const char *url);
|
||||
|
||||
#endif /*SLACK_WORKSPACE_H*/
|
Loading…
Reference in New Issue