/// <summary> /// Get a list of Historics queries in your account. /// </summary> /// <param name="user">The user making the request.</param> /// <param name="page">The page number to get.</param> /// <param name="per_page">The number of items per page.</param> /// <returns>A list of Historic objects.</returns> public static HistoricList list(User user, int page = 1, int per_page = 20) { try { Dictionary <string, string> parameters = new Dictionary <string, string>(); parameters.Add("page", page.ToString()); parameters.Add("per_page", per_page.ToString()); JSONdn res = user.callApi("historics/get", parameters); if (!res.has("count")) { throw new ApiException("No count in the response"); } HistoricList retval = new HistoricList(res.getIntVal("count")); if (!res.has("data") && retval.TotalCount > 0) { throw new ApiException("No historics in the response"); } JToken[] children = res.getChildren("data"); for (int i = 0; i < children.Length; i++) { retval.Add(new Historic(user, new JSONdn(children[i]))); } return(retval); } catch (ApiException e) { if (e.Code == 400) { throw new InvalidDataException(e.Message); } throw new ApiException("Unexpected API response code: " + e.Code.ToString() + " " + e.Message); } }
/// <summary> /// Called by derived classes when a complete JSON string has been received. /// </summary> /// <param name="json">The JSON string.</param> protected void onData(string json) { JSONdn data = new JSONdn(json); if (data.has("status")) { if (data.has("tick")) { // Ignore ticks } else switch (data.getStringVal("status")) { case "failure": case "error": onError(data.getStringVal("message")); break; case "warning": onWarning(data.getStringVal("message")); break; default: onWarning("Unhandled status message: \"" + data.getStringVal("status") + "\""); break; } } else if (data.has("hash")) { // The data contains a hash so the connection is consuming // multiple streams. if (data.has("data.deleted")) { m_event_handler.onDeleted(this, new Interaction(data.getJVal("data")), data.getStringVal("hash")); } else { m_event_handler.onInteraction(this, new Interaction(data.getJVal("data")), data.getStringVal("hash")); } } else if (data.has("interaction")) { // The data does not contain a hash so the connection is // consuming a single stream. Use the first element in // the hashes array as the hash for the callback. if (data.has("deleted")) { m_event_handler.onDeleted(this, new Interaction(data.getJVal()), m_hashes[0]); } else { m_event_handler.onInteraction(this, new Interaction(data.getJVal()), m_hashes[0]); } } else { // Hitting this means the data structure did not have any of // the expected elements. onError("Unhandled data received: " + json); } }
/// <summary> /// Prepare this Historics query. /// </summary> public void prepare() { if (isDeleted()) { throw new InvalidDataException("Cannot set the name of a deleted Historics query"); } if (m_playback_id.Length > 0) { throw new InvalidDataException("This Historics query has already been prepared"); } Dictionary <string, string> parameters = new Dictionary <string, string>(); parameters.Add("hash", m_stream_hash); parameters.Add("start", Utils.DateTimeToUnixTimestamp(m_start_date).ToString()); parameters.Add("end", Utils.DateTimeToUnixTimestamp(m_end_date).ToString()); parameters.Add("name", m_name); parameters.Add("sources", string.Join(",", m_sources.ToArray())); try { JSONdn res = m_user.callApi("historics/prepare", parameters); if (!res.has("id")) { throw new InvalidDataException("Prepared successfully but no playback ID in the response"); } m_playback_id = res.getStringVal("id"); if (!res.has("dpus")) { throw new InvalidDataException("Prepared successfully but no DPU cost in the response"); } m_dpus = res.getDoubleVal("dpus"); if (!res.has("availability")) { throw new InvalidDataException("Prepared successfully but no availability in the response"); } m_availability = new HistoricDataAvailability(new JSONdn(res.getJVal("availability"))); } catch (ApiException e) { // 400 = Missing or bad parameters. // 404 = Historics query not found. if (e.Code == 400 || e.Code == 404) { throw new InvalidDataException(e.Message); } throw new ApiException("Unexpected API response code: " + e.Code.ToString() + " " + e.Message); } // Update our data. reloadData(); }
/// <summary> /// Page through recent Push log entries. /// </summary> /// <param name="user">The user making the request.</param> /// <param name="page">Which page to fetch.</param> /// <param name="per_page">How many entries per page.</param> /// <param name="order_by">Which field to sort by.</param> /// <param name="order_dir">In asc[ending] or desc[ending] order.</param> /// <param name="id">Optional subscription ID.</param> /// <returns>A PushLog object.</returns> public static PushLog getLogs(User user, int page, int per_page, string order_by = ORDERBY_REQUEST_TIME, string order_dir = ORDERDIR_DESC, string id = "") { Dictionary <string, string> parameters = new Dictionary <string, string>(); if (page < 1) { throw new InvalidDataException("The specified page number is invalid"); } if (per_page < 1) { throw new InvalidDataException("The specified per_page value is invalid"); } if (order_by != ORDERBY_REQUEST_TIME) { throw new InvalidDataException("The specified order_by is not supported"); } if (order_dir != ORDERDIR_ASC && order_dir != ORDERDIR_DESC) { throw new InvalidDataException("The specified order_dir is not supported"); } if (id.Length > 0) { parameters.Add("id", id); } parameters.Add("page", page.ToString()); parameters.Add("per_page", per_page.ToString()); parameters.Add("order_by", order_by); parameters.Add("order_dir", order_dir); JSONdn res = user.callApi("push/log", parameters); if (!res.has("count")) { throw new ApiException("No count in the response"); } PushLog retval = new PushLog(res.getIntVal("count")); if (!res.has("log_entries") && retval.TotalCount > 0) { throw new ApiException("No log entries in the response"); } JToken[] children = res.getChildren("log_entries"); for (int i = 0; i < children.Length; i++) { retval.Add(new PushLogEntry(new JSONdn(children[i]))); } return(retval); }
public void Test_Parse() { JSONdn json = new JSONdn("{\"delivery_frequency\":10,\"url\":\"http://www.example.com/push_endpoint\",\"auth\":{\"type\":\"basic\",\"username\":\"wooop\",\"password\":\"dsadsa\"}}"); PushOutputParams pop = new PushOutputParams(json); Assert.AreEqual("10", pop["delivery_frequency"], "Parsed value for 'delivery_frequency' is incorrect"); Assert.AreEqual("http://www.example.com/push_endpoint", pop["url"], "Parsed value for 'url' is incorrect"); Assert.AreEqual("basic", pop["auth.type"], "Parsed value for 'auth.type' is incorrect"); Assert.AreEqual("wooop", pop["auth.username"], "Parsed value for 'auth.username' is incorrect"); Assert.AreEqual("dsadsa", pop["auth.password"], "Parsed value for 'auth.password' is incorrect"); }
public HistoricDataAvailability(JSONdn json) { m_start = json.getDateTimeFromLongVal("start"); m_end = json.getDateTimeFromLongVal("end"); if (json.has("sources")) { foreach (string key in json.getKeys("sources")) { m_sources.Add(key, new HistoricDataAvailabilitySource(new JSONdn(json.getJVal("sources." + key)))); } } }
public HistoricDataAvailabilitySource(JSONdn json) { m_status = json.getIntVal("status"); foreach (JToken version in json.getJVal("versions")) { m_versions.Add(Convert.ToInt32(version.ToString())); } foreach (string key in json.getKeys("augmentations")) { m_augmentations.Add(key, json.getIntVal("augmentations." + key)); } }
/// <summary> /// Recursive method to parse a tree in JSON into the flat /// dot-notation parameters used by the API. /// </summary> /// <param name="json">The JSON object.</param> /// <param name="key_prefix">The current key prefix.</param> protected void setOutputParams(JSONdn json, string key_prefix) { foreach (string key in json.getKeys()) { string full_key = (key_prefix.Length == 0 ? "" : key_prefix + ".") + key; if (json.hasChildren(key)) { setOutputParams(new JSONdn(json.getJVal(key)), full_key); } else { set(full_key, json.getStringVal(key)); } } }
/// <summary> /// Construct an instance from a JSONdn object. /// </summary> /// <param name="data">The source JSONdn object.</param> public Usage(JSONdn data) { // Validate that the object has the required data if (!data.has("start")) { throw new InvalidDataException("No start date in the usage data"); } if (!data.has("end")) { throw new InvalidDataException("No end date in the usage data"); } if (!data.has("streams")) { throw new InvalidDataException("No stream info in the usage data"); } // Save it for later. m_data = data; }
/// <summary> /// Send the CSDL to DataSift for compilation. /// </summary> public void compile() { // We must have some CSDL in order to compile the CSDL! if (m_csdl.Length == 0) { throw new InvalidDataException("Cannot compile an empty definition"); } try { Dictionary <string, string> parameters = new Dictionary <string, string>(); parameters.Add("csdl", m_csdl); JSONdn res = m_user.callApi("compile", parameters); if (!res.has("hash")) { throw new CompileFailedException("Compiled successfully but no hash in the response"); } m_hash = res.getStringVal("hash"); if (!res.has("created_at")) { throw new CompileFailedException("Compiled successfully but no created_at in the response"); } m_created_at = res.getDateTimeVal("created_at", "yyyy-MM-dd HH:mm:ss"); if (!res.has("dpu")) { throw new CompileFailedException("Compiled successfully but no DPU in the response"); } m_total_dpu = res.getDoubleVal("dpu"); } catch (ApiException e) { clearHash(); if (e.Code == 400) { throw new CompileFailedException(e.Message); } throw new CompileFailedException("Unexpected API response code: " + e.Code.ToString() + " " + e.Message); } }
/// <summary> /// Constructor. /// </summary> /// <param name="status_code">The HTTP status code.</param> /// <param name="response_data">The content of the response - expected to be JSON.</param> /// <param name="rate_limit">The value of the x-rate-limit-limit header.</param> /// <param name="rate_limit_remaining">The value of the x-rate-limit-remaining header.</param> public ApiResponse(int status_code, string response_data, int rate_limit = -1, int rate_limit_remaining = -1) { try { m_response_code = status_code; if (response_data.Length == 0) { m_data = new JSONdn("{}"); } else { m_data = new JSONdn(response_data); } m_rate_limit = rate_limit; m_rate_limit_remaining = rate_limit_remaining; } catch (Exception e) { throw new ApiException("Request failed: " + e.Message, 503); } }
/// <summary> /// Constructor. /// </summary> /// <param name="data">The JSON API response.</param> public Dpu(JSONdn data) { m_dpu = new Dictionary <string, DpuItem>(); foreach (string key in data.getKeys("detail")) { DpuItem item = new DpuItem(data.getIntVal("detail." + key + ".count"), data.getDoubleVal("detail." + key + ".dpu")); if (data.has("detail." + key + ".targets")) { JToken t = data.getJVal("detail." + key + ".targets"); foreach (string targetkey in data.getKeys("detail." + key + ".targets")) { JSONdn t2 = new JSONdn(t[targetkey]); item.addTarget(targetkey, new DpuItem(t2.getIntVal("count"), t2.getDoubleVal("dpu"))); } } m_dpu.Add(key, item); } m_total = data.getDoubleVal("dpu"); }
/// <summary> /// Constructor. /// </summary> /// <param name="data">The JSON API response.</param> public Dpu(JSONdn data) { m_dpu = new Dictionary<string, DpuItem>(); foreach (string key in data.getKeys("detail")) { DpuItem item = new DpuItem(data.getIntVal("detail." + key + ".count"), data.getDoubleVal("detail." + key + ".dpu")); if (data.has("detail." + key + ".targets")) { JToken t = data.getJVal("detail." + key + ".targets"); foreach (string targetkey in data.getKeys("detail." + key + ".targets")) { JSONdn t2 = new JSONdn(t[targetkey]); item.addTarget(targetkey, new DpuItem(t2.getIntVal("count"), t2.getDoubleVal("dpu"))); } } m_dpu.Add(key, item); } m_total = data.getDoubleVal("dpu"); }
/// <summary> /// Get buffered tweets. /// </summary> /// <param name="count">The number of tweets to get - see http://dev.datasift.com/ for the limit.</param> /// <param name="from_id">The ID of the latest interaction that you received.</param> /// <returns>An array of Interaction objects.</returns> public Interaction[] getBuffered(uint count = 0, ulong from_id = 0) { if (m_csdl.Length == 0) { throw new InvalidDataException("Cannot get buffered interactions for an empty definition"); } Dictionary <string, string> parameters = new Dictionary <string, string>(); parameters.Add("hash", getHash()); if (count > 0) { parameters.Add("count", count.ToString()); } if (from_id > 0) { parameters.Add("from_id", from_id.ToString()); } JSONdn res = m_user.callApi("stream", parameters); if (!res.has("stream")) { throw new ApiException("No data in the response", -1); } List <Interaction> retval = new List <Interaction>(); JToken[] children = res.getChildren("stream"); for (int i = 0; i < children.Length; i++) { retval.Add(new Interaction(children[i])); } return(retval.ToArray()); }
/// <summary> /// Construct a PushSubscription object from a JSON object. /// </summary> /// <param name="user"></param> /// <param name="json"></param> public PushSubscription(User user, JSONdn json) : base(user) { init(json); }
/// <summary> /// Initialise this object from teh data in a JSON object. /// </summary> /// <param name="data">The JSON object.</param> public void init(JSONdn data) { if (!data.has("id")) { throw new ApiException("No playback ID in the response"); } if (m_playback_id.Length > 0 && m_playback_id.CompareTo(data.getStringVal("id")) != 0) { throw new ApiException("Incorrect playback ID in the response"); } m_playback_id = data.getStringVal("id"); if (!data.has("definition_id")) { throw new ApiException("No definition hash in the response"); } m_stream_hash = data.getStringVal("definition_id"); if (!data.has("name")) { throw new ApiException("No name in the response"); } m_name = data.getStringVal("name"); if (!data.has("start")) { throw new ApiException("No start timestamp in the response"); } m_start_date = data.getDateTimeFromLongVal("start"); if (!data.has("end")) { throw new ApiException("No end timestamp in the response"); } m_end_date = data.getDateTimeFromLongVal("end"); if (!data.has("created_at")) { throw new ApiException("No created at timestamp in the response"); } m_created_at = data.getDateTimeFromLongVal("created_at"); if (!data.has("status")) { throw new ApiException("No status in the response"); } m_status = data.getStringVal("status"); if (!data.has("progress")) { throw new ApiException("No progress in the response"); } m_progress = data.getIntVal("progress"); if (!data.has("sources")) { throw new ApiException("No sources in the response"); } m_sources.Clear(); foreach (JToken source in data.getJVal("sources")) { m_sources.Add(source.ToString()); } if (!data.has("sample")) { throw new ApiException("No sample in the response"); } m_sample = data.getDoubleVal("sample"); }
/// <summary> /// Constrcutor. Creates a Historic object from the data contained within a JSON object. /// </summary> /// <param name="user">The User creating the object.</param> /// <param name="data">The JSON data.</param> public Historic(User user, JSONdn data) { m_user = user; init(data); }
/// <summary> /// Extract data from a JSON object. /// </summary> /// <param name="json">The JSON object.</param> protected void init(JSONdn json) { if (!json.has("id")) { throw new InvalidDataException("No ID found"); } m_id = json.getStringVal("id"); if (!json.has("name")) { throw new InvalidDataException("No name found"); } m_name = json.getStringVal("name"); if (!json.has("created_at")) { throw new InvalidDataException("No created at date found"); } m_created_at = Utils.UnixTimestampToDateTime(json.getLongVal("created_at")); if (!json.has("status")) { throw new InvalidDataException("No status found"); } m_status = json.getStringVal("status"); if (!json.has("hash_type")) { throw new InvalidDataException("No hash_type found"); } m_hash_type = json.getStringVal("hash_type"); if (!json.has("hash")) { throw new InvalidDataException("No hash found"); } m_hash = json.getStringVal("hash"); if (!json.has("last_request")) { throw new InvalidDataException("No last request date found"); } try { m_last_request = Utils.UnixTimestampToDateTime(json.getLongVal("last_request")); } catch (Exception) { m_last_request = DateTime.MinValue; } if (!json.has("last_success")) { throw new InvalidDataException("No last success date found"); } try { m_last_success = Utils.UnixTimestampToDateTime(json.getLongVal("last_success")); } catch (Exception) { m_last_success = DateTime.MinValue; } if (!json.has("output_type")) { throw new InvalidDataException("No output type found"); } m_output_type = json.getStringVal("output_type"); if (!json.has("id")) { throw new InvalidDataException("No ID found"); } m_output_params.Clear(); m_output_params.parse(new JSONdn(json.getJVal("output_params"))); }
/// <summary> /// Called by the base class when it wants the consumer to start. /// </summary> /// <param name="auto_reconnect">True to reconnect should the connection get dropped.</param> protected override void onStart(bool auto_reconnect = true) { bool firstConnection = true; int connectionDelay = 0; while ((firstConnection || auto_reconnect) && isRunning(true)) { firstConnection = false; // Do we need to wait before trying to reconnect? if (connectionDelay > 0) { Thread.Sleep(connectionDelay * 1000); } byte[] buffer = new byte[65536]; HttpWebResponse response; // TODO: check status in exception handler to treat timeouts differently if needed WebExceptionStatus status; try { // Build the request. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(getUrl()); request.Timeout = 65000; request.ReadWriteTimeout = 65000; request.Headers["Auth"] = getAuthHeader(); request.UserAgent = getUserAgent(); // Get the response. response = (HttpWebResponse)request.GetResponse(); } catch (WebException e) { // An error occurred, but we handle the response with the same code below. response = (HttpWebResponse)e.Response; status = e.Status; } catch (Exception e) { // Have we exhausted the recommended retries? if (connectionDelay < 16) { // No. Increment the retry delay by a second and tell the user about the problem. connectionDelay += 1; onWarning("Connection failed (" + e.Message + "), retrying in " + connectionDelay + " second" + (connectionDelay == 1 ? "" : "s")); // Try again. continue; } // No more retries. Tell the user and break out of the reconnect loop. onWarning("Connection failed (" + e.Message + "), no more retries"); break; } int statusCode = (response == null ? -1 : (int)response.StatusCode); if (statusCode == 200) { // Yay, connected. Reset the delay, tell the user we're connected and start reading the stream. connectionDelay = 0; onConnect(); readStream(new StreamReader(response.GetResponseStream())); } else if (statusCode == 404) { // Unknown hash. onError("Hash not found"); break; } else if (statusCode >= 400 && statusCode < 500 && statusCode != 420) { // A 4xx (excluding 420) response should contain an error message in JSON. StreamReader response_stream = new StreamReader(response.GetResponseStream()); string json_data = "init"; while (json_data.Length <= 4) { json_data = response_stream.ReadLine(); } JSONdn json = new JSONdn(json_data); if (json.has("message")) { onError(json.getStringVal("message")); } else { onError("Unhandled error code: " + statusCode.ToString() + " " + json_data); } // Break out of the reconnect loop. break; } else { // All other response codes follow the recommended retry pattern for server-side errors. if (connectionDelay == 0) { connectionDelay = 10; } else if (connectionDelay < 320) { connectionDelay *= 2; } else { // We've hit the retry limit, tell the user and break out of the reconnect loop. onError((statusCode == -1 ? "Connection failed" : "Received " + statusCode.ToString() + " response") + ", no more retries"); break; } // Tell the user that we're retrying. onWarning((statusCode == -1 ? "Connection failed" : "Received " + statusCode.ToString() + " response") + ", retrying in " + connectionDelay + " seconds"); } } // Tell the user we've disconnected. onDisconnect(); }
/// <summary> /// Parse the data in a JSON object and store it in this instance. /// </summary> /// <param name="json">The JSON object.</param> public void parse(JSONdn json) { setOutputParams(json, ""); }
/// <summary> /// Constructor from a JSON object. /// </summary> /// <param name="json">The JSON object.</param> public PushLogEntry(JSONdn json) : this(json.getStringVal("subscription_id"), Utils.UnixTimestampToDateTime(json.getLongVal("request_time")), json.getBoolVal("success"), json.has("message") ? json.getStringVal("message") : "") { }
/// <summary> /// Get a page of Push subscriptions in the given user's account, /// where each page contains up to per_page items. Results will be /// ordered according to the supplied ordering parameters. /// </summary> /// <param name="user">The user object making the request.</param> /// <param name="page">The page number to get.</param> /// <param name="per_page">The number of items per page.</param> /// <param name="order_by">The field by which to order the results.</param> /// <param name="order_dir">Ascending or descending.</param> /// <param name="include_finished">True to include subscriptions against finished Historics queries.</param> /// <param name="hash_type">Optional hash type to look for (hash is also required)</param> /// <param name="hash">Optional hash to look for (hash_type is also required)</param> /// <returns>A PushSubscriptionList object.</returns> public static PushSubscriptionList list(User user, int page, int per_page, string order_by = ORDERBY_CREATED_AT, string order_dir = ORDERDIR_ASC, bool include_finished = false, string hash_type = "", string hash = "") { Dictionary <string, string> parameters = new Dictionary <string, string>(); if (hash_type.Length > 0) { if (hash_type != "hash" && hash_type != "playback_id") { throw new InvalidDataException("Hash type is invalid"); } if (hash.Length == 0) { throw new InvalidDataException("Hash type given but the hash is empty"); } parameters.Add(hash_type, hash); } if (page < 1) { throw new InvalidDataException("The specified page number is invalid"); } if (per_page < 1) { throw new InvalidDataException("The specified per_page value is invalid"); } if (order_by != ORDERBY_ID && order_by != ORDERBY_CREATED_AT) { throw new InvalidDataException("The specified order_by is not supported"); } if (order_dir != ORDERDIR_ASC && order_dir != ORDERDIR_DESC) { throw new InvalidDataException("The specified order_dir is not supported"); } parameters.Add("page", page.ToString()); parameters.Add("per_page", per_page.ToString()); parameters.Add("order_by", order_by); parameters.Add("order_dir", order_dir); if (include_finished) { parameters.Add("include_finished", "1"); } JSONdn res = user.callApi("push/get", parameters); if (!res.has("count")) { throw new ApiException("No count in the response"); } PushSubscriptionList retval = new PushSubscriptionList(res.getIntVal("count")); if (!res.has("subscriptions") && retval.TotalCount > 0) { throw new ApiException("No subscriptions in the response"); } JToken[] children = res.getChildren("subscriptions"); for (int i = 0; i < children.Length; i++) { retval.Add(new PushSubscription(user, new JSONdn(children[i]))); } return(retval); }
/// <summary> /// Construct from data in a JSON object. /// </summary> /// <param name="json">The JSON object.</param> public PushOutputParams(JSONdn json) : base() { parse(json); }