Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for rtm.start deprecation #308

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions SlackAPI.Tests/Configuration/IntegrationFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,12 @@ private SlackSocketClient CreateClient(string authToken, IWebProxy proxySettings
{
SlackSocketClient client;

var slackNowTakesAgesToConnectTimeout = TimeSpan.FromSeconds(60);

LoginResponse loginResponse = null;
using (var syncClient = new InSync($"{nameof(SlackClient.Connect)} - Connected callback"))
using (var syncClientSocket = new InSync($"{nameof(SlackClient.Connect)} - SocketConnected callback"))
using (var syncClientSocketHello = new InSync($"{nameof(SlackClient.Connect)} - SocketConnected hello callback"))
using (var syncClient = new InSync($"{nameof(SlackClient.Connect)} - Connected callback", slackNowTakesAgesToConnectTimeout))
using (var syncClientSocket = new InSync($"{nameof(SlackClient.Connect)} - SocketConnected callback", slackNowTakesAgesToConnectTimeout))
using (var syncClientSocketHello = new InSync($"{nameof(SlackClient.Connect)} - SocketConnected hello callback", slackNowTakesAgesToConnectTimeout))
{
client = new SlackSocketClient(authToken, proxySettings, maintainPresenceChanges);

Expand Down
2 changes: 1 addition & 1 deletion SlackAPI.Tests/Update.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void UpdatePresence()
var client = this.fixture.UserClient;
using (var sync = new InSync(nameof(SlackClient.EmitPresence)))
{
client.EmitPresence((presence) =>
client.EmitPresence(presence =>
{
presence.AssertOk();
sync.Proceed();
Expand Down
4 changes: 2 additions & 2 deletions SlackAPI.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30320.27
# Visual Studio Version 17
VisualStudioVersion = 17.2.32526.322
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlackAPI", "SlackAPI\SlackAPI.csproj", "{7EED3D9B-9B7A-49A4-AFBF-599153A47DDA}"
EndProject
Expand Down
8 changes: 8 additions & 0 deletions SlackAPI/RPCMessages/BotInfoResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace SlackAPI.RPCMessages
{
[RequestPath("bots.info")]
public class BotInfoResponse : Response
{
public Bot bot;
}
}
1 change: 1 addition & 0 deletions SlackAPI/RPCMessages/ChannelListResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace SlackAPI
{
[RequestPath("channels.list")]
[Obsolete("Replaced by ConversationsListResponse", true)]
public class ChannelListResponse : Response
{
public Channel[] channels;
Expand Down
1 change: 0 additions & 1 deletion SlackAPI/RPCMessages/ConversationsOpenResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ public class ConversationsOpenResponse : Response
public string no_op;
public string already_open;
public Channel channel;
public string error;
}
}
6 changes: 0 additions & 6 deletions SlackAPI/RPCMessages/DialogOpenResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,5 @@ namespace SlackAPI.RPCMessages
[RequestPath("dialog.open")]
public class DialogOpenResponse : Response
{
public ResponseMetadata response_metadata { get; set; }

public class ResponseMetadata
{
public string[] messages { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace SlackAPI
{
[RequestPath("im.list")]
[Obsolete("Replaced by ConversationsListResponse", true)]
public class DirectMessageConversationListResponse : Response
{
public DirectMessageConversation[] ims;
Expand Down
1 change: 1 addition & 0 deletions SlackAPI/RPCMessages/GroupListResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace SlackAPI
{
[RequestPath("groups.list")]
[Obsolete("Replaced by ConversationsListResponse", true)]
public class GroupListResponse : Response
{
public Channel[] groups;
Expand Down
22 changes: 6 additions & 16 deletions SlackAPI/RPCMessages/LoginResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,17 @@

namespace SlackAPI
{
[RequestPath("rtm.start")]
[RequestPath("rtm.connect")]
public class LoginResponse : Response
{
public Bot[] bots;
public Channel[] channels;
public Channel[] groups;
public DirectMessageConversation[] ims;
public Self self;
public int svn_rev;
public int min_svn_rev;
public Team team;
public string url;
public User[] users;
}
{
public string url;
public Team team;
public Self self;
}

public class Self
{
public DateTime created;
public string id;
public string manual_presence;
public string name;
public Preferences prefs;
}
}
145 changes: 107 additions & 38 deletions SlackAPI/SlackClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using SlackAPI.RPCMessages;

namespace SlackAPI
Expand All @@ -25,17 +26,17 @@ public class SlackClient : SlackClientBase

public List<string> starredChannels;

public List<User> Bots;
public List<User> Users;
public List<Bot> Bots;
public List<Channel> Channels;
public List<Channel> Groups;
public List<DirectMessageConversation> DirectMessages;

public Dictionary<string, User> UserLookup;
public Dictionary<string, Channel> ChannelLookup;
public Dictionary<string, Channel> GroupLookup;
public Dictionary<string, DirectMessageConversation> DirectMessageLookup;
public Dictionary<string, Conversation> ConversationLookup;
public Dictionary<string, DirectMessageConversation> DirectMessageLookup;

public SlackClient(string token)
{
Expand All @@ -48,60 +49,114 @@ public SlackClient(string token, IWebProxy proxySettings)
APIToken = token;
}

public virtual void Connect(Action<LoginResponse> onConnected = null, Action onSocketConnected = null)
public virtual void Connect(Action<LoginResponse> onConnected = null, Action onSocketConnected = null, int timeoutSeconds = 60)
{
EmitLogin((loginDetails) =>
EmitLogin(loginDetails =>
{
if (loginDetails.ok)
Connected(loginDetails);
Connected(loginDetails, timeoutSeconds);

if (onConnected != null)
onConnected(loginDetails);
});
}

protected virtual void Connected(LoginResponse loginDetails)
protected virtual void Connected(LoginResponse loginDetails, int timeoutSeconds)
{
MySelf = loginDetails.self;
MyData = loginDetails.users.First((c) => c.id == MySelf.id);
MyTeam = loginDetails.team;

Users = new List<User>(loginDetails.users.Where((c) => !c.deleted));
Bots = new List<Bot>(loginDetails.bots.Where((c) => !c.deleted));
Channels = new List<Channel>(loginDetails.channels);
Groups = new List<Channel>(loginDetails.groups);
DirectMessages = new List<DirectMessageConversation>(loginDetails.ims.Where((c) => Users.Exists((a) => a.id == c.user) && c.id != MySelf.id));
starredChannels =
Groups.Where((c) => c.is_starred).Select((c) => c.id)
.Union(
DirectMessages.Where((c) => c.is_starred).Select((c) => c.user)
).Union(
Channels.Where((c) => c.is_starred).Select((c) => c.id)
).ToList();

UserLookup = new Dictionary<string, User>();
foreach (User u in Users) UserLookup.Add(u.id, u);

ChannelLookup = new Dictionary<string, Channel>();
ConversationLookup = new Dictionary<string, Conversation>();
foreach (Channel c in Channels)
var taskWaiter = new CountdownEvent(2);
var channels = new List<Channel>();

GetUserList(response =>
{
ChannelLookup.Add(c.id, c);
ConversationLookup.Add(c.id, c);
}
if (response.ok)
{
MyData = response.members.First(c => c.id == MySelf.id);
Users = new List<User>(response.members.Where(c => !c.deleted && !c.IsSlackBot));
Bots = new List<User>(response.members.Where(c => !c.deleted && c.IsSlackBot));
}
else
{
loginDetails.ok = false;
loginDetails.error = response.error;
}

GroupLookup = new Dictionary<string, Channel>();
foreach (Channel g in Groups)
taskWaiter.Signal();
});

GetConversationsList(response =>
{
GroupLookup.Add(g.id, g);
ConversationLookup.Add(g.id, g);
}
if (response.ok)
{
channels.AddRange(response.channels);
}
else
{
loginDetails.ok = false;
loginDetails.error = response.error;
}

taskWaiter.Signal();
}, ExcludeArchived: true);

var released = taskWaiter.Wait(TimeSpan.FromSeconds(timeoutSeconds));

DirectMessageLookup = new Dictionary<string, DirectMessageConversation>();
foreach (DirectMessageConversation im in DirectMessages)
if (released && loginDetails.ok)
{
DirectMessageLookup.Add(im.id, im);
ConversationLookup.Add(im.id, im);
Channels = new List<Channel>(channels.Where(x => x.is_channel));
Groups = new List<Channel>(channels.Where(x => x.is_group));
starredChannels =
Channels.Where(c => c.is_starred).Select(c => c.id)
.Union(
DirectMessages.Where(c => c.is_starred).Select(c => c.user)
).Union(
Channels.Where(c => c.is_starred).Select(c => c.id)
).ToList();
DirectMessages = new List<DirectMessageConversation>(
channels
.Where(x => x.is_im && Users.Exists(u => u.id == x.user) && x.id != MySelf.id)
.Select(x => new DirectMessageConversation
{
created = x.created,
id = x.id,
is_open = x.is_open,
is_starred = x.is_starred,
is_user_deleted = UserLookup[x.user].deleted,
last_read = x.last_read,
latest = x.latest,
unread_count = x.unread_count,
user = x.user
}));

UserLookup = new Dictionary<string, User>();
foreach (User u in Users) UserLookup.Add(u.id, u);

ChannelLookup = new Dictionary<string, Channel>();
ConversationLookup = new Dictionary<string, Conversation>();
foreach (Channel c in Groups)
{
ChannelLookup.Add(c.id, c);
ConversationLookup.Add(c.id, c);
}

GroupLookup = new Dictionary<string, Channel>();
foreach (Channel g in Channels)
{
GroupLookup.Add(g.id, g);
ConversationLookup.Add(g.id, g);
}

DirectMessageLookup = new Dictionary<string, DirectMessageConversation>();
foreach (DirectMessageConversation im in DirectMessages)
DirectMessageLookup.Add(im.id, im);

}
else if (!released && loginDetails.ok)
{
loginDetails.ok = false;
loginDetails.error = "Timed out loading login details";
}
}

Expand Down Expand Up @@ -170,16 +225,20 @@ public void GetConversationsMembers(Action<ConversationsMembersResponse> callbac
APIRequestWithToken(callback, parameters.ToArray());
}


[Obsolete("Replaced by GetConversionsList", true)]
public void GetChannelList(Action<ChannelListResponse> callback, bool ExcludeArchived = true)
{
APIRequestWithToken(callback, new Tuple<string, string>("exclude_archived", ExcludeArchived ? "1" : "0"));
}

[Obsolete("Replaced by GetConversionsList", true)]
public void GetGroupsList(Action<GroupListResponse> callback, bool ExcludeArchived = true)
{
APIRequestWithToken(callback, new Tuple<string, string>("exclude_archived", ExcludeArchived ? "1" : "0"));
}

[Obsolete("Replaced by GetConversionsList", true)]
public void GetDirectMessageList(Action<DirectMessageConversationListResponse> callback)
{
APIRequestWithToken(callback);
Expand Down Expand Up @@ -606,6 +665,16 @@ public void GetInfo(Action<UserInfoResponse> callback, string user)
APIRequestWithToken(callback, new Tuple<string, string>("user", user));
}

public void GetBotInfo(Action<BotInfoResponse> callback, string botUser, string teamId = null)
{
var parameters = new List<Tuple<string, string>> { new Tuple<string, string>("bot", botUser) };

if (!string.IsNullOrWhiteSpace(teamId))
parameters.Add(new Tuple<string, string>("team_id", teamId));

APIRequestWithToken(callback, parameters.ToArray());
}

#endregion

public void EmitLogin(Action<LoginResponse> callback, string agent = "Inumedia.SlackAPI")
Expand Down
2 changes: 1 addition & 1 deletion SlackAPI/SlackClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public void RegisterConverter(JsonConverter converter)
{
if (converter == null)
{
throw new ArgumentNullException("converter");
throw new ArgumentNullException(nameof(converter));
}

Extensions.Converters.Add(converter);
Expand Down
6 changes: 3 additions & 3 deletions SlackAPI/SlackSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public SlackSocket(LoginResponse loginDetails, object routingTo, Action onConnec
currentId = 1;

cts = new CancellationTokenSource();
socket.ConnectAsync(new Uri(string.Format("{0}?svn_rev={1}&login_with_boot_data-0-{2}&on_login-0-{2}&connect-1-{2}", loginDetails.url, loginDetails.svn_rev, DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds)), cts.Token).Wait();
socket.ConnectAsync(new Uri(string.Format("{0}?login_with_boot_data-0-{1}&on_login-0-{1}&connect-1-{1}", loginDetails.url, DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds)), cts.Token).Wait();
if(onConnected != null)
onConnected();
SetupReceiving();
Expand Down Expand Up @@ -136,7 +136,7 @@ public void Send<K>(SlackSocketMessage message, Action<K> callback)
{
int sendingId = Interlocked.Increment(ref currentId);
message.id = sendingId;
callbacks.Add(sendingId, (c) =>
callbacks.Add(sendingId, c =>
{
K obj = c.Deserialize<K>();
callback(obj);
Expand Down Expand Up @@ -232,7 +232,7 @@ void SetupReceiving()
continue;
}

string data = string.Join("", buffers.Select((c) => Encoding.UTF8.GetString(c).TrimEnd('\0')));
string data = string.Join("", buffers.Select(c => Encoding.UTF8.GetString(c).TrimEnd('\0')));
//Console.WriteLine("SlackSocket data = " + data);
SlackSocketMessage message = null;
try
Expand Down
Loading