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 cone(body: dict) -> dict: """Cones user, adds information to database and sends return messages""" discordmessage = body['message'].split() ConeOfShameDiscordId = '525870180505747467' returnmessage = {} config = CommonFramework.RetrieveConfigOptions('discord') try: if len(discordmessage) < 3: returnmessage['author'] = 'Invalid command format' return returnmessage timetocone = int(discordmessage[2]) if timetocone > 2880: returnmessage[ 'author'] = 'You cannot Cone someone longer then 2 days' return returnmessage discordid = int(__discord_id_from_mention( discordmessage[1])) ##Trys int to make sure it's int result = __query_cosmos_for_info_by_discordid(discordid) if result is None: newitem = {} newitem['discordid'] = str(discordid) result = CosmosFramework.InsertItem(newitem, 'users') if 'cone' in result: returnmessage['author'] = 'User is already coned' statuscode = DiscordFramework.AddUserRole(ConeOfShameDiscordId, discordid, config['serverid']) if statuscode == 204: #Meaning add role was successful result['cone'] = int(time.time()) + (60 * int(timetocone)) CosmosFramework.ReplaceItem(result['_self'], result) returnmessage['channel'] = '{0} muted user for {1} minutes'.format( body['authordisplayname'], timetocone) returnmessage['author'] = 'Cone issued as requested' returnmessage['targetdiscordid'] = discordid returnmessage[ 'target'] = 'You were muted for {0} minutes by {1}'.format( timetocone, body['authordisplayname']) except Exception as e: returnmessage['author'] = 'Following error has occured: {0}'.format(e) 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
import json import MySQLdb import Modules.CommonFramework as CommonFramework import Modules.CosmosFramework as CosmosFramework import time mysqlcinfo = CommonFramework.RetrieveConfigOptions("mysql") mysqlconn = MySQLdb.connect(host=mysqlcinfo['server'], user=mysqlcinfo['username'], passwd=mysqlcinfo['password'], db=mysqlcinfo['database']) mysqlconn.autocommit(True) mysqlcur = mysqlconn.cursor() cmd = "SELECT discordid,wgid,clan,rank,wgtoken,updated FROM users" mysqlcur.execute(cmd) data = mysqlcur.fetchall() #discordserverid = CommonFramework.RetrieveConfigOptions('discord') #discordserverid = discordserverid['discordserverid'] #Upload Users csdbdoc = {} for row in data: csdbdoc.clear() csdbdoc['discordid'] = str(row[0]) csdbdoc['wgid'] = row[1] csdbdoc['clan'] = row[2] csdbdoc['rank'] = row[3] csdbdoc['wgtoken'] = str(row[4]) csdbdoc['server'] = 'NA' CosmosFramework.InsertItem(csdbdoc, 'users') #time.sleep(.03)
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()
#This module is to provide web interface for users to register. This module simply takes token generated by another application and matches up WG OpenID response then stores WGID in #the database for RDDT_Teamspeak_Bot Module to interact with. from flask import Flask, request, redirect, session from flask_openid import OpenID import re #import MySQLdb import Modules.CommonFramework as CommonFramework import Modules.CosmosFramework as CosmosFramework #Flask Setup config = CommonFramework.RetrieveConfigOptions('registration') app_id = config['app_id'] oid = OpenID() app = Flask(__name__) app.secret_key = config['app_secret'] port = 8080 wgid_handler = '/wgid/redirect' response_message = 'Processing registration' login_message = 'Please click here to log in with wargaming' auth_url = '/wgid/auth' min_battles = 0 @app.route(auth_url) def landing_page(): if 'token' not in request.values: return 'Invalid request'
import discord from azure.servicebus import QueueClient, Message import json #Local Modules import Modules.CommonFramework as CommonFramework import Modules.DiscordFramework as DiscordFramework import Modules.CosmosFramework as CosmosFramework #import Modules.EventGridFramework as EventGridFramework #import Modules.DiscordBotFramework as DiscordBotFramework ##Discord options discordoptions = CommonFramework.RetrieveConfigOptions('discord') token = discordoptions['token'] discordclient = discord.Client() commandprefix = '!' #Discord Incoming Service Bus setup servicebusoptions = CommonFramework.RetrieveConfigOptions('discordlisten') connection_str = servicebusoptions['connectionstring'] queue_path = servicebusoptions['queue'] servicebusclient = QueueClient.from_connection_string(connection_str, queue_path) ### @discordclient.event async def on_message(message): if message.author == discordclient.user: return None #Bot ignores itself
import json import requests import os from time import sleep import Modules.CommonFramework as CommonFramework baseuri = "https://discord.com/api" config = CommonFramework.RetrieveConfigOptions("discord") class DiscordHTTP: def __init__(self) -> None: global config self.token = config['token'] self.baseuri = "https://discord.com/api" def __generate_discord_header(self) -> dict: header = { 'Authorization': str(f"Bot {self.token}"), 'User-Agent': '/r/worldoftanks Discord Bot (https://github.com/Rabbit994/RDDT-Discord-Bot-Azure, v1.0.5)' } return header def __send_discord_put_request(self, uri: str): statuscode = 0 for x in range(0, 3): r = requests.put(uri, headers=self.__generate_discord_header()) statuscode = r.status_code if statuscode == 429: #If
#This handles incoming discord messages import json from time import sleep import requests ##3rd Party Modules from azure.servicebus import QueueClient, Message ##Local Modules import Modules.CosmosFramework as CosmosFramework import Modules.CommonFramework as CommonFramework import Modules.DiscordFramework as DiscordFramework import Modules.DiscordBotFramework as DiscordBotFramework from Modules.DiscordBotFramework import MessageHandler #region Service Bus for incoming config = CommonFramework.RetrieveConfigOptions('discordlisten') connection_str = config['connectionstring'] queue = config['queue'] sbclient = QueueClient.from_connection_string(connection_str,queue) #endregion def __return_message(body:dict, returnmessage:dict) -> None: """Gets original message and return message and sends to proper channels""" if 'channel' in returnmessage: DiscordFramework.SendDiscordMessage(returnmessage['channel'],body['guildchannelid']) if 'author' in returnmessage: DiscordFramework.send_discord_private_message(returnmessage['author'],body['authorid']) if 'target' in returnmessage and 'targetdiscordid' in returnmessage: DiscordFramework.send_discord_private_message(returnmessage['target'],returnmessage['targetdiscordid']) return None
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 genURL(token: str) -> str: """Generate FLask URI""" link = CommonFramework.RetrieveConfigOptions("registration") link = link['flaskuri'] return "{0}?token={1}".format(link, token)
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
""" This is check for Wargaming NA Stream and posting if active """ import time from Modules.twitch import TwitchAPI import Modules.CommonFramework as CommonFramework import Modules.DiscordFramework as DiscordFramework i = 0 channelid = '414607006821777440' options = CommonFramework.RetrieveConfigOptions("twitch") twitch = TwitchAPI(options['clientid'], options['clientsecret']) users = ['worldoftanksna'] active = {} for user in users: active[user] = False while i < 1008: for user in users: currentstreams = twitch.get_streams_by_userlogin(userlogin=user) if len(currentstreams['data']) > 0 and active[user] is False: embed = {"title": f"Twitch Streamer {user} is active"} embed['type'] = 'rich' title = currentstreams['data'][0]['title'] embed[ 'description'] = f"Twitch Stream {user} is currently active and streaming {title}" embed['url'] = f"https://www.twitch.tv/{user}" DiscordFramework.SendDiscordMessage(message=None, channelid=channelid, embed=embed) active[user] = True
def GetClanInfo(wgclanid: int) -> dict: apikey = CommonFramework.RetrieveConfigOptions("wargaming") apikey = apikey['apitoken'] uri = f"https://api.worldoftanks.com/wot/clans/info/?application_id={apikey}&clan_id={wgclanid}" return CommonFramework.get_json_data(uri)