def RunUpdate():
    def get_responsible_clans():
        results = CosmosFramework.QueryItems(
            "SELECT DISTINCT(c.wotclan) FROM c WHERE c.wotclan <> null",
            'roles')
        returnlist = []
        for result in results:
            returnlist.append(result['wotclan'])
        return returnlist

    familyclans = get_responsible_clans()

    results = CosmosFramework.QueryItems(
        "SELECT * FROM c WHERE c.wgid <> null AND c.server = 'NA'")
    users = {}
    userinfo = {}
    for result in results:
        userinfo.clear()
        userinfo['clan'] = result['clan']
        userinfo['rank'] = result['rank']
        #userinfo['wgid'] = result['wgid']
        userinfo['discordid'] = result['discordid']
        users[result['wgid']] = dict(userinfo)
    listofusers = []
    wotresults = []
    for user in users:
        if len(listofusers) < 99:
            listofusers.append(user)
        else:
            listofusers.append(user)
            wotresults += wotframework.GetPlayersClanInfo(listofusers)
            listofusers.clear()
    wotresults += wotframework.GetPlayersClanInfo(listofusers)
    for wotresult in wotresults:
        if wotresult[1] in familyclans:  #check if they are in family
            if users[wotresult[0]]['clan'] != wotresult[1] or users[
                    wotresult[0]]['rank'] != wotresult[2]:
                results = CosmosFramework.QueryItems(
                    "SELECT * FROM c WHERE c.wgid={0}".format(wotresult[0]),
                    'users')
                results = results[0]
                results['clan'] = wotresult[1]
                results['rank'] = wotresult[2]
                CosmosFramework.ReplaceItem(results['_self'], results)
                DiscordBotFramework.checkroles(results['discordid'])
        else:
            if users[wotresult[0]]['clan'] != wotresult[1] or users[
                    wotresult[0]]['rank'] != 'friend':
                results = CosmosFramework.QueryItems(
                    "SELECT * FROM c WHERE c.wgid={0}".format(wotresult[0]),
                    'users')
                results = results[0]
                results['clan'] = wotresult[1]
                results['rank'] = 'friend'
                CosmosFramework.ReplaceItem(results['_self'], results)
                DiscordBotFramework.checkroles(results['discordid'])
def __query_cosmos_for_info_by_discordid(discordid: str) -> dict:
    """Querys Cosmos for user info and returns first entry"""
    results = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.discordid="{0}"'.format(discordid), 'users')
    if not bool(results):
        return None
    else:
        return results[0]
 def get_responsible_roles() -> list:
     """Gets a list of Discordid roles that bot thinks it's responsible for"""
     results = CosmosFramework.QueryItems(
         "SELECT DISTINCT(c.discordid) FROM c", 'roles')
     listofroles = []
     for result in results:
         listofroles.append(result['discordid'])
     return listofroles
 def get_responsible_clans():
     results = CosmosFramework.QueryItems(
         "SELECT DISTINCT(c.wotclan) FROM c WHERE c.wotclan <> null",
         'roles')
     returnlist = []
     for result in results:
         returnlist.append(result['wotclan'])
     return returnlist
 def __end_current_contest(channelid: str) -> None:
     contestresults = CosmosFramework.QueryItems(
         'SELECT * FROM c WHERE c.active = true', 'contest')
     contestresults = contestresults[0]
     winnerresults = CosmosFramework.QueryItems(
         'SELECT TOP 10 * FROM c WHERE IS_DEFINED(c.contest.currentscore) AND c.contest.currentscore != 0 ORDER BY c.contest.currentscore DESC',
         'users')
     message = 'Contest is over, congratulations to the winners. Stat being tracked this contest was: {0}. Rewards will be issued shortly.'.format(
         contestresults['stat'])
     DiscordFramework.SendDiscordMessage(message=message,
                                         channelid=channelid)
     placedict = {}
     place = 1
     for result in winnerresults:
         placedict[str(place)] = {
             result['wgid']: result['contest']['currentscore']
         }
         place += 1
     contestresults['winners'] = dict(placedict)
     contestresults['active'] = False
     CosmosFramework.ReplaceItem(contestresults['_self'], contestresults)
 def __start_new_contest(channelid: str) -> None:
     """Starts new contest by removing old contest results"""
     results = CosmosFramework.QueryItems(
         'SELECT * FROM c WHERE IS_DEFINED(c.contest)')
     for result in results:
         del result['contest']
         CosmosFramework.ReplaceItem(result['_self'], result)
     results = CosmosFramework.QueryItems(
         'SELECT * FROM c WHERE c.start = true', 'contest')
     results = results[0]
     results['start'] = False
     results['active'] = True
     CosmosFramework.ReplaceItem(results['_self'], results)
     days = int((results['endtime'] - results['starttime']) / 86400)
     startmessage = 'Reddit World of Tanks contest has started! It will run for {0} days.'.format(
         days)
     startmessage += '\nContest is measurement of World of Tanks single stat in random battles from now until end of contest.'
     startmessage += '\nStat is chosen randomly and not available to any staff member.'
     startmessage += '\nContest is open to anyone with who has register with bot or registers with bot while contest is running. RDDT clan membership is not required.'
     DiscordFramework.SendDiscordMessage(message=startmessage,
                                         channelid=channelid)
