Skip to content

Commit

Permalink
Switch initial chan loading to conversations.list
Browse files Browse the repository at this point in the history
  • Loading branch information
dylex committed Mar 10, 2018
1 parent 6b4783b commit e49ac69
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 107 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
C_SRCS = slack.c \
slack-cmd.c \
slack-message.c \
slack-conversation.c \
slack-channel.c \
slack-im.c \
slack-user.c \
Expand Down
55 changes: 4 additions & 51 deletions slack-channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static void channel_depart(SlackAccount *sa, SlackChannel *chan) {
}
}

static SlackChannel *channel_update(SlackAccount *sa, json_value *json, SlackChannelType type) {
SlackChannel *slack_channel_set(SlackAccount *sa, json_value *json, SlackChannelType type) {
const char *sid = json_get_strptr(json);
if (sid)
json = NULL;
Expand Down Expand Up @@ -127,54 +127,7 @@ static SlackChannel *channel_update(SlackAccount *sa, json_value *json, SlackCha
}

void slack_channel_update(SlackAccount *sa, json_value *json, SlackChannelType event) {
channel_update(sa, json_get_prop(json, "channel"), event);
}

static void channels_list_cb(SlackAccount *sa, gpointer data, json_value *json, const char *error) {
json_value *chans = json_get_prop_type(json, "channels", array);
if (!chans) {
purple_connection_error_reason(sa->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error ?: "Missing channel list");
return;
}

for (unsigned i = 0; i < chans->u.array.length; i++)
channel_update(sa, chans->u.array.values[i], SLACK_CHANNEL_PUBLIC);

char *cursor = json_get_prop_strptr(json_get_prop(json, "response_metadata"), "next_cursor");
if (cursor && *cursor)
slack_api_call(sa, channels_list_cb, NULL, "channels.list", "exclude_archived", "true", "exclude_members", "true", SLACK_PAGINATE_LIMIT, "cursor", cursor, NULL);
else
slack_groups_load(sa);
}

static void groups_list_cb(SlackAccount *sa, gpointer data, json_value *json, const char *error) {
json_value *chans = json_get_prop_type(json, "groups", array);
if (!chans) {
purple_connection_error_reason(sa->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error ?: "Missing group list");
return;
}

for (unsigned i = 0; i < chans->u.array.length; i++)
channel_update(sa, chans->u.array.values[i], SLACK_CHANNEL_GROUP);

char *cursor = json_get_prop_strptr(json_get_prop(json, "response_metadata"), "next_cursor");
if (cursor && *cursor)
slack_api_call(sa, groups_list_cb, NULL, "groups.list", "exclude_archived", "true", SLACK_PAGINATE_LIMIT, "cursor", cursor, NULL);
else
purple_connection_set_state(sa->gc, PURPLE_CONNECTED);
}

void slack_channels_load(SlackAccount *sa) {
purple_connection_update_progress(sa->gc, "Loading Channels", 6, SLACK_CONNECT_STEPS);
g_hash_table_remove_all(sa->channels);
slack_api_call(sa, channels_list_cb, NULL, "channels.list", "exclude_archived", "true", "exclude_members", "true", SLACK_PAGINATE_LIMIT, NULL);
}

void slack_groups_load(SlackAccount *sa) {
purple_connection_update_progress(sa->gc, "Loading Groups", 7, SLACK_CONNECT_STEPS);
slack_api_call(sa, groups_list_cb, NULL, "groups.list", "exclude_archived", "true", SLACK_PAGINATE_LIMIT, NULL);
slack_channel_set(sa, json_get_prop(json, "channel"), event);
}

struct join_channel {
Expand All @@ -198,7 +151,7 @@ static void channels_info_cb(SlackAccount *sa, gpointer data, json_value *json,
return;
}

SlackChannel *chan = channel_update(sa, json, SLACK_CHANNEL_PUBLIC);
SlackChannel *chan = slack_channel_set(sa, json, SLACK_CHANNEL_PUBLIC);

PurpleConvChat *conv = slack_channel_get_conversation(sa, chan);
if (!conv)
Expand Down Expand Up @@ -256,7 +209,7 @@ static void channels_join_cb(SlackAccount *sa, gpointer data, json_value *json,
struct join_channel *join = data;

SlackChannel *chan = json
? channel_update(sa, json_get_prop(json, "channel"), SLACK_CHANNEL_MEMBER)
? slack_channel_set(sa, json_get_prop(json, "channel"), SLACK_CHANNEL_MEMBER)
: join->chan;

if (!chan || error) {
Expand Down
3 changes: 1 addition & 2 deletions slack-channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ static inline PurpleChat *channel_buddy(SlackChannel *chan) {
}

/* Initialization */
void slack_channels_load(SlackAccount *sa);
void slack_groups_load(SlackAccount *sa);
SlackChannel *slack_channel_set(SlackAccount *sa, json_value *json, SlackChannelType type);

/* Open a purple conversation for a channel */
void slack_chat_open(SlackAccount *sa, SlackChannel *chan);
Expand Down
39 changes: 39 additions & 0 deletions slack-conversation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "slack-json.h"
#include "slack-api.h"
#include "slack-channel.h"
#include "slack-im.h"
#include "slack-conversation.h"

static void conversation_update(SlackAccount *sa, json_value *json) {
if (json_get_prop_boolean(json, "is_im", FALSE))
slack_im_set(sa, json, &json_value_none);
else
slack_channel_set(sa, json, SLACK_CHANNEL_UNKNOWN);
}

#define CONVERSATIONS_LIST_CALL(sa, ARGS...) \
slack_api_call(sa, conversations_list_cb, NULL, "conversations.list", "types", "public_channel,private_channel,mpim,im", "exclude_archived", "true", SLACK_PAGINATE_LIMIT, ##ARGS, NULL)

static void conversations_list_cb(SlackAccount *sa, gpointer data, json_value *json, const char *error) {
json_value *chans = json_get_prop_type(json, "channels", array);
if (!chans) {
purple_connection_error_reason(sa->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error ?: "Missing conversation list");
return;
}

for (unsigned i = 0; i < chans->u.array.length; i++)
conversation_update(sa, chans->u.array.values[i]);

char *cursor = json_get_prop_strptr(json_get_prop(json, "response_metadata"), "next_cursor");
if (cursor && *cursor)
CONVERSATIONS_LIST_CALL(sa, "cursor", cursor);
else
slack_login_step(sa);
}

void slack_conversations_load(SlackAccount *sa) {
g_hash_table_remove_all(sa->channels);
g_hash_table_remove_all(sa->ims);
CONVERSATIONS_LIST_CALL(sa);
}
23 changes: 23 additions & 0 deletions slack-conversation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef _PURPLE_SLACK_CONVERSATION_H
#define _PURPLE_SLACK_CONVERSATION_H

#include "json.h"
#include "slack-object.h"
#include "slack.h"

static inline SlackObject *slack_conversation_lookup_id(SlackAccount *sa, const slack_object_id id) {
return g_hash_table_lookup(sa->channels, id) ?: g_hash_table_lookup(sa->ims, id);
}

static inline SlackObject *slack_conversation_lookup_sid(SlackAccount *sa, const char *sid) {
if (!sid)
return NULL;
slack_object_id id;
slack_object_id_set(id, sid);
return slack_conversation_lookup_id(sa, id);
}

/* Initialization */
void slack_conversations_load(SlackAccount *sa);

#endif // _PURPLE_SLACK_CONVERSATION_H
36 changes: 5 additions & 31 deletions slack-im.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "slack-channel.h"
#include "slack-im.h"

static void slack_presence_sub(SlackAccount *sa) {
void slack_presence_sub(SlackAccount *sa) {
GString *ids = g_string_new("[");
GHashTableIter iter;
gpointer id;
Expand All @@ -31,7 +31,7 @@ static void slack_presence_sub(SlackAccount *sa) {
g_string_free(ids, TRUE);
}

static gboolean im_update(SlackAccount *sa, json_value *json, const json_value *open_user) {
gboolean slack_im_set(SlackAccount *sa, json_value *json, const json_value *open_user) {
const char *sid = json_get_strptr(json);
if (sid)
json = NULL;
Expand Down Expand Up @@ -99,41 +99,15 @@ static gboolean im_update(SlackAccount *sa, json_value *json, const json_value *
}

void slack_im_close(SlackAccount *sa, json_value *json) {
if (im_update(sa, json_get_prop(json, "channel"), NULL))
if (slack_im_set(sa, json_get_prop(json, "channel"), NULL))
slack_presence_sub(sa);
}

void slack_im_open(SlackAccount *sa, json_value *json) {
if (im_update(sa, json_get_prop(json, "channel"), json_get_prop(json, "user")))
if (slack_im_set(sa, json_get_prop(json, "channel"), json_get_prop(json, "user")))
slack_presence_sub(sa);
}

static void im_list_cb(SlackAccount *sa, gpointer data, json_value *json, const char *error) {
json_value *ims = json_get_prop_type(json, "ims", array);
if (!ims) {
purple_connection_error_reason(sa->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error ?: "Missing IM channel list");
return;
}

for (unsigned i = 0; i < ims->u.array.length; i ++)
im_update(sa, ims->u.array.values[i], &json_value_none);

char *cursor = json_get_prop_strptr(json_get_prop(json, "response_metadata"), "next_cursor");
if (cursor && *cursor)
slack_api_call(sa, im_list_cb, NULL, "im.list", SLACK_PAGINATE_LIMIT, "cursor", cursor, NULL);
else {
slack_presence_sub(sa);
slack_channels_load(sa);
}
}

void slack_ims_load(SlackAccount *sa) {
purple_connection_update_progress(sa->gc, "Loading IM channels", 5, SLACK_CONNECT_STEPS);
g_hash_table_remove_all(sa->ims);
slack_api_call(sa, im_list_cb, NULL, "im.list", SLACK_PAGINATE_LIMIT, NULL);
}

struct send_im {
SlackUser *user;
char *msg;
Expand All @@ -160,7 +134,7 @@ static void send_im_open_cb(SlackAccount *sa, gpointer data, json_value *json, c

json = json_get_prop_type(json, "channel", object);
if (json)
im_update(sa, json, &json_value_none);
slack_im_set(sa, json, &json_value_none);

if (error || !*send->user->im) {
purple_conv_present_error(send->user->object.name, sa->account, error ?: "failed to open IM channel");
Expand Down
3 changes: 2 additions & 1 deletion slack-im.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#include "slack.h"

/* Initialization */
void slack_ims_load(SlackAccount *sa);
void slack_presence_sub(SlackAccount *sa);
gboolean slack_im_set(SlackAccount *sa, json_value *json, const json_value *open_user);

/* RTM event handlers */
void slack_im_close(SlackAccount *sa, json_value *json);
Expand Down
4 changes: 2 additions & 2 deletions slack-message.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "slack-api.h"
#include "slack-user.h"
#include "slack-channel.h"
#include "slack-conversation.h"
#include "slack-message.h"

gchar *slack_html_to_message(SlackAccount *sa, const char *s, PurpleMessageFlags flags) {
Expand Down Expand Up @@ -434,8 +435,7 @@ static void handle_message(SlackAccount *sa, SlackObject *obj, json_value *json,
void slack_message(SlackAccount *sa, json_value *json) {
const char *channel_id = json_get_prop_strptr(json, "channel");

handle_message(sa, slack_object_hash_table_lookup(sa->channels, channel_id)
?: slack_object_hash_table_lookup(sa->ims, channel_id),
handle_message(sa, slack_conversation_lookup_sid(sa, channel_id),
json, PURPLE_MESSAGE_RECV);
}

Expand Down
7 changes: 3 additions & 4 deletions slack-rtm.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void rtm_msg(SlackAccount *sa, const char *type, json_value *json) {
slack_channel_update(sa, json, SLACK_CHANNEL_DELETED);
}
else if (!strcmp(type, "hello")) {
slack_users_load(sa);
slack_login_step(sa);
}
else {
purple_debug_info("slack", "Unhandled RTM type %s\n", type);
Expand All @@ -93,7 +93,7 @@ static void rtm_cb(PurpleWebsocket *ws, gpointer data, PurpleWebsocketOp op, con
sa->rtm = NULL;
break;
case PURPLE_WEBSOCKET_OPEN:
purple_connection_update_progress(sa->gc, "RTM Connected", 3, SLACK_CONNECT_STEPS);
slack_login_step(sa);
default:
return;
}
Expand Down Expand Up @@ -164,7 +164,7 @@ static void rtm_connect_cb(SlackAccount *sa, gpointer data, json_value *json, co
/* now that we have team info... */
slack_blist_init(sa);

purple_connection_update_progress(sa->gc, "Connecting to RTM", 2, SLACK_CONNECT_STEPS);
slack_login_step(sa);
purple_debug_info("slack", "RTM URL: %s\n", url);
sa->rtm = purple_websocket_connect(sa->account, url, NULL, rtm_cb, sa);
}
Expand Down Expand Up @@ -206,6 +206,5 @@ void slack_rtm_send(SlackAccount *sa, SlackRTMCallback *callback, gpointer user_
}

void slack_rtm_connect(SlackAccount *sa) {
purple_connection_update_progress(sa->gc, "Requesting RTM", 1, SLACK_CONNECT_STEPS);
slack_api_call(sa, rtm_connect_cb, NULL, "rtm.connect", "batch_presence_aware", "1", "presence_sub", "true", NULL);
}
3 changes: 1 addition & 2 deletions slack-user.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,10 @@ static void users_list_cb(SlackAccount *sa, gpointer data, json_value *json, con
if (cursor && *cursor)
slack_api_call(sa, users_list_cb, NULL, "users.list", "presence", "false", SLACK_PAGINATE_LIMIT, "cursor", cursor, NULL);
else
slack_ims_load(sa);
slack_login_step(sa);
}

void slack_users_load(SlackAccount *sa) {
purple_connection_update_progress(sa->gc, "Loading Users", 4, SLACK_CONNECT_STEPS);
g_hash_table_remove_all(sa->users);
slack_api_call(sa, users_list_cb, NULL, "users.list", "presence", "false", SLACK_PAGINATE_LIMIT, NULL);
}
Expand Down
44 changes: 32 additions & 12 deletions slack.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "slack-user.h"
#include "slack-im.h"
#include "slack-channel.h"
#include "slack-conversation.h"
#include "slack-blist.h"
#include "slack-message.h"
#include "slack-cmd.h"
Expand Down Expand Up @@ -146,18 +147,37 @@ static void slack_login(PurpleAccount *account) {
purple_connection_set_display_name(gc, account->alias ?: account->username);
purple_connection_set_state(gc, PURPLE_CONNECTING);

/* connect order (SLACK_CONNECT_STEPS):
1. slack_rtm_connect
2. slack_connect_cb
purple_websocket_connect
3. rtm_cb
rtm_msg("hello")
4. slack_users_load
5. slack_ims_load
6. slack_channels_load
7. slack_groups_load
*/
slack_rtm_connect(sa);
slack_login_step(sa);
}

void slack_login_step(SlackAccount *sa) {
#define MSG(msg) \
purple_connection_update_progress(sa->gc, msg, ++sa->login_step, 6)
switch (sa->login_step) {
case 0:
MSG("Requesting RTM");
slack_rtm_connect(sa);
break;
case 1: /* slack_connect_cb */
MSG("Connecting to RTM");
/* purple_websocket_connect */
break;
case 2: /* rtm_cb */
MSG("RTM Connected");
break;
case 3: /* rtm_msg("hello") */
MSG("Loading Users");
slack_users_load(sa);
break;
case 4:
MSG("Loading conversations");
slack_conversations_load(sa);
break;
case 5:
slack_presence_sub(sa);
purple_connection_set_state(sa->gc, PURPLE_CONNECTED);
}
#undef MSG
}

static void slack_close(PurpleConnection *gc) {
Expand Down
4 changes: 2 additions & 2 deletions slack.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@

#define SLACK_PLUGIN_ID "prpl-slack"

#define SLACK_CONNECT_STEPS 8

typedef struct _SlackAccount {
PurpleAccount *account;
PurpleConnection *gc;
char *api_url; /* e.g., "https://slack.com/api" */
char *token; /* url encoded */

short login_step;
PurpleWebsocket *rtm;
gulong rtm_id;
GHashTable *rtm_call; /* unsigned rtm_id -> SlackRTMCall */
Expand All @@ -43,6 +42,7 @@ typedef struct _SlackAccount {
PurpleRoomlist *roomlist;
} SlackAccount;

void slack_login_step(SlackAccount *sa);
GHashTable *slack_chat_info_defaults(PurpleConnection *gc, const char *name);

static inline SlackAccount *get_slack_account(PurpleAccount *account) {
Expand Down

0 comments on commit e49ac69

Please sign in to comment.