ChingYi 1 rok temu
rodzic
commit
8c60542ccb

+ 3 - 0
KdanCommon.csproj

@@ -136,6 +136,9 @@
     <Compile Include="Helpers\HttpClientHelper.cs" />
     <Compile Include="Helpers\JsonTool.cs" />
     <Compile Include="Log\MetroLogService.cs" />
+    <Compile Include="Mixpanel\Data\ImportRequest.cs" />
+    <Compile Include="Mixpanel\Data\ImportResult.cs" />
+    <Compile Include="Mixpanel\Mixpanel.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <EmbeddedResource Include="Properties\KdanCommon.rd.xml" />
   </ItemGroup>

+ 160 - 0
Mixpanel/Data/ImportRequest.cs

@@ -0,0 +1,160 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.Data.Json;
+
+namespace KdanCommon.Mixpanel.Data
+{
+    public class EventData
+    {
+        [JsonProperty("event")]
+        public string Event { get; }
+
+        [JsonProperty("properties")]
+        public Dictionary<string, object> Properties
+        {
+            get
+            {
+                return GetDictionary();
+            }
+        }
+
+        private string _distinctId { get; }
+
+        private Dictionary<string, object> _customProperties { get; }
+
+        public EventData(string eventName, string distinctId, Dictionary<string, object> customProperties = null)
+        {
+            Event = eventName;
+            _distinctId = distinctId;
+            _customProperties = customProperties;
+        }
+
+        private Dictionary<string, object> GetDictionary()
+        {
+            DateTime gtm = new DateTime(1970, 1, 1);
+            long timeStamp = Convert.ToInt64(((TimeSpan)DateTime.UtcNow.Subtract(gtm)).TotalSeconds);
+
+            var properties = new Dictionary<string, object>
+            {
+                { "time", timeStamp },
+                { "distinct_id", _distinctId },
+                { "$insert_id", GetInsertId(_distinctId, timeStamp, _customProperties) },
+                { "$city", "台南"}
+            };
+
+            if (_customProperties != null)
+            {
+                foreach (var kvp in _customProperties)
+                    properties.Add(kvp.Key, kvp.Value);
+            }
+
+            return properties;
+        }
+
+        private string GetInsertId(string distinctId, long timestamp, Dictionary<string, object> properties)
+        {
+            return Guid.NewGuid().ToString("N");
+            /*
+            try
+            {
+                var str = Guid.NewGuid();
+                var str2 = Guid.NewGuid().ToString("N");
+
+                string semanticallyUniqueStr = $"{distinctId}{timestamp}";
+                if (properties != null)
+                {
+                    foreach (var value in properties.Values)
+                        semanticallyUniqueStr += value;
+                }
+
+                byte[] semanticallyUniqueBytes = Encoding.UTF8.GetBytes(semanticallyUniqueStr);
+                using (var sha256 = SHA256.Create())
+                {
+                    byte[] hashBytes = sha256.ComputeHash(semanticallyUniqueBytes);
+                    string hashStr = Convert.ToBase64String(hashBytes);
+                    return hashStr.Substring(0, 36);
+                }
+            }
+            catch
+            {
+                return "";
+                //return Guid.NewGuid().ToString("N").Substring(0, 36);
+            }
+            */
+        }
+    }
+    public class ProfileData
+    {
+        [JsonProperty("token")]
+        public string Token { get; }
+
+        [JsonProperty("$distinct_id")]
+        public string DistinctId { get; }
+
+        [JsonProperty("$set")]
+        public Dictionary<string, object> Set
+        {
+            get
+            {
+                return GetDictionary();
+            }
+        }
+        private string _name { get; }
+        private string _mail { get; }
+
+        private Dictionary<string, object> _customProperties { get; }
+
+        public ProfileData(string projectToken, string distinctId, string name, string mail, Dictionary<string, object> customProperties = null)
+        {
+            Token = projectToken;
+            DistinctId = distinctId;
+            _name = name;
+            _mail = mail;
+            _customProperties = customProperties;
+        }
+
+        private Dictionary<string, object> GetDictionary()
+        {
+            var properties = new Dictionary<string, object>
+            {
+                { "$name", _name },
+                { "$email", _mail }
+            };
+
+            if (_customProperties != null)
+            {
+                foreach (var kvp in _customProperties)
+                    properties.Add(kvp.Key, kvp.Value);
+            }
+            return properties;
+        }
+    }
+
+    public class AliasData
+    {
+        [JsonProperty("event")]
+        public string Event { get; set; }
+
+        [JsonProperty("properties")]
+        public Properties Properties { get; set; }
+    }
+
+    public class Properties
+    {
+        [JsonProperty("distinct_id")]
+        public string DistinctId { get; set; }
+
+        [JsonProperty("alias")]
+        public string Alias { get; set; }
+
+        [JsonProperty("token")]
+        public string Token { get; set; }
+    }
+}