def addgame(body: dict) -> dict:
    returnmessage = {}
    discordmessage = __get_split_message(body['message'])
    try:
        game = discordmessage[1]
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.game = %s'.format(game), 'game')
        if not bool(results):
            game = {'game': game}
            game['messageid'] = body['messageid']
            CosmosFramework.InsertItem(game, 'game')
    except ValueError:
        returnmessage['channel'] = "You didn't pass in a game"
def respond_to_login(resp):
    url = resp.identity_url
    pattern = re.compile('\d{10}')
    wgid = pattern.search(url).group()
    token = session['token']
    print('User logged in with wgid {} and token {}.'.format(wgid, token))
    #Wargaming id is now wgid
    #Token passed in is now token

    #Starting Processing Code Block
    response_message = "Beginning processing<br/>"
    if len(token) != 8:  #Greater then 8, someone is f*****g with me
        response_message += "Token rejected <br/>"
    elif token == "00000000":
        response_message += "Token invalid. If you think this is incorrect, contact an Administrator <br/>"
    else:
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.wgtoken = "{0}"'.format(token), 'users')
        wgidcheck = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.wgid={0}'.format(wgid), 'users')

        if not bool(results):
            response_message += "Unknown token"
        elif bool(wgidcheck):
            response_message += "You are already registered with the bot, please contact Rabbit for further assistance"
        else:
            results = results[0]
            results['wgid'] = int(wgid)
            results['server'] = 'NA'
            results['clan'] = None
            results['rank'] = None
            results['wgtoken'] = '00000000'
            CosmosFramework.ReplaceItem(results['_self'], results)
            response_message += "You have been added to database. Updater will process you in 15 minutes or less."

    #End Processing code block
    return '{} <br/><br/> Debug Info:  WGID: {}, Token: {}'.format(
        response_message, wgid, token)
def citadel(body: dict) -> dict:
    returnmessage = {}
    citadelroleid = 636372439261249566
    citadelchannelid = 636374196355858452
    result = __query_cosmos_for_info_by_discordid(str(body['authorid']))
    discordserverid = CommonFramework.RetrieveConfigOptions('discord')
    discordserverid = discordserverid['serverid']
    if result is None or 'wgid' not in result:
        returnmessage[
            'author'] = "You have not registered with the bot, this is mandatory. Please visit <#507725600073449482> to register or please complete registration."
        return returnmessage
    wgid = [int(result['wgid'])]
    claninfo = wotframework.GetPlayersClanInfo(wgid)
    claninfo = claninfo[0]
    if claninfo[1] is None:
        returnmessage[
            'author'] = "You are not a member of clan, citadel access is denied"
        return returnmessage
    elif claninfo[2] not in [
            'commander', 'executive_officer', 'combat_officer',
            'personnel_officer'
    ]:
        returnmessage[
            'author'] = "Citadel access is restricted to Clan officers only"
        return returnmessage
    results = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.wgid = {0}'.format(claninfo[1]), 'citadel')
    if bool(results):  #Meaning their clan ID is in citadel container
        result = results[0]
        if result['citadel'] is True:
            DiscordFramework.AddUserRole(citadelroleid, body['authorid'],
                                         discordserverid)
            returnmessage['author'] = "Access granted"
            DiscordFramework.SendDiscordMessage(
                "{0} from {1} has joined the citadel.".format(
                    body['authordisplayname'], result['name']),
                citadelchannelid)
            result = __query_cosmos_for_info_by_discordid(str(
                body['authorid']))
            result['citadel'] = True
            CosmosFramework.ReplaceItem(result['_self'], result)
        else:
            returnmessage[
                'author'] = 'Citadel access has been revoked because: {0}. If you believe access should be granted, please see moderator.'.format(
                    result['excludereason'])
    else:
        returnmessage[
            'author'] = 'Citadel access is restricted to clans who rank on Global Map ELO. If you believe access should be granted, please see moderator.'
    return returnmessage
 def __get_citadel_results() -> dict:
     primary = {}
     secondary = {}
     results = CosmosFramework.QueryItems(
         'SELECT * FROM c WHERE c.citadel = true', 'citadel')
     for result in results:
         secondary['tag'] = result.get('tag')
         secondary['name'] = result.get('name')
         secondary['citadel'] = result.get('citadel')
         secondary['override'] = result.get('citadeloverride')
         secondary['excludereason'] = result.get('excludereason')
         secondary['excludetime'] = result.get('excludetime')
         primary[result['wgid']] = dict(secondary)
         secondary.clear()
     return primary
 def __exclude_wgid_from_citadel(wgid: int) -> None:
     """Removes WGID from citadel"""
     citadelroleid = 636372439261249566
     discordserverid = CommonFramework.RetrieveConfigOptions('discord')
     discordserverid = discordserverid['serverid']
     result = CosmosFramework.QueryItems(
         'SELECT * FROM c WHERE c.discordid="{0}"'.format(wgid), 'users')
     if bool(result):
         result = result[0]
         DiscordFramework.RemoveUserRole(citadelroleid, result['discordid'],
                                         discordserverid)
         DiscordFramework.send_discord_private_message(
             'You have been removed from RDDT citadel due clan/rank changes',
             result['discordid'])
         del result['citadel']
         CosmosFramework.ReplaceItem(result['_self'], result)
 def __exclude_clan_from_citadel(clanid):
     citadelroleid = 636372439261249566
     discordserverid = CommonFramework.RetrieveConfigOptions('discord')
     discordserverid = discordserverid['serverid']
     results = CosmosFramework.QueryItems(
         'SELECT * FROM c WHERE c.clan = {0} AND c.citadel = true'.format(
             clanid), 'users')
     for result in results:
         status_code = DiscordFramework.RemoveUserRole(
             citadelroleid, result['discordid'], discordserverid)
         if status_code == 204:
             del result['citadel']
             CosmosFramework.ReplaceItem(result['_self'], result)
         else:
             DiscordFramework.send_discord_private_message(
                 "Citadel checker is having issues", 113304266269003776)
             raise "Clan removal failed"
