public void Initialize() { logger.Info("Initializing core"); InitializeEndpoints(); httpListener.Start(); VK.Init(); logger.Success("Started serving"); tokenSource = new CancellationTokenSource(); ct = tokenSource.Token; listener = Task.Factory.StartNew(Listen, ct); }
public static string RawGet(string uri, WebHeaderCollection headers) { Log.Info($"Executing {uri} with headers {headers}"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Proxy = null; request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; request.Headers = headers; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { return(reader.ReadToEnd()); } }
public static async Task <bool> WaitForFalseOrTimeout(Func <bool> condition, int timeout) { if (timeout <= 3000) { await Task.Delay(timeout); return(!condition()); } Console.WriteLine($"Timeout: {timeout}"); var tokenSource2 = new CancellationTokenSource(); CancellationToken ct = tokenSource2.Token; Task waitTask = Task.Run(async() => { try { while (!ct.IsCancellationRequested && condition()) { await Task.Delay(1000, ct); } } catch (Exception) { } }); Task delayTask = Task.Run(async() => { try { await Task.Delay(timeout, ct); } catch (Exception) { } }); Task temp = await Task.WhenAny(waitTask, delayTask); tokenSource2.Cancel(); try { Task.WaitAll(waitTask, delayTask); } catch (Exception e) { taskLog.Info($"{e}"); } finally { tokenSource2.Dispose(); } return(temp == waitTask); }
public JObject PingPong( HttpListenerContext context, [PathParam] string botname) { logger.Info($"{botname} ping"); LastPing[botname] = DateTime.Now; ipCache[botname] = context.Request.RemoteEndPoint.ToString(); return(new JObject { ["success"] = true, ["ping"] = "pong", }); }
void RefreshConfig() { JObject data = JObject.Parse(Utility.Request.Get(Consts.Endpoints.BotConfig)); if (!data.TryGetValue(botName, out JToken Jtoken)) { Log.Error("Gist config contains no bot definition."); } else { JObject token = Jtoken as JObject; if (token.ContainsKey("obsolete_bot") && token["obsolete_bot"].Type == JTokenType.Boolean && (bool)token["obsolete_bot"]) { if (obsolete_bot != (bool)token["obsolete_bot"]) { obsolete_bot = (bool)token["obsolete_bot"]; if (obsolete_bot) { Log.Info("Bot became obsolete."); } else { Log.Warn("Bot became non-obsolete"); } } } if (token["stopsell"].Type != JTokenType.Integer) { Log.Error("Have no idea when to stop selling"); } else { if (stopsell != (int)token["stopsell"]) { stopsell = (int)token["stopsell"]; } } if (token["stopbuy"].Type != JTokenType.Boolean) { Log.Error("Have no idea when to stop buying"); } else { if (stopbuy != (bool)token["stopbuy"]) { stopbuy = (bool)token["stopbuy"]; } } if (token["sell_only"].Type != JTokenType.Boolean) { Log.Error($"Sell only is not a boolean for {botName}"); } else { if (sellOnly != (bool)token["sell_only"]) { Log.Info("Sellonly was changed from {0} to {1}", sellOnly, (bool)token["sell_only"]); sellOnly = (bool)token["sell_only"]; } } if (token["want_to_buy"].Type != JTokenType.Float) { Log.Error($"Want to buy is not a float for {botName}"); } else { if (WANT_TO_BUY != (double)token["want_to_buy"]) { Log.Info("Want to buy was changed from {0} to {1}", WANT_TO_BUY, (double)token["want_to_buy"]); WANT_TO_BUY = (double)token["want_to_buy"]; } } if (token["max_from_median"].Type != JTokenType.Float) { Log.Error($"Max from median is not a float for {botName}"); } else { if (MAXFROMMEDIAN != (double)token["max_from_median"]) { Log.Info("Max from median was changed from {0} to {1}", WANT_TO_BUY, (double)token["max_from_median"]); MAXFROMMEDIAN = (double)token["max_from_median"]; } } if (token["unstickered_order"].Type != JTokenType.Float) { Log.Error($"Unstickered order is not a float for {botName}"); } else { if (UNSTICKERED_ORDER != (double)token["unstickered_order"]) { Log.Info("Unsctickered order was changed from {0} to {1}", UNSTICKERED_ORDER, (double)token["unstickered_order"]); UNSTICKERED_ORDER = (double)token["unstickered_order"]; } } if (token["experiments"] != null) { if (token["experiments"]["new_buy_formula"] is JToken new_buy_formula && new_buy_formula != null) { try { DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); DateTime start = DateTime.MinValue; if (new_buy_formula["start"] != null) { start = dtDateTime.AddSeconds((double)new_buy_formula["start"]).ToLocalTime(); } DateTime end = dtDateTime.AddSeconds((double)new_buy_formula["end"]).ToLocalTime(); if (DateTime.Now < end) { double want_to_buy = (double)new_buy_formula["want_to_buy"]; NewBuyFormula temp = new NewBuyFormula(start, end, want_to_buy); if (newBuyFormula != temp) { newBuyFormula = temp; Log.Info("New newBuyFormula applied:"); Log.Info(new_buy_formula.ToString(Formatting.None)); } } } catch { Log.Error("Incorrect experiment"); } } if (token["experiments"]["sell_multiplier"] is JToken sell_multiplier && sell_multiplier != null) { try { DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); DateTime start = DateTime.MinValue; if (sell_multiplier["start"] != null) { start = dtDateTime.AddSeconds((double)sell_multiplier["start"]).ToLocalTime(); } DateTime end = dtDateTime.AddSeconds((double)sell_multiplier["end"]).ToLocalTime(); if (DateTime.Now < end) { double sellmultiplier = (double)sell_multiplier["multiplier"]; SellMultiplier temp = new SellMultiplier(start, end, sellmultiplier); if (sellMultiplier != temp) { sellMultiplier = temp; Log.Info("New sellmultiplier applied:"); Log.Info(sell_multiplier.ToString(Formatting.None)); } } } catch { Log.Error("Incorrect experiment"); } } } } }
private void Process(object o) { var context = o as HttpListenerContext; JObject resp = null; try { logger.Info($"[Request {++requestsServed}] {context.Request.RemoteEndPoint.ToString()} - {context.Request.Url.AbsolutePath}"); string Endpoint = context.Request.Url.AbsolutePath; if (Endpoint == Consts.Endpoints.GetBestToken) { var Forced = coreConfig.Bots.Where(x => x.Force && PingedRecently(x.Username)); if (Forced.Any()) { BotConfig forcedBot = Forced.First(); resp = new JObject { ["success"] = true, ["token"] = TokenCache[forcedBot.Username], ["botname"] = forcedBot.Username, }; } else { var Filtered = CurSizes.Where(t => t.Value < Consts.CRITICALTHRESHHOLD && PingedRecently(t.Key)); if (!Filtered.Any()) { throw new Exception("All bots are overflowing!"); } KeyValuePair <string, int> kv = Filtered.OrderBy( t => t.Value / coreConfig.Bots.First(x => x.Username == t.Key).Weight ).FirstOrDefault(); if (kv.Key == null) { throw new Exception("Don't know about bot inventory sizes"); } JToken extrainfo = new JObject(); foreach (var kvp in CurSizes) { extrainfo[kvp.Key] = new JObject { ["inventorysize"] = kvp.Value }; } NameValueCollection qscoll = HttpUtility.ParseQueryString(context.Request.Url.Query); bool extradb = qscoll.AllKeys.Contains("extradb"); foreach (var key in qscoll.AllKeys) { if (key == "dbhit") { int value = int.Parse(qscoll[key]); foreach (var kvp in salesHistorySizes) { while (kvp.Value.TryPeek(out var result)) { if (DateTime.Now.Subtract(result.First).TotalHours <= 1) { break; } if (!kvp.Value.TryDequeue(out result)) { break; } } if (!kvp.Value.IsEmpty) { extrainfo[kvp.Key]["dbhit"] = kvp.Value.Where(x => x.Second >= value).Count() / (double)kvp.Value.Count; if (extradb) { extrainfo[kvp.Key]["dbcnt"] = kvp.Value.Count; } } } } } resp = new JObject { ["success"] = true, ["token"] = TokenCache[kv.Key], ["botname"] = kv.Key, ["extrainfo"] = extrainfo }; } } else if (Endpoint == Consts.Endpoints.BanUser) { long id = context.Request.QueryString["id"] == null ? -1 : long.Parse(context.Request.QueryString["id"]); if (id == -1) { throw new Exception($"Id {id} doesn't look good"); } if (mongoBannedUsers.Add(id)) { resp = new JObject { ["success"] = true }; } else { throw new Exception($"Could not add user (possibly he is present)"); } } else if (Endpoint == Consts.Endpoints.UnBanUser) { long id = context.Request.QueryString["id"] == null ? -1 : long.Parse(context.Request.QueryString["id"]); if (id == -1) { throw new Exception($"Id {id} doesn't look good"); } if (mongoBannedUsers.Delete(id)) { resp = new JObject { ["success"] = true }; } else { throw new Exception($"Could not delete user (possibly he isn't in banned)"); } } else if (Endpoint == Consts.Endpoints.GetBannedUsers) { var stuff = new JArray(mongoBannedUsers.GetBannedUsers().Select(user => user.SteamID64)); resp = new JObject { ["success"] = true, ["userlist"] = stuff }; } else if (Endpoint == Consts.Endpoints.PutTradeToken) { string[] usernames = context.Request.Headers.GetValues("botname") ?? new string[0]; if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string[] data = context.Request.Headers.GetValues("data") ?? new string[0]; if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } TokenCache[usernames[0]] = data[0]; resp = new JObject { ["success"] = true }; } else if (Endpoint == Consts.Endpoints.PutCurrentInventory) { string[] usernames = context.Request.Headers.GetValues("botname") ?? new string[0]; if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string[] data = context.Request.Headers.GetValues("data") ?? new string[0]; if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } CurSizes[usernames[0]] = int.Parse(data[0]); resp = new JObject { ["success"] = true }; } else if (Endpoint == Consts.Endpoints.GetAuthFile) { string[] usernames = context.Request.Headers.GetValues("botname") ?? new string[0]; if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string authPath = Path.Combine("authfiles", usernames[0] + ".auth"); if (File.Exists(authPath)) { resp = new JObject { ["success"] = true, ["data"] = File.ReadAllText(authPath) }; } else { resp = new JObject { ["success"] = false, ["error"] = "File not found" }; } } else if (Endpoint == Consts.Endpoints.PutEmptyStickered) { string[] usernames = context.Request.Headers.GetValues("botname") ?? new string[0]; string[] data = context.Request.Headers.GetValues("data") ?? new string[0]; if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } string[] splitter = data[0].Split('_'); unstickeredCache.Add(long.Parse(splitter[0]), long.Parse(splitter[1])); resp = new JObject { ["success"] = true }; } else if (Endpoint == Consts.Endpoints.GetConfig) { BotConfig chosen = null; foreach (BotConfig bot in coreConfig.Bots) { if (ipCache.TryGetValue(bot.Username, out string ip) && ip == context.Request.RemoteEndPoint.ToString()) { chosen = bot; break; } } if (chosen == null) { foreach (BotConfig bot in coreConfig.Bots) { if (LastPing.TryGetValue(bot.Username, out DateTime dt)) { if (DateTime.Now.Subtract(dt).TotalSeconds > 120) { chosen = bot; break; } } else { chosen = bot; break; } } } if (chosen == null) { resp = new JObject { ["success"] = false, ["error"] = "No free instance available" }; } else { Configuration cfg = JsonConvert.DeserializeObject <Configuration>(JsonConvert.SerializeObject(coreConfig)); cfg.Bots = new BotInfo[] { JsonConvert.DeserializeObject <BotInfo>(JsonConvert.SerializeObject(chosen)) }; resp = new JObject { ["success"] = true, ["config"] = JObject.FromObject(cfg) }; } } else if (Endpoint == Consts.Endpoints.MongoFind) { string query = context.Request.QueryString["query"] ?? "{}"; int limit = int.Parse(context.Request.QueryString["limit"] ?? "-1"); int skip = int.Parse(context.Request.QueryString["skip"] ?? "-1"); //TODO(noobgam): add other tables var filtered = mongoLogs.Find(query, limit, skip); var cursor = filtered.ToCursor(); JArray logs = new JArray(); while (cursor.MoveNext()) { foreach (var msg in cursor.Current) { logs.Add(msg.ToString()); } } resp = new JObject { ["success"] = true, ["extrainfo"] = logs }; } else if (Endpoint == Consts.Endpoints.PingPong) { string[] usernames = context.Request.Headers.GetValues("botname") ?? new string[0]; if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } logger.Info($"{usernames[0]} ping"); LastPing[usernames[0]] = DateTime.Now; ipCache[usernames[0]] = context.Request.RemoteEndPoint.ToString(); resp = new JObject { ["success"] = true, ["ping"] = "pong", }; } else if (Endpoint == Consts.Endpoints.SalesHistorySize) { // deprecated string[] usernames = context.Request.Headers.GetValues("botname"); if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string[] data = context.Request.Headers.GetValues("data"); if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } if (!salesHistorySizes.ContainsKey(usernames[0])) { salesHistorySizes[usernames[0]] = new ConcurrentQueue <Pair <DateTime, int> >(); } salesHistorySizes[usernames[0]].Enqueue(new Pair <DateTime, int>(DateTime.Now, int.Parse(data[0]))); } else if (Endpoint == Consts.Endpoints.PutTradableCost) { string[] usernames = context.Request.Headers.GetValues("botname"); if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string[] data = context.Request.Headers.GetValues("data"); if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } string[] stuff = data[0].Split(':'); CurTradable[usernames[0]] = double.Parse(stuff[0]); CurUntracked[usernames[0]] = int.Parse(stuff[1]); resp = new JObject { ["success"] = true }; } else if (Endpoint == Consts.Endpoints.PutMedianCost) { string[] usernames = context.Request.Headers.GetValues("botname"); if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string[] data = context.Request.Headers.GetValues("data"); if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } CurMedian[usernames[0]] = double.Parse(data[0]); resp = new JObject { ["success"] = true }; } else if (Endpoint == Consts.Endpoints.PutMoney) { string[] usernames = context.Request.Headers.GetValues("botname"); if (usernames.Length != 1) { throw new Exception($"You have to provide 1 username, {usernames.Length} were provided"); } string[] data = context.Request.Headers.GetValues("data"); if (data.Length != 1) { throw new Exception($"You have to provide 1 data, {data.Length} were provided"); } CurMoney[usernames[0]] = int.Parse(data[0]); resp = new JObject { ["success"] = true }; } else if (Endpoint == Consts.Endpoints.GetSalesDatabase) { byte[] bytes = File.ReadAllBytes(Path.Combine("assets", "newDatabase")); resp = new JObject { ["success"] = true, ["data"] = StringUtils.ToBase64(bytes) }; } else if (Endpoint == Consts.Endpoints.GetEmptyStickeredDatabase) { string[] lines = unstickeredCache.Dump(); byte[] bytes = BinarySerialization.NS.Serialize(lines, true); resp = new JObject { ["success"] = true, ["data"] = StringUtils.ToBase64(bytes) }; } else if (Endpoint == Consts.Endpoints.GetSalesDatabase) { byte[] bytes = BinarySerialization.NS.Serialize(unstickeredCache); resp = new JObject { ["success"] = true, ["data"] = StringUtils.ToBase64(bytes) }; } else if (Endpoint == Consts.Endpoints.RPS) { resp = new JObject { ["success"] = true, //["rps"] = Balancer.GetNewItemsRPS() }; } else if (Endpoint == Consts.Endpoints.Status) { bool full = context.Request.QueryString["full"] == null ? false : bool.Parse(context.Request.QueryString["full"]); bool table = context.Request.QueryString["table"] == null ? false : bool.Parse(context.Request.QueryString["table"]); JToken extrainfo = new JObject(); double moneySum = 0; foreach (var kvp in CurSizes) { if (extrainfo[kvp.Key] == null) { extrainfo[kvp.Key] = new JObject(); } extrainfo[kvp.Key]["inventorysize"] = kvp.Value; } foreach (var kvp in CurMoney) { double myMoney = (double)kvp.Value / 100; if (full) { if (extrainfo[kvp.Key] == null) { extrainfo[kvp.Key] = new JObject(); } extrainfo[kvp.Key]["curmoney"] = myMoney.ToString("C", new CultureInfo("ru-RU")); } moneySum += myMoney; } foreach (var kvp in CurMedian) { if (kvp.Value == 0) { continue; } if (extrainfo[kvp.Key] == null) { extrainfo[kvp.Key] = new JObject(); } extrainfo[kvp.Key]["median_sum"] = kvp.Value.ToString("C", new CultureInfo("en-US")); } double usd_trade_sum = 0; foreach (var kvp in CurTradable) { if (full) { if (extrainfo[kvp.Key] == null) { extrainfo[kvp.Key] = new JObject(); } extrainfo[kvp.Key]["tradable_usd_cost"] = kvp.Value.ToString("C", new CultureInfo("en-US")); } usd_trade_sum += kvp.Value; } resp = new JObject { ["success"] = true, ["extrainfo"] = extrainfo, ["moneysum"] = new JObject() { ["RUB"] = moneySum, ["USD"] = Economy.ConvertCurrency(Economy.Currency.RUB, Economy.Currency.USD, moneySum).ToString("C", new CultureInfo("en-US")), ["TRADE"] = usd_trade_sum.ToString("C", new CultureInfo("en-US")) } }; if (table) { if (RespondTable(context, resp)) { return; } } } if (resp == null) { resp = new JObject { ["success"] = false, ["error"] = "Unsupported request" } } ; Respond(context, resp); } catch (Exception ex) { resp = new JObject { ["success"] = false, ["error"] = ex.Message, ["trace"] = ex.StackTrace }; Respond(context, resp); } }