def mp_timer(): matchID = get_match_id_from_channel(chan) userID = userUtils.getID(fro) if not can_user_touch_lobby(matchID, userID): return False if len(message) < 2 or not message[1].isdigit() or int(message[1]) < 1: return "Wrong argument" secondsWatch = int(message[1]) match = glob.matches.matches[matchID] if match.timerRunned: chat.sendMessage( glob.BOT_NAME, chan, "You can't run another timer, if you had another runned timer.\nEnter !mp aborttimer to stop." ) return False def _decreaseTimer(t): if match.timerForce: chat.sendMessage(glob.BOT_NAME, chan, "Time is up!") match.timerForce = False match.timerRunned = False elif t <= 0: chat.sendMessage(glob.BOT_NAME, chan, "Time is up!") match.timerRunned = False else: if t % 10 == 0 or t <= 5: chat.sendMessage(glob.BOT_NAME, chan, "Timer ends in {} seconds.".format(t)) threading.Timer(1.00, _decreaseTimer, [t - 1]).start() match.timerRunned = True threading.Timer(1.00, _decreaseTimer, [secondsWatch - 1]).start() return "Timer started!"
def report(fro, chan, message): msg = "" try: # TODO: Rate limit # Get username, report reason and report info target, reason, additionalInfo = message[0], message[1], message[2] target = chat.fixUsernameForBancho(target) # Make sure the target is not foka if target == glob.BOT_NAME: raise exceptions.invalidUserException() # Make sure the user exists targetID = userUtils.getID(target) if targetID == 0: raise exceptions.userNotFoundException() # Make sure that the user has specified additional info if report reason is 'Other' if reason.lower() == "other" and not additionalInfo: raise exceptions.missingReportInfoException() # Get the token if possible chatlog = "" token = glob.tokens.getTokenFromUsername(userUtils.safeUsername(target), safe=True) if token is not None: chatlog = token.getMessagesBufferString() # Everything is fine, submit report glob.db.execute( "INSERT INTO reports (id, from_uid, to_uid, reason, chatlog, time, assigned) VALUES (NULL, %s, %s, %s, %s, %s, 0)", [userUtils.getID(fro), targetID, "{reason} - ingame {info}".format(reason=reason, info="({})".format( additionalInfo) if additionalInfo is not None else ""), chatlog, int(time.time())]) msg = "You've reported {target} for {reason}{info}. A Community Manager will check your report as soon as possible. Every !report message you may see in chat wasn't sent to anyone, so nobody in chat, but admins, know about your report. Thank you for reporting!".format( target=target, reason=reason, info="" if additionalInfo is None else " (" + additionalInfo + ")") adminMsg = "{user} has reported {target} for {reason} ({info})".format(user=fro, target=target, reason=reason, info=additionalInfo) # Log report in #admin and on discord chat.sendMessage(glob.BOT_NAME, "#admin", adminMsg) log.warning(adminMsg, discord="cm") except exceptions.invalidUserException: msg = "Hello, {} here! You can't report me. I won't forget what you've tried to do. Watch out.".format( glob.BOT_NAME) except exceptions.invalidArgumentsException: msg = "Invalid report command syntax. To report an user, click on it and select 'Report user'." except exceptions.userNotFoundException: msg = "The user you've tried to report doesn't exist." except exceptions.missingReportInfoException: msg = "Please specify the reason of your report." except: raise finally: if msg != "": token = glob.tokens.getTokenFromUsername(fro) if token is not None: if token.irc: chat.sendMessage(glob.BOT_NAME, fro, msg) else: token.enqueue(serverPackets.notification(msg)) return False
def invite(self, sender, target, force=True): """ Fro invites to in this match. :param sender: sender userID :param target: receiver userID :return: """ # Get tokens sendToken = glob.tokens.getTokenFromUserID(sender) recvToken = glob.tokens.getTokenFromUserID(target) if sendToken is None or recvToken is None: return # BOT IS BUSY!!! if target == 1: chat.sendMessage( glob.BOT_NAME, sendToken.username, "I would love to join your match, but I can't let my guard down from watching this place. Sorry!" ) # Send message recvToken.enqueue( serverPackets.matchInvite(sendToken.username, recvToken.username, self.matchID, force=force))
def _decreaseTimer(t): if t <= 0: _start() else: if t % 10 == 0 or t <= 5: chat.sendMessage("FokaBot", chan, "Match starts in {} seconds.".format(t)) threading.Timer(1.00, _decreaseTimer, [t - 1]).start()
def asyncGet(self): statusCode = 400 data = {"message": "unknown error"} try: # Check arguments if not requestsManager.checkArguments(self.request.arguments, ["k", "to", "msg"]): raise exceptions.invalidArgumentsException() # Check ci key key = self.get_argument("k") if key is None or key != glob.conf.config["server"]["cikey"]: raise exceptions.invalidArgumentsException() chatHelper.sendMessage( glob.BOT_NAME, self.get_argument("to").encode().decode("ASCII", "ignore"), self.get_argument("msg").encode().decode('utf-8')) # Status code and message statusCode = 200 data["message"] = "ok" except exceptions.invalidArgumentsException: statusCode = 400 data["message"] = "invalid parameters" finally: # Add status code to data data["status"] = statusCode # Send response self.write(json.dumps(data)) self.set_status(statusCode)
def invite(self, fro, to): """ Fro invites to in this match. :param fro: sender userID :param to: receiver userID :return: """ # Get tokens froToken = glob.tokens.getTokenFromUserID(fro) toToken = glob.tokens.getTokenFromUserID(to) if froToken is None or toToken is None: return # FokaBot is too busy if to == 999: chat.sendMessage( glob.BOT_NAME, froToken.username, "I would love to join your match, but I'm busy keeping Mansion up and running. Sorry. Beep Boop." ) # Send message message = "Come join my multiplayer match: \"[osump://{}/{} {}]\"".format( self.matchID, self.matchPassword.replace(" ", "_"), self.matchName) chat.sendMessage(token=froToken, to=toToken.username, message=message)
def sendReadyStatus(self): chanName = "#multi_{}".format(self.matchID) # Make sure match exists before attempting to do anything else if chanName not in glob.channels.channels: return totalUsers = 0 readyUsers = 0 for slot in self.slots: # Make sure there is a user in this slot if slot.user is None: continue # In this slot there is a user, so we increase the amount of total users # in this multi room. totalUsers += 1 if slot.status == slotStatuses.READY: readyUsers += 1 message = "{} users ready out of {}.".format(readyUsers, totalUsers) if totalUsers == readyUsers: message += " All users ready!" # Check whether there is anyone left in this match. if totalUsers == 0: message = "The match is now empty." chat.sendMessage(glob.BOT_NAME, chanName, message)
def setRestricted(self): """ Set this token as restricted, send FokaBot message to user and send offline packet to everyone :return: """ chat.sendMessage(glob.BOT_NAME, self.username, "Your account has been restricted! Please contact the RealistikOsu staff through our Discord server for more info!")
def resetRestricted(self): """ Send FokaBot message to alert the user that he has been unrestricted and he has to log in again. :return: """ chat.sendMessage(glob.BOT_NAME, self.username, "Your account has been unrestricted! Please re-log to refresh your status.")
def handle(self, data): handler_data = super().parseData(data) if handler_data is None: return chatHelper.sendMessage( fro=glob.BOT_NAME, to=handler_data["to"].encode("latin-1").decode("utf-8"), message=handler_data["message"].encode("latin-1").decode("utf-8"))
def onTick(tick): fmt = "" if tick >= 60: fmt = f"{tick // 60} minute{'s' if (tick // 60) > 1 else ''}" else: fmt = f"{tick} second{'s' if (tick) > 1 else ''}" chat.sendMessage(glob.BOT_NAME, channel, f"Countdown ends in {fmt}")
def _start(): matchID = getMatchIDFromChannel(chan) success = glob.matches.matches[matchID].start() if not success: chat.sendMessage("FokaBot", chan, "Couldn't start match. Make sure there are enough players and " "teams are valid. The match has been unlocked.") else: chat.sendMessage("FokaBot", chan, "Have fun!")
def resetRestricted(self): """ Send Aika message to alert the user that he has been unrestricted and he has to log in again. :return: """ chat.sendMessage(glob.BOT_NAME, self.username, "Your account has been unrestricted! Please log in again.")
def setRestricted(self): """ Set this token as restricted, send Aika message to user and send offline packet to everyone :return: """ self.restricted = True chat.sendMessage(glob.BOT_NAME, self.username, "Your account is currently in restricted mode. Please visit Akatsuki's website for more information.")
def allPlayersCompleted(self): """ Cleanup match stuff and send match end packet to everyone :return: """ # Collect some info about the match that just ended to send to the api infoToSend = { "id": self.matchID, "name": self.matchName, "beatmap_id": self.beatmapID, "mods": self.mods, "game_mode": self.gameMode, "scores": {} } # Add score info for each player for i in range(0, 16): if self.slots[i].user is not None and self.slots[ i].status == slotStatuses.PLAYING: infoToSend["scores"][glob.tokens.tokens[ self.slots[i].user].userID] = { "score": self.slots[i].score, "mods": self.slots[i].mods, "failed": self.slots[i].failed, "pass": self.slots[i].passed, "team": self.slots[i].team } # Send the info to the api glob.redis.publish("api:mp_complete_match", json.dumps(infoToSend)) # Reset inProgress self.inProgress = False # Reset slots self.resetSlots() # Send match update self.sendUpdates() # Send match complete glob.streams.broadcast(self.streamName, serverPackets.matchComplete()) # Destroy playing stream glob.streams.dispose(self.playingStreamName) glob.streams.remove(self.playingStreamName) # Console output log.info("MPROOM{}: Match completed".format(self.matchID)) # If this is a tournament match, then we send a notification in the chat # saying that the match has completed. chanName = "#multi_{}".format(self.matchID) if self.isTourney and (chanName in glob.channels.channels): chat.sendMessage(glob.BOT_NAME, chanName, "Match has just finished.")
def triggerStart(): success = match.start(force=True) if not success: chat.sendMessage( glob.BOT_NAME, channel, "Couldn't start match. Make sure there are enough players and " "teams are valid. The match has been unlocked.") else: chat.sendMessage(glob.BOT_NAME, channel, "Match have started.")
def resetRestricted(self): """ Send FokaBot message to alert the user that he has been unrestricted and he has to log in again. :return: """ chat.sendMessage( "FokaBot", self.username, "Your account has been unrestricted! Please log in again.")
def setRestricted(self): """ Set this token as restricted, send FokaBot message to user and send offline packet to everyone :return: """ self.restricted = True chat.sendMessage( glob.botName, self.username, "Your account is currently in restricted mode. Please visit Yozora's website for more information." )
def setRestricted(self): """ Set this token as restricted, send FokaBot message to user and send offline packet to everyone :return: """ self.restricted = True chat.sendMessage( glob.BOT_NAME, self.username, "Your account is currently in restricted mode. Please visit (Datenshi)[https://osu.troke.id] website or (Discord)[https://link.troke.id/datenshi] for more information." )
def onTick(tick): fmt = "" if tick >= 60: fmt = f"{tick // 60} minute{'s' if (tick // 60) > 1 else ''}" elif tick >= 3: fmt = f"{tick} second{'s' if (tick) > 1 else ''}" elif tick == 2: chat.sendMessage(glob.BOT_NAME, channel, "glhf!") return else: return chat.sendMessage(glob.BOT_NAME, channel, f"Match starts in {fmt}")
def spamProtection(self, increaseSpamRate = True): """ Silences the user if is spamming. :param increaseSpamRate: set to True if the user has sent a new message. Default: True :return: """ # Increase the spam rate if needed if increaseSpamRate: self.spamRate += 1 # Silence the user if needed if self.spamRate > 10: self.silence(600, "Spamming (auto spam protection)") chat.sendMessage( glob.BOT_NAME, self.username.encode().decode("ASCII", "ignore"), "You have silenced, reason {}".format("Spamming (auto spam protection)") )
def help(response, token, sender, channel, message): userID = userUtils.getID(sender) for command, command_data in commands.items(): chat.sendMessage( glob.BOT_NAME, sender, f"mp {command} {command_data.syntax} {('(requires %s or higher)' % (command_data.perm,) if command_data.perm != 'basic' else '') if command_data.mpOnly else '*can be used outside mp room*'}" .strip()) chat.sendMessage( glob.BOT_NAME, sender, "This command still underwent heavy rewriting, those ugly terms and such will go soon(TM)." ) chat.sendMessage( glob.BOT_NAME, sender, "Let (us) me know about the bancho mimicking that I need to do, I'll do my best!" ) gloryID = 3 # oi. if userID == gloryID: chat.sendMessage(glob.BOT_NAME, sender, "-- a note that you left behind.") else: gloryName = userUtils.getUsername(gloryID) chat.sendMessage(glob.BOT_NAME, sender, f"-- {gloryName}.") pass
def noticePrivmsgHandler(self, command, arguments): """NOTICE and PRIVMSG commands handler (same syntax)""" # Syntax check if len(arguments) == 0: self.replyCode(411, "No recipient given ({})".format(command)) return if len(arguments) == 1: self.replyCode(412, "No text to send") return recipientIRC = arguments[0] message = arguments[1] # Send the message to bancho and reply if not recipientIRC.startswith("#"): recipientBancho = chat.fixUsernameForBancho(recipientIRC) else: recipientBancho = recipientIRC response = chat.sendMessage(self.banchoUsername, recipientBancho, message, toIRC=False) if response == 404: self.replyCode(404, "Cannot send to channel", channel=recipientIRC) return elif response == 403: self.replyCode(403, "No such channel", channel=recipientIRC) return elif response == 401: self.replyCode(401, "No such nick/channel", channel=recipientIRC) return # Send the message to IRC and bancho if recipientIRC.startswith("#"): # Public message (IRC) if recipientIRC not in glob.channels.channels: self.replyCode(401, "No such nick/channel", channel=recipientIRC) return for _, value in self.server.clients.items(): if recipientIRC in value.joinedChannels and value != self: value.message(":{} PRIVMSG {} :{}".format( self.IRCUsername, recipientIRC, message)) else: # Private message (IRC) for _, value in self.server.clients.items(): if value.IRCUsername == recipientIRC: value.message(":{} PRIVMSG {} :{}".format( self.IRCUsername, recipientIRC, message))
def _decreaseTimer(t): if match.timerForce: chat.sendMessage(glob.BOT_NAME, chan, "Time is up!") match.timerForce = False match.timerRunned = False elif t <= 0: chat.sendMessage(glob.BOT_NAME, chan, "Time is up!") match.timerRunned = False else: if t % 10 == 0 or t <= 5: chat.sendMessage(glob.BOT_NAME, chan, "Timer ends in {} seconds.".format(t)) threading.Timer(1.00, _decreaseTimer, [t - 1]).start()
def handle(userToken, packetData): # Send private message packet packetData = clientPackets.sendPrivateMessage(packetData) chat.sendMessage(token=userToken, to=packetData["to"], message=packetData["message"])
def handle(userToken, packetData): # Send public message packet packetData = clientPackets.sendPublicMessage(packetData) chat.sendMessage(token=userToken, target=packetData["to"], message=packetData["message"])
def allPlayersCompleted(self): """ Cleanup match stuff and send match end packet to everyone :return: """ # Collect some info about the match that just ended to send to the api infoToSend = { "id": self.matchID, "name": self.matchName, "beatmap_id": self.beatmapID, "mods": self.mods, "game_mode": self.gameMode, "host_id": self.hostUserID, "host_user_name": userUtils.getUsername(self.hostUserID), "game_type": self.matchTeamType, "game_score_condition": self.matchScoringType, "game_mod_mode": self.matchModMode, "scores": {} } # Add score info for each player for i in range(0, 16): if self.slots[i].user is not None and self.slots[ i].status == slotStatuses.PLAYING: infoToSend["scores"][glob.tokens.tokens[ self.slots[i].user].userID] = { "score": self.slots[i].score, "mods": self.slots[i].mods, "failed": self.slots[i].failed, "pass": self.slots[i].passed, "team": self.slots[i].team, "username": userUtils.getUsername(glob.tokens.tokens[ self.slots[i].user].userID) # vinse shit ;3 } # Send the info to the api glob.redis.publish("api:mp_complete_match", json.dumps(infoToSend)) self.games.append(json.dumps(infoToSend)) # Reset inProgress self.inProgress = False # Reset slots self.resetSlots() # Send match update self.sendUpdates() # Send match complete glob.streams.broadcast(self.streamName, serverPackets.matchComplete()) # Destroy playing stream glob.streams.dispose(self.playingStreamName) glob.streams.remove(self.playingStreamName) # Console output log.info("MPROOM{}: Match completed".format(self.matchID)) chanName = "#multi_{}".format(self.matchID) if self.vinseID is None: self.vinseID = (int(time.time()) // (60 * 15)) << 32 | self.matchID chat.sendMessage( glob.BOT_NAME, chanName, "Match history available [{} here]".format( "https://kurikku.pw/matches/{}".format(self.vinseID))) # If this is a tournament match, then we send a notification in the chat # saying that the match has completed. if self.isTourney and (chanName in glob.channels.channels): chat.sendMessage(glob.BOT_NAME, chanName, "Match has just finished.")
def allPlayersCompleted(self): """ Cleanup match stuff and send match end packet to everyone :return: """ # Collect some info about the match that just ended to send to the api infoToSend = { "id": self.matchID, "name": self.matchName, "beatmap_id": self.beatmapID, "mods": self.mods, "game_mode": self.gameMode, "scores": {} } # Add score info for each player for i in range(0,16): if self.slots[i].user is not None and self.slots[i].status == slotStatuses.PLAYING: infoToSend["scores"][glob.tokens.tokens[self.slots[i].user].userID] = { "score": self.slots[i].score, "mods": self.slots[i].mods, "failed": self.slots[i].failed, "pass": self.slots[i].passed, "team": self.slots[i].team } # Send the info to the api glob.redis.publish("api:mp_complete_match", json.dumps(infoToSend)) # Reset inProgress self.inProgress = False # Reset slots self.resetSlots() # Send match update self.sendUpdates() # Send match complete glob.streams.broadcast(self.streamName, serverPackets.matchComplete()) # Destroy playing stream glob.streams.dispose(self.playingStreamName) glob.streams.remove(self.playingStreamName) # Console output log.info("MPROOM{}: Match completed".format(self.matchID)) # Set vinse id if needed chanName = "#multi_{}".format(self.matchID) if self.vinseID is None: self.vinseID = (int(time.time()) // (60 * 15)) << 32 | self.matchID chat.sendMessage("FokaBot", chanName, "Match history available [{} here]".format( "https://vinse.ripple.moe/match/{}".format(self.vinseID) )) if not self.bloodcatAlert: chat.sendMessage( "FokaBot", chanName, "Oh by the way, in case you're playing unranked or broken maps " "that are now available through ripple's osu!direct, you can " "type '!bloodcat' in the chat to get a download link for the " "currently selected map from Bloodcat!" ) self.bloodcatAlert = True # If this is a tournament match, then we send a notification in the chat # saying that the match has completed. if self.isTourney and (chanName in glob.channels.channels): chat.sendMessage(glob.BOT_NAME, chanName, "Match has just finished.")
def allPlayersCompleted(self): """ Cleanup match stuff and send match end packet to everyone :return: """ # Collect some info about the match that just ended to send to the api infoToSend = { "id": self.matchID, "name": self.matchName, "beatmap_id": self.beatmapID, "mods": self.mods, "game_mode": self.gameMode, "scores": {} } # Add score info for each player for i in range(0, 16): if self.slots[i].user is not None and self.slots[ i].status == slotStatuses.PLAYING: infoToSend["scores"][glob.tokens.tokens[ self.slots[i].user].userID] = { "score": self.slots[i].score, "mods": self.slots[i].mods, "failed": self.slots[i].failed, "pass": self.slots[i].passed, "team": self.slots[i].team } # Send the info to the api glob.redis.publish("api:mp_complete_match", json.dumps(infoToSend)) # Reset inProgress self.inProgress = False # Reset slots self.resetSlots() # Send match update self.sendUpdates() # Send match complete glob.streams.broadcast(self.streamName, serverPackets.matchComplete()) # Destroy playing stream glob.streams.dispose(self.playingStreamName) glob.streams.remove(self.playingStreamName) # Console output log.info("MPROOM{}: Match completed".format(self.matchID)) # Set vinse id if needed chanName = "#multi_{}".format(self.matchID) if self.vinseID is None: self.vinseID = (int(time.time()) // (60 * 15)) << 32 | self.matchID chat.sendMessage( glob.BOT_NAME, chanName, "Match history available [{} here]".format( "https://multi.troke.id/match/{}".format(self.vinseID))) #ganti ke if not kalau error if not self.bloodcatAlert: chat.sendMessage( glob.BOT_NAME, chanName, "You can use !bloodcat for another beatmap mirror, in case if you have a problem with osudirect" ) self.bloodcatAlert = True # If this is a tournament match, then we send a notification in the chat # saying that the match has completed. if self.isTourney and (chanName in glob.channels.channels): chat.sendMessage(glob.BOT_NAME, chanName, "Match has just finished.")
def edit_map(fro, chan, message): # Edit maps ranking status ingame. // Added by cmyui :) // cmyui why u dont like PEP8? messages = [m.lower() for m in message] rank_type = message[0] map_type = message[1] map_id = message[2] # Get persons username & ID user_id = userUtils.getID(fro) name = userUtils.getUsername(user_id) typeBM = None # Figure out what to do if rank_type == 'rank': rank_typed_str = 'ranke' rank_type_id = 2 freeze_status = 1 elif rank_type == 'love': rank_typed_str = 'love' rank_type_id = 5 freeze_status = 1 elif rank_type == 'unrank': rank_typed_str = 'unranke' rank_type_id = 0 freeze_status = 0 # Grab beatmap_data from db beatmap_data = glob.db.fetch("SELECT * FROM beatmaps WHERE beatmap_id = {} LIMIT 1".format(map_id)) if map_type == 'set': glob.db.execute( "UPDATE beatmaps SET ranked = {}, ranked_status_freezed = {} WHERE beatmapset_id = {} LIMIT 100".format( rank_type_id, freeze_status, beatmap_data["beatmapset_id"])) if freeze_status == 1: glob.db.execute("""UPDATE scores s JOIN (SELECT userid, MAX(score) maxscore FROM scores JOIN beatmaps ON scores.beatmap_md5 = beatmaps.beatmap_md5 WHERE beatmaps.beatmap_md5 = (SELECT beatmap_md5 FROM beatmaps WHERE beatmapset_id = {} LIMIT 1) GROUP BY userid) s2 ON s.score = s2.maxscore AND s.userid = s2.userid SET completed = 3""".format( beatmap_data["beatmapset_id"])) typeBM = 'set' elif map_type == 'map': glob.db.execute( "UPDATE beatmaps SET ranked = {}, ranked_status_freezed = {} WHERE beatmap_id = {} LIMIT 1".format( rank_type_id, freeze_status, map_id)) if freeze_status == 1: glob.db.execute("""UPDATE scores s JOIN (SELECT userid, MAX(score) maxscore FROM scores JOIN beatmaps ON scores.beatmap_md5 = beatmaps.beatmap_md5 WHERE beatmaps.beatmap_md5 = (SELECT beatmap_md5 FROM beatmaps WHERE beatmap_id = {} LIMIT 1) GROUP BY userid) s2 ON s.score = s2.maxscore AND s.userid = s2.userid SET completed = 3""".format( beatmap_data["beatmap_id"])) typeBM = 'beatmap' else: return "Please specify whether it is a set/map. eg: '!map unrank/rank/love set/map 123456'" # Announce / Log to AP logs when ranked status is changed if rank_type == "love": log.rap(user_id, "has {}d beatmap ({}): {} ({}).".format(rank_type, map_type, beatmap_data["song_name"], map_id), True) if map_type == 'set': msg = "{} has loved beatmap set: [https://osu.ppy.sh/s/{} {}]".format(name, beatmap_data["beatmapset_id"], beatmap_data["song_name"]) else: msg = "{} has loved beatmap: [https://osu.ppy.sh/s/{} {}]".format(name, map_id, beatmap_data["song_name"]) glob.db.execute( "UPDATE scores s JOIN (SELECT userid, MAX(score) maxscore FROM scores JOIN beatmaps ON scores.beatmap_md5 = beatmaps.beatmap_md5 WHERE beatmaps.beatmap_md5 = (SELECT beatmap_md5 FROM beatmaps WHERE beatmap_id = {} LIMIT 1) GROUP BY userid) s2 ON s.score = s2.maxscore AND s.userid = s2.userid SET completed = 2".format( beatmap_data["beatmap_id"])) elif rank_type == "rank": log.rap(user_id, "has {}ed beatmap ({}): {} ({}).".format(rank_type, map_type, beatmap_data["song_name"], map_id), True) if map_type == 'set': msg = "{} has {}ed beatmap set: [https://osu.ppy.sh/s/{} {}]".format(name, rank_type, beatmap_data["beatmapset_id"], beatmap_data["song_name"]) else: msg = "{} has {}ed beatmap: [https://osu.ppy.sh/s/{} {}]".format(name, rank_type, map_id, beatmap_data["song_name"]) glob.db.execute( "UPDATE scores s JOIN (SELECT userid, MAX(score) maxscore FROM scores JOIN beatmaps ON scores.beatmap_md5 = beatmaps.beatmap_md5 WHERE beatmaps.beatmap_md5 = (SELECT beatmap_md5 FROM beatmaps WHERE beatmap_id = {} LIMIT 1) GROUP BY userid) s2 ON s.score = s2.maxscore AND s.userid = s2.userid SET completed = 2".format( beatmap_data["beatmap_id"])) else: log.rap(user_id, "has {}ed beatmap ({}): {} ({}).".format(rank_type, map_type, beatmap_data["song_name"], map_id), True) if map_type == 'set': msg = "{} has {}ed beatmap set: [https://osu.ppy.sh/s/{} {}]".format(name, rank_type, beatmap_data["beatmapset_id"], beatmap_data["song_name"]) else: msg = "{} has {}ed beatmap: [https://osu.ppy.sh/s/{} {}]".format(name, rank_type, map_id, beatmap_data["song_name"]) glob.db.execute( "UPDATE scores s JOIN (SELECT userid, MAX(score) maxscore FROM scores JOIN beatmaps ON scores.beatmap_md5 = beatmaps.beatmap_md5 WHERE beatmaps.beatmap_md5 = (SELECT beatmap_md5 FROM beatmaps WHERE beatmap_id = {} LIMIT 1) GROUP BY userid) s2 ON s.score = s2.maxscore AND s.userid = s2.userid SET completed = 2".format( beatmap_data["beatmap_id"])) need_params = { 'token': glob.conf.config["discord"]["krbotToken"], 'poster': fro, 'type': rank_typed_str } if typeBM == 'set': need_params['sid'] = beatmap_data["beatmapset_id"] else: need_params['bid'] = beatmap_data["beatmap_id"] requests.get(glob.conf.config["discord"]["krbot"] + "api/v1/submitMap", params=need_params) chat.sendMessage(glob.BOT_NAME, "#nowranked", msg) return msg