def startcontest(body: dict) -> dict:
    """Starts the contest in database for contest"""
    returnmessage = {}
    currenttime = int(time.time())
    if str(body['authorid']) not in [
            '298272014005829642', '113304266269003776'
    ]:
        returnmessage['author'] = 'You are not authorized to start a contest'
        return returnmessage
    discordmessage = __get_split_message(body['message'])
    try:  #Catching user not sending number
        if int(discordmessage[1]) > 28:
            returnmessage['author'] = 'Contests may not be longer then 28 days'
            return returnmessage
        endtime = currenttime + (86400 * int(discordmessage[1]))
    except:
        returnmessage[
            'author'] = 'You do not specify how long contests can be for'
        return returnmessage
    results = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.active = true OR c.start = true', 'contest')
    if len(results) > 1:
        returnmessage[
            'author'] = 'It appears multiple contests are currently underway at this time, please let rabbit know'
        return returnmessage
    elif len(results) == 1:
        returnmessage['author'] = 'Contest is currently under way'
        return returnmessage
    else:
        doc = {'starttime': int(currenttime)}
        doc['endtime'] = int(endtime)
        doc['active'] = False
        doc['start'] = True
        statlist = [
            'capture_points', 'damage_dealt', 'damage_received',
            'direct_hits_received', 'dropped_capture_points', 'explosion_hits',
            'explosion_hits_received', 'frags', 'hits', 'piercings',
            'piercings_received', 'shots', 'spotted', 'stun_assisted_damage',
            'stun_number', 'survived_battles'
        ]
        doc['stat'] = statlist[(random.randint(0, len(statlist) - 1))]
        CosmosFramework.InsertItem(doc, 'contest')
        returnmessage['author'] = 'Contest started for {0} days'.format(
            discordmessage[1])
        return returnmessage
Beispiel #14
0
def CheckCones() -> None:
    def __remove_cone_role(discordid: str) -> int:
        ConeOfShameDiscordId = '525870180505747467'
        config = CommonFramework.RetrieveConfigOptions('discord')
        status_code = DiscordFramework.RemoveUserRole(ConeOfShameDiscordId,
                                                      discordid,
                                                      config['serverid'])
        return status_code

    currenttime = int(time.time())
    results = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.cone < {0}'.format(currenttime))
    if bool(results):  #meaning people to process
        for result in results:
            status_code = __remove_cone_role(result['discordid'])
            if status_code == 204:
                del result['cone']
                CosmosFramework.ReplaceItem(result['_self'], result)
