using CircleSDK.Api; using CircleSDK.Model; using System.Diagnostics; using System.Net.WebSockets; using System.Net; using System.Security.Cryptography; using System.Text; using Newtonsoft.Json; namespace CDPShared { public class CircleAPIHelper { private string _customerCode; private string _appKey; private string _endUserId; private string _secret; private ClientWebSocket _socket; private CancellationTokenSource _cts; private string _token; // this needs to be kept up to date public string Token => _token; private Timer _refreshToken; private CircleApi _api; public CircleApi Api => _api; private Boolean _authorized = false; public Boolean Ready => _authorized; public string Status { get; set; } public CircleAPIHelper(string customerCode, string appKey, string endUserId, string secret) { _api = new CircleApi(); // to use CircleAPI, you need RESTSharp v105.0.0 _customerCode = customerCode; _appKey = appKey; _endUserId = endUserId; _secret = secret; _refreshToken = new Timer(RefreshToken, null, 100, 5 * 1000); // check every 30 seconds Status = "Starting up"; } private void RefreshToken(object state) { Status = "Looking for Circle Service"; Boolean bCircleServiceExists = Process.GetProcesses().Any(dr => (dr.ProcessName.ToLower() == "CircleServiceDebug".ToLower()) || (dr.ProcessName.ToLower() == "CircleService".ToLower())); if (bCircleServiceExists) { // we found the service, switch to refresh every 9 minutes. _refreshToken.Change(9 * 60 * 1000, 9 * 60 * 1000); GetToken(); Authorize(); } } void GetToken() { Status = "Getting permission to call Circle Service."; string nonce = Guid.NewGuid().ToString(); string query = string.Format($"customerId={_customerCode}&AppKey={_appKey}&EndUserId={_endUserId}&nonce={nonce}"); string signature = ComputeSignature(query, _secret); string fullLine = query + "&signature=" + signature; WebClient wc = new WebClient(); try { string s = wc.DownloadString("https://api.gocircle.ai/api/token?" + fullLine); s = s.Replace("\\\"", "\"").Trim('\"'); PrettyJWT pt = JsonConvert.DeserializeObject(s); _token = pt.Token; } catch (Exception e) { Status = "Unable to get token."; } } string ComputeSignature(string stringToSign, string secret) { using (var hmacsha256 = new HMACSHA256(System.Text.ASCIIEncoding.UTF8.GetBytes(secret))) { var bytes = Encoding.ASCII.GetBytes(stringToSign); var hashedBytes = hmacsha256.ComputeHash(bytes); return Convert.ToBase64String(hashedBytes); } } private void Authorize() { Status = "Asking Circle Service for authorization"; var body = new AppAuthorizationRequest(); // AppAuthorizationRequest | body.Token = _token; _api.Configuration.AccessToken = _token; var xCircleAppkey = "Dashboard"; // String | Application `AppKey` try { // authorize AppAuthorizationReply result = _api.Authorize(body, xCircleAppkey); _authorized = true; Debug.WriteLine(result); Status = "Authorized to use Circle Service"; } catch (Exception ex) { Debug.Print("Exception when calling CircleApi.authorize: " + ex.Message); _authorized = false; return; } } public async Task WhoAmI(string circleId) { WhoAmIRequest body = new WhoAmIRequest(); body.CircleId = circleId; WhoAmIReply result = await _api.WhoAmIAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result; } return null; } public async Task CreateCircle(string name, string description) { CreateCircleRequest body = new CreateCircleRequest(); body.CircleName = name; body.CircleDescription = description; body.CustomerId = Constants.CustomerCode; body.CustomerToken = Constants.AuthCode; CreateCircleReply result = await _api.CreateCircleAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result; } return null; } public async Task GenInvite(string circleId) { GenInviteRequest body = new GenInviteRequest(); body.CircleId = circleId; body.IsAddDevice = false; GenInviteReply result = await _api.GenInviteAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result; } return null; } public async Task ProcessInvite(string inviteCode, string authCode) { ProcessInviteRequest body = new ProcessInviteRequest(); body.InviteId = inviteCode; body.AuthCode = authCode; body.Wait20Second = true; ProcessInviteReply result = await _api.ProcessInviteAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result; } return null; } public async Task RevokeDevice(string circleId, string deviceId) { RevokeDeviceRequest body = new RevokeDeviceRequest(); body.CircleId = circleId; body.DeviceId = deviceId; RevokeDeviceReply result = await _api.RevokeDeviceAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result; } return null; } public async Task RemoveMember(string circleId, string memberId) { RemoveMemberRequest body = new RemoveMemberRequest(); body.CircleId = circleId; body.MemberId = memberId; RemoveMemberReply result = await _api.RemoveMemberAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result; } return null; } public async Task> EnumCircleMembers(string circleId) { EnumCircleMembersRequest body = new EnumCircleMembersRequest(); body.CircleId = circleId; EnumCircleMembersReply result = await _api.EnumCircleMembersAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result.Profiles; } return null; } public async Task> EnumTopicMembers(string circleId, string topicId) { EnumTopicMembersRequest body = new EnumTopicMembersRequest(); body.CircleId = circleId; body.TopicId = topicId; EnumTopicMembersReply result = await _api.EnumTopicMembersAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result.Profiles; } return null; } public async Task> EnumCircles() { EnumCirclesRequest body = new EnumCirclesRequest(); EnumCirclesReply result = await _api.EnumCirclesAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result.CircleMeta; } return null; } public async Task GetCircleById(string circleId) { List circles = await EnumCircles(); if (circles == null) return null; foreach (CircleInfo info in circles) { if (string.Compare(info.CircleId, circleId, StringComparison.CurrentCultureIgnoreCase) == 0) { return info; } } return null; } public async Task> EnumTopics(string circleId) { EnumTopicsRequest body = new EnumTopicsRequest(); body.CircleId = circleId; EnumTopicsReply result = await _api.EnumTopicsAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return result.Topics; } return null; } public async Task GetTopicById(string circleId, string topicId) { List topics = await EnumTopics(circleId); foreach (TopicInfo info in topics) { if (string.Compare(info.TopicId, topicId, StringComparison.CurrentCultureIgnoreCase) == 0) { return info; } } return null; } public async Task EncryptFile(string circleId, string topicId, string filename) { EncryptRequest body = new EncryptRequest(); body.CircleId = circleId; body.TopicId = topicId; body.FileName = filename; try { body.ToEncrypt = Convert.ToBase64String(File.ReadAllBytes(filename)); EncryptReply result = await _api.EncryptAsync(body, "Bearer " + Token, "Dashboard"); if (result.Status.Result.GetValueOrDefault(false)) { return Convert.FromBase64String(result.EncryptedData); } } catch (Exception e) { MinLogging.LogIt(" **** " + e.Message); } return null; } public async Task AddMessage(string circleId, string topicId, string message, Int32 msgId, DataGather g = null) { if (g == null) g = new DataGather(this); AddMessageRequest msg = new AddMessageRequest(circleId, topicId, msgId); msg.Message = message; msg.AdditionalJson = JsonConvert.SerializeObject(g.Gather()); return await Api.AddMessageAsync(msg, "Bearer " + Token, "Dashboard"); } public async Task GetCircleViewwMessages(string circleId, string topicId) { GetMessagesRequest gm = new GetMessagesRequest(circleId, topicId) { MsgTypeFilters = new List() }; for (int i = (Int32)CircleViewMessages.FileViewed; i < (Int32)CircleViewMessages.LastMessage; i++) { gm.MsgTypeFilters.Add(i); } return await Api.GetMessagesAsync(gm, "Bearer " + Token, "Dashboard"); } //public async Task SetProfileProperty(string circleId, string name, string value) //{ // SetProfilePropertyRequest gm = new SetProfilePropertyRequest(circleId, name, value); // return await Api.SetProfilePropertyAsync(gm, "Bearer " + Token, "Dashboard"); //} } class PrettyJWT { public string Token { get; set; } public DateTime Expiry { get; set; } } }