Giter Club home page Giter Club logo

mixpanel.data's People

Contributors

marcbarbosa avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

leverate-gai

mixpanel.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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.