SHARE
TWEET

Untitled

a guest May 25th, 2019 198 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import base64
  2. import collections
  3. import json
  4. import sys
  5. import threading
  6. import traceback
  7. from urllib.parse import urlencode
  8.  
  9. import requests
  10. import tornado.gen
  11. import tornado.web
  12.  
  13. import secret.achievements.utils
  14. from common.constants import gameModes
  15. from common.constants import mods
  16. from common.log import logUtils as log
  17. from common.ripple import userUtils
  18. from common.sentry import sentry
  19. from common.web import requestsManager
  20. from constants import exceptions
  21. from constants import rankedStatuses
  22. from constants.exceptions import ppCalcException
  23. from helpers import aeshelper
  24. from helpers import replayHelper
  25. from helpers import leaderboardHelper
  26. from helpers.generalHelper import zingonify
  27. from objects import beatmap
  28. from objects import glob
  29. from objects import score
  30. from objects import scoreboard
  31. from objects.charts import BeatmapChart, OverallChart
  32. from secret import butterCake
  33.  
  34. MODULE_NAME = "submit_modular"
  35. class handler(requestsManager.asyncRequestHandler):
  36.     """
  37.     Handler for /web/osu-submit-modular.php
  38.     """
  39.     @tornado.web.asynchronous
  40.     @tornado.gen.engine
  41.     #@sentry.captureTornado
  42.     def asyncPost(self):
  43.         newCharts = self.request.uri == "/web/osu-submit-modular-selector.php"
  44.         try:
  45.             # Resend the score in case of unhandled exceptions
  46.             keepSending = True
  47.  
  48.             # Get request ip
  49.             ip = self.getRequestIP()
  50.  
  51.             # Print arguments
  52.             if glob.conf["DEBUG"]:
  53.                 requestsManager.printArguments(self)
  54.  
  55.             # Check arguments
  56.             if not requestsManager.checkArguments(self.request.arguments, ["score", "iv", "pass"]):
  57.                 raise exceptions.invalidArgumentsException(MODULE_NAME)
  58.  
  59.             # TODO: Maintenance check
  60.  
  61.             # Get parameters and IP
  62.             scoreDataEnc = self.get_argument("score")
  63.             iv = self.get_argument("iv")
  64.             password = self.get_argument("pass")
  65.             ip = self.getRequestIP()
  66.             quit_ = self.get_argument("x", "0") == "1"
  67.             try:
  68.                 failTime = max(0, int(self.get_argument("ft", 0)))
  69.             except ValueError:
  70.                 raise exceptions.invalidArgumentsException(MODULE_NAME)
  71.             failed = not quit_ and failTime > 0
  72.  
  73.             # Get bmk and bml (notepad hack check)
  74.             if "bmk" in self.request.arguments and "bml" in self.request.arguments:
  75.                 bmk = self.get_argument("bmk")
  76.                 bml = self.get_argument("bml")
  77.             else:
  78.                 bmk = None
  79.                 bml = None
  80.  
  81.             # Get right AES Key
  82.             if "osuver" in self.request.arguments:
  83.                 aeskey = "osu!-scoreburgr---------{}".format(self.get_argument("osuver"))
  84.             else:
  85.                 aeskey = "h89f2-890h2h89b34g-h80g134n90133"
  86.  
  87.             # Get score data
  88.             log.debug("Decrypting score data...")
  89.             scoreData = aeshelper.decryptRinjdael(aeskey, iv, scoreDataEnc, True).split(":")
  90.             if len(scoreData) < 16 or len(scoreData[0]) != 32:
  91.                 return
  92.             username = scoreData[1].strip()
  93.  
  94.             # Login and ban check
  95.             userID = userUtils.getID(username)
  96.             # User exists check
  97.             if userID == 0:
  98.                 raise exceptions.loginFailedException(MODULE_NAME, userID)
  99.  
  100.             # Score submission lock check
  101.             lock_key = "lets:score_submission_lock:{}:{}:{}".format(userID, scoreData[0], int(scoreData[9]))
  102.             if glob.redis.get(lock_key) is not None:
  103.                 # The same score score is being submitted and it's taking a lot
  104.                 log.warning("Score submission blocked because there's a submission lock in place ({})".format(lock_key))
  105.                 return
  106.  
  107.             # Set score submission lock
  108.             log.debug("Setting score submission lock {}".format(lock_key))
  109.             glob.redis.set(lock_key, "1", 120)
  110.  
  111.             # Bancho session/username-pass combo check
  112.             if not userUtils.checkLogin(userID, password, ip):
  113.                 raise exceptions.loginFailedException(MODULE_NAME, username)
  114.             # 2FA Check
  115.             if userUtils.check2FA(userID, ip):
  116.                 raise exceptions.need2FAException(MODULE_NAME, userID, ip)
  117.             # Generic bancho session check
  118.             #if not userUtils.checkBanchoSession(userID):
  119.                 # TODO: Ban (see except exceptions.noBanchoSessionException block)
  120.             #   raise exceptions.noBanchoSessionException(MODULE_NAME, username, ip)
  121.             # Ban check
  122.             if userUtils.isBanned(userID):
  123.                 raise exceptions.userBannedException(MODULE_NAME, username)
  124.             # Data length check
  125.             if len(scoreData) < 16:
  126.                 raise exceptions.invalidArgumentsException(MODULE_NAME)
  127.  
  128.             # Get restricted
  129.             restricted = userUtils.isRestricted(userID)
  130.  
  131.             # Create score object and set its data
  132.             log.info("{} has submitted a score on {}...".format(username, scoreData[0]))
  133.             s = score.score()
  134.             s.setDataFromScoreData(scoreData, quit_=quit_, failed=failed)
  135.  
  136.             if s.completed == -1:
  137.                 # Duplicated score
  138.                 log.warning("Duplicated score detected, this is normal right after restarting the server")
  139.                 return
  140.  
  141.             # Set score stuff missing in score data
  142.             s.playerUserID = userID
  143.  
  144.             # Get beatmap info
  145.             beatmapInfo = beatmap.beatmap()
  146.             beatmapInfo.setDataFromDB(s.fileMd5)
  147.  
  148.             # Make sure the beatmap is submitted and updated
  149.             if beatmapInfo.rankedStatus in (
  150.                 rankedStatuses.NOT_SUBMITTED, rankedStatuses.NEED_UPDATE, rankedStatuses.UNKNOWN
  151.             ):
  152.                 log.debug("Beatmap is not submitted/outdated/unknown. Score submission aborted.")
  153.                 return
  154.  
  155.             # Set play time and full play time
  156.             s.fullPlayTime = beatmapInfo.hitLength
  157.             if quit_ or failed:
  158.                 s.playTime = failTime // 1000
  159.  
  160.             # Calculate PP
  161.             midPPCalcException = None
  162.             try:
  163.                 s.calculatePP()
  164.             except Exception as e:
  165.                 # Intercept ALL exceptions and bypass them.
  166.                 # We want to save scores even in case PP calc fails
  167.                 # due to some rippoppai bugs.
  168.                 # I know this is bad, but who cares since I'll rewrite
  169.                 # the scores server again.
  170.                 log.error("Caught an exception in pp calculation, re-raising after saving score in db")
  171.                 s.pp = 0
  172.                 midPPCalcException = e
  173.  
  174.             # Restrict obvious cheaters
  175.             if (s.pp >= 1000 and s.gameMode == gameModes.STD) and not restricted:
  176.                 userUtils.restrict(userID)
  177.                 userUtils.appendNotes(userID, "Restricted due to too high pp gain ({}pp)".format(s.pp))
  178.                 log.warning("**{}** ({}) has been restricted due to too high pp gain **({}pp)**".format(username, userID, s.pp), "cm")
  179.  
  180.             # Check notepad hack
  181.             if bmk is None and bml is None:
  182.                 # No bmk and bml params passed, edited or super old client
  183.                 #log.warning("{} ({}) most likely submitted a score from an edited client or a super old client".format(username, userID), "cm")
  184.                 pass
  185.             elif bmk != bml and not restricted:
  186.                 # bmk and bml passed and they are different, restrict the user
  187.                 userUtils.restrict(userID)
  188.                 userUtils.appendNotes(userID, "Restricted due to notepad hack")
  189.                 log.warning("**{}** ({}) has been restricted due to notepad hack".format(username, userID), "cm")
  190.                 return
  191.  
  192.             # Right before submitting the score, get the personal best score object (we need it for charts)
  193.             if s.passed and s.oldPersonalBest > 0:
  194.                 # We have an older personal best. Get its rank (try to get it from cache first)
  195.                 oldPersonalBestRank = glob.personalBestCache.get(userID, s.fileMd5)
  196.                 if oldPersonalBestRank == 0:
  197.                     # oldPersonalBestRank not found in cache, get it from db through a scoreboard object
  198.                     oldScoreboard = scoreboard.scoreboard(username, s.gameMode, beatmapInfo, False)
  199.                     oldScoreboard.setPersonalBestRank()
  200.                     oldPersonalBestRank = max(oldScoreboard.personalBestRank, 0)
  201.                 oldPersonalBest = score.score(s.oldPersonalBest, oldPersonalBestRank)
  202.             else:
  203.                 oldPersonalBestRank = 0
  204.                 oldPersonalBest = None
  205.  
  206.             # Save score in db
  207.             s.saveScoreInDB()
  208.  
  209.             # Remove lock as we have the score in the database at this point
  210.             # and we can perform duplicates check through MySQL
  211.             log.debug("Resetting score lock key {}".format(lock_key))
  212.             glob.redis.delete(lock_key)
  213.  
  214.             # Client anti-cheat flags
  215.             '''ignoreFlags = 4
  216.             if glob.debug:
  217.                 # ignore multiple client flags if we are in debug mode
  218.                 ignoreFlags |= 8
  219.             haxFlags = (len(scoreData[17])-len(scoreData[17].strip())) & ~ignoreFlags
  220.             if haxFlags != 0 and not restricted:
  221.                 userHelper.restrict(userID)
  222.                 userHelper.appendNotes(userID, "-- Restricted due to clientside anti cheat flag ({}) (cheated score id: {})".format(haxFlags, s.scoreID))
  223.                 log.warning("**{}** ({}) has been restricted due clientside anti cheat flag **({})**".format(username, userID, haxFlags), "cm")'''
  224.  
  225.             # Mi stavo preparando per scendere
  226.             # Mi stavo preparando per comprare i dolci
  227.             # Oggi e' il compleanno di mio nipote
  228.             # Dovevamo festeggiare staseraaaa
  229.             # ----
  230.             # Da un momento all'altro ho sentito una signora
  231.             # Correte, correte se ne e' sceso un muro
  232.             # Da un momento all'altro ho sentito una signora
  233.             # Correte, correte se ne e' sceso un muro
  234.             # --- (io sto angora in ganottier ecche qua) ---
  235.             # Sono scesa e ho visto ilpalazzochesenee'caduto
  236.             # Ho preso a mio cognato, che stava svenuto
  237.             # Mia figlia e' scesa, mia figlia ha urlato
  238.             # "C'e' qualcuno sotto, C'e' qualcuno sotto"
  239.             # "C'e' qualcuno sotto, C'e' qualcuno sottoooooooooo"
  240.             # --- (scusatm che sto angor emozzionat non parlo ancora moltobbene) ---
  241.             # Da un momento all'altro ho sentito una signora
  242.             # Correte, correte se ne e' sceso un muro
  243.             # Da un momento all'altro ho sentito una signora
  244.             # Correte, correte se ne e' sceso un muro
  245.             # -- THIS IS THE PART WITH THE GOOD SOLO (cit <3) --
  246.             # Vedete quel palazzo la' vicino
  247.             # Se ne sta scendendo un po' alla volta
  248.             # Piano piano, devono prendere provvedimenti
  249.             # Al centro qua hanno fatto una bella ristrututuitriazione
  250.             # Hanno mess le panghina le fondane iffiori
  251.             # LALALALALALALALALA
  252.             if s.score < 0 or s.score > (2 ** 63) - 1:
  253.                 userUtils.ban(userID)
  254.                 userUtils.appendNotes(userID, "Banned due to negative score (score submitter)")
  255.  
  256.             # Make sure the score is not memed
  257.             if s.gameMode == gameModes.MANIA and s.score > 1000000:
  258.                 userUtils.ban(userID)
  259.                 userUtils.appendNotes(userID, "Banned due to mania score > 1000000 (score submitter)")
  260.  
  261.             # Ci metto la faccia, ci metto la testa e ci metto il mio cuore
  262.             if ((s.mods & mods.DOUBLETIME) > 0 and (s.mods & mods.HALFTIME) > 0) \
  263.                     or ((s.mods & mods.HARDROCK) > 0 and (s.mods & mods.EASY) > 0)\
  264.                     or ((s.mods & mods.SUDDENDEATH) > 0 and (s.mods & mods.NOFAIL) > 0):
  265.                 userUtils.ban(userID)
  266.                 userUtils.appendNotes(userID, "Impossible mod combination {} (score submitter)".format(s.mods))
  267.  
  268.             # NOTE: Process logging was removed from the client starting from 20180322
  269.             if s.completed == 3 and "pl" in self.request.arguments:
  270.                 butterCake.bake(self, s)
  271.  
  272.             # Save replay for all passed scores
  273.             # Make sure the score has an id as well (duplicated?, query error?)
  274.             if s.passed and s.scoreID > 0:
  275.                 if "score" in self.request.files:
  276.                     # Save the replay if it was provided
  277.                     log.debug("Saving replay ({})...".format(s.scoreID))
  278.                     replay = self.request.files["score"][0]["body"]
  279.  
  280.                     # Save raw osr in all folders
  281.                     saved_replays = 0
  282.                     replay_save_exception = None
  283.                     for i, replay_folder in enumerate(glob.conf["REPLAYS_FOLDERS"]):
  284.                         # We don't want everything to fail if s3 is offline,
  285.                         # oiseau will take care or re-uploading failed replays to s3 anyways
  286.                         try:
  287.                             with open("{}/replay_{}.osr".format(replay_folder, s.scoreID), "wb") as f:
  288.                                 f.write(replay)
  289.                             saved_replays += 1
  290.                         except Exception as e:
  291.                             replay_save_exception = e
  292.                             sentry.captureMessage(
  293.                                 "Replay saving error ({}), path index {} ({}). S3 may be offline".format(
  294.                                     e, i, replay_folder
  295.                                 )
  296.                             )
  297.  
  298.                     # Could not save the replay at all. Re-raise exception and abort score submission
  299.                     if saved_replays == 0:
  300.                         log.debug("Could not save replay! Re-raising exception and aborting score submission.")
  301.                         raise replay_save_exception
  302.  
  303.                     # Send to cono ALL passed replays, even non high-scores
  304.                     if glob.conf["CONO_ENABLE"]:
  305.                         # We run this in a separate thread to avoid slowing down scores submission,
  306.                         # as cono needs a full replay
  307.                         threading.Thread(target=lambda: glob.redis.publish(
  308.                             "cono:analyze", json.dumps({
  309.                                 "score_id": s.scoreID,
  310.                                 "beatmap_id": beatmapInfo.beatmapID,
  311.                                 "user_id": s.playerUserID,
  312.                                 "game_mode": s.gameMode,
  313.                                 "pp": s.pp,
  314.                                 "completed": s.completed,
  315.                                 "replay_data": base64.b64encode(
  316.                                     replayHelper.buildFullReplay(
  317.                                         s.scoreID,
  318.                                         rawReplay=self.request.files["score"][0]["body"]
  319.                                     )
  320.                                 ).decode(),
  321.                             })
  322.                         )).start()
  323.                 else:
  324.                     # Restrict if no replay was provided
  325.                     if not restricted:
  326.                         userUtils.restrict(userID)
  327.                         userUtils.appendNotes(userID, "Restricted due to missing replay while submitting a score "
  328.                                                       "(most likely he used a score submitter)")
  329.                         log.warning("**{}** ({}) has been restricted due to replay not found on map {}".format(
  330.                             username, userID, s.fileMd5
  331.                         ), "cm")
  332.  
  333.             # Update beatmap playcount (and passcount)
  334.             beatmap.incrementPlaycount(s.fileMd5, s.passed)
  335.  
  336.             # Let the api know of this score
  337.             if s.scoreID:
  338.                 glob.redis.publish("api:score_submission", s.scoreID)
  339.  
  340.             # Re-raise pp calc exception after saving score, cake, replay etc
  341.             # so Sentry can track it without breaking score submission
  342.             if midPPCalcException is not None:
  343.                 raise ppCalcException(midPPCalcException)
  344.  
  345.             # If there was no exception, update stats and build score submitted panel
  346.             # Get "before" stats for ranking panel (only if passed)
  347.             if s.passed:
  348.                 # Get old stats and rank
  349.                 oldUserStats = glob.userStatsCache.get(userID, s.gameMode)
  350.                 oldRank = userUtils.getGameRank(userID, s.gameMode)
  351.  
  352.             # Always update users stats (total/ranked score, playcount, level, acc and pp)
  353.             # even if not passed
  354.             log.debug("Updating {}'s stats...".format(username))
  355.             userUtils.updateStats(userID, s)
  356.  
  357.             # Get "after" stats for ranking panel
  358.             # and to determine if we should update the leaderboard
  359.             # (only if we passed that song)
  360.             if s.passed:
  361.                 # Get new stats
  362.                 newUserStats = userUtils.getUserStats(userID, s.gameMode)
  363.                 glob.userStatsCache.update(userID, s.gameMode, newUserStats)
  364.  
  365.                 # Update leaderboard (global and country) if score/pp has changed
  366.                 if s.completed == 3 and newUserStats["pp"] != oldUserStats["pp"]:
  367.                     leaderboardHelper.update(userID, newUserStats["pp"], s.gameMode)
  368.                     leaderboardHelper.updateCountry(userID, newUserStats["pp"], s.gameMode)
  369.  
  370.             # Update total hits
  371.             userUtils.updateTotalHits(score=s)
  372.             # TODO: max combo
  373.  
  374.             # Update latest activity
  375.             userUtils.updateLatestActivity(userID)
  376.  
  377.             # IP log
  378.             userUtils.IPLog(userID, ip)
  379.  
  380.             # Score submission and stats update done
  381.             log.debug("Score submission and user stats update done!")
  382.  
  383.             # Score has been submitted, do not retry sending the score if
  384.             # there are exceptions while building the ranking panel
  385.             keepSending = False
  386.  
  387.             # At the end, check achievements
  388.             if s.passed:
  389.                 new_achievements = secret.achievements.utils.unlock_achievements(s, beatmapInfo, newUserStats)
  390.  
  391.             # Output ranking panel only if we passed the song
  392.             # and we got valid beatmap info from db
  393.             if beatmapInfo is not None and beatmapInfo != False and s.passed:
  394.                 log.debug("Started building ranking panel")
  395.  
  396.                 # Trigger bancho stats cache update
  397.                 glob.redis.publish("peppy:update_cached_stats", userID)
  398.  
  399.                 # Get personal best after submitting the score
  400.                 newScoreboard = scoreboard.scoreboard(username, s.gameMode, beatmapInfo, False)
  401.                 newScoreboard.setPersonalBestRank()
  402.                 personalBestID = newScoreboard.getPersonalBestID()
  403.                 assert personalBestID is not None
  404.                 currentPersonalBest = score.score(personalBestID, newScoreboard.personalBestRank)
  405.  
  406.                 # Get rank info (current rank, pp/score to next rank, user who is 1 rank above us)
  407.                 rankInfo = leaderboardHelper.getRankInfo(userID, s.gameMode)
  408.  
  409.                 # Output dictionary
  410.                 if newCharts:
  411.                     log.debug("Using new charts")
  412.                     dicts = [
  413.                         collections.OrderedDict([
  414.                             ("beatmapId", beatmapInfo.beatmapID),
  415.                             ("beatmapSetId", beatmapInfo.beatmapSetID),
  416.                             ("beatmapPlaycount", beatmapInfo.playcount + 1),
  417.                             ("beatmapPasscount", beatmapInfo.passcount + (s.completed == 3)),
  418.                             ("approvedDate", "")
  419.                         ]),
  420.                         BeatmapChart(
  421.                             oldPersonalBest if s.completed == 3 else currentPersonalBest,
  422.                             currentPersonalBest if s.completed == 3 else s,
  423.                             beatmapInfo.beatmapID,
  424.                         ),
  425.                         OverallChart(
  426.                             userID, oldUserStats, newUserStats, s, new_achievements, oldRank, rankInfo["currentRank"]
  427.                         )
  428.                     ]
  429.                 else:
  430.                     log.debug("Using old charts")
  431.                     dicts = [
  432.                         collections.OrderedDict([
  433.                             ("beatmapId", beatmapInfo.beatmapID),
  434.                             ("beatmapSetId", beatmapInfo.beatmapSetID),
  435.                             ("beatmapPlaycount", beatmapInfo.playcount),
  436.                             ("beatmapPasscount", beatmapInfo.passcount),
  437.                             ("approvedDate", "")
  438.                         ]),
  439.                         collections.OrderedDict([
  440.                             ("chartId", "overall"),
  441.                             ("chartName", "Overall Ranking"),
  442.                             ("chartEndDate", ""),
  443.                             ("beatmapRankingBefore", oldPersonalBestRank),
  444.                             ("beatmapRankingAfter", newScoreboard.personalBestRank),
  445.                             ("rankedScoreBefore", oldUserStats["rankedScore"]),
  446.                             ("rankedScoreAfter", newUserStats["rankedScore"]),
  447.                             ("totalScoreBefore", oldUserStats["totalScore"]),
  448.                             ("totalScoreAfter", newUserStats["totalScore"]),
  449.                             ("playCountBefore", newUserStats["playcount"]),
  450.                             ("accuracyBefore", float(oldUserStats["accuracy"])/100),
  451.                             ("accuracyAfter", float(newUserStats["accuracy"])/100),
  452.                             ("rankBefore", oldRank),
  453.                             ("rankAfter", rankInfo["currentRank"]),
  454.                             ("toNextRank", rankInfo["difference"]),
  455.                             ("toNextRankUser", rankInfo["nextUsername"]),
  456.                             ("achievements", ""),
  457.                             ("achievements-new", secret.achievements.utils.achievements_response(new_achievements)),
  458.                             ("onlineScoreId", s.scoreID)
  459.                         ])
  460.                     ]
  461.                 output = "\n".join(zingonify(x) for x in dicts)
  462.  
  463.                 # Some debug messages
  464.                 log.debug("Generated output for online ranking screen!")
  465.                 log.debug(output)
  466.  
  467.                 # send message to #announce if we're rank #1
  468.                 if newScoreboard.personalBestRank == 1 and s.completed == 3 and not restricted:
  469.                     annmsg = "[https://ripple.moe/?u={} {}] achieved rank #1 on [https://osu.ppy.sh/b/{} {}] ({})".format(
  470.                         userID,
  471.                         username.encode().decode("ASCII", "ignore"),
  472.                         beatmapInfo.beatmapID,
  473.                         beatmapInfo.songName.encode().decode("ASCII", "ignore"),
  474.                         gameModes.getGamemodeFull(s.gameMode)
  475.                     )
  476.                     params = urlencode({"k": glob.conf["BANCHO_API_KEY"], "to": "#announce", "msg": annmsg})
  477.                     requests.get("{}/api/v1/fokabotMessage?{}".format(glob.conf["BANCHO_URL"], params))
  478.  
  479.                 # Write message to client
  480.                 self.write(output)
  481.             else:
  482.                 # No ranking panel, send just "ok"
  483.                 self.write("ok")
  484.  
  485.             # Send username change request to bancho if needed
  486.             # (key is deleted bancho-side)
  487.             newUsername = glob.redis.get("ripple:change_username_pending:{}".format(userID))
  488.             if newUsername is not None:
  489.                 log.debug("Sending username change request for user {} to Bancho".format(userID))
  490.                 glob.redis.publish("peppy:change_username", json.dumps({
  491.                     "userID": userID,
  492.                     "newUsername": newUsername.decode("utf-8")
  493.                 }))
  494.  
  495.             # Datadog stats
  496.             glob.dog.increment(glob.DATADOG_PREFIX+".submitted_scores")
  497.         except exceptions.invalidArgumentsException:
  498.             pass
  499.         except exceptions.loginFailedException:
  500.             self.write("error: pass")
  501.         except exceptions.need2FAException:
  502.             # Send error pass to notify the user
  503.             # resend the score at regular intervals
  504.             # for users with memy connection
  505.             self.set_status(408)
  506.             self.write("error: 2fa")
  507.         except exceptions.userBannedException:
  508.             self.write("error: ban")
  509.         except exceptions.noBanchoSessionException:
  510.             # We don't have an active bancho session.
  511.             # Don't ban the user but tell the client to send the score again.
  512.             # Once we are sure that this error doesn't get triggered when it
  513.             # shouldn't (eg: bancho restart), we'll ban users that submit
  514.             # scores without an active bancho session.
  515.             # We only log through schiavo atm (see exceptions.py).
  516.             self.set_status(408)
  517.             self.write("error: pass")
  518.         except:
  519.             # Try except block to avoid more errors
  520.             try:
  521.                 log.error("Unknown error in {}!\n```{}\n{}```".format(MODULE_NAME, sys.exc_info(), traceback.format_exc()))
  522.                 if glob.conf.sentry_enabled:
  523.                     yield tornado.gen.Task(self.captureException, exc_info=True)
  524.             except:
  525.                 pass
  526.  
  527.             # Every other exception returns a 408 error (timeout)
  528.             # This avoids lost scores due to score server crash
  529.             # because the client will send the score again after some time.
  530.             if keepSending:
  531.                 self.set_status(408)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top