From 851e8ea6a72adbb365c43222b3b361dbc143d839 Mon Sep 17 00:00:00 2001 From: Sky Morey Date: Fri, 12 Jan 2018 12:01:41 -0600 Subject: [PATCH] Added PresenceSub --- README.md | 4 +- SlackAPI.Console/Program.cs | 8 +- .../Configuration/IntegrationFixture.cs | 8 +- SlackAPI.Tests/Configuration/SlackConfig.cs | 2 +- .../Configuration/config.default.json | 10 +- SlackAPI.Tests/Connect.cs | 9 +- SlackAPI.Tests/PostMessage.cs | 6 +- SlackAPI.Tests/PresenceSub.cs | 41 +++++++ SlackAPI.Tests/SlackAPI.Tests.csproj | 1 + SlackAPI.Tests/Update.cs | 5 +- SlackAPI.Tests/Users.cs | 1 + SlackAPI/Extensions.cs | 2 +- SlackAPI/JavascriptBotsToArray.cs | 4 +- SlackAPI/JavascriptDateTimeConverter.cs | 4 +- ...resenseResponse.cs => PresenceResponse.cs} | 0 SlackAPI/Request.cs | 14 +-- SlackAPI/RequestStateForTask.cs | 12 +- SlackAPI/SlackAPI.csproj | 3 +- SlackAPI/SlackClient.cs | 106 ++++++++++-------- SlackAPI/SlackSocket.cs | 58 +++++----- SlackAPI/SlackSocketClient.cs | 36 +++--- SlackAPI/SlackTaskClient.cs | 71 ++++++------ SlackAPI/Utilities/LockFreeQueue.cs | 18 +-- SlackAPI/WebSocketMessages/Hello.cs | 4 +- SlackAPI/WebSocketMessages/Ping.cs | 4 +- SlackAPI/WebSocketMessages/Pong.cs | 4 +- SlackAPI/WebSocketMessages/PresenceChange.cs | 4 +- SlackAPI/WebSocketMessages/PresenceSub.cs | 8 ++ SlackAPI/WebSocketMessages/ReactionAdded.cs | 9 +- SlackAPI/WebSocketMessages/Typing.cs | 4 +- SlackAPI/WebSocketMessages/UserChange.cs | 1 - appveyor.yml | 2 +- 32 files changed, 262 insertions(+), 201 deletions(-) create mode 100644 SlackAPI.Tests/PresenceSub.cs rename SlackAPI/RPCMessages/{PresenseResponse.cs => PresenceResponse.cs} (100%) create mode 100644 SlackAPI/WebSocketMessages/PresenceSub.cs diff --git a/README.md b/README.md index 2d3ac70..e5e0e7d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # SlackAPI -This is a third party implementation of Slack's API written in C#. This supports their WebAPI aswell as their Real Time Messaging API. +This is a third party implementation of Slack's API written in C#. This supports their WebAPI as well as their Real Time Messaging API. # Examples @@ -24,7 +24,7 @@ Want committer access? Feel like I'm too lazy to keep up with Slack's ever chang Create some pull requests, give me a reason to give you access. -# Howto build the solution +# How to build the solution ###### (aka where is the config.json file?) The project **SlackAPI.Tests** requires a valid `config.json` file for tests. You have two options to build the solution: - Unload SlackAPI.Tests project and you're able to build SlackAPI solution. diff --git a/SlackAPI.Console/Program.cs b/SlackAPI.Console/Program.cs index f5e62a6..e57cf22 100644 --- a/SlackAPI.Console/Program.cs +++ b/SlackAPI.Console/Program.cs @@ -10,9 +10,9 @@ static void Main(string[] args) { try { - var clientId = "PUT CLIENT ID FROM SLACK APPLICATION REGISTATION HERE"; - var clientSecret = "PUT CLIENT SECRET FROM SLACK APPLICATION REGISTATION HERE"; - var redirectUri = "PUT REDIRECT FROM SLACK APPLICATION REGISTATION HERE"; + var clientId = "58195700114.297428006771"; // PUT CLIENT ID FROM SLACK APPLICATION REGISTATION HERE"; + var clientSecret = "70e8cbec2fa97cf376d526954a86b289"; // PUT CLIENT SECRET FROM SLACK APPLICATION REGISTATION HERE"; + var redirectUri = "http://localhost"; // PUT REDIRECT FROM SLACK APPLICATION REGISTATION HERE"; Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("This app will open your web browser pointing at an authentication"); @@ -26,7 +26,7 @@ static void Main(string[] args) // start... var state = Guid.NewGuid().ToString(); - var uri = SlackClient.GetAuthorizeUri(clientId, SlackScope.Identify | SlackScope.Read | SlackScope.Post, redirectUri, state, "socialsaleslounge"); + var uri = SlackClient.GetAuthorizeUri(clientId, SlackScope.Identify | SlackScope.Read | SlackScope.Post | SlackScope.Client, redirectUri, state, "socialsaleslounge"); Console.WriteLine("Directing to: " + uri); Process.Start(uri.ToString()); diff --git a/SlackAPI.Tests/Configuration/IntegrationFixture.cs b/SlackAPI.Tests/Configuration/IntegrationFixture.cs index f8ac8cf..79638b7 100755 --- a/SlackAPI.Tests/Configuration/IntegrationFixture.cs +++ b/SlackAPI.Tests/Configuration/IntegrationFixture.cs @@ -13,6 +13,7 @@ public IntegrationFixture() { this.Config = this.GetConfig(); this.UserClient = this.GetClient(this.Config.UserAuthToken); + this.UserClientWithPresence = this.GetClient(this.Config.UserAuthToken, new[] { new Tuple("batch_presence_aware", "true") }); this.BotClient = this.GetClient(this.Config.BotAuthToken); } @@ -20,11 +21,14 @@ public IntegrationFixture() public SlackSocketClient UserClient { get; } + public SlackSocketClient UserClientWithPresence { get; } + public SlackSocketClient BotClient { get; } public void Dispose() { this.UserClient.CloseSocket(); + this.UserClientWithPresence.CloseSocket(); this.BotClient.CloseSocket(); } @@ -39,14 +43,14 @@ private SlackConfig GetConfig() return JsonConvert.DeserializeAnonymousType(json, jsonObject).slack; } - private SlackSocketClient GetClient(string authToken) + private SlackSocketClient GetClient(string authToken, Tuple[] loginParameters = null) { SlackSocketClient client; using (var syncClient = new InSync($"{nameof(SlackClient.Connect)} - Connected callback")) using (var syncClientSocket = new InSync($"{nameof(SlackClient.Connect)} - SocketConnected callback")) { - client = new SlackSocketClient(authToken); + client = new SlackSocketClient(authToken, loginParameters); client.Connect(x => { Console.WriteLine("Connected"); diff --git a/SlackAPI.Tests/Configuration/SlackConfig.cs b/SlackAPI.Tests/Configuration/SlackConfig.cs index dbaaa67..84111b6 100644 --- a/SlackAPI.Tests/Configuration/SlackConfig.cs +++ b/SlackAPI.Tests/Configuration/SlackConfig.cs @@ -4,7 +4,7 @@ public class SlackConfig { public string UserAuthToken { get; set; } public string BotAuthToken { get; set; } - public string TestChannel { get; set; } + public string TestChannelId { get; set; } public string DirectMessageUser { get; set; } public string AuthCode { get; set; } public string ClientId { get; set; } diff --git a/SlackAPI.Tests/Configuration/config.default.json b/SlackAPI.Tests/Configuration/config.default.json index bec134d..244df4b 100644 --- a/SlackAPI.Tests/Configuration/config.default.json +++ b/SlackAPI.Tests/Configuration/config.default.json @@ -2,10 +2,10 @@ "slack": { "userAuthToken": "token-tokentoken-tokentoken-tokentoken-token", "botAuthToken": "bottoken-bottoken-bottoken-bottoken", - "testChannel": "SuperSecretChannel", - "directMessageUser": "someUserId", - "authCode": "some-super-secret-code-from-Slack-specially-created-for-you-=)", - "clientId": "your-special-id", - "clientSecret": "such-special-secret-key" + "testChannelId": "someChannelId", + "directMessageUser": "someUserId", + "authCode": "some-super-secret-code-from-Slack-specially-created-for-you-=)", + "clientId": "your-special-id", + "clientSecret": "such-special-secret-key" } } diff --git a/SlackAPI.Tests/Connect.cs b/SlackAPI.Tests/Connect.cs index a0863eb..0bb4cc7 100644 --- a/SlackAPI.Tests/Connect.cs +++ b/SlackAPI.Tests/Connect.cs @@ -24,6 +24,13 @@ public void TestConnectAsUser() Assert.True(client.IsConnected, "Invalid, doesn't think it's connected."); } + [Fact] + public void TestConnectAsUserWithPresence() + { + var client = this.fixture.UserClientWithPresence; + Assert.True(client.IsConnected, "Invalid, doesn't think it's connected."); + } + [Fact(Skip = "Unable to get a working test with data we have in config.json")] public void TestGetAccessToken() { @@ -71,7 +78,7 @@ public void TestConnectPostAndDelete() { // given SlackSocketClient client = this.fixture.UserClient; - string channel = this.fixture.Config.TestChannel; + string channel = this.fixture.Config.TestChannelId; // when DateTime messageTimestamp = PostMessage(client, channel); diff --git a/SlackAPI.Tests/PostMessage.cs b/SlackAPI.Tests/PostMessage.cs index b1949dd..442df89 100644 --- a/SlackAPI.Tests/PostMessage.cs +++ b/SlackAPI.Tests/PostMessage.cs @@ -30,7 +30,7 @@ public void SimpleMessageDelivery() actual = response; sync.Proceed(); }, - this.fixture.Config.TestChannel, + this.fixture.Config.TestChannelId, "Hi there!"); } @@ -56,7 +56,7 @@ public void Attachments() actual = response; sync.Proceed(); }, - this.fixture.Config.TestChannel, + this.fixture.Config.TestChannelId, string.Empty, attachments: SlackMother.SomeAttachments); } @@ -81,7 +81,7 @@ public void AttachmentsWithActions() actual = response; sync.Proceed(); }, - this.fixture.Config.TestChannel, + this.fixture.Config.TestChannelId, string.Empty, attachments: SlackMother.SomeAttachmentsWithActions); } diff --git a/SlackAPI.Tests/PresenceSub.cs b/SlackAPI.Tests/PresenceSub.cs new file mode 100644 index 0000000..a11ac50 --- /dev/null +++ b/SlackAPI.Tests/PresenceSub.cs @@ -0,0 +1,41 @@ +using SlackAPI.Tests.Configuration; +using SlackAPI.Tests.Helpers; +using System.Linq; +using Xunit; + +namespace SlackAPI.Tests +{ + [Collection("Integration tests")] + public class PresenceSub + { + private readonly IntegrationFixture fixture; + + public PresenceSub(IntegrationFixture fixture) + { + this.fixture = fixture; + } + + [Fact] + public void PresenceSubscribe() + { + var client = this.fixture.UserClientWithPresence; + var directMessageUser = client.Users.FirstOrDefault(x => x.name == this.fixture.Config.DirectMessageUser); + Assert.NotNull(directMessageUser); + + //UserListResponse actual = null; + using (var sync = new InSync(nameof(SlackClient.UserLookup))) + { + client.OnPresenceChangeReceived += (user) => + { + + }; + client.OnUserChangeReceived += (user) => + { + + }; + client.SendPresenceSub(new[] { directMessageUser.id }); + sync.Proceed(); + } + } + } +} \ No newline at end of file diff --git a/SlackAPI.Tests/SlackAPI.Tests.csproj b/SlackAPI.Tests/SlackAPI.Tests.csproj index 1389905..b738631 100644 --- a/SlackAPI.Tests/SlackAPI.Tests.csproj +++ b/SlackAPI.Tests/SlackAPI.Tests.csproj @@ -73,6 +73,7 @@ + diff --git a/SlackAPI.Tests/Update.cs b/SlackAPI.Tests/Update.cs index 8853e19..c60bcbd 100644 --- a/SlackAPI.Tests/Update.cs +++ b/SlackAPI.Tests/Update.cs @@ -1,5 +1,6 @@ using SlackAPI.Tests.Configuration; using SlackAPI.Tests.Helpers; +using System; using Xunit; namespace SlackAPI.Tests @@ -32,7 +33,7 @@ public void SimpleUpdate() sync.Proceed(); }, messageId, - this.fixture.Config.TestChannel, + this.fixture.Config.TestChannelId, "[changed]", attachments: SlackMother.SomeAttachments, as_user: true); @@ -56,7 +57,7 @@ private string PostedMessage(SlackSocketClient client) Assert.True(response.ok, "Error while posting message to channel. "); sync.Proceed(); }, - this.fixture.Config.TestChannel, + this.fixture.Config.TestChannelId, "Hi there!", as_user: true); } diff --git a/SlackAPI.Tests/Users.cs b/SlackAPI.Tests/Users.cs index 3cb85f6..ffa5563 100644 --- a/SlackAPI.Tests/Users.cs +++ b/SlackAPI.Tests/Users.cs @@ -14,6 +14,7 @@ public Users(IntegrationFixture fixture) { this.fixture = fixture; } + [Fact] public void UserList() { diff --git a/SlackAPI/Extensions.cs b/SlackAPI/Extensions.cs index 04206ed..04ecdc3 100644 --- a/SlackAPI/Extensions.cs +++ b/SlackAPI/Extensions.cs @@ -36,7 +36,7 @@ public static object Deserialize(this string data, Type type) private static JsonSerializerSettings CreateSettings() { - JsonSerializerSettings settings = new JsonSerializerSettings(); + var settings = new JsonSerializerSettings(); settings.Converters = Converters; return settings; diff --git a/SlackAPI/JavascriptBotsToArray.cs b/SlackAPI/JavascriptBotsToArray.cs index c8f3e15..565f1a0 100644 --- a/SlackAPI/JavascriptBotsToArray.cs +++ b/SlackAPI/JavascriptBotsToArray.cs @@ -12,12 +12,12 @@ public override bool CanConvert(Type objectType) public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { - List bots = new List(); + var bots = new List(); int d = reader.Depth; while (reader.Read() && reader.Depth > d) { - Bot current = new Bot(); + var current = new Bot(); int depth = reader.Depth; current.name = reader.Value.ToString(); diff --git a/SlackAPI/JavascriptDateTimeConverter.cs b/SlackAPI/JavascriptDateTimeConverter.cs index d37fa13..7d6c73e 100644 --- a/SlackAPI/JavascriptDateTimeConverter.cs +++ b/SlackAPI/JavascriptDateTimeConverter.cs @@ -12,8 +12,8 @@ public override bool CanConvert(Type objectType) public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { - decimal value = decimal.Parse(reader.Value.ToString(), CultureInfo.InvariantCulture); - DateTime res = new DateTime(621355968000000000 + (long)(value * 10000000m)).ToLocalTime(); + var value = decimal.Parse(reader.Value.ToString(), CultureInfo.InvariantCulture); + var res = new DateTime(621355968000000000 + (long)(value * 10000000m)).ToLocalTime(); System.Diagnostics.Debug.Assert( Decimal.Equals( Decimal.Parse(res.ToProperTimeStamp()), diff --git a/SlackAPI/RPCMessages/PresenseResponse.cs b/SlackAPI/RPCMessages/PresenceResponse.cs similarity index 100% rename from SlackAPI/RPCMessages/PresenseResponse.cs rename to SlackAPI/RPCMessages/PresenceResponse.cs diff --git a/SlackAPI/Request.cs b/SlackAPI/Request.cs index 5a84971..3e54473 100644 --- a/SlackAPI/Request.cs +++ b/SlackAPI/Request.cs @@ -43,9 +43,9 @@ public void GotRequest(IAsyncResult result) if (result.AsyncState != this) throw new InvalidOperationException("This shouldn't be happening! D:"); - using (Stream requestStream = request.EndGetRequestStream(result)) + using (var requestStream = request.EndGetRequestStream(result)) if (Post.Length > 0) - using (StreamWriter writer = new StreamWriter(requestStream)) + using (var writer = new StreamWriter(requestStream)) { bool first = true; foreach (Tuple postEntry in Post) @@ -81,8 +81,8 @@ internal void GotResponse(IAsyncResult result) K responseObj; - using (Stream responseReading = response.GetResponseStream()) - using (StreamReader reader = new StreamReader(responseReading)) + using (var responseReading = response.GetResponseStream()) + using (var reader = new StreamReader(responseReading)) { string responseData = reader.ReadToEnd(); responseObj = responseData.Deserialize(); @@ -109,13 +109,13 @@ public RequestPath(string requestPath, bool isPrimaryAPI = true) public static RequestPath GetRequestPath() { - Type t = typeof(K); + var t = typeof(K); if (paths.ContainsKey(t)) return paths[t]; - TypeInfo info = t.GetTypeInfo(); + var info = t.GetTypeInfo(); - RequestPath path = info.GetCustomAttribute(); + var path = info.GetCustomAttribute(); if (path == null) throw new InvalidOperationException(string.Format("No valid request path for {0}", t.Name)); paths.Add(t, path); diff --git a/SlackAPI/RequestStateForTask.cs b/SlackAPI/RequestStateForTask.cs index 6ffc955..735f625 100644 --- a/SlackAPI/RequestStateForTask.cs +++ b/SlackAPI/RequestStateForTask.cs @@ -48,9 +48,9 @@ private async Task ExecuteResult() K responseObj; - using (Stream responseReading = response.GetResponseStream()) + using (var responseReading = response.GetResponseStream()) { - using (StreamReader reader = new StreamReader(responseReading)) + using (var reader = new StreamReader(responseReading)) { string responseData = reader.ReadToEnd(); responseObj = responseData.Deserialize(); @@ -64,14 +64,14 @@ private async Task ExecutePost() { request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; - using (Stream requestStream = await request.GetRequestStreamAsync()) + using (var requestStream = await request.GetRequestStreamAsync()) { if (Post.Length > 0) { - using (StreamWriter writer = new StreamWriter(requestStream)) + using (var writer = new StreamWriter(requestStream)) { - bool first = true; - foreach (Tuple postEntry in Post) + var first = true; + foreach (var postEntry in Post) { if (!first) writer.Write('&'); diff --git a/SlackAPI/SlackAPI.csproj b/SlackAPI/SlackAPI.csproj index e1c54aa..bf8eff9 100644 --- a/SlackAPI/SlackAPI.csproj +++ b/SlackAPI/SlackAPI.csproj @@ -114,7 +114,7 @@ - + @@ -173,6 +173,7 @@ + diff --git a/SlackAPI/SlackClient.cs b/SlackAPI/SlackClient.cs index dfc0c08..6bc3e8c 100644 --- a/SlackAPI/SlackClient.cs +++ b/SlackAPI/SlackClient.cs @@ -19,7 +19,8 @@ namespace SlackAPI public class SlackClient { readonly string APIToken; - bool authWorks = false; + readonly Tuple[] APILoginParameters; + //bool authWorks = false; const string APIBaseLocation = "https://slack.com/api/"; const int Timeout = 5000; @@ -57,9 +58,10 @@ public class SlackClient //public event Action OnPresenceChanged; //public event Action OnHello; - public SlackClient(string token) + public SlackClient(string token, Tuple[] loginParameters = null) { APIToken = token; + APILoginParameters = loginParameters; } public virtual void Connect(Action onConnected = null, Action onSocketConnected = null) @@ -68,6 +70,8 @@ public virtual void Connect(Action onConnected = null, Action onS { if (loginDetails.ok) Connected(loginDetails); + else + throw new InvalidOperationException(loginDetails.error); if (onConnected != null) onConnected(loginDetails); }); @@ -92,25 +96,25 @@ protected virtual void Connected(LoginResponse loginDetails) ).ToList(); UserLookup = new Dictionary(); - foreach (User u in Users) UserLookup.Add(u.id, u); + foreach (var u in Users) UserLookup.Add(u.id, u); ChannelLookup = new Dictionary(); ConversationLookup = new Dictionary(); - foreach (Channel c in Channels) + foreach (var c in Channels) { ChannelLookup.Add(c.id, c); ConversationLookup.Add(c.id, c); } GroupLookup = new Dictionary(); - foreach (Channel g in Groups) + foreach (var g in Groups) { GroupLookup.Add(g.id, g); ConversationLookup.Add(g.id, g); } DirectMessageLookup = new Dictionary(); - foreach (DirectMessageConversation im in DirectMessages) + foreach (var im in DirectMessages) { DirectMessageLookup.Add(im.id, im); ConversationLookup.Add(im.id, im); @@ -119,7 +123,7 @@ protected virtual void Connected(LoginResponse loginDetails) internal static Uri GetSlackUri(string path, Tuple[] getParameters) { - string parameters = getParameters + var parameters = getParameters .Where(x => x.Item2 != null) .Select(new Func, string>(a => { @@ -127,22 +131,22 @@ internal static Uri GetSlackUri(string path, Tuple[] getParamete catch (Exception ex) { throw new InvalidOperationException(string.Format("Failed when processing '{0}'.", a), ex); } })) .Aggregate((a, b) => (string.IsNullOrEmpty(a) ? b : string.Format("{0}&{1}", a, b))); - Uri requestUri = new Uri(string.Format("{0}?{1}", path, parameters)); + var requestUri = new Uri(string.Format("{0}?{1}", path, parameters)); return requestUri; } public static void APIRequest(Action callback, Tuple[] getParameters, Tuple[] postParameters) where K : Response { - RequestPath path = RequestPath.GetRequestPath(); + var path = RequestPath.GetRequestPath(); //TODO: Custom paths? Appropriate subdomain paths? Not sure. //Maybe store custom path in the requestpath.path itself? - Uri requestUri = GetSlackUri(Path.Combine(APIBaseLocation, path.Path), getParameters); - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri); + var requestUri = GetSlackUri(Path.Combine(APIBaseLocation, path.Path), getParameters); + var request = (HttpWebRequest)HttpWebRequest.Create(requestUri); //This will handle all of the processing. - RequestState state = new RequestState(request, postParameters, callback); + var state = new RequestState(request, postParameters, callback); state.Begin(); } @@ -155,7 +159,7 @@ public static void APIGetRequest(Action callback, params Tuple(Action callback, params Tuple[] getParameters) where K : Response { - Tuple[] tokenArray = new Tuple[]{ + var tokenArray = new Tuple[]{ new Tuple("token", APIToken) }; @@ -175,7 +179,7 @@ public static void FindTeam(Action callback, string team) { //This seems to accept both 'team.slack.com' and just plain 'team'. //Going to go with the latter. - Tuple domainName = new Tuple("domain", team); + var domainName = new Tuple("domain", team); APIRequest(callback, new Tuple[] { domainName }, new Tuple[0]); } @@ -218,7 +222,7 @@ public void GetDirectMessageList(Action c public void GetFiles(Action callback, string userId = null, DateTime? from = null, DateTime? to = null, int? count = null, int? page = null, FileTypes types = FileTypes.all) { - List> parameters = new List>(); + var parameters = new List>(); if (!string.IsNullOrEmpty(userId)) parameters.Add(new Tuple("user", userId)); @@ -231,11 +235,11 @@ public void GetFiles(Action callback, string userId = null, Da if (!types.HasFlag(FileTypes.all)) { - FileTypes[] values = (FileTypes[])Enum.GetValues(typeof(FileTypes)); + var values = (FileTypes[])Enum.GetValues(typeof(FileTypes)); - StringBuilder building = new StringBuilder(); - bool first = true; - for (int i = 0; i < values.Length; ++i) + var building = new StringBuilder(); + var first = true; + for (var i = 0; i < values.Length; ++i) { if (types.HasFlag(values[i])) { @@ -263,7 +267,7 @@ public void GetFiles(Action callback, string userId = null, Da void GetHistory(Action historyCallback, string channel, DateTime? latest = null, DateTime? oldest = null, int? count = null) where K : MessageHistory { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channel)); if (latest.HasValue) @@ -301,7 +305,7 @@ public void MarkChannel(Action callback, string channelId, DateTim public void GetFileInfo(Action callback, string fileId, int? page = null, int? count = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("file", fileId)); @@ -313,6 +317,7 @@ public void GetFileInfo(Action callback, string fileId, int? p APIRequestWithToken(callback, parameters.ToArray()); } + #region Groups public void GroupsArchive(Action callback, string channelId) { @@ -336,7 +341,7 @@ public void GroupsCreateChild(Action callback, string public void GroupsInvite(Action callback, string userId, string channelId) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("user", userId)); @@ -346,7 +351,7 @@ public void GroupsInvite(Action callback, string userId, st public void GroupsKick(Action callback, string userId, string channelId) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("user", userId)); @@ -371,7 +376,7 @@ public void GroupsOpen(Action callback, string channelId) public void GroupsRename(Action callback, string channelId, string name) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("name", name)); @@ -381,7 +386,7 @@ public void GroupsRename(Action callback, string channelId, public void GroupsSetPurpose(Action callback, string channelId, string purpose) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("purpose", purpose)); @@ -391,7 +396,7 @@ public void GroupsSetPurpose(Action callback, string ch public void GroupsSetTopic(Action callback, string channelId, string topic) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("topic", topic)); @@ -408,7 +413,7 @@ public void GroupsUnarchive(Action callback, string chan public void SearchAll(Action callback, string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) @@ -431,7 +436,7 @@ public void SearchAll(Action callback, string query, SearchSo public void SearchMessages(Action callback, string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) @@ -454,7 +459,7 @@ public void SearchMessages(Action callback, string query public void SearchFiles(Action callback, string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) @@ -477,7 +482,7 @@ public void SearchFiles(Action callback, string query, Sear public void GetStars(Action callback, string userId = null, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); if (!string.IsNullOrEmpty(userId)) parameters.Add(new Tuple("user", userId)); @@ -493,7 +498,7 @@ public void GetStars(Action callback, string userId = null, in public void DeleteMessage(Action callback, string channelId, DateTime ts) { - List> parameters = new List>() + var parameters = new List>() { new Tuple("ts", ts.ToProperTimeStamp()), new Tuple("channel", channelId) @@ -533,7 +538,14 @@ public void GetInfo(Action callback, string user) public void EmitLogin(Action callback, string agent = "Inumedia.SlackAPI") { - APIRequestWithToken(callback, new Tuple("agent", agent)); + var parameterArray = new Tuple[]{ + new Tuple("agent", agent) + }; + + if (APILoginParameters != null && APILoginParameters.Length > 0) + parameterArray = parameterArray.Concat(APILoginParameters).ToArray(); + + APIRequestWithToken(callback, parameterArray); } public void Update( @@ -547,7 +559,7 @@ public void Update( Attachment[] attachments = null, bool as_user = false) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("ts", ts)); parameters.Add(new Tuple("channel", channelId)); @@ -590,7 +602,7 @@ public void PostMessage( bool as_user = false, string thread_ts = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("text", text)); @@ -636,7 +648,7 @@ public void AddReaction( string channel = null, string timestamp = null) { - List> parameters = new List>(); + var parameters = new List>(); if (!string.IsNullOrEmpty(name)) parameters.Add(new Tuple("name", name)); @@ -652,9 +664,9 @@ public void AddReaction( public void UploadFile(Action callback, byte[] fileData, string fileName, string[] channelIds, string title = null, string initialComment = null, bool useAsync = false, string fileType = null) { - Uri target = new Uri(Path.Combine(APIBaseLocation, useAsync ? "files.uploadAsync" : "files.upload")); + var target = new Uri(Path.Combine(APIBaseLocation, useAsync ? "files.uploadAsync" : "files.upload")); - List parameters = new List(); + var parameters = new List(); parameters.Add(string.Format("token={0}", APIToken)); //File/Content @@ -672,12 +684,12 @@ public void UploadFile(Action callback, byte[] fileData, str parameters.Add(string.Format("{0}={1}", "channels", string.Join(",", channelIds))); - using (HttpClient client = new HttpClient()) - using (MultipartFormDataContent form = new MultipartFormDataContent()) + using (var client = new HttpClient()) + using (var form = new MultipartFormDataContent()) { form.Add(new ByteArrayContent(fileData), "file", fileName); - HttpResponseMessage response = client.PostAsync(string.Format("{0}?{1}", target, string.Join("&", parameters.ToArray())), form).Result; - string result = response.Content.ReadAsStringAsync().Result; + var response = client.PostAsync(string.Format("{0}?{1}", target, string.Join("&", parameters.ToArray())), form).Result; + var result = response.Content.ReadAsStringAsync().Result; callback(result.Deserialize()); } } @@ -685,27 +697,27 @@ public void UploadFile(Action callback, byte[] fileData, str private static string BuildScope(SlackScope scope) { var builder = new StringBuilder(); - if ((int)(scope & SlackScope.Identify) != 0) + if ((scope & SlackScope.Identify) != 0) builder.Append("identify"); - if ((int)(scope & SlackScope.Read) != 0) + if ((scope & SlackScope.Read) != 0) { if (builder.Length > 0) builder.Append(","); builder.Append("read"); } - if ((int)(scope & SlackScope.Post) != 0) + if ((scope & SlackScope.Post) != 0) { if (builder.Length > 0) builder.Append(","); builder.Append("post"); } - if ((int)(scope & SlackScope.Client) != 0) + if ((scope & SlackScope.Client) != 0) { if (builder.Length > 0) builder.Append(","); builder.Append("client"); } - if ((int)(scope & SlackScope.Admin) != 0) + if ((scope & SlackScope.Admin) != 0) { if (builder.Length > 0) builder.Append(","); @@ -717,7 +729,7 @@ private static string BuildScope(SlackScope scope) public static Uri GetAuthorizeUri(string clientId, SlackScope scopes, string redirectUri = null, string state = null, string team = null) { - string theScopes = BuildScope(scopes); + var theScopes = BuildScope(scopes); return GetSlackUri("https://slack.com/oauth/authorize", new Tuple[] { new Tuple("client_id", clientId), new Tuple("redirect_uri", redirectUri), diff --git a/SlackAPI/SlackSocket.cs b/SlackAPI/SlackSocket.cs index ced070c..5936573 100644 --- a/SlackAPI/SlackSocket.cs +++ b/SlackAPI/SlackSocket.cs @@ -51,7 +51,7 @@ static SlackSocket() #else #error Platform not supported #endif - foreach (Assembly assembly in assemblies) + foreach (var assembly in assemblies) { Type[] assemblyTypes; try @@ -63,9 +63,9 @@ static SlackSocket() return; } - foreach (Type type in assemblyTypes) + foreach (var type in assemblyTypes) { - foreach (SlackSocketRouting route in type.GetTypeInfo().GetCustomAttributes()) + foreach (var route in type.GetTypeInfo().GetCustomAttributes()) { if (!routing.ContainsKey(route.Type)) { @@ -109,19 +109,19 @@ void BuildRoutes(object routingTo) { routes = new Dictionary>(); - Type routingToType = routingTo.GetType(); - Type slackMessage = typeof(SlackSocketMessage); - foreach (MethodInfo m in routingTo.GetType().GetMethods(BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public)) + var routingToType = routingTo.GetType(); + var slackMessage = typeof(SlackSocketMessage); + foreach (var m in routingTo.GetType().GetMethods(BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public)) { - ParameterInfo[] parameters = m.GetParameters(); + var parameters = m.GetParameters(); if (parameters.Length != 1) continue; if (parameters[0].ParameterType.GetTypeInfo().IsSubclassOf(slackMessage)) { - Type t = parameters[0].ParameterType; - foreach (SlackSocketRouting route in t.GetTypeInfo().GetCustomAttributes()) + var t = parameters[0].ParameterType; + foreach (var route in t.GetTypeInfo().GetCustomAttributes()) { - Type genericAction = typeof(Action<>).MakeGenericType(parameters[0].ParameterType); - Delegate d = m.CreateDelegate(genericAction, routingTo); + var genericAction = typeof(Action<>).MakeGenericType(parameters[0].ParameterType); + var d = m.CreateDelegate(genericAction, routingTo); if (d == null) { System.Diagnostics.Debug.WriteLine(string.Format("Couldn't create delegate for {0}.{1}", routingToType.FullName, m.Name)); @@ -141,11 +141,11 @@ void BuildRoutes(object routingTo) public void Send(SlackSocketMessage message, Action callback) where K : SlackSocketMessage { - int sendingId = Interlocked.Increment(ref currentId); + var sendingId = Interlocked.Increment(ref currentId); message.id = sendingId; callbacks.Add(sendingId, (c) => { - K obj = c.Deserialize(); + var obj = c.Deserialize(); callback(obj); }); Send(message); @@ -159,10 +159,10 @@ public void Send(SlackSocketMessage message) if (string.IsNullOrEmpty(message.type)) { - IEnumerable routes = message.GetType().GetTypeInfo().GetCustomAttributes(); + var routes = message.GetType().GetTypeInfo().GetCustomAttributes(); SlackSocketRouting route = null; - foreach (SlackSocketRouting r in routes) + foreach (var r in routes) { route = r; } @@ -181,9 +181,8 @@ public void Send(SlackSocketMessage message) public void BindCallback(Action callback) { - Type t = typeof(K); - - foreach (SlackSocketRouting route in t.GetTypeInfo().GetCustomAttributes()) + var t = typeof(K); + foreach (var route in t.GetTypeInfo().GetCustomAttributes()) { if (!routes.ContainsKey(route.Type)) routes.Add(route.Type, new Dictionary()); @@ -196,13 +195,13 @@ public void BindCallback(Action callback) public void UnbindCallback(Action callback) { - Type t = typeof(K); - foreach (SlackSocketRouting route in t.GetTypeInfo().GetCustomAttributes()) + var t = typeof(K); + foreach (var route in t.GetTypeInfo().GetCustomAttributes()) { - Delegate d = routes.ContainsKey(route.Type) ? (routes.ContainsKey(route.SubType ?? "null") ? routes[route.Type][route.SubType ?? "null"] : null) : null; + var d = routes.ContainsKey(route.Type) ? (routes.ContainsKey(route.SubType ?? "null") ? routes[route.Type][route.SubType ?? "null"] : null) : null; if (d != null) { - Delegate newd = Delegate.Remove(d, callback); + var newd = Delegate.Remove(d, callback); routes[route.Type][route.SubType ?? "null"] = newd; } } @@ -213,10 +212,10 @@ void SetupReceiving() Task.Factory.StartNew( async () => { - List buffers = new List(); - byte[] bytes = new byte[1024]; + var buffers = new List(); + var bytes = new byte[1024]; buffers.Add(bytes); - ArraySegment buffer = new ArraySegment(bytes); + var buffer = new ArraySegment(bytes); while (socket.State == WebSocketState.Open) { WebSocketReceiveResult result = null; @@ -240,7 +239,7 @@ void SetupReceiving() continue; } - string data = string.Join("", buffers.Select((c) => Encoding.UTF8.GetString(c).TrimEnd('\0'))); + var data = string.Join("", buffers.Select((c) => Encoding.UTF8.GetString(c).TrimEnd('\0'))); //Console.WriteLine("SlackSocket data = " + data); SlackSocketMessage message = null; try @@ -283,7 +282,7 @@ void HandleMessage(SlackSocketMessage message, string data) else { //I believe this method is slower than the former. If I'm wrong we can just use this instead. :D - Type t = routes[message.type][message.subtype ?? "null"].GetMethodInfo().GetParameters()[0].ParameterType; + var t = routes[message.type][message.subtype ?? "null"].GetMethodInfo().GetParameters()[0].ParameterType; o = data.Deserialize(t); } routes[message.type][message.subtype ?? "null"].DynamicInvoke(o); @@ -308,8 +307,8 @@ void HandleSending() string message; while (sendingQueue.Pop(out message) && socket.State == WebSocketState.Open && !cts.Token.IsCancellationRequested) { - byte[] sending = Encoding.UTF8.GetBytes(message); - ArraySegment buffer = new ArraySegment(sending); + var sending = Encoding.UTF8.GetBytes(message); + var buffer = new ArraySegment(sending); try { socket.SendAsync(buffer, WebSocketMessageType.Text, true, cts.Token).Wait(); @@ -334,7 +333,6 @@ public void Close() } catch (Exception ex) { - } if (Interlocked.CompareExchange(ref closedEmitted, 1, 0) == 0 && ConnectionClosed != null) diff --git a/SlackAPI/SlackSocketClient.cs b/SlackAPI/SlackSocketClient.cs index 5c296b0..1c236d4 100644 --- a/SlackAPI/SlackSocketClient.cs +++ b/SlackAPI/SlackSocketClient.cs @@ -1,7 +1,6 @@ using SlackAPI.WebSocketMessages; using System; using System.Net.WebSockets; -using System.Threading; namespace SlackAPI { @@ -12,11 +11,13 @@ public class SlackSocketClient : SlackClient public event Action OnMessageReceived; public event Action OnReactionAdded; public event Action OnPongReceived; + public event Action OnPresenceChangeReceived; + public event Action OnUserChangeReceived; bool HelloReceived; public const int PingInterval = 3000; - int pinging; - Timer pingingThread; + //int pinging; + //Timer pingingThread; public long PingRoundTripMilliseconds { get; private set; } public bool IsReady { get { return HelloReceived; } } @@ -25,10 +26,9 @@ public class SlackSocketClient : SlackClient public event Action OnHello; internal LoginResponse loginDetails; - public SlackSocketClient(string token) - : base(token) + public SlackSocketClient(string token, Tuple[] loginParameters = null) + : base(token, loginParameters) { - } public override void Connect(Action onConnected, Action onSocketConnected = null) @@ -81,6 +81,11 @@ public void SendPresence(Presence status) underlyingSocket.Send(new PresenceChange() { presence = Presence.active, user = base.MySelf.id }); } + public void SendPresenceSub(string[] ids) + { + underlyingSocket.Send(new PresenceSub() { ids = ids }); + } + public void SendTyping(string channelId) { underlyingSocket.Send(new Typing() { channel = channelId }); @@ -131,11 +136,15 @@ public void HandleHello(Hello hello) public void HandlePresence(PresenceChange change) { UserLookup[change.user].presence = change.presence.ToString().ToLower(); + if (OnPresenceChangeReceived != null) + OnPresenceChangeReceived(UserLookup[change.user]); } public void HandleUserChange(UserChange change) { UserLookup[change.user.id] = change.user; + if (OnUserChangeReceived != null) + OnUserChangeReceived(UserLookup[change.user.id]); } public void HandleTeamJoin(TeamJoin newuser) @@ -204,31 +213,24 @@ public void HandleGroupRename(GroupRename rename) GroupLookup[rename.channel.id].created = rename.channel.created; } - public void UserTyping(Typing t) + public void HandleUserTyping(Typing t) { - } - public void Message(NewMessage m) + public void HandleMessage(NewMessage m) { if (OnMessageReceived != null) OnMessageReceived(m); } - public void FileShareMessage(FileShareMessage m) + public void HandleFileShareMessage(FileShareMessage m) { if (OnMessageReceived != null) OnMessageReceived(m); } - public void PresenceChange(PresenceChange p) + public void HandleChannelMarked(ChannelMarked m) { - - } - - public void ChannelMarked(ChannelMarked m) - { - } public void CloseSocket() diff --git a/SlackAPI/SlackTaskClient.cs b/SlackAPI/SlackTaskClient.cs index e1c8574..f7ae390 100644 --- a/SlackAPI/SlackTaskClient.cs +++ b/SlackAPI/SlackTaskClient.cs @@ -13,7 +13,8 @@ namespace SlackAPI public class SlackTaskClient { readonly string APIToken; - bool authWorks = false; + readonly Tuple[] APILoginParameters; + //bool authWorks = false; const string APIBaseLocation = "https://slack.com/api/"; const int Timeout = 5000; @@ -50,9 +51,10 @@ public class SlackTaskClient //public event Action OnPresenceChanged; //public event Action OnHello; - public SlackTaskClient(string token) + public SlackTaskClient(string token, Tuple[] loginParameters = null) { APIToken = token; + APILoginParameters = loginParameters; } public virtual async Task ConnectAsync() @@ -98,12 +100,12 @@ protected virtual void Connected(LoginResponse loginDetails) public static Task APIRequestAsync(Tuple[] getParameters, Tuple[] postParameters) where K : Response { - RequestPath path = RequestPath.GetRequestPath(); + var path = RequestPath.GetRequestPath(); //TODO: Custom paths? Appropriate subdomain paths? Not sure. //Maybe store custom path in the requestpath.path itself? - Uri requestUri = SlackClient.GetSlackUri(Path.Combine(APIBaseLocation, path.Path), getParameters); - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri); + var requestUri = SlackClient.GetSlackUri(Path.Combine(APIBaseLocation, path.Path), getParameters); + var request = (HttpWebRequest)HttpWebRequest.Create(requestUri); //This will handle all of the processing. var state = new RequestStateForTask(request, postParameters); @@ -125,7 +127,7 @@ public Task APIRequestWithTokenAsync() public Task APIRequestWithTokenAsync(params Tuple[] postParameters) where K : Response { - Tuple[] tokenArray = new Tuple[]{ + var tokenArray = new Tuple[]{ new Tuple("token", APIToken) }; @@ -142,7 +144,7 @@ public static Task FindTeam(string team) { //This seems to accept both 'team.slack.com' and just plain 'team'. //Going to go with the latter. - Tuple domainName = new Tuple("domain", team); + var domainName = new Tuple("domain", team); return APIRequestAsync(new Tuple[] { domainName }, new Tuple[0]); } @@ -182,7 +184,7 @@ public Task GetDirectMessageListAsync() public Task GetFilesAsync(string userId = null, DateTime? from = null, DateTime? to = null, int? count = null, int? page = null, FileTypes types = FileTypes.all) { - List> parameters = new List>(); + var parameters = new List>(); if (!string.IsNullOrEmpty(userId)) parameters.Add(new Tuple("user", userId)); @@ -195,11 +197,11 @@ public Task GetFilesAsync(string userId = null, DateTime? from if (!types.HasFlag(FileTypes.all)) { - FileTypes[] values = (FileTypes[])Enum.GetValues(typeof(FileTypes)); + var values = (FileTypes[])Enum.GetValues(typeof(FileTypes)); - StringBuilder building = new StringBuilder(); - bool first = true; - for (int i = 0; i < values.Length; ++i) + var building = new StringBuilder(); + var first = true; + for (var i = 0; i < values.Length; ++i) { if (types.HasFlag(values[i])) { @@ -227,7 +229,7 @@ public Task GetFilesAsync(string userId = null, DateTime? from private Task GetHistoryAsync(string channel, DateTime? latest = null, DateTime? oldest = null, int? count = null) where K : MessageHistory { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channel)); if (latest.HasValue) @@ -264,7 +266,7 @@ public Task MarkChannelAsync(string channelId, DateTime ts) public Task GetFileInfoAsync(string fileId, int? page = null, int? count = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("file", fileId)); @@ -276,6 +278,7 @@ public Task GetFileInfoAsync(string fileId, int? page = null, return APIRequestWithTokenAsync(parameters.ToArray()); } + #region Groups public Task GroupsArchiveAsync(string channelId) { @@ -299,7 +302,7 @@ public Task GroupsCreateChildAsync(string channelId) public Task GroupsInviteAsync(string userId, string channelId) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("user", userId)); @@ -309,7 +312,7 @@ public Task GroupsInviteAsync(string userId, string channel public Task GroupsKickAsync(string userId, string channelId) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("user", userId)); @@ -334,7 +337,7 @@ public Task GroupsOpenAsync(string channelId) public Task GroupsRenameAsync(string channelId, string name) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("name", name)); @@ -344,7 +347,7 @@ public Task GroupsRenameAsync(string channelId, string name public Task GroupsSetPurposeAsync(string channelId, string purpose) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("purpose", purpose)); @@ -354,7 +357,7 @@ public Task GroupsSetPurposeAsync(string channelId, str public Task GroupsSetTopicAsync(string channelId, string topic) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("topic", topic)); @@ -371,7 +374,7 @@ public Task GroupsUnarchiveAsync(string channelId) public Task SearchAllAsync(string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) @@ -394,7 +397,7 @@ public Task SearchAllAsync(string query, SearchSort? sorting public Task SearchMessagesAsync(string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) @@ -417,7 +420,7 @@ public Task SearchMessagesAsync(string query, SearchSort public Task SearchFilesAsync(string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) @@ -440,7 +443,7 @@ public Task SearchFilesAsync(string query, SearchSort? sort public Task GetStarsAsync(string userId = null, int? count = null, int? page = null) { - List> parameters = new List>(); + var parameters = new List>(); if (!string.IsNullOrEmpty(userId)) parameters.Add(new Tuple("user", userId)); @@ -456,7 +459,7 @@ public Task GetStarsAsync(string userId = null, int? count = n public Task DeleteMessageAsync(string channelId, DateTime ts) { - List> parameters = new List>() + var parameters = new List>() { new Tuple("ts", ts.ToProperTimeStamp()), new Tuple("channel", channelId) @@ -503,7 +506,7 @@ public Task PostMessageAsync( string icon_emoji = null, bool as_user = false) { - List> parameters = new List>(); + var parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("text", text)); @@ -536,12 +539,12 @@ public Task PostMessageAsync( public Task UploadFileAsync(byte[] fileData, string fileName, string[] channelIds, string title = null, string initialComment = null, bool useAsync = false, string fileType = null) { - Uri target = new Uri(Path.Combine(APIBaseLocation, useAsync ? "files.uploadAsync" : "files.upload")); + var target = new Uri(Path.Combine(APIBaseLocation, useAsync ? "files.uploadAsync" : "files.upload")); - List parameters = new List(); + var parameters = new List(); parameters.Add(string.Format("token={0}", APIToken)); - //File/Content + // File/Content if (!string.IsNullOrEmpty(fileType)) parameters.Add(string.Format("{0}={1}", "filetype", fileType)); @@ -556,12 +559,12 @@ public Task UploadFileAsync(byte[] fileData, string fileName parameters.Add(string.Format("{0}={1}", "channels", string.Join(",", channelIds))); - using (HttpClient client = new HttpClient()) - using (MultipartFormDataContent form = new MultipartFormDataContent()) + using (var client = new HttpClient()) + using (var form = new MultipartFormDataContent()) { form.Add(new ByteArrayContent(fileData), "file", fileName); - HttpResponseMessage response = client.PostAsync(string.Format("{0}?{1}", target, string.Join("&", parameters.ToArray())), form).Result; - string result = response.Content.ReadAsStringAsync().Result; + var response = client.PostAsync(string.Format("{0}?{1}", target, string.Join("&", parameters.ToArray())), form).Result; + var result = response.Content.ReadAsStringAsync().Result; //callback(JsonConvert.DeserializeObject(result, new JavascriptDateTimeConverter())); throw new NotImplementedException("This operation has not been implemented."); } @@ -570,8 +573,8 @@ public Task UploadFileAsync(byte[] fileData, string fileName public Task ChannelSetTopicAsync(string channelId, string newTopic) { return APIRequestWithTokenAsync( - new Tuple("channel", channelId), - new Tuple("topic", newTopic)); + new Tuple("channel", channelId), + new Tuple("topic", newTopic)); } #region Channel diff --git a/SlackAPI/Utilities/LockFreeQueue.cs b/SlackAPI/Utilities/LockFreeQueue.cs index 824c72e..1b057ea 100644 --- a/SlackAPI/Utilities/LockFreeQueue.cs +++ b/SlackAPI/Utilities/LockFreeQueue.cs @@ -37,10 +37,10 @@ public void Unshift(T pItem) { SingleLinkNode oldHead = null; - SingleLinkNode newNode = new SingleLinkNode(); + var newNode = new SingleLinkNode(); newNode.Item = pItem; - bool newNodeWasAdded = false; + var newNodeWasAdded = false; while (!newNodeWasAdded) { oldHead = mHead.Next; @@ -57,10 +57,10 @@ public override void Push(T pItem) SingleLinkNode oldTail = null; SingleLinkNode oldTailNext; - SingleLinkNode newNode = new SingleLinkNode(); + var newNode = new SingleLinkNode(); newNode.Item = pItem; - bool newNodeWasAdded = false; + var newNodeWasAdded = false; while (!newNodeWasAdded) { oldTail = mTail; @@ -82,12 +82,12 @@ public override bool Pop(out T pItem) pItem = default(T); SingleLinkNode oldHead = null; - bool haveAdvancedHead = false; + var haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = mHead; - SingleLinkNode oldTail = mTail; - SingleLinkNode oldHeadNext = oldHead.Next; + var oldTail = mTail; + var oldHeadNext = oldHead.Next; if (oldHead == mHead) { @@ -124,13 +124,13 @@ public bool Shift(out T pItem) return false; SingleLinkNode oldHead = null; - bool haveAdvancedHead = false; + var haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = mHead; if (oldHead != null) { - SingleLinkNode oldHeadNext = oldHead.Next; + var oldHeadNext = oldHead.Next; if (CompareAndExchange(ref mHead, oldHead, oldHeadNext)) { pItem = oldHead.Item; diff --git a/SlackAPI/WebSocketMessages/Hello.cs b/SlackAPI/WebSocketMessages/Hello.cs index beb4825..e561dd9 100644 --- a/SlackAPI/WebSocketMessages/Hello.cs +++ b/SlackAPI/WebSocketMessages/Hello.cs @@ -1,6 +1,4 @@ -using System; - -namespace SlackAPI.WebSocketMessages +namespace SlackAPI.WebSocketMessages { [SlackSocketRouting("hello")] public class Hello : SlackSocketMessage diff --git a/SlackAPI/WebSocketMessages/Ping.cs b/SlackAPI/WebSocketMessages/Ping.cs index 0132253..42a4bb6 100644 --- a/SlackAPI/WebSocketMessages/Ping.cs +++ b/SlackAPI/WebSocketMessages/Ping.cs @@ -1,6 +1,4 @@ -using System; - -namespace SlackAPI.WebSocketMessages +namespace SlackAPI.WebSocketMessages { [SlackSocketRouting("ping")] public class Ping : SlackSocketMessage diff --git a/SlackAPI/WebSocketMessages/Pong.cs b/SlackAPI/WebSocketMessages/Pong.cs index 6979303..571ccad 100644 --- a/SlackAPI/WebSocketMessages/Pong.cs +++ b/SlackAPI/WebSocketMessages/Pong.cs @@ -1,6 +1,4 @@ -using System; - -namespace SlackAPI.WebSocketMessages +namespace SlackAPI.WebSocketMessages { [SlackSocketRouting("pong")] public class Pong : SlackSocketMessage diff --git a/SlackAPI/WebSocketMessages/PresenceChange.cs b/SlackAPI/WebSocketMessages/PresenceChange.cs index cf8578a..1cbb2e1 100644 --- a/SlackAPI/WebSocketMessages/PresenceChange.cs +++ b/SlackAPI/WebSocketMessages/PresenceChange.cs @@ -1,6 +1,4 @@ -using System; - -namespace SlackAPI.WebSocketMessages +namespace SlackAPI.WebSocketMessages { [SlackSocketRouting("presence_change")] public class PresenceChange : SlackSocketMessage diff --git a/SlackAPI/WebSocketMessages/PresenceSub.cs b/SlackAPI/WebSocketMessages/PresenceSub.cs new file mode 100644 index 0000000..db9cec3 --- /dev/null +++ b/SlackAPI/WebSocketMessages/PresenceSub.cs @@ -0,0 +1,8 @@ +namespace SlackAPI.WebSocketMessages +{ + [SlackSocketRouting("presence_sub")] + public class PresenceSub : SlackSocketMessage + { + public string[] ids; + } +} diff --git a/SlackAPI/WebSocketMessages/ReactionAdded.cs b/SlackAPI/WebSocketMessages/ReactionAdded.cs index 50b2e19..69c0784 100644 --- a/SlackAPI/WebSocketMessages/ReactionAdded.cs +++ b/SlackAPI/WebSocketMessages/ReactionAdded.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SlackAPI.WebSocketMessages +namespace SlackAPI.WebSocketMessages { [SlackSocketRouting("reaction_added")] public class ReactionAdded : SlackSocketMessage diff --git a/SlackAPI/WebSocketMessages/Typing.cs b/SlackAPI/WebSocketMessages/Typing.cs index 2979409..55e0bd1 100644 --- a/SlackAPI/WebSocketMessages/Typing.cs +++ b/SlackAPI/WebSocketMessages/Typing.cs @@ -1,6 +1,4 @@ -using System; - -namespace SlackAPI.WebSocketMessages +namespace SlackAPI.WebSocketMessages { [SlackSocketRouting("typing")] [SlackSocketRouting("user_typing")] diff --git a/SlackAPI/WebSocketMessages/UserChange.cs b/SlackAPI/WebSocketMessages/UserChange.cs index 9bbac45..abe68ed 100644 --- a/SlackAPI/WebSocketMessages/UserChange.cs +++ b/SlackAPI/WebSocketMessages/UserChange.cs @@ -6,4 +6,3 @@ public class UserChange : SlackSocketMessage public User user; } } - diff --git a/appveyor.yml b/appveyor.yml index b9c5120..d967ce1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ before_build: "slack": { "userAuthToken": "$env:userAuthToken", "botAuthToken": "$env:botAuthToken", - "testChannel": "$env:testChannel", + "testChannelId": "$env:testChannel", "directMessageUser": "$env:directMessageUser", "authCode": "$env:authCode", "clientId": "$env:clientId",