7 次代碼提交 5e7486349b ... e2d33ef97d

作者 SHA1 備註 提交日期
  姜青儀 e2d33ef97d Merge branch 'master' of https://gitlab.kdanmobile.com/windows-team/kdancommon 1 年之前
  姜青儀 4c26192def Merge branch 'mixPanel' of https://gitlab.kdanmobile.com/windows-team/kdancommon 1 年之前
  姜青儀 749f50e576 新增欄位 1 年之前
  姜青儀 84991196cd 修正mixpanel 1 年之前
  姜青儀 1f71cf2299 add gitignore 1 年之前
  ChingYi 8c60542ccb add mixpanel 1 年之前
  ChingYi 8de17cb646 add gitignore file 1 年之前
共有 6 個文件被更改,包括 441 次插入1 次删除
  1. 190 0
      .gitignore
  2. 1 1
      CMSCollection/CMSCollection.cs
  3. 3 0
      KdanCommon.csproj
  4. 101 0
      Mixpanel/Data/ImportRequest.cs
  5. 30 0
      Mixpanel/Data/ImportResult.cs
  6. 116 0
      Mixpanel/Mixpanel.cs

+ 190 - 0
.gitignore

@@ -0,0 +1,190 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+x64/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Roslyn cache directories
+*.ide/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding addin-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+## TODO: Comment the next line if you want to checkin your
+## web deploy settings but do note that will include unencrypted
+## passwords
+#*.pubxml
+
+# NuGet Packages Directory
+packages/*
+## TODO: If the tool you use requires repositories.config
+## uncomment the next line
+#!packages/repositories.config
+
+# Enable "build/" folder in the NuGet Packages folder since
+# NuGet packages use it for MSBuild targets.
+# This line needs to be after the ignore of the build folder
+# (and the packages folder if the line above has been uncommented)
+!packages/build/
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml

+ 1 - 1
CMSCollection/CMSCollection.cs

@@ -24,7 +24,7 @@ namespace KdanCommon.CMSCollection
         private List<ISetting> _settingList = null;
         private HttpClient _httpClient = null;
         private Uri _windowsCardsUri = null;
-          private Uri _windowsEventbarUri = null;
+        private Uri _windowsEventbarUri = null;
         private Uri _pdfViewerEventBarSettingUri = null;
         private Uri _pdfOtherSettingUri = null;
         private string _appType = null;

+ 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>

+ 101 - 0
Mixpanel/Data/ImportRequest.cs

@@ -0,0 +1,101 @@
+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;
+using Windows.Globalization;
+
+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", Guid.NewGuid().ToString("N") },
+                { "UwpRegion", new GeographicRegion().CodeTwoLetter}
+            };
+
+            if (_customProperties != null)
+            {
+                foreach (var kvp in _customProperties)
+                    properties.Add(kvp.Key, kvp.Value);
+            }
+
+            return properties;
+        }
+    }
+    public class ProfileData
+    {
+        [JsonProperty("token")]
+        public string Token { get; }
+
+        [JsonProperty("$distinct_id")]
+        public string DistinctId { get; }
+
+        [JsonProperty("$set")]
+        public Dictionary<string, object> Set { get; }
+
+        public ProfileData(string projectToken, string distinctId, Dictionary<string, object> customProperties = null)
+        {
+            Token = projectToken;
+            DistinctId = distinctId;
+            Set = customProperties;
+        }
+    }
+
+    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; }
+    }
+}

+ 116 - 0
Mixpanel/Mixpanel.cs

@@ -0,0 +1,116 @@
+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 System.Xml.Linq;
+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 _projectToken = null;
+
+        private Uri _importUri = null;
+        private Uri _setProfileUri = null;
+        private Uri _createAlias = null;
+
+        public Mixpanel(string userName, string userSecret, string projectId, string projectToken)
+        {
+            _projectToken = projectToken;
+            _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<bool> ImportEvents(string distinctId, string eventName, Dictionary<string, object> customProperties)
+        {
+            var events = new EventData[]
+            {
+                new EventData(eventName, distinctId, customProperties)
+            };
+            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.StatusCode == System.Net.HttpStatusCode.OK)
+            {
+                if (res.Content != null)
+                {
+                    var jsonString = await res.Content.ReadAsStringAsync();
+                    var response = JsonTool.DeserializeJSON<ImportResult>(jsonString);
+                    if (response.Code == 200)
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        public async Task<bool> SetProfile(string distinctId, Dictionary<string, object> customProperties)
+        {
+            var profiles = new ProfileData[]
+            {
+                new ProfileData(_projectToken, distinctId, customProperties)
+            };
+            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.StatusCode == System.Net.HttpStatusCode.OK)
+            {
+                if (res.Content != null)
+                {
+                    var jsonString = await res.Content.ReadAsStringAsync();
+                    var response = JsonTool.DeserializeJSON<SetProfileResult>(jsonString);
+                    if (response.Error == null)
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        public async Task<bool> CreateAlias(string distinctId, string aliasTo)
+        {
+            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.StatusCode == System.Net.HttpStatusCode.OK)
+                return true;
+            return false;
+        }
+    }
+}