+ 30 - 0
Mixpanel/Data/ImportResult.cs

@@ -0,0 +1,30 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KdanCommon.Mixpanel.Data
+{
+    public class ImportResult
+    {
+        [JsonProperty("code")]
+        public int Code { get; set; }
+
+        [JsonProperty("num_records_imported")]
+        public int NumRecordsImported { get; set; }
+
+        [JsonProperty("status")]
+        public string Status { get; set; }
+    }
+
+    public class SetProfileResult
+    {
+        [JsonProperty("error")]
+        public string Error { get; set; }
+
+        [JsonProperty("status")]
+        public int Status { get; set; }
+    }
+}

+ 110 - 0
Mixpanel/Mixpanel.cs

@@ -0,0 +1,110 @@
+using KdanCommon.CMSCollection.Data;
+using KdanCommon.GoogleCloud.Data.Vision;
+using KdanCommon.Helpers;
+using KdanCommon.Mixpanel.Data;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.ApplicationModel.Email.DataProvider;
+using Windows.Data.Json;
+using Windows.Media.Protection.PlayReady;
+
+namespace KdanCommon.Mixpanel
+{
+    public class Mixpanel
+    {
+        private static string MixpanelDomain = "https://api.mixpanel.com";
+
+        private HttpClient _httpClient = null;
+        private string _projectId = null;
+        private string _projectToken = null;
+
+        private Uri _importUri = null;
+        private Uri _setProfileUri = null;
+        private Uri _createAlias = null;
+
+        public Mixpanel(string userName, string userSecret, string projectId)
+        {
+            _projectId = projectId;
+            _httpClient = new HttpClient();
+            string authValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(userName + ":" + userSecret));
+            _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authValue);
+
+            _importUri = new Uri($"{MixpanelDomain}/import?strict=1&project_id={projectId}");
+            _setProfileUri = new Uri($"{MixpanelDomain}/engage?verbose=1#profile-set");
+            _createAlias = new Uri($"{MixpanelDomain}/import?project_id={projectId}#identity-create-alias");
+        }
+
+        ~Mixpanel()
+        {
+            _httpClient.Dispose();
+        }
+
+        public async Task ImportEvents(EventData[] events)
+        {
+            var eventsJsonStr = JsonConvert.SerializeObject(events);
+            var content = new StringContent(eventsJsonStr, System.Text.Encoding.UTF8, "application/json");
+            var res = await _httpClient.PostAsync(_importUri, content);
+            if(res.Content != null)
+            {
+                var jsonString = await res.Content.ReadAsStringAsync();
+                var response = JsonTool.DeserializeJSON<ImportResult>(jsonString);
+                if(response.Code != 200)
+                {
+                    // log
+                }
+            }
+        }
+
+        public async Task SetProfile(ProfileData[] profiles)
+        {
+            var profilesJsonStr = JsonConvert.SerializeObject(profiles);
+            var content = new StringContent(profilesJsonStr, System.Text.Encoding.UTF8, "application/json");
+            var res = await _httpClient.PostAsync(_setProfileUri, content);
+            if (res.Content != null)
+            {
+                var jsonString = await res.Content.ReadAsStringAsync();
+                var response = JsonTool.DeserializeJSON<SetProfileResult>(jsonString);
+                if (response.Error != null)
+                {
+                    // log
+                }
+            }
+        }
+
+        public async Task CreateAlias(string distinctId, string aliasTo, string projectToken)
+        {
+            var alias = new AliasData()
+            {
+                Event = "$create_alias",
+                Properties = new Properties()
+                {
+                    DistinctId = distinctId,
+                    Alias = aliasTo,
+                    Token = projectToken
+                }
+            };
+            var aliasJsonStr = JsonConvert.SerializeObject(alias);
+            var formData = new FormUrlEncodedContent(new[]
+            {
+                new KeyValuePair<string, string>("data", aliasJsonStr),
+                new KeyValuePair<string, string>("strict", "1"),
+            });
+            var res = await _httpClient.PostAsync(_createAlias, formData);
+            if (res.Content != null)
+            {
+                var jsonString = await res.Content.ReadAsStringAsync();
+                var response = JsonTool.DeserializeJSON<SetProfileResult>(jsonString);
+                if (response.Error != null)
+                {
+                    // log
+                }
+            }
+        }
+    }
+}