def loot(request): try: # payload = cache.get(f"api_loot", False) # if payload: # print("[api.loot] get loot (cache)") # return JsonResponse(payload, status=200) # if getattr(request, 'limited', False): # return JsonResponse({"error": {"code": 3, "error": "Too many requests (10 calls / hour)"}}, status=429) # get time ts = tsnow() # get npcs npcs = { npc.tId: npc.hospitalTS for npc in NPC.objects.filter(show=True).order_by('hospitalTS') } # by default next update is in an hour next_update = ts + DEFAULT_UPDATE for id, hosp_out in npcs.items(): # check if not to be ignored (IGNORE_TIME seconds after loot level) if ts + IGNORE_TIME < hosp_out + UPDATE_LEVEL: next_update = hosp_out + UPDATE_LEVEL + UPDATE_TIME break debug = { "hosp_out": {k: timestampToDate(v, fmt=True) for k, v in npcs.items()}, "next_update": timestampToDate(next_update, fmt=True), "timestamp": timestampToDate(ts, fmt=True), "message": "This field is temporary to help debug cloudflare cache system. Don't use it in your code." } payload = { "hosp_out": npcs, "next_update": next_update, "timestamp": ts, "debug": debug } print("[api.loot] get loot (computed)") # cache.set("api_loot", payload, 600) return JsonResponse(payload, status=200) except BaseException as e: return JsonResponse({"error": { "code": 1, "error": str(e) }}, status=500)
def prices(request, itemId): try: if request.method == "POST": item = Item.objects.filter(tId=itemId).first() # create price histogram priceHistory = sorted(json.loads(item.priceHistory).items(), key=lambda x: x[0]) # plot only last 8 points of the Tendency graph = [[t, p, item.weekTendencyA * float(t) + item.weekTendencyB, item.monthTendencyA * float(t) + item.monthTendencyB] for t, p in priceHistory] graphLength = 0 maxTS = priceHistory[-1][0] for i, (t, p, wt, mt) in enumerate(graph): if not int(p): graph[i][1] = "null" # graph[i][2] = "null" # graph[i][3] = "null" else: graphLength += 1 if int(maxTS) - int(t) > 3600 * 24 * 7 or wt < 0: graph[i][2] = "null" if int(maxTS) - int(t) > 3600 * 24 * 31 or mt < 0: graph[i][3] = "null" # convert timestamp to date graph[i][0] = timestampToDate(int(t)) context = {'item': item, "graph": graph, "graphLength": graphLength} return render(request, 'bazaar/prices.html', context) else: message = "You might want to log in." if request.method == "POST" else "You need to post. Don\'t try to be a smart ass." return returnError(type=403, msg=message) except Exception: return returnError()
def apiCallAttacks(faction, chain, key=None): # get faction factionId = faction.tId beginTS = chain.start beginTSPreviousStep = 0 endTS = chain.end report = chain.report_set.first() # get all faction keys keys = faction.getAllPairs(enabledKeys=True) # add + 2 s to the endTS endTS += 2 # init variables chainDict = dict({}) # returned dic of attacks feedAttacks = True # set if the report is over or not i = 1 # indice for the number of iteration (db + api calls) nAPICall = 0 # indice for the number of api calls tmp = "" allReq = report.attacks_set.all() while feedAttacks and nAPICall < faction.nAPICall: # SANITY CHECK 0: ask for same beginTS than previous chain # shouldn't happen because fedback = False if so (see below) if beginTS - beginTSPreviousStep <= 0: print("[function.chain.apiCallAttacks] \t[WARNING] will ask for same beginTS next iteration") # try to get req from database tryReq = allReq.filter(tss=beginTS).first() # take attacks from torn API if tryReq is None: if key is None: keyToUse = keys[i % len(keys)][1] print("[function.chain.apiCallAttacks] iteration #{}: API call using {} key".format(i, keys[i % len(keys)][0])) else: print("[function.chain.apiCallAttacks] iteration #{}: API call using personal key".format(i)) keyToUse = key tsDiff = int(timezone.now().timestamp()) - faction.lastAPICall print("[function.chain.apiCallAttacks] \tLast API call: {}s ago".format(tsDiff)) while tsDiff < 32: sleepTime = 32 - tsDiff print("[function.chain.apiCallAttacks] \tLast API call: {}s ago, sleeping for {} seconds".format(tsDiff, sleepTime)) time.sleep(sleepTime) tsDiff = int(timezone.now().timestamp()) - faction.lastAPICall nAPICall += 1 print("[function.chain.apiCallAttacks] \tFrom {} to {}".format(timestampToDate(beginTS), timestampToDate(endTS))) # make the API call selection = "attacks,timestamp&from={}&to={}".format(beginTS, endTS) req = apiCall("faction", faction.tId, selection, keyToUse, verbose=False) # get timestamps reqTS = int(timezone.now().timestamp()) tornTS = int(req.get("timestamp", 0)) # save payload faction.lastAPICall = int(req.get("timestamp", reqTS)) faction.save() # check if no api call if 'error' in req: chainDict["apiError"] = "API error code {}: {}.".format(req["error"]["code"], req["error"]["error"]) chainDict["apiErrorCode"] = int(req["error"]["code"]) break # get attacks from api request attacks = req.get("attacks", dict({})) print("[function.chain.apiCallAttacks] \ttornTS={}, reqTS={} diff={}".format(tornTS, reqTS, tornTS - reqTS)) # SANITY CHECK 1: empty payload if not len(attacks): print("[function.chain.apiCallAttacks] \t[WARNING] empty payload (blank turn)") break # SANITY CHECK 2: api timestamp delayed from now elif abs(tornTS - reqTS) > 25: print("[function.chain.apiCallAttacks] \t[WARNING] returned cache response from API tornTS={}, reqTS={} (blank turn)".format(tornTS, reqTS)) break # SANITY CHECK 3: check if payload different than previous call elif json.dumps([attacks]) == tmp: print("[function.chain.apiCallAttacks] \t[WARNING] same response as before (blank turn)") break else: tmp = json.dumps([attacks]) # all tests passed: push attacks in the database report.attacks_set.create(tss=beginTS, tse=endTS, req=json.dumps([attacks])) # take attacks from the database else: print("[function.chain.apiCallAttacks] iteration #{} from database".format(i)) print("[function.chain.apiCallAttacks] \tFrom {} to {}".format(timestampToDate(beginTS), timestampToDate(endTS))) attacks = json.loads(tryReq.req)[0] # filter all attacks and compute new TS beginTSPreviousStep = beginTS beginTS = 0 chainCounter = 0 for k, v in attacks.items(): if v["defender_faction"] != factionId: chainDict[k] = v # dictionnary of filtered attacks chainCounter = max(v["chain"], chainCounter) # get max chain counter beginTS = max(v["timestamp_started"], beginTS) # get latest timestamp # stoping criterion if same timestamp if beginTS - beginTSPreviousStep <= 0: feedAttacks = False print("[function.chain.apiCallAttacks] stopped chain because was going to ask for the same timestamp") # stoping criterion too many attack requests if i > 1500: feedAttacks = False print("[function.chain.apiCallAttacks] stopped chain because too many iterations") # stoping criterion for walls elif chain.wall: feedAttacks = len(attacks) > 10 # stoping criterion for regular reports elif chain.tId: feedAttacks = not chain.nHits == chainCounter # stoping criterion for live reports else: feedAttacks = len(attacks) > 95 print("[function.chain.apiCallAttacks] \tattacks={} chainCounter={} beginTS={}, endTS={} feed={}".format(len(attacks), chainCounter, beginTS, endTS, feedAttacks)) i += 1 # SANITY CHECK 4: check if timestamps are out of bounds if chain.start > beginTS or chain.end < beginTS: print("[function.chain.apiCallAttacks] ERRORS Attacks out of bounds: chain.starts = {} < beginTS = {} < chain.end = {}".format(chain.start, beginTS, endTS)) print("[function.chain.apiCallAttacks] ERRORS Attacks out of bounds: chain.starts = {} < beginTS = {} < chain.end = {}".format(timestampToDate(chain.start), timestampToDate(beginTS), timestampToDate(endTS))) report.attacks_set.last().delete() print('[function.chain.apiCallAttacks] Deleting last attacks and exiting') return chainDict print('[function.chain.apiCallAttacks] stop iterating') # potentially delete last set of attacks for live chains if not chain.tId: try: lastAttacks = report.attacks_set.last() n = len(json.loads(lastAttacks.req)[0]) if n < 100: lastAttacks.delete() print('[function.chain.apiCallAttacks] Delete last attacks for live chains') else: print('[function.chain.apiCallAttacks] Not delete last attacks for live chains since length = {}'.format(n)) except BaseException: pass # special case for walls if chain.wall and not feedAttacks: print('[function.chain.apiCallAttacks] set chain createReport to False') chain.createReport = False chain.save() return chainDict
def prices(request, tId, period=None): try: if request.method == "POST": if request.session.get('player'): print('[view.stock.prices] get player id from session') playerId = request.session["player"].get("tId") else: print('[view.stock.prices] anon') playerId = -1 player = Player.objects.filter(tId=playerId).first() stock = {'t': Stock.objects.filter(tId=tId).first()} # timestamp rounded at the hour ts = int(timezone.now().timestamp()) ts = int(ts) - int(ts) % 3600 page = "stock/prices.html" if period is None else "stock/prices-graphs.html" period = "7" if period is None else period try: periodS = int(period) * 24 * 3600 except BaseException: periodS = ts history = stock.get('t').history_set.filter( timestamp__gte=(ts - periodS)).order_by('timestamp') av = stock.get('t').averagePrice graph = [] for h in history: t = h.timestamp dt = stock.get('t').dayTendencyA * float(t) + stock.get( 't').dayTendencyB # day tendancy wt = stock.get('t').weekTendencyA * float(t) + stock.get( 't').weekTendencyB # week tendancy line = [ t, h.tCurrentPrice, dt, wt, h.tAvailableShares, h.tTotalShares, h.tForecast, h.tDemand, av ] graph.append(line) graphLength = 0 maxTS = ts for i, (t, p, dt, wt, _, _, _, _, _) in enumerate(graph): # remove 0 prices if not int(p): graph[i][1] = "null" # graph[i][2] = "null" # graph[i][3] = "null" else: graphLength += 1 if int(maxTS) - int(t) > 3600 * 24 or dt < 0: graph[i][2] = "null" if int(maxTS) - int(t) > 3600 * 24 * 7 or wt < 0: graph[i][3] = "null" # convert timestamp to date graph[i][0] = timestampToDate(int(t)) # # add personal stocks to torn stocks for k, v in json.loads(player.stocksJson).items(): if int(v['stock_id']) == int(tId): # add profit v['profit'] = (float(stock.get('t').tCurrentPrice) - float( v["bought_price"])) / float(v["bought_price"]) # add if bonus if stock.get('t').tRequirement: v['bonus'] = 1 if v['shares'] >= stock.get( 't').tRequirement else 0 if stock.get('p') is None: stock['p'] = [v] else: stock['p'].append(v) context = { 'stock': stock, "graph": graph, "graphLength": graphLength, "period": period } return render(request, page, context) else: message = "You might want to log in." if request.method == "POST" else "You need to post. Don\'t try to be a smart ass." return returnError(type=403, msg=message) except Exception: return returnError()
def abroadStocks(request): try: if request.method == "POST": item_id = request.POST.get('item_id', False) country_key = request.POST.get('country_key', False) old = tsnow() - 48 * 3600 stocks = AbroadStocks.objects.filter( country_key=country_key, item__tId=item_id, timestamp__gt=old).order_by("-timestamp") if stocks is None: context = {'item': None, "graph": []} return render(request, 'bazaar/abroad/graph.html', context) # get clients statistics clients = dict({}) for stock in stocks: if stock.client == "": continue if stock.client not in clients: clients[stock.client] = 0 clients[stock.client] += 1 clients = { c: [i, n] for i, (c, n) in enumerate( sorted(clients.items(), key=lambda x: -x[1])) } # graph = [[timestampToDate(s.timestamp), s.quantity, s.cost, s.client, clients.get(s.client)[0], clients.get(s.client)[1]] for s in stocks] # average the prices floatTS = stocks.first().timestamp avg_val = [0, 0, 0] # ts, quantity, cost n = 0 graph = [] for s in stocks: n += 1 avg_val[0] += s.timestamp avg_val[1] += s.quantity if (floatTS - s.timestamp) > 5 * 60: floatTS = s.timestamp line = [ timestampToDate(avg_val[0] // n), avg_val[1] // n, avg_val[2] // n ] graph.append(line) avg_val = [0, 0, 0] n = 0 # record last point if n > 0: line = [ timestampToDate(avg_val[0] // n), avg_val[1] // n, avg_val[2] // n ] graph.append(line) stock = stocks.first() context = { 'stock': stocks.first(), 'graph': graph, 'x': [ timestampToDate(tsnow() - 48 * 3600), timestampToDate(tsnow() - 24 * 3600), timestampToDate(tsnow()) ] } return render(request, 'bazaar/abroad/graph.html', context) else: message = "You might want to log in." if request.method == "POST" else "You need to post. Don\'t try to be a smart ass." return returnError(type=403, msg=message) except Exception as e: return returnError(exc=e, session=request.session)
def __str__(self): return "{} at {}".format(self.stock.tAcronym, timestampToDate(self.timestamp))
def last_action(self, instance): return timestampToDate(instance.lastActionTS)
def last_update(self, instance): return timestampToDate(instance.lastUpdateTS)
def last_check(self, instance): return timestampToDate(instance.lastCheckTS)
def apiCallAttacks(faction, chain, key=None): # WARNING no fallback for this method if api crashed. Will yeld server error. # WINS = ["Arrested", "Attacked", "Looted", "None", "Special", "Hospitalized", "Mugged"] # get faction factionId = faction.tId beginTS = chain.start endTS = chain.end report = chain.report_set.first() # get all faction keys keys = faction.getAllPairs(enabledKeys=True) # add + 2 s to the endTS endTS += 1 # init chainDict = dict({}) feedAttacks = True i = 1 nAPICall = 0 # key = None tmp = "" while feedAttacks and nAPICall < faction.nAPICall: # try to get req from database tryReq = report.attacks_set.filter(tss=beginTS).first() if tryReq is None: if key is None: keyToUse = keys[i % len(keys)][1] print( "[function.chain.apiCallAttacks] iteration #{}: API call using {} key" .format(i, keys[i % len(keys)][0])) else: print( "[function.chain.apiCallAttacks] iteration #{}: API call using personal key" .format(i)) keyToUse = key tsDiff = int(timezone.now().timestamp()) - faction.lastAPICall print("[function.chain.apiCallAttacks] \tLast API call: {}s ago". format(tsDiff)) while tsDiff < 32: sleepTime = 32 - tsDiff print( "[function.chain.apiCallAttacks] \tLast API call: {}s ago, sleeping for {} seconds" .format(tsDiff, sleepTime)) time.sleep(sleepTime) tsDiff = int(timezone.now().timestamp()) - faction.lastAPICall nAPICall += 1 url = "https://api.torn.com/faction/{}?selections=attacks,timestamp&key={}&from={}&to={}".format( faction.tId, keyToUse, beginTS, endTS) print("[function.chain.apiCallAttacks] \tFrom {} to {}".format( timestampToDate(beginTS), timestampToDate(endTS))) print("[function.chain.apiCallAttacks] \tnumber {}: {}".format( nAPICall, url.replace("&key=" + keyToUse, ""))) req = requests.get(url).json() faction.lastAPICall = int( req.get("timestamp", timezone.now().timestamp())) faction.save() if 'error' in req: chainDict["apiError"] = "API error code {}: {}.".format( req["error"]["code"], req["error"]["error"]) chainDict["apiErrorCode"] = int(req["error"]["code"]) break attacks = req.get("attacks", dict({})) if len(attacks): report.attacks_set.create(tss=beginTS, tse=endTS, req=json.dumps([attacks])) else: print( "[function.chain.apiCallAttacks] iteration #{} from database". format(i)) print("[function.chain.apiCallAttacks] \tFrom {} to {}".format( timestampToDate(beginTS), timestampToDate(endTS))) attacks = json.loads(tryReq.req)[0] if json.dumps([attacks]) == tmp: print( "[function.chain.apiCallAttacks] \tWarning same response as before" ) report.attacks_set.filter(tss=beginTS).all().delete() chainDict["error"] = "same response" break else: tmp = json.dumps([attacks]) tableTS = [] maxHit = 0 if len(attacks): for j, (k, v) in enumerate(attacks.items()): if v["defender_faction"] != factionId: chainDict[k] = v maxHit = max(v["chain"], maxHit) # print(v["timestamp_started"]) tableTS.append(v["timestamp_started"]) # beginTS = max(beginTS, v["timestamp_started"]) # feedattacks = True if int(v["timestamp_started"])-beginTS else False # print(chain.nHits, v["chain"]) # print(v["chain"], maxHit, chain.nHits) # if(len(attacks) < 2): # feedAttacks = False if chain.tId: feedAttacks = not chain.nHits == maxHit else: feedAttacks = len(attacks) > 95 beginTS = max(tableTS) print( "[function.chain.apiCallAttacks] \tattacks={} count={} beginTS={}, endTS={} feed={}" .format(len(attacks), maxHit, beginTS, endTS, feedAttacks)) i += 1 else: print("[function.chain.apiCallAttacks] call number {}: {} attacks". format(i, len(attacks))) feedAttacks = False # check if attack timestamp out of bound if chain.start > beginTS or chain.end < beginTS: print( "[function.chain.apiCallAttacks] ERRORS Attacks out of bounds: chain.starts = {} < beginTS = {} w chain.end = {}" .format(chain.start, beginTS, endTS)) print( "[function.chain.apiCallAttacks] ERRORS Attacks out of bounds: chain.starts = {} < beginTS = {} w chain.end = {}" .format(timestampToDate(chain.start), timestampToDate(beginTS), timestampToDate(endTS))) report.attacks_set.last().delete() print( '[function.chain.apiCallAttacks] Deleting last attacks and exiting' ) return chainDict if not chain.tId: try: lastAttacks = report.attacks_set.last() n = len(json.loads(lastAttacks.req)[0]) if n < 100: lastAttacks.delete() print( '[function.chain.apiCallAttacks] Delete last attacks for live chains' ) else: print( '[function.chain.apiCallAttacks] Not delete last attacks for live chains since length = {}' .format(n)) except: pass return chainDict
def date_end(self, instance): return timestampToDate(instance.tse)
def date_start(self, instance): return timestampToDate(instance.tss)
def last_api_call(self, instance): return (timestampToDate(instance.lastAPICall))
def date(self, instance): return timestampToDate(instance.timestamp)
def prices(request, tId, period=None): try: if request.method == "POST": if request.session.get('player'): print('[view.stock.prices] get player id from session') playerId = request.session["player"].get("tId") else: print('[view.stock.prices] anon') playerId = -1 player = Player.objects.filter(tId=playerId).first() stock = {'t': Stock.objects.filter(tId=tId).first()} # timestamp rounded at the hour ts = int(timezone.now().timestamp()) ts = int(ts) - int(ts) % 3600 page = "stock/prices.html" if period is None else "stock/prices-graphs.html" period = "7" if period is None else period try: periodS = int(period) * 24 * 3600 except BaseException: periodS = ts history = stock.get('t').history_set.filter( timestamp__gte=(ts - periodS)).order_by('timestamp') av = stock.get('t').averagePrice graph = [] firstTS = history.first().timestamp lastTS = history.last().timestamp # if periodS > 2592000: # use averaged values for larg graphs (> 1 month) if periodS > 1209600: # use averaged values for larg graphs (> 2 weeks) floatingTS = history.first().timestamp avg_val = [0, 0, 0, 0] n = 0 for h in history: n += 1 t = h.timestamp dt = stock.get('t').dayTendencyA * float(t) + stock.get( 't').dayTendencyB # day tendancy wt = stock.get('t').weekTendencyA * float(t) + stock.get( 't').weekTendencyB # week tendancy avg_val[0] += h.timestamp avg_val[1] += h.tCurrentPrice avg_val[2] += h.tAvailableShares avg_val[3] += h.tTotalShares # make the average and save the line every week if t - floatingTS > (lastTS - firstTS) / 256: floatingTS = t line = [ avg_val[0] // n, avg_val[1] / float(n), dt, wt, avg_val[2] // n, avg_val[3] // n, h.tForecast, h.tDemand, av ] graph.append(line) avg_val = [0, 0, 0, 0] n = 0 # record last point if n > 0: line = [ avg_val[0] // n, avg_val[1] / float(n), dt, wt, avg_val[2] // n, avg_val[3] // n, h.tForecast, h.tDemand, av ] graph.append(line) else: # use all values for recent data for h in history: t = h.timestamp dt = stock.get('t').dayTendencyA * float(t) + stock.get( 't').dayTendencyB # day tendancy wt = stock.get('t').weekTendencyA * float(t) + stock.get( 't').weekTendencyB # week tendancy line = [ t, h.tCurrentPrice, dt, wt, h.tAvailableShares, h.tTotalShares, h.tForecast, h.tDemand, av ] graph.append(line) # convert timestamp to date and remove clean interplation lines # keep last point as is (for interpolation problems) graphLength = 0 maxTS = ts for i, (t, p, dt, wt, _, _, _, _, _) in enumerate(graph[:-1]): # remove 0 prices if not int(p): graph[i][1] = "null" else: graphLength += 1 if int(maxTS) - int(t) > 3600 * 24 or dt < 0: graph[i][2] = "null" if int(maxTS) - int(t) > 3600 * 24 * 7 or wt < 0: graph[i][3] = "null" # convert timestamp to date graph[i][0] = timestampToDate(int(t)) graph[-1][0] = timestampToDate(graph[-1][0]) # add personal stocks to torn stocks for k, v in json.loads(player.stocksJson).items(): if int(v['stock_id']) == int(tId): # add profit v['profit'] = (float(stock.get('t').tCurrentPrice) - float( v["bought_price"])) / float(v["bought_price"]) # add if bonus if stock.get('t').tRequirement: v['bonus'] = 1 if v['shares'] >= stock.get( 't').tRequirement else 0 if stock.get('p') is None: stock['p'] = [v] else: stock['p'].append(v) context = { 'stock': stock, "graph": graph, "graphLength": graphLength, "period": period } return render(request, page, context) else: message = "You might want to log in." if request.method == "POST" else "You need to post. Don\'t try to be a smart ass." return returnError(type=403, msg=message) except Exception: return returnError()
def apiCallAttacksV2(breakdown): # shortcuts faction = breakdown.faction tss = breakdown.tss tse = breakdown.tse if breakdown.tse else int(timezone.now().timestamp()) # recompute last ts tmp = breakdown.attack_set.order_by("-timestamp_ended").first() if tmp is not None: tsl = tmp.timestamp_ended else: tsl = breakdown.tss print("[function.chain.apiCallAttacks] Breakdown from {} to {}. Live = {}".format(timestampToDate(tss), timestampToDate(tse), breakdown.live)) # add + 2 s to the endTS tse += 2 # get existing attacks (just the ids) attacks = [r.tId for r in breakdown.attack_set.all()] print("[function.chain.apiCallAttacks] {} existing attacks".format(len(attacks))) # get key keys = faction.getAllPairs(enabledKeys=True) if not len(keys): print("[function.chain.apiCallAttacks] no key for faction {} --> deleting breakdown".format(faction)) breakdown.delete() return False, "no key in faction {} (delete contract)".format(faction) keyHolder, key = random.choice(keys) # make call selection = "attacks,timestamp&from={}&to={}".format(tsl, tse) req = apiCall("faction", faction.tId, selection, key, verbose=True) # in case there is an API error if "apiError" in req: print('[function.chain.apiCallAttacks] api key error: {}'.format((req['apiError']))) if req['apiErrorCode'] in API_CODE_DELETE: print("[function.chain.apiCallAttacks] --> deleting {}'s key'".format(keyHolder)) faction.delKey(keyHolder) return False, "wrong master key in faction {} for user {} (blank turn)".format(faction, keyHolder) # try to catch cache response tornTS = int(req["timestamp"]) nowTS = int(timezone.now().timestamp()) cacheDiff = abs(nowTS - tornTS) apiAttacks = req.get("attacks") # in case empty payload if not len(apiAttacks): breakdown.computing = False breakdown.save() return False, "Empty payload (stop computing)" print("[function.chain.apiCallAttacks] {} attacks from the API".format(len(apiAttacks))) print("[function.chain.apiCallAttacks] start {}".format(timestampToDate(tss))) print("[function.chain.apiCallAttacks] end {}".format(timestampToDate(tse))) print("[function.chain.apiCallAttacks] last before the call {}".format(timestampToDate(tsl))) newEntry = 0 for k, v in apiAttacks.items(): ts = int(v["timestamp_ended"]) # stop because out of bound # probably because of cache # if int(v["timestamp_started"]) < tsl or int(v["timestamp_ended"]) > tse: # print(ts) # print(tsl) # print(tse) # return False, "timestamp out of bound for faction {} with cacheDiff = {} (added {} entry before exiting)".format(faction, cacheDiff, newEntry) if int(k) not in attacks: for tmpKey in ["fairFight", "war", "retaliation", "groupAttack", "overseas", "chainBonus"]: v[tmpKey] = float(v["modifiers"][tmpKey]) del v["modifiers"] breakdown.attack_set.create(tId=int(k), **v) newEntry += 1 tsl = max(tsl, ts) print("[function.chain.apiCallAttacks] last after the call {}".format(timestampToDate(tsl))) # compute contract variables attacks = breakdown.attack_set.all() # breakdown.revivesContract = len(revives) # breakdown.first = revives.order_by("timestamp").first().timestamp # breakdown.last = revives.order_by("-timestamp").first().timestamp if not newEntry and len(apiAttacks) > 1: return False, "No new entry for faction {} with cacheDiff = {} (continue)".format(faction, cacheDiff) if len(apiAttacks) < 2 and not breakdown.live: print("[function.chain.apiCallAttacks] no api entry for non live breakdown (stop)") breakdown.computing = False breakdown.save() return True, "Everything's fine"
def apiCallRevives(contract): # shortcuts faction = contract.faction start = contract.start end = contract.end if contract.end else int(timezone.now().timestamp()) # recompute last tmp = contract.revive_set.order_by("-timestamp").first() if tmp is not None: last = tmp.timestamp else: last = contract.start print("[function.chain.apiCallRevives] Contract from {} to {}".format(timestampToDate(start), timestampToDate(end))) # add + 2 s to the endTS end += 2 # get existing revives (just the ids) revives = [r.tId for r in contract.revive_set.all()] print("[function.chain.apiCallRevives] {} existing revives".format(len(revives))) # # last timestamp # if len(revives): # lastRevive = contract.revive_set.order_by("-timestamp").first() # last = lastRevive.timestamp # else: # last = start # get key keys = faction.getAllPairs(enabledKeys=True) if not len(keys): print("[function.chain.apiCallRevives] no key for faction {} --> deleting contract".format(faction)) contract.delete() return False, "no key in faction {} (delete contract)".format(faction) keyHolder, key = random.choice(keys) # make call selection = "revives,timestamp&from={}&to={}".format(last, end) req = apiCall("faction", faction.tId, selection, key, verbose=True) # in case there is an API error if "apiError" in req: print('[function.chain.apiCallRevives] api key error: {}'.format((req['apiError']))) if req['apiErrorCode'] in API_CODE_DELETE: print("[function.chain.apiCallRevives] --> deleting {}'s key'".format(keyHolder)) faction.delKey(keyHolder) return False, "wrong master key in faction {} for user {} (blank turn)".format(faction, keyHolder) # try to catch cache response tornTS = int(req["timestamp"]) nowTS = int(timezone.now().timestamp()) cacheDiff = abs(nowTS - tornTS) apiRevives = req.get("revives") # in case empty payload if not len(apiRevives): contract.computing = False contract.save() return False, "Empty payload (stop computing)" print("[function.chain.apiCallRevives] {} revives from the API".format(len(apiRevives))) print("[function.chain.apiCallRevives] start {}".format(timestampToDate(start))) print("[function.chain.apiCallRevives] end {}".format(timestampToDate(end))) print("[function.chain.apiCallRevives] last before the call {}".format(timestampToDate(last))) newEntry = 0 for k, v in apiRevives.items(): ts = int(v["timestamp"]) # stop because out of bound # probably because of cache if ts < last or ts > end: return False, "timestamp out of bound for faction {} with cacheDiff = {} (added {} entry before exiting)".format(faction, cacheDiff, newEntry) if int(k) not in revives: contract.revive_set.create(tId=int(k), **v) newEntry += 1 last = max(last, ts) print("[function.chain.apiCallRevives] last after the call {}".format(timestampToDate(last))) # compute contract variables revives = contract.revive_set.all() contract.revivesContract = len(revives) contract.first = revives.order_by("timestamp").first().timestamp contract.last = revives.order_by("-timestamp").first().timestamp if not newEntry and len(apiRevives) > 1: return False, "No new entry for faction {} with cacheDiff = {} (continue)".format(faction, cacheDiff) if len(apiRevives) < 2: contract.computing = False contract.save() return True, "Everything's fine"
def _update(self, instance): return timestampToDate(instance.update, fmt="%m/%d %H:%M")