def update(message):
    returnmessage = {}
    discordmessage = message['message'].split()
    try:
        discordid = int(discordmessage[1])
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.discordid="{0}"'.format(discordid),
            'users')
        if not bool(results):  #unknown Discord id
            returnmessage['channel'] = "Unknown Discord ID"
            return returnmessage
        checkroles(str(discordid))
        returnmessage[
            'channel'] = "Roles checked and adjusted. If roles do not match, it's likely Wargaming API or bot is not up to date. Wait 15 minutes and check again."
        return returnmessage
    except:
        returnmessage[
            'channel'] = "You did not pass in numerical Discord ID. See Pizar/Canteen for how to get that information"
        return returnmessage
 def __post_contest_results(channelid: str,
                            statrandom: bool = True) -> None:
     """Posts Contest results, Needs Channel ID and if results should be randomized"""
     results = CosmosFramework.QueryItems(
         'SELECT TOP 3 * FROM c WHERE IS_DEFINED(c.contest.currentscore) AND c.contest.currentscore != 0 ORDER BY c.contest.currentscore DESC',
         'users')
     if not bool(results):  ##No users with score greater then 1
         return None
     config = CommonFramework.RetrieveConfigOptions('discord')
     place = 1
     if statrandom is True:
         message = 'Please note that score is slightly randomized when displayed and may lead to appear that lower place is winning, true score is used when determining place.'
         DiscordFramework.SendDiscordMessage(message=message,
                                             channelid=channelid)
     DiscordFramework.SendDiscordMessage('Current Contest results:',
                                         channelid)
     for result in results:
         userdata = DiscordFramework.get_user_guild_info(
             result['discordid'], config['serverid'])
         if result['contest']['currentscore'] == 0:
             place += 1
             continue
         if 'code' in userdata and userdata['code'] == 10007:
             CosmosFramework.delete_user_from_cosmos_by_discordid(
                 result['discordid'])
             continue
         if userdata['nick'] is None:
             nick = userdata['user']['username']
         else:
             nick = userdata['nick']
         if statrandom is True:
             score = int(result['contest']['currentscore'] *
                         (random.randint(100, 110) / 100))
         else:
             score = int(result['contest']['currentscore'])
         discordmessage = "{0} is currently in #{1} place with score: {2}".format(
             nick, place, score)
         DiscordFramework.SendDiscordMessage(discordmessage, channelid)
         place += 1
