async def cdoDefaultCategory(msg : Message,**kwargs): """ Sets a default category for the channels created :param kwargs: :return: """ try: defaultCategory = Settings.objects.get(name="defaultCategory") except ObjectDoesNotExist: defaultCategory = None if "parameter0" not in kwargs.keys(): if defaultCategory is not None: return CDOInteralResponseData(f"Default category is **{defaultCategory.value}**") else: return CDOInteralResponseData(f"No default category set yet") if defaultCategory is not None: defaultCategory.value = kwargs['parameter0'] else: defaultCategory = Settings(name="defaultCategory",value=kwargs['parameter0']) defaultCategory.save() return CDOInteralResponseData(f"Default category set to **{defaultCategory.value}**")
async def cdoGetUserPermissions(**kwargs): """ Gets the userlevel of a mentioned user :param kwargs: :return: """ data = list(kwargs['msg'].content.split(" ")) if len(kwargs['msg'].mentions) == 0: return CDOInteralResponseData("You need to mention a user to set its permission levels") for i in data: if i.startswith("<@"): del data[data.index(i)] if len(data) != 1: return CDOInteralResponseData("Wrong number of parameters. Needs !getUserPermissions *mentions* ") addInfo = OrderedDict() for user in kwargs['msg'].mentions: try: user = DiscordUsers.objects.get(id=user.id) addInfo[user.name] = f"User level: {user.userLevel}" except ObjectDoesNotExist: addInfo[user.name] = f"User level: 0" retObj = CDOInteralResponseData("UserLevels:") retObj.additionalInfo = addInfo return retObj
async def cdoUpdateBot(msg : Message,**kwargs): """ Updates bot :param kwargs: :return: """ def spawnAndWait(listObj): p = subprocess.Popen(listObj) p.wait() if "parameter0" not in kwargs.keys(): return CDOInteralResponseData("Please provide the version you want to update to (master (_**experimental**_)" ", or version)") version = kwargs['parameter0'] if version != "master" and version not in getVersions(): return CDOInteralResponseData(f"Version {data[1]} not available") if not checkoutVersion(version): return CDOInteralResponseData(f"Sorry, {version} is not available") spawnAndWait([sys.executable, path + "/../manage.py", "migrate"]) spawnAndWait([sys.executable, "-m", "pip", "install", "-r", f"{path}/../requirements.txt"]) return CDOInteralResponseData(f"Updated Bot to **{version}**. Please restart to apply changes")
async def cdoSetUserPermissions(**kwargs): """ Sets the userlevel for the mentioned users. :param kwargs: :return: """ data = list(kwargs['msg'].content.split(" ")) if len(kwargs['msg'].mentions) == 0: return CDOInteralResponseData("You need to mention a user to set its permission levels") for i in data: if i.startswith("<@"): del data[data.index(i)] if len(data) != 2: return CDOInteralResponseData("Wrong number of parameters. Needs !setUserPermissions *mentions* userLevel") try: userLevel = int(data[1]) except ValueError: return CDOInteralResponseData("Userlevel needs to be a number between 0 and 5") if userLevel > 5 or userLevel < 0: return CDOInteralResponseData("Only user levels from 0 to 5 are available") retString = "" for user in kwargs['msg'].mentions: DiscordUsers(id=user.id,name=user.name,userLevel=userLevel).save() retString += f"Setting {user.name} with id {user.id} to user level {userLevel}\n" return CDOInteralResponseData(retString)
async def cdoSetUserPermissions(msg : Message,**kwargs): """ Sets the userlevel for the mentioned users. :param kwargs: :return: """ if len(msg.mentions) == 0: return CDOInteralResponseData("You need to mention a user to set its permission levels") level = None for key,val in kwargs.items(): if key.startswith("parameter"): if val.startswith("<@"): continue else: try: level = int(val) except ValueError: continue if level == None: return CDOInteralResponseData(f"Wrong parameters! Needs a mention and user level." f"User Level needs to be a number between 0 and 5") if level > 5 or level < 0: return CDOInteralResponseData("Only user levels from 0 to 5 are available") retString = "" for user in msg.mentions: DiscordUsers(id=user.id,name=user.name,userLevel=level).save() retString += f"Setting {user.name} with id {user.id} to user level {level}\n" return CDOInteralResponseData(retString)
async def cdoRemoveCompetition(**kwargs): """ Removes a competition from the watchlist. :return: Answer message """ responseData = CDOInteralResponseData() parameter = checkCompetitionParameter(kwargs['msg'].content) if isinstance(parameter, str): return parameter else: competition_string = parameter["competition"] association = parameter["association"] watcher = CompetitionWatcher.objects.filter(competition__clear_name=competition_string) if len(watcher) == 0: responseData.response = f"Competition {competition_string} was not monitored" return responseData if len(watcher) > 1: watcher = watcher.filter(competition__association=association) logger.info(f"Deleting {watcher}") await Scheduler.removeCompetition(watcher.first()) watcher.delete() responseData.response = f"Removed {competition_string} from monitoring" return responseData
async def cdoLog(**kwargs): """ Posts the last lines of a given logfile :param kwargs: :return: """ fileList = ["debug","info","errors"] data = kwargs['msg'].content.split(" ") if len(data) != 2: return CDOInteralResponseData("Data needs to contain logname and length") if data[1] not in fileList: return CDOInteralResponseData(f"Possible logfiles are {fileList}") with open(data[1]+".log") as f: fileContent = f.read() respStr = "LogContent: " addInfo = OrderedDict() try: addInfo[f"Lines 1 to 1000"] = fileContent[0:200] except IndexError: addInfo[f"Lines 1 to {len(fileContent)}"] = fileContent[0:len(fileContent) -1] class pageContent: index = 1 @staticmethod def page(page): oldIndex = pageContent.index pageString = respStr + f" _(page {pageContent.index+1})_" if page == pageNav.forward: pageContent.index +=1 else: pageContent.index -=1 lowerIndex = (pageContent.index - 1) * 1000 upperIndex = (pageContent.index) * 1000 addInfo = OrderedDict() try: addInfo[f"Lines {lowerIndex} to {upperIndex}"] = fileContent[lowerIndex:upperIndex] except IndexError: addInfo[f"Lines {lowerIndex} to {len(fileContent)}"] = fileContent[lowerIndex:len(fileContent) - 1] try: return CDOInteralResponseData(pageString,addInfo) except IndexError: pageContent.index = oldIndex return CDOInteralResponseData(pageString, addInfo) response = CDOInteralResponseData(respStr,addInfo) if len(fileContent) != 0: response.paging = pageContent.page return response
def page(page): oldIndex = pageContent.index pageString = respStr + f" _(page {pageContent.index+1})_" if page == pageNav.forward: pageContent.index +=1 else: pageContent.index -=1 try: return CDOInteralResponseData(pageString,addInfoList[pageContent.index]) except IndexError: pageContent.index = oldIndex return CDOInteralResponseData(pageString, addInfoList[pageContent.index])
async def cdoUpcomingGames(**kwargs): """ Lists all upcoming games :param kwargs: :return: """ matchList = Scheduler.upcomingMatches() addInfo = OrderedDict() count = 0 addInfoList = [] for match in matchList: addInfo[match.title] = f"{match.match.date} (UTC)" count +=1 if count == 10: addInfoList.append(addInfo) addInfo = OrderedDict() count = 0 if addInfo != OrderedDict(): addInfoList.append(addInfo) if addInfoList == []: respStr = "No upcoming matches" else: respStr = "Upcoming matches:" resp = CDOInteralResponseData(respStr) if addInfoList != []: resp.additionalInfo = addInfoList[0] class pageContent: index = 0 @staticmethod def page(page): oldIndex = pageContent.index pageString = respStr + f" _(page {pageContent.index+1})_" if page == pageNav.forward: pageContent.index +=1 else: pageContent.index -=1 try: return CDOInteralResponseData(pageString,addInfoList[pageContent.index]) except IndexError: pageContent.index = oldIndex return CDOInteralResponseData(pageString, addInfoList[pageContent.index]) if addInfoList != []: resp.paging = pageContent.page return resp
async def cdoSetStartCDO(**kwargs): """ Sets a commandline argument to start the bot. :param kwargs: :return: """ data = kwargs['msg'].content.split(" ") if len(data) == 0: return CDOInteralResponseData("You need to set a command to be executed to start the bot") commandString = kwargs['msg'].content.replace(data[0] + " ", "") obj = Settings(name="startCommando",value=commandString) obj.save() return CDOInteralResponseData(f"Setting startup command to {commandString}")
async def cdoGetHelp(msg : Message,**kwargs): """ Returns all available Commandos and their documentation. :return: """ retString = "Available Commandos:" addInfo = InfoObj() try: userQuery = DiscordUsers.objects.get(id=msg.author.id) authorUserLevel = userQuery.userLevel except ObjectDoesNotExist: authorUserLevel = 0 for i in DiscordCommando.allCommandos(): if i.userLevel <= authorUserLevel: doc = i.docstring doc = re.sub(':.+\n', "", doc) doc = re.sub('\n+', "", doc) if authorUserLevel >= 5: level = f" lvl:{i.userLevel}" else: level = "" addInfo[kwargs['prefix'] + i.commando + level] = doc responseData = CDOInteralResponseData(retString, addInfo) return responseData
async def cdoShowMonitoredCompetitions(msg : Message,**kwargs): """ Lists all watched competitions by soccerbot. :return: Answer message """ retString = f"React with number emojis to remove.Only the first {len(emojiList())} can " \ f"be added this way):\n\n" addInfo = InfoObj() compList = [] for watchers in CompetitionWatcher.objects.all(): compList.append(watchers.competition) try: addInfo[watchers.competition.association.clear_name].description +=(f"\n{watchers.competition.clear_name}") except KeyError: addInfo[watchers.competition.association.clear_name] = watchers.competition.clear_name def check(reaction : Reaction, user): if reaction.emoji in emojiList(): index = emojiList().index(reaction.emoji) if index < len(compList): msg.content = f"{kwargs['prefix']}removeCompetition {compList[index].clear_name},{compList[index].association_id}" client.loop.create_task(cmdHandler(msg)) return True return CDOInteralResponseData(retString, addInfo, check)
async def cdoCurrentGames(msg : Message,**kwargs): """ Lists all current games within a matchday channel :param kwargs: :return: """ if "parameter0" in kwargs.keys(): competition = Competition.objects.filter(clear_name=kwargs['parameter0']) else: competition = None matchList = Scheduler.startedMatches() addInfo = InfoObj() for match in matchList: if competition == None: addInfo[match.title] = f"{match.minute}" else: if match.match.competition == competition.first(): addInfo[match.title] = f"{match.minute}" if addInfo == InfoObj(): respStr = "No running matches" else: respStr = "Running matches:" resp = CDOInteralResponseData(respStr,addInfo) return resp
async def cdoPlayerInfo(msg : Message,**kwargs): """ Shows information on a given player :param kwargs: :return: """ if 'parameter0' not in kwargs.keys(): return CDOInteralResponseData("You need to tell me the name of the player!") searchString = kwargs['parameter0'] res = getPlayerInfo(searchString) if res != None: playerName = res[0] addInfo = res[1] else: return CDOInteralResponseData(f"Sorry, nothing was found for {kwargs['parameter0']}") return CDOInteralResponseData(playerName,addInfo,paging=1)
async def cdoRestartBot(msg : Message,**kwargs): """ Restart Kommando :param kwargs: :return: """ try: Settings.objects.get(name="startCommando") logger.info(f"Command: {sys.executable} {path+'/../restart.py'}") cmdList = [sys.executable,path+"/../restart.py"] logger.info(cmdList) p = subprocess.Popen(cmdList) logger.info(f"ID of subprocess : {p.pid}") return CDOInteralResponseData("Shutting down in 10 seconds. Restart will take around 30 seconds") except ObjectDoesNotExist: return CDOInteralResponseData("You need to set the startup Command with !setStartCommando before this" "commando is available")
async def cdoStopBot(msg : Message,**kwargs): """ Stops the execution of the bot :param kwargs: :return: """ responseData = CDOInteralResponseData() retString = f"To confirm the shutdown, please react with {emojiList()[0]} to this message." responseData.response = retString def check(reaction : Reaction, user): if reaction.emoji == emojiList()[0]: client.loop.create_task(msg.channel.send("Bot is shutting down in 10 seconds")) client.loop.create_task(shutdown()) return True responseData.reactionFunc = check return responseData
async def cdoSetPrefix(msg : Message,**kwargs): """ Sets the prefix for the commands :param kwargs: :return: """ if kwargs['parameter0'] in kwargs.keys(): return CDOInteralResponseData("You need to set a command to be executed to start the bot") commandString = kwargs['parameter0'] try: prefix = Settings.objects.get(name="prefix") prefix.value = commandString except ObjectDoesNotExist: prefix = Settings(name="prefix",value=commandString) prefix.save() return CDOInteralResponseData(f"New prefix is {prefix.value}")
async def cdoUpcomingGames(msg : Message,**kwargs): """ Lists all upcoming games :param kwargs: :return: """ if "parameter0" in kwargs.keys(): competition = Competition.objects.filter(clear_name=kwargs['parameter0']) watchers = CompetitionWatcher.objects.filter(competition=competition) else: competition = None watchers = [] if len(watchers) == 0 and competition is not None: return CDOInteralResponseData(f"Sorry {competition.clear_name} is not watched by Soccerbot.") matchList = Scheduler.upcomingMatches() if len(matchList) == 0: return CDOInteralResponseData("No upcoming matches.") addInfo = InfoObj() for match in matchList: if competition == None: addInfo[match.title] = match.match.date else: if match.match.competition == competition.first(): addInfo[match.title] = match.match.date tmpAddInfo = dict([(k, addInfo[k]) for k in sorted(addInfo, key=addInfo.get, reverse=False)]) addInfo = InfoObj() for key,value in tmpAddInfo.items(): addInfo[key] = f"{tmpAddInfo[key].description.strftime('%d %b %Y, %H:%M')} (UTC)" respStr = "Upcoming matches:" resp = CDOInteralResponseData(respStr,addInfo) return resp
async def cdoSetPrefix(**kwargs): """ Sets the prefix for the commands :param kwargs: :return: """ data = kwargs['msg'].content.split(" ") if len(data) == 0: return CDOInteralResponseData("You need to set a command to be executed to start the bot") commandString = kwargs['msg'].content.replace(data[0] + " ", "") try: prefix = Settings.objects.get(name="prefix") prefix.value = commandString except ObjectDoesNotExist: prefix = Settings(name="prefix",value=commandString) prefix.save() return CDOInteralResponseData(f"New prefix is {prefix.value}")
async def cdoAbout(**kwargs): """ About the bot :param kwargs: :return: """ retstring = "**Soccerbot - a live threading experience**\n\n" retstring += f"Current version: {currentVersion()}\n" retstring += f"State: good" return CDOInteralResponseData(retstring)
def page(page): oldIndex = pageContent.index pageString = respStr + f" _(page {pageContent.index+1})_" if page == pageNav.forward: pageContent.index +=1 else: pageContent.index -=1 lowerIndex = (pageContent.index - 1) * 1000 upperIndex = (pageContent.index) * 1000 addInfo = OrderedDict() try: addInfo[f"Lines {lowerIndex} to {upperIndex}"] = fileContent[lowerIndex:upperIndex] except IndexError: addInfo[f"Lines {lowerIndex} to {len(fileContent)}"] = fileContent[lowerIndex:len(fileContent) - 1] try: return CDOInteralResponseData(pageString,addInfo) except IndexError: pageContent.index = oldIndex return CDOInteralResponseData(pageString, addInfo)
async def cdoVersions(msg : Message,**kwargs): """ Shows all available versions for the bot :param kwargs: :return: """ retString = "" for i in getVersions(): retString += f"Version: **{i}**\n" return CDOInteralResponseData(retString)
async def cdoGetUserPermissions(msg : Message,**kwargs): """ Gets the userlevel of a mentioned user :param kwargs: :return: """ addInfo = InfoObj() for user in msg.mentions: try: user = DiscordUsers.objects.get(id=user.id) addInfo[user.name] = f"User level: {user.userLevel}" except ObjectDoesNotExist: addInfo[user.name] = f"User level: 0" if addInfo == InfoObj(): return CDOInteralResponseData("You need to mention a user to get its permission status!") retObj = CDOInteralResponseData("UserLevels:") retObj.additionalInfo = addInfo return retObj
async def cdoUpdateBot(**kwargs): """ Updates bot :param kwargs: :return: """ def spawnAndWait(listObj): p = subprocess.Popen(listObj) p.wait() data = kwargs['msg'.split(" ")] if len(data) != 2: return CDOInteralResponseData("Exactly one parameter is allowed. Pass the version or master") if data[1] != "master" and data[1] not in getVersions(): return CDOInteralResponseData(f"Version {data[1]} not available") checkoutVersion(data[1]) spawnAndWait([sys.executable, path + "/../manage.py", "migrate"]) spawnAndWait([sys.executable, "-m", "pip", "install", "-r", f"{path}/../requirements.txt"]) return CDOInteralResponseData(f"Updated Bot to {data[1]}. Please restart to apply changes")
async def cdoRemoveCompetition(msg : Message,**kwargs): """ Removes a competition from the watchlist. :return: Answer message """ responseData = CDOInteralResponseData() if "parameter0" in kwargs.keys(): parameter = kwargs['parameter0'] else: return CDOInteralResponseData("You need to give me a competition, mate") watcher = CompetitionWatcher.objects.filter(competition__clear_name=parameter) if len(watcher) == 0: responseData.response = f"Competition {parameter} was not monitored" return responseData if len(watcher) > 1: if "parameter1" in kwargs.keys(): watcher = watcher.filter(competition__association=kwargs['parameter1']) else: nameCode = [f"{i.competition.clear_name},{i.competition.association}" for i in watcher] return CDOInteralResponseData(f"We have multiple competitions that match {parameter}, " f"naming " f"{nameCode}" f", please provide an association with a second parameter. For example: " f"**{kwargs['prefix']}removeCompetition Premier League,ENG**") logger.info(f"Deleting {watcher}") await Scheduler.removeCompetition(watcher.first()) watcher.delete() responseData.response = f"Removed {parameter} from monitoring" return responseData
async def cdoAddCompetition(**kwargs): """ Adds a competition to be watched by soccerbot. It will be regularly checked for new games :return: Answer message """ responseData = CDOInteralResponseData() parameter = checkCompetitionParameter(kwargs['msg'].content) if isinstance(parameter, str): responseData.response = "Error within Commando!" logger.error("Parameter is not string instance, please check logic!") return responseData else: competition_string = parameter["competition"] association = parameter["association"] comp = Competition.objects.filter(clear_name=competition_string) logger.debug(f"Available competitions: {comp}") if len(comp) == 0: responseData.response = f"Can't find competition {competition_string}" return responseData if len(comp) != 1: if association == None: names = [existing_com.clear_name for existing_com in comp] countryCodes = [existing_com.association for existing_com in comp] name_code = list(zip(names, countryCodes)) responseData.response = f"Found competitions {name_code} with that name. Please be more specific (add #ENG for example)." return responseData else: comp = Competition.objects.filter(clear_name=competition_string, association=association) if len(comp) != 1: names = [existing_com.clear_name for existing_com in comp] countryCodes = [existing_com.association for existing_com in comp] name_code = list(zip(names, countryCodes)) responseData.response = f"Found competitions {name_code} with that name. Please be more specific (add #ENG for example)." return responseData watcher = CompetitionWatcher.objects.filter(competition=comp.first()) logger.debug(f"Watcher objects: {watcher}") if len(watcher) != 0: return CDOInteralResponseData(f"Allready watching {competition_string}") client.loop.create_task(watchCompetition(comp.first(), kwargs['msg'].server)) responseData.response = f"Start watching competition {competition_string}" return responseData
async def cdoAbout(msg : Message,**kwargs): """ About the bot :param kwargs: :return: """ retstring = "**Soccerbot - a live threading experience**\n\n" retstring += f"Current version: {currentVersion()}\n" retstring += f"Website: https://soccerbot.eu\n" retstring += f"More info: https://github.com/muma7490/soccerbot\n" retstring += f"Click https://paypal.me/soccerbot if you want to buy my creator a beer" return CDOInteralResponseData(retstring)
async def cdoShowRunningTasks(msg : Message,**kwargs): """ Shows all currently running tasks on the server :return: """ tasks = Task.getAllTaks() responseString = "Running tasks:" addInfo = InfoObj() for i in tasks: args = str(i.args).replace("<", "").replace(">", "").replace(",)", ")") addInfo[f"{i.name}{args}"] = f"Started at {i.time}" return CDOInteralResponseData(responseString, addInfo)
async def cdoGoals(msg : Message,**kwargs): """ Lists the goals stored in the database :param msg: :param kwargs: :return: """ if "parameter0" in kwargs.keys(): teams = Team.objects.filter(clear_name=kwargs['parameter0']) if len(teams) != 0: goalListHome = Goal.objects.filter(match_home_Team__clear_name=kwargs['parameter0']).order_by( 'match__date') goalListAway = Goal.objects.filter(match_away_Team__clear_name=kwargs['parameter0']).order_by( 'match__date') goalist = goalListHome | goalListAway else: goalList = Goal.objects.filter(player=kwargs['parameter0']).order_by('match__date') if len(goalList) == 0: return CDOInteralResponseData(f"Sorry, nothing found for {kwargs['parameter0']}") else: goalList = Goal.objects.all().order_by('match__date') retDict = InfoObj() for i in reversed(goalList): keyStr = f"{i.match.home_team.clear_name} : {i.match.home_team.clear_name}" try: retDict[keyStr].description += f"{i.minute}: {i.player} {i.link}\n" except KeyError: retDict[keyStr] = f"{i.minute}: {i.player} {i.link}\n" if retDict == InfoObj(): return CDOInteralResponseData("No goals found") else: return CDOInteralResponseData("Goallinks:",additionalInfo=retDict)
async def cdoSetStartCDO(msg : Message,**kwargs): """ Sets a commandline argument to start the bot. :param kwargs: :return: """ if kwargs['parameter0'] not in kwargs.keys(): if len(Settings.objects.filter(name="startCommando")) == 0: return CDOInteralResponseData("You need to set a command to be executed to start the bot") else: obj = Settings.objects.get(name='startCommando') return CDOInteralResponseData(f"Current restart command: _{obj.value}_") commandString = kwargs['parameter0'] try: Settings(name="startCommando",value=commandString) except IntegrityError: obj = Settings.objects.get(name='startCommando') obj.value=commandString obj.save() obj = Settings(name="startCommando",value=commandString) obj.save() return CDOInteralResponseData(f"Setting startup command to {commandString}")