using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace SlackAPI { public class SlackTaskClient : SlackClientBase { private readonly string APIToken; public Self MySelf; public User MyData; public Team MyTeam; public List starredChannels; public List Users; public List Channels; public List Groups; public List DirectMessages; public Dictionary UserLookup; public Dictionary ChannelLookup; public Dictionary GroupLookup; public Dictionary DirectMessageLookup; public SlackTaskClient(string token) { APIToken = token; } public SlackTaskClient(string token, IWebProxy proxySettings) : base(proxySettings) { APIToken = token; } public virtual async Task ConnectAsync() { var loginDetails = await EmitLoginAsync(); if(loginDetails.ok) Connected(loginDetails); return loginDetails; } protected virtual void Connected(LoginResponse loginDetails) { MySelf = loginDetails.self; MyData = loginDetails.users.First((c) => c.id == MySelf.id); MyTeam = loginDetails.team; Users = new List(loginDetails.users.Where((c) => !c.deleted)); Channels = new List(loginDetails.channels); Groups = new List(loginDetails.groups); DirectMessages = new List(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(); foreach (User u in Users) UserLookup.Add(u.id, u); ChannelLookup = new Dictionary(); foreach (Channel c in Channels) ChannelLookup.Add(c.id, c); GroupLookup = new Dictionary(); foreach (Channel g in Groups) GroupLookup.Add(g.id, g); DirectMessageLookup = new Dictionary(); foreach (DirectMessageConversation im in DirectMessages) DirectMessageLookup.Add(im.id, im); } public Task APIRequestWithTokenAsync() where K : Response { return APIRequestWithTokenAsync(new Tuple[] { }); } public Task APIRequestWithTokenAsync(params Tuple[] postParameters) where K : Response { Tuple[] tokenArray = new Tuple[]{ new Tuple("token", APIToken) }; return APIRequestAsync(tokenArray, postParameters); } public Task TestAuthAsync() { return APIRequestWithTokenAsync(); } public Task GetUserListAsync() { return APIRequestWithTokenAsync(); } public Task GetChannelListAsync(bool ExcludeArchived = true) { return APIRequestWithTokenAsync(new Tuple("exclude_archived", ExcludeArchived ? "1" : "0")); } public Task GetGroupsListAsync(bool ExcludeArchived = true) { return APIRequestWithTokenAsync(new Tuple("exclude_archived", ExcludeArchived ? "1" : "0")); } public Task GetDirectMessageListAsync() { return APIRequestWithTokenAsync(); } 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>(); if (!string.IsNullOrEmpty(userId)) parameters.Add(new Tuple("user", userId)); if (from.HasValue) parameters.Add(new Tuple("ts_from", from.Value.ToProperTimeStamp())); if (to.HasValue) parameters.Add(new Tuple("ts_to", to.Value.ToProperTimeStamp())); if (!types.HasFlag(FileTypes.all)) { FileTypes[] values = (FileTypes[])Enum.GetValues(typeof(FileTypes)); StringBuilder building = new StringBuilder(); bool first = true; for (int i = 0; i < values.Length; ++i) { if (types.HasFlag(values[i])) { if (!first) building.Append(","); building.Append(values[i].ToString()); first = false; } } if (building.Length > 0) parameters.Add(new Tuple("types", building.ToString())); } if (count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); if (page.HasValue) parameters.Add(new Tuple("page", page.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } private Task GetHistoryAsync(string channel, DateTime? latest = null, DateTime? oldest = null, int? count = null) where K : MessageHistory { List> parameters = new List>(); parameters.Add(new Tuple("channel", channel)); if(latest.HasValue) parameters.Add(new Tuple("latest", latest.Value.ToProperTimeStamp())); if(oldest.HasValue) parameters.Add(new Tuple("oldest", oldest.Value.ToProperTimeStamp())); if(count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GetChannelHistoryAsync(Channel channelInfo, DateTime? latest = null, DateTime? oldest = null, int? count = null) { return GetHistoryAsync(channelInfo.id, latest, oldest, count); } public Task GetDirectMessageHistoryAsync(DirectMessageConversation conversationInfo, DateTime? latest = null, DateTime? oldest = null, int? count = null) { return GetHistoryAsync(conversationInfo.id, latest, oldest, count); } public Task GetGroupHistoryAsync(Channel groupInfo, DateTime? latest = null, DateTime? oldest = null, int? count = null) { return GetHistoryAsync(groupInfo.id, latest, oldest, count); } public Task MarkChannelAsync(string channelId, DateTime ts) { return APIRequestWithTokenAsync(new Tuple("channel", channelId), new Tuple("ts", ts.ToProperTimeStamp()) ); } public Task GetFileInfoAsync(string fileId, int? page = null, int? count = null) { List> parameters = new List>(); parameters.Add(new Tuple("file", fileId)); if(count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); if (page.HasValue) parameters.Add(new Tuple("page", page.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } #region Groups public Task GroupsArchiveAsync(string channelId) { return APIRequestWithTokenAsync(new Tuple("channel", channelId)); } public Task GroupsCloseAsync(string channelId) { return APIRequestWithTokenAsync(new Tuple("channel", channelId)); } public Task GroupsCreateAsync(string name) { return APIRequestWithTokenAsync(new Tuple("name", name)); } public Task GroupsCreateChildAsync(string channelId) { return APIRequestWithTokenAsync(new Tuple("channel", channelId)); } public Task GroupsInviteAsync(string userId, string channelId) { List> parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("user", userId)); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GroupsKickAsync(string userId, string channelId) { List> parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("user", userId)); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GroupsLeaveAsync(string channelId) { return APIRequestWithTokenAsync(new Tuple("channel", channelId)); } public Task GroupsMarkAsync(string channelId, DateTime ts) { return APIRequestWithTokenAsync(new Tuple("channel", channelId), new Tuple("ts", ts.ToProperTimeStamp())); } public Task GroupsOpenAsync(string channelId) { return APIRequestWithTokenAsync(new Tuple("channel", channelId)); } public Task GroupsRenameAsync(string channelId, string name) { List> parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("name", name)); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GroupsSetPurposeAsync(string channelId, string purpose) { List> parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("purpose", purpose)); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GroupsSetTopicAsync(string channelId, string topic) { List> parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("topic", topic)); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GroupsUnarchiveAsync(string channelId) { return APIRequestWithTokenAsync(new Tuple("channel", channelId)); } #endregion public Task SearchAllAsync(string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { List> parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) parameters.Add(new Tuple("sort", sorting.Value.ToString())); if (direction.HasValue) parameters.Add(new Tuple("sort_dir", direction.Value.ToString())); if (enableHighlights) parameters.Add(new Tuple("highlight", "1")); if (count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); if (page.HasValue) parameters.Add(new Tuple("page", page.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task SearchMessagesAsync(string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { List> parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) parameters.Add(new Tuple("sort", sorting.Value.ToString())); if (direction.HasValue) parameters.Add(new Tuple("sort_dir", direction.Value.ToString())); if (enableHighlights) parameters.Add(new Tuple("highlight", "1")); if (count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); if (page.HasValue) parameters.Add(new Tuple("page", page.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task SearchFilesAsync(string query, SearchSort? sorting = null, SearchSortDirection? direction = null, bool enableHighlights = false, int? count = null, int? page = null) { List> parameters = new List>(); parameters.Add(new Tuple("query", query)); if (sorting.HasValue) parameters.Add(new Tuple("sort", sorting.Value.ToString())); if (direction.HasValue) parameters.Add(new Tuple("sort_dir", direction.Value.ToString())); if (enableHighlights) parameters.Add(new Tuple("highlight", "1")); if (count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); if (page.HasValue) parameters.Add(new Tuple("page", page.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task GetStarsAsync(string userId = null, int? count = null, int? page = null){ List> parameters = new List>(); if(!string.IsNullOrEmpty(userId)) parameters.Add(new Tuple("user", userId)); if(count.HasValue) parameters.Add(new Tuple("count", count.Value.ToString())); if(page.HasValue) parameters.Add(new Tuple("page", page.Value.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } public Task DeleteMessageAsync(string channelId, DateTime ts) { List> parameters = new List>() { new Tuple("ts", ts.ToProperTimeStamp()), new Tuple("channel", channelId) }; return APIRequestWithTokenAsync(parameters.ToArray()); } public Task EmitPresence(Presence status) { return APIRequestWithTokenAsync(new Tuple("presence", status.ToString())); } public Task GetPreferencesAsync() { return APIRequestWithTokenAsync(); } public Task GetCountsAsync() { return APIRequestWithTokenAsync(); } public Task EmitLoginAsync(string agent = "Inumedia.SlackAPI") { return APIRequestWithTokenAsync(new Tuple("agent", agent)); } public Task JoinDirectMessageChannelAsync(string user) { var param = new Tuple("user", user); return APIRequestWithTokenAsync(param); } public Task PostMessageAsync( string channelId, string text, string botName = null, string parse = null, bool linkNames = false, Attachment[] attachments = null, bool unfurl_links = false, string icon_url = null, string icon_emoji = null, bool as_user = false) { List> parameters = new List>(); parameters.Add(new Tuple("channel", channelId)); parameters.Add(new Tuple("text", text)); if(!string.IsNullOrEmpty(botName)) parameters.Add(new Tuple("username", botName)); if (!string.IsNullOrEmpty(parse)) parameters.Add(new Tuple("parse", parse)); if (linkNames) parameters.Add(new Tuple("link_names", "1")); if (attachments != null && attachments.Length > 0) parameters.Add(new Tuple("attachments", JsonConvert.SerializeObject(attachments))); if (unfurl_links) parameters.Add(new Tuple("unfurl_links", "1")); if (!string.IsNullOrEmpty(icon_url)) parameters.Add(new Tuple("icon_url", icon_url)); if (!string.IsNullOrEmpty(icon_emoji)) parameters.Add(new Tuple("icon_emoji", icon_emoji)); parameters.Add(new Tuple("as_user", as_user.ToString())); return APIRequestWithTokenAsync(parameters.ToArray()); } public async 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")); List parameters = new List(); parameters.Add(string.Format("token={0}", APIToken)); //File/Content if (!string.IsNullOrEmpty(fileType)) parameters.Add(string.Format("{0}={1}", "filetype", fileType)); if (!string.IsNullOrEmpty(fileName)) parameters.Add(string.Format("{0}={1}", "filename", fileName)); if (!string.IsNullOrEmpty(title)) parameters.Add(string.Format("{0}={1}", "title", title)); if (!string.IsNullOrEmpty(initialComment)) parameters.Add(string.Format("{0}={1}", "initial_comment", initialComment)); parameters.Add(string.Format("{0}={1}", "channels", string.Join(",", channelIds))); using (MultipartFormDataContent form = new MultipartFormDataContent()) { form.Add(new ByteArrayContent(fileData), "file", fileName); HttpResponseMessage response = PostRequest(string.Format("{0}?{1}", target, string.Join("&", parameters.ToArray())), form); string result = await response.Content.ReadAsStringAsync(); return result.Deserialize(); } } public Task ChannelSetTopicAsync(string channelId, string newTopic) { return APIRequestWithTokenAsync( new Tuple("channel", channelId), new Tuple("topic", newTopic)); } } }