def checkroles(discordid: str) -> None:
    """Checks user for proper roles"""
    def get_responsible_roles() -> list:
        """Gets a list of Discordid roles that bot thinks it's responsible for"""
        results = CosmosFramework.QueryItems(
            "SELECT DISTINCT(c.discordid) FROM c", 'roles')
        listofroles = []
        for result in results:
            listofroles.append(result['discordid'])
        return listofroles

    discord_request = DiscordFramework.DiscordHTTP()
    config = CommonFramework.RetrieveConfigOptions('discord')
    playerresult = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.discordid="{0}"'.format(discordid), 'users')
    if not bool(playerresult):  #Meaning unknown Discord ID
        return None
    playerresult = playerresult[0]
    resproles = get_responsible_roles()  #Roles controlled by the bot
    userroles = DiscordFramework.GetUserRoles(discordid, config['serverid'])
    if userroles == 0:
        return None  #User unknown, exit
    if playerresult['rank'] == "friend":
        friendrole = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.wotrank = "friend"', 'roles')
        friendrole = friendrole[0]
        friendrole = friendrole['discordid']
        if int(friendrole) not in userroles:
            discord_request.add_role_to_user(guildid=config['serverid'],
                                             userid=discordid,
                                             roleid=friendrole)
            #DiscordFramework.AddUserRole(friendrole,discordid,config['serverid'])
        resproles.remove(friendrole)
    else:
        userrankrole = CosmosFramework.QueryItems(
            'SELECT c.discordid FROM c WHERE c.wotrank ="{0}" AND c.wotclan = {1}'
            .format(playerresult['rank'], playerresult['clan']), 'roles')
        userrankrole = userrankrole[0]['discordid']
        userclanrole = CosmosFramework.QueryItems(
            'SELECT c.discordid FROM c WHERE c.wotclan = {0} AND c.wotrank = null'
            .format(playerresult['clan']), 'roles')
        userclanrole = userclanrole[0]['discordid']
        if int(userrankrole) not in userroles or int(
                userclanrole) not in userroles:
            discord_request.add_role_to_user(guildid=config['serverid'],
                                             userid=discordid,
                                             roleid=userclanrole)
            discord_request.add_role_to_user(guildid=config['serverid'],
                                             userid=discordid,
                                             roleid=userrankrole)
            #DiscordFramework.AddUserRole(userclanrole,discordid,config['serverid'])
            #DiscordFramework.AddUserRole(userrankrole,discordid,config['serverid'])
        resproles.remove(userclanrole)
        resproles.remove(userrankrole)
    commonroles = set(int(i) for i in resproles) & set(
        userroles)  #userroles comes back as int
    if bool(commonroles
            ):  #Meaning there is roles showing up that shouldn't be there
        for role in commonroles:
            discord_request.remove_role_from_user(guildid=config['serverid'],
                                                  userid=discordid,
                                                  roleid=role)
            time.sleep(2)
            #DiscordFramework.RemoveUserRole(role,discordid,config['serverid'])
    return None
    def handle_info(self):
        output_channelid = "808513555824771092"
        if len(self.message_split[1]) == 10:  #WGID
            query = f"SELECT * FROM c WHERE c.wgid = {self.message_split[1]}"
            result = CosmosFramework.QueryItems(cosmosdbquery=query,
                                                container='users')

        elif len(self.message_split[1]) in range(17, 19):
            query = f"SELECT * FROM c WHERE c.discordid='{self.message_split[1]}'"
            result = CosmosFramework.QueryItems(cosmosdbquery=query,
                                                container='users')

        else:
            self.discord.post_message(
                message=
                "Improper request, please pass in DiscordID or Wargaming ID",
                channelid=self.message['guildchannelid'])
            return None
        if not result:  #User doesn't exist
            self.discord.post_message(
                message=
                f"User has not registered {self.message['authormention']}",
                channelid=output_channelid,
            )
            return None
        if result[0].get('wgid') is None:
            self.discord.post_message(
                message=
                f"User has not registered {self.message['authormention']}",
                channelid=output_channelid)
            return None
        userinfo = TomatoGG().get_user_info(wgid=result[0]['wgid'])
        if result[0].get('clan') is None:
            clan = "None"
            clan_tag = None
        else:
            clan = wotframework.GetClanInfo(result[0].get('clan'))
            clan_tag = clan['data'][str(result[0]['clan'])]['tag']
            clan = clan['data'][str(result[0]['clan'])]['name']

        discord_user_info = DiscordHTTP().get_user(f"{result[0]['discordid']}")
        discord_user_info = discord_user_info.json()
        if discord_user_info['nick'] is None:
            discord_nickname = discord_user_info['user']['username']
        else:
            discord_nickname = discord_user_info['nick']

        discord_user_info_field = {
            'name': '*Discord Nick*',
            'value': f"{discord_nickname}",
            'inline': False
        }
        embed = {"title": f"User info"}
        embed['type'] = 'rich'
        user_info_field = {
            'name': '*WoT User Name*',
            'value': f"{userinfo['summary']['nickname']}",
            'inline': False
        }
        user_clan_field = {
            'name': '*Clan Name*',
            'value': f"{clan}",
            'inline': False
        }
        user_clan_tag_field = {
            'name': '*Clan Tag*',
            'value': f"None",
            'inline': False
        }
        if clan_tag is not None:
            #user_clan_field = {"Clan Tag:": clan_tag}
            user_clan_tag_field = {
                'name': "*Clan Tag*",
                'value': f"{clan_tag}",
                'inline': False
            }
        #user_wn8_recent_field = {"WN8 60 Day Recent:": userinfo['recents']['recent60days']['overallWN8']}
        user_wn8_recent_field = {
            'name': "*60 Day WN8*",
            'value': f"{userinfo['recents']['recent60days']['overallWN8']}",
            'inline': True
        }
        winrate = (int(userinfo['recents']['recent60days']['wins']) /
                   (int(userinfo['recents']['recent60days']['wins']) +
                    int(userinfo['recents']['recent60days']['losses']))) * 100
        winrate = round(winrate, 2)
        #user_winrate_field = {"60 Day WinRate": winrate}
        user_winrate_field = {
            'name': "*60 Day WinRate*",
            'value': f"{winrate}",
            'inline': False
        }
        #data_info_field = {"Data Provided by tomato.gg": f"https://www.tomato.gg/stats/NA/{userinfo['username']}-{result[0]['wgid']}"}
        #data_info_field = {'name': 'Data Provided by tomato.gg',
        #    'value': f"https://www.tomato.gg/stats/NA/{userinfo['username']}-{result[0]['wgid']}",
        #    'inline': True}
        embed[
            'url'] = f"https://www.tomato.gg/stats/NA/{userinfo['summary']['nickname']}={result[0]['wgid']}"
        fields = [
            discord_user_info_field, user_info_field, user_clan_field,
            user_clan_tag_field, user_wn8_recent_field, user_winrate_field
        ]
        embed['fields'] = fields
        DiscordHTTP().post_message(
            channelid=output_channelid,
            message=
            f"User info as requested by {self.message['authormention']}",
            embed=embed)
