mixpanel.data's People
Forkers
leverate-gaimixpanel.data's Issues
Support new Basic authentication as signature is now deprecated
This might help someone. I had some problems with signatures not validating correctly. MixPanel documentation now says the signature way of authenticating is deprecated. So I've made changes to make the code work again.
I've pasted my changes to MixPanelDataClient.cs, MixPanelEndpoint.cs and MixPanelClientWrapper.cs below which include:
- Added Segmentation Method for my own benefit
- Fixed URL encoding of query string parameters
- Replace old HTTP + signature authentication code with HTTPS + Basic auth
I don't have the time or will to commit this and create a pull request but maybe someone else does.
public class MixpanelDataClient : IMixpanelData {
private readonly IHttpClient httpClient;
public string ApiKey { get; private set; }
public string ApiSecret { get; private set; }
public string Token { get; private set; }
public MixpanelDataClient(string apiKey, string apiSecret, string apiToken) {
ApiKey = apiKey;
ApiSecret = apiSecret;
Token = apiToken;
httpClient = new HttpClientWrapper(apiSecret);
}
public async Task<Stream> ExportStream(DateTime from, DateTime to, ICollection<string> events = null, string where = "", string bucket = "") {
var parameters = new NameValueCollection();
parameters.AddIfNotIsNullOrWhiteSpace("from_date", from.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("to_date", to.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("where", where);
var endpoint = new Endpoint().Create()
.ForMethod(MethodEnum.Export)
.WithParameters(parameters)
.Build();
this.httpClient.TimeOut = TimeSpan.FromHours(1);
var response = await this.httpClient.GetAsync(endpoint, HttpCompletionOption.ResponseHeadersRead);
if(response.IsSuccessStatusCode) {
return await response.Content.ReadAsStreamAsync();
}
return null;
}
public async Task<ExportResponse> Export(DateTime from, DateTime to, ICollection<string> events = null, string where = "", string bucket = "") {
var stream = await this.ExportStream(from, to, events, where, bucket);
var reader = new StreamReader(stream);
var exportResponse = new ExportResponse();
while(reader.Peek() > -1) {
exportResponse.Add(JsonConvert.DeserializeObject<Event>(reader.ReadLine()));
}
return exportResponse;
}
public async Task<EngageResponse> Engage(string where = "", string sessionId = "", int page = 0) {
var parameters = new NameValueCollection();
parameters.AddIfNotIsNullOrWhiteSpace("where", where);
parameters.AddIfNotIsNullOrWhiteSpace("session_id", sessionId);
parameters.AddIfNotIsNullOrWhiteSpace("page", page.ToString());
var endpoint = new Endpoint().Create()
.ForMethod(MethodEnum.Engage)
.WithParameters(parameters)
.Build();
var response = await this.httpClient.GetAsync(endpoint);
if(response.IsSuccessStatusCode) {
return await response.Content.ReadAsAsync<EngageResponse>();
}
return null;
}
public async Task<SegmentationResponse> Segmentation(string eventName, DateTime from, DateTime to, string on = null, string where = null) {
var parameters = new NameValueCollection();
parameters.AddIfNotIsNullOrWhiteSpace("event", eventName);
parameters.AddIfNotIsNullOrWhiteSpace("from_date", from.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("to_date", to.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("on", on);
parameters.AddIfNotIsNullOrWhiteSpace("where", where);
var endpoint = new Endpoint().Create()
.ForMethod(MethodEnum.Segmentation)
.WithParameters(parameters)
.Build();
var response = await this.httpClient.GetAsync(endpoint);
if(response.IsSuccessStatusCode) {
return await response.Content.ReadAsAsync<SegmentationResponse>();
}
string body = await response.Content.ReadAsStringAsync();
throw new ApplicationException($"MixPanel API returned HTTP status:{response.StatusCode} response: {body}");
}
}
public class HttpClientWrapper : IHttpClient {
private readonly HttpClient httpClient;
public HttpClientWrapper(string apiSecret) {
httpClient = new HttpClient();
var byteArray = Encoding.ASCII.GetBytes($"{apiSecret}:");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}
public async Task<HttpResponseMessage> GetAsync(string requestUri) {
return await httpClient.GetAsync(requestUri);
}
public async Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption httpCompletionOption) {
return await httpClient.GetAsync(requestUri, httpCompletionOption);
}
public async Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content) {
return await httpClient.PostAsync(requestUri, content);
}
public TimeSpan TimeOut {
get { return httpClient.Timeout; }
set { httpClient.Timeout = value; }
}
}
public class Endpoint {
public string BaseEndpoint { get; private set; }
public string Method { get; private set; }
public NameValueCollection Parameters { get; private set; }
public Endpoint Create() {
return this;
}
public Endpoint ForMethod(MethodEnum method) {
this.Method = method.ToDescriptionString();
this.BaseEndpoint = "https://mixpanel.com/api/2.0/";
if(method == MethodEnum.Export) {
this.BaseEndpoint = "https://data.mixpanel.com/api/2.0/";
}
return this;
}
public Endpoint WithParameters(NameValueCollection parameters) {
this.Parameters = parameters;
return this;
}
public string Build() {
return this.ToString();
}
public override string ToString() {
var uriBuilder = new UriBuilder($"{BaseEndpoint}/{Method}"); ;
uriBuilder.Query = ToQueryString(this.Parameters);
var endpoint = uriBuilder.ToString();
return endpoint;
}
private string ToQueryString(NameValueCollection nvc) {
var array = (from key in nvc.AllKeys
from value in nvc.GetValues(key)
select string.Format("{0}={1}", WebUtility.UrlEncode(key), WebUtility.UrlEncode(value)))
.ToArray();
return string.Join("&", array);
}
}
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.