def UpdateStats() -> None:
    channelid = 414606940660957184

    def __update_list_of_wgid(wgid: list, stattocheck: str) -> None:
        """Updates a list of WGID, maximum of 100"""
        wgapiresults = wotframework.player_data_info(wgid)
        wgapiresults = wgapiresults['data']
        for wgapiresult in wgapiresults.items():
            wgapiresult = wgapiresult[1]
            if wgapiresult is None:
                continue  #Unknown user, skip (Banned, deleted user)
            userdbdata = CosmosFramework.query_cosmos_for_user_by_wgid(
                wgapiresult['account_id'])
            if userdbdata is None:
                continue  #Not in database, This shouldn't happen
            if 'contest' in userdbdata:  #Meaning I've seen user before
                stat = wgapiresult['statistics']['random'][stattocheck]
                userdbdata['contest']['points'].append(stat)
                if (int(stat) - int(userdbdata['contest']['points'][0]) != 0):
                    userdbdata['contest']['currentscore'] = int(stat) - int(
                        userdbdata['contest']['points'][0])
                CosmosFramework.ReplaceItem(userdbdata['_self'], userdbdata)
            elif 'contest' not in userdbdata:
                stat = [wgapiresult['statistics']['random'][stattocheck]]
                points = {'points': stat}
                points['currentscore'] = 0
                userdbdata['contest'] = dict(points)
                CosmosFramework.ReplaceItem(userdbdata['_self'], userdbdata)

    def __start_new_contest(channelid: str) -> None:
        """Starts new contest by removing old contest results"""
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE IS_DEFINED(c.contest)')
        for result in results:
            del result['contest']
            CosmosFramework.ReplaceItem(result['_self'], result)
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.start = true', 'contest')
        results = results[0]
        results['start'] = False
        results['active'] = True
        CosmosFramework.ReplaceItem(results['_self'], results)
        days = int((results['endtime'] - results['starttime']) / 86400)
        startmessage = 'Reddit World of Tanks contest has started! It will run for {0} days.'.format(
            days)
        startmessage += '\nContest is measurement of World of Tanks single stat in random battles from now until end of contest.'
        startmessage += '\nStat is chosen randomly and not available to any staff member.'
        startmessage += '\nContest is open to anyone with who has register with bot or registers with bot while contest is running. RDDT clan membership is not required.'
        DiscordFramework.SendDiscordMessage(message=startmessage,
                                            channelid=channelid)

    def __post_contest_results(channelid: str,
                               statrandom: bool = True) -> None:
        """Posts Contest results, Needs Channel ID and if results should be randomized"""
        results = CosmosFramework.QueryItems(
            'SELECT TOP 3 * FROM c WHERE IS_DEFINED(c.contest.currentscore) AND c.contest.currentscore != 0 ORDER BY c.contest.currentscore DESC',
            'users')
        if not bool(results):  ##No users with score greater then 1
            return None
        config = CommonFramework.RetrieveConfigOptions('discord')
        place = 1
        if statrandom is True:
            message = 'Please note that score is slightly randomized when displayed and may lead to appear that lower place is winning, true score is used when determining place.'
            DiscordFramework.SendDiscordMessage(message=message,
                                                channelid=channelid)
        DiscordFramework.SendDiscordMessage('Current Contest results:',
                                            channelid)
        for result in results:
            userdata = DiscordFramework.get_user_guild_info(
                result['discordid'], config['serverid'])
            if result['contest']['currentscore'] == 0:
                place += 1
                continue
            if 'code' in userdata and userdata['code'] == 10007:
                CosmosFramework.delete_user_from_cosmos_by_discordid(
                    result['discordid'])
                continue
            if userdata['nick'] is None:
                nick = userdata['user']['username']
            else:
                nick = userdata['nick']
            if statrandom is True:
                score = int(result['contest']['currentscore'] *
                            (random.randint(100, 110) / 100))
            else:
                score = int(result['contest']['currentscore'])
            discordmessage = "{0} is currently in #{1} place with score: {2}".format(
                nick, place, score)
            DiscordFramework.SendDiscordMessage(discordmessage, channelid)
            place += 1

    def __end_current_contest(channelid: str) -> None:
        contestresults = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.active = true', 'contest')
        contestresults = contestresults[0]
        winnerresults = CosmosFramework.QueryItems(
            'SELECT TOP 10 * FROM c WHERE IS_DEFINED(c.contest.currentscore) AND c.contest.currentscore != 0 ORDER BY c.contest.currentscore DESC',
            'users')
        message = 'Contest is over, congratulations to the winners. Stat being tracked this contest was: {0}. Rewards will be issued shortly.'.format(
            contestresults['stat'])
        DiscordFramework.SendDiscordMessage(message=message,
                                            channelid=channelid)
        placedict = {}
        place = 1
        for result in winnerresults:
            placedict[str(place)] = {
                result['wgid']: result['contest']['currentscore']
            }
            place += 1
        contestresults['winners'] = dict(placedict)
        contestresults['active'] = False
        CosmosFramework.ReplaceItem(contestresults['_self'], contestresults)

    currenttime = int(time.time())
    contestresults = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.active = true OR c.start = true', 'contest')
    if not bool(contestresults):
        return None  #No contest is currently running, abort
    contestresults = contestresults[0]
    stattocheck = contestresults['stat']

    #Start New Contest
    if contestresults['start'] == True:
        __start_new_contest(channelid)

    #Update all WGID
    results = CosmosFramework.QueryItems(
        'SELECT c.wgid FROM c WHERE c.wgid <> null', 'users')
    wgidlist = []
    for result in results:
        if len(wgidlist) < 99:
            wgidlist.append(result['wgid'])
        else:
            wgidlist.append(result['wgid'])
            __update_list_of_wgid(wgidlist, stattocheck)
            time.sleep(3)  #WG API rate limiting
            wgidlist.clear()
    __update_list_of_wgid(wgidlist, stattocheck)

    #Post Contest Results
    if contestresults['endtime'] < currenttime:
        __post_contest_results(channelid=channelid, statrandom=False)
        __end_current_contest(channelid=channelid)
    else:
        __post_contest_results(channelid=channelid, statrandom=True)
def register(message: dict) -> dict:
    """Registration"""
    def genToken(discordId: str) -> str:
        time = str(datetime.datetime.utcnow().microsecond
                   )  # only microseconds in last second. i.e. <100
        hasher = hashlib.sha256(discordId.encode('utf-8'))
        hasher.update(time.encode('utf-8'))
        return hasher.hexdigest()[-8:]

    def genURL(token: str) -> str:
        """Generate FLask URI"""
        link = CommonFramework.RetrieveConfigOptions("registration")
        link = link['flaskuri']
        return "{0}?token={1}".format(link, token)

    authordiscordid = message['authorid']
    link = CommonFramework.RetrieveConfigOptions("registration")
    link = link['flaskuri']
    returnmessage = {}
    result = CosmosFramework.QueryItems(
        'SELECT * FROM c WHERE c.discordid = "{0}"'.format(authordiscordid))
    if not bool(result):  #meaning no result
        document = {}
        document['discordid'] = str(
            authordiscordid)  #Discord IDs are in strings
        document['wgtoken'] = str(genToken(str(authordiscordid)))
        CosmosFramework.InsertItem(document)
        returnmessage[
            'channel'] = "Welcome {0}! Check your direct messages for a link. Please note, I only support NA Server for sign in.".format(
                message['authordisplayname'])
        #returnmessage['author'] = genURL(document['wgtoken'])
        pmresult = DiscordFramework.send_discord_private_message(
            message=genURL(document['wgtoken']), discordid=message['authorid'])
        if pmresult.get('message') == 'Cannot send messages to this user':
            DiscordFramework.DiscordHTTP().add_reaction_to_message(
                channelid=message.get('guildchannelid'),
                messageid=message['messageid'],
                emoji="❌")
        else:
            DiscordFramework.DiscordHTTP().add_reaction_to_message(
                channelid=message.get('guildchannelid'),
                messageid=message['messageid'],
                emoji="\N{WHITE HEAVY CHECK MARK}")
    elif result[0]['wgtoken'] is not None and 'wgid' not in result[0]:
        pmresult = DiscordFramework.send_discord_private_message(
            message=genURL(result[0]['wgtoken']),
            discordid=message['authorid'])
        if pmresult.get('message') == 'Cannot send messages to this user':
            DiscordFramework.DiscordHTTP().add_reaction_to_message(
                channelid=message.get('guildchannelid'),
                messageid=message['messageid'],
                emoji="❌")
        else:
            DiscordFramework.DiscordHTTP().add_reaction_to_message(
                channelid=message.get('guildchannelid'),
                messageid=message['messageid'],
                emoji="\N{WHITE HEAVY CHECK MARK}")
        #returnmessage['author'] = genURL(result[0]['wgtoken'])
    elif result[0]['wgid'] is not None:
        pmresult = DiscordFramework.send_discord_private_message(
            message="You have already registered",
            discordid=message['authorid'])
        if pmresult.get('message') == 'Cannot send messages to this user':
            DiscordFramework.DiscordHTTP().add_reaction_to_message(
                channelid=message.get('guildchannelid'),
                messageid=message['messageid'],
                emoji="❌")
        else:
            DiscordFramework.DiscordHTTP().add_reaction_to_message(
                channelid=message.get('guildchannelid'),
                messageid=message['messageid'],
                emoji="\N{WHITE HEAVY CHECK MARK}")
        #returnmessage['author'] = "You have already registered"
    return returnmessage
def run_citadel_check():
    def __get_citadel_results() -> dict:
        primary = {}
        secondary = {}
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.citadel = true', 'citadel')
        for result in results:
            secondary['tag'] = result.get('tag')
            secondary['name'] = result.get('name')
            secondary['citadel'] = result.get('citadel')
            secondary['override'] = result.get('citadeloverride')
            secondary['excludereason'] = result.get('excludereason')
            secondary['excludetime'] = result.get('excludetime')
            primary[result['wgid']] = dict(secondary)
            secondary.clear()
        return primary

    def __exclude_clan_from_citadel(clanid):
        citadelroleid = 636372439261249566
        discordserverid = CommonFramework.RetrieveConfigOptions('discord')
        discordserverid = discordserverid['serverid']
        results = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.clan = {0} AND c.citadel = true'.format(
                clanid), 'users')
        for result in results:
            status_code = DiscordFramework.RemoveUserRole(
                citadelroleid, result['discordid'], discordserverid)
            if status_code == 204:
                del result['citadel']
                CosmosFramework.ReplaceItem(result['_self'], result)
            else:
                DiscordFramework.send_discord_private_message(
                    "Citadel checker is having issues", 113304266269003776)
                raise "Clan removal failed"

    def __exclude_wgid_from_citadel(wgid: int) -> None:
        """Removes WGID from citadel"""
        citadelroleid = 636372439261249566
        discordserverid = CommonFramework.RetrieveConfigOptions('discord')
        discordserverid = discordserverid['serverid']
        result = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.discordid="{0}"'.format(wgid), 'users')
        if bool(result):
            result = result[0]
            DiscordFramework.RemoveUserRole(citadelroleid, result['discordid'],
                                            discordserverid)
            DiscordFramework.send_discord_private_message(
                'You have been removed from RDDT citadel due clan/rank changes',
                result['discordid'])
            del result['citadel']
            CosmosFramework.ReplaceItem(result['_self'], result)

    citadelchannelid = 636374196355858452  #Actual citadel channel
    wgapi = CommonFramework.RetrieveConfigOptions('wargaming')
    results = __get_citadel_results()
    apiresults = CommonFramework.get_json_data(
        "https://api.worldoftanks.com/wot/clanratings/top/?application_id={0}&rank_field=gm_elo_rating&limit=200"
        .format(wgapi['apitoken']))
    wgidlist = []
    #Do clan checks ##TODO put this in it's own def block
    for apiresult in apiresults[
            'data']:  #Get information about clans from Wargaming API
        wgidlist.append(apiresult['clan_id'])
        if apiresult['clan_id'] not in results:
            item = {}
            item['wgid'] = apiresult['clan_id']
            item['name'] = apiresult['clan_name']
            item['tag'] = apiresult['clan_tag']
            item['citadel'] = True
            CosmosFramework.InsertItem(item, 'citadel')
        elif apiresult['clan_id'] in results and (
                results[apiresult['clan_id']]['tag'] != apiresult['clan_tag']
                or results[apiresult['clan_id']]['name'] !=
                apiresult['clan_name']):
            #Checks the database and Wargaming API match around clan tag and name, if not, it updates it
            updateitem = CosmosFramework.QueryItems(
                'SELECT * FROM c WHERE c.wgid={0}'.format(
                    apiresult['clan_id']), 'citadel')
            updateitem = updateitem[0]
            updateitem['name'] = apiresult['clan_name']
            updateitem['tag'] = apiresult['clan_tag']
            CosmosFramework.ReplaceItem(updateitem['_self'], updateitem)
    clanlist = list(results.keys())
    removeclans = list(set(clanlist) -
                       set(wgidlist))  #List of clans to be removed
    for removeclan in removeclans:
        claninfo = CosmosFramework.QueryItems(
            'SELECT * FROM c WHERE c.wgid={0}'.format(removeclan), 'citadel')
        claninfo = claninfo[0]
        if 'override' in claninfo and claninfo['override'] is True:
            continue  #Overrides are not removed
        elif 'excludetime' not in claninfo:  #Step 2, put in removal time
            claninfo['excludetime'] = int(time.time(
            )) + 604700  #This is 6 days, 23 hours and ~58 minutes
            message = "WARNING: Clan {0} ({1}) will be removed within 7 days due to lack of clan rating.".format(
                claninfo['name'], claninfo['tag'])
            DiscordFramework.SendDiscordMessage(message, citadelchannelid)
            CosmosFramework.ReplaceItem(claninfo['_self'], claninfo)
        elif claninfo['excludetime'] < int(
                time.time()
        ):  #when their time is hit, mark them no longer allowed in citadel with reason and remove all clan members
            __exclude_clan_from_citadel(removeclan)
            message = "Clan {0} ({1}) has been removed from citadel.".format(
                claninfo['name'], claninfo['tag'])
            DiscordFramework.SendDiscordMessage(message, citadelchannelid)
            claninfo['citadel'] = False
            claninfo['excludetime'] = None
            claninfo['excludereason'] = 'Excluded due to lack of ranking'
            CosmosFramework.ReplaceItem(claninfo['_self'], claninfo)
    #Do user checks ##TODO Put this in it's own def block
    userresults = CosmosFramework.QueryItems(
        'SELECT c.wgid FROM c WHERE c.citadel = true', 'users')
    wgidtocheck = []
    for userresult in userresults:
        wgidtocheck.append(userresult['wgid'])
        if len(wgidtocheck) >= 99:
            apiresults = wotframework.GetPlayersClanInfo(wgidtocheck)
            for apiresult in apiresults:
                if apiresult[1] is None or apiresult[2] not in [
                        'commander', 'executive_officer', 'combat_officer',
                        'personnel_officer'
                ]:
                    __exclude_wgid_from_citadel(apiresult[0])
            wgidtocheck.clear()
import Modules.CommonFramework as CommonFramework
import Modules.CosmosFramework as CosmosFramework
import time

results = CosmosFramework.QueryItems("SELECT * FROM c",'users')
i = 0
for result in results:
    i += 1
    CosmosFramework.RemoveItem(result['_self'],result['discordid'])
    print("Deleting {0} row out {1}".format(i,len(results)))