From 243495480e880a86d1a4496d132d1ad552ebfb29 Mon Sep 17 00:00:00 2001 From: stolenvw Date: Fri, 7 May 2021 18:09:12 -0400 Subject: Added code for showing percent of world explored. Will not show right on an existing world --- README.md | 6 ++ code/botcmds/helpcmds.py | 4 +- code/config.py | 11 ++++ code/dbsetup.py | 144 +++++++++++++++++++++++++++++++++++++++++++++++ code/plusbot.py | 42 ++++++++++++++ optional/explorecmds.py | 60 ++++++++++++++++++++ 6 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 code/dbsetup.py create mode 100644 optional/explorecmds.py diff --git a/README.md b/README.md index b8f0355..29cef2b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ Add `-logfile /location/to/file.log` to your start command to get a logfile. For `WORLDSIZE` user running the bot must have read permissions to the world.db.old file +## [dbsetup.py](code/dbsetup.py) +Tables and data for the MySQL database. + +**Warning: Set up the config.py before running this** +Run `python3 dbsetup.py` from the code dir to create tables. + ## Usage: `python3 plusbot.py` While in the `code` dir. `nohup python3 plusbot.py &` Too run in background. diff --git a/code/botcmds/helpcmds.py b/code/botcmds/helpcmds.py index aa32dcb..2cf899f 100644 --- a/code/botcmds/helpcmds.py +++ b/code/botcmds/helpcmds.py @@ -45,11 +45,11 @@ class Help(commands.Cog): if ctx.channel.id == config.LOGCHAN_ID or commands.is_owner(): return True - @commands.command() + @commands.command(hidden=True) @commands.check(chancheck) # @commands.bot_has_permissions(add_reactions=True,embed_links=True) async def help(self, ctx, *input): - """Shows all modules of that bot""" + """Shows all modules of the bot""" # !SET THOSE VARIABLES TO MAKE THE COG FUNCTIONAL! prefix = config.BOT_PREFIX diff --git a/code/config.py b/code/config.py index 82a8c86..69119e7 100644 --- a/code/config.py +++ b/code/config.py @@ -58,3 +58,14 @@ VERSIONS_CMD = "@everyone" VPLUS_CMD = "@everyone" SETSTATUS_CMD = "Admin" SAVESTATS_CMD = "Admin","Mod" +#MODS_CMD = "@everyone" +PLOC_CMD = "@everyone" + +# MODSINFO - used to enable server installed mods data info gathering from logs ***Must rerun dbsetup.py if changing this to True if you ran it all ready*** +#MODSINFO = True + +# MODDIR - Path of the BepInEx plugins folder +#MODDIR = "/var/lib/pterodactyl/volumes/a8fae5c1-4b08-4a96-bdd8-b673e458b3f3/BepInEx/plugins" + +# PLOCINFO - used for tracking placed locations to determine percent of world exploed ***Must rerun dbsetup.py if changing this to True if you ran it all ready*** +PLOCINFO = True diff --git a/code/dbsetup.py b/code/dbsetup.py new file mode 100644 index 0000000..acd6ce6 --- /dev/null +++ b/code/dbsetup.py @@ -0,0 +1,144 @@ +import os, re, config, sys, mysql.connector +from colorama import Fore, Style, init +from mysql.connector import errorcode +from config import SQL_HOST as MYhost +from config import SQL_PORT as MYport +from config import SQL_USER as MYuser +from config import SQL_PASS as MYpass +from config import SQL_DATABASE as MYbase + +TABLES = {} +TABLES['events'] = ( + "CREATE TABLE `events` (" + " `id` int NOT NULL AUTO_INCREMENT," + " `type` text NOT NULL," + " `smessage` text NOT NULL," + " `image` text NOT NULL," + " PRIMARY KEY (`id`)," + " UNIQUE KEY `type` (`type`(7)) USING BTREE" + ") ENGINE=InnoDB") + +if config.EXSERVERINFO: + TABLES['exstats'] = ( + "CREATE TABLE `exstats` (" + " `id` int NOT NULL AUTO_INCREMENT," + " `savezdos` varchar(50) DEFAULT NULL," + " `savesec` varchar(10) DEFAULT NULL," + " `worldsize` varchar(10) DEFAULT NULL," + " `serverversion` varchar(10) DEFAULT NULL," + " `plusversion` varchar(10) DEFAULT NULL," + " `gameday` int DEFAULT NULL," + " `timestamp` bigint DEFAULT NULL," + " PRIMARY KEY (`id`)" + ") ENGINE=InnoDB") + +if config.PLOCINFO: + TABLES['plocinfo'] = ( + "CREATE TABLE `plocinfo` (" + " `id` int NOT NULL AUTO_INCREMENT," + " `locations` varchar(10) DEFAULT NULL," + " `zone` varchar(10) DEFAULT NULL," + " `duration` varchar(10) DEFAULT NULL," + " PRIMARY KEY (`id`)" + ") ENGINE=InnoDB") + +TABLES['players'] = ( + "CREATE TABLE `players` (" + " `id` int NOT NULL AUTO_INCREMENT," + " `user` varchar(100) NOT NULL," + " `deaths` int NOT NULL DEFAULT '0'," + " `valid` varchar(50) DEFAULT NULL," + " `startdate` varchar(20) DEFAULT NULL," + " `playtime` bigint DEFAULT '0'," + " `jointime` bigint DEFAULT NULL," + " `ingame` int NOT NULL DEFAULT '0'," + " PRIMARY KEY (`id`) USING BTREE," + " UNIQUE KEY `users` (`user`)" + ") ENGINE=InnoDB") + +TABLES['serverstats'] = ( + "CREATE TABLE `serverstats` (" + " `id` int NOT NULL AUTO_INCREMENT," + " `date` varchar(20) DEFAULT NULL," + " `timestamp` bigint DEFAULT NULL," + " `users` int NOT NULL DEFAULT '0'," + " PRIMARY KEY (`id`) USING BTREE," + " UNIQUE KEY `timestamp` (`timestamp`)" + ") ENGINE=InnoDB") + +def mydbconnect(): + global mydb + mydb = mysql.connector.connect( + host=MYhost, + user=MYuser, + password=MYpass, + database=MYbase, + port=MYport, + ) + try: + if mydb.is_connected(): + db_Info = mydb.get_server_info() + print(Fore.GREEN + "Connected to MySQL database... MySQL Server version ", db_Info + Style.RESET_ALL) + except mysql.connector.Error as err: + print(Fore.RED + err + 'From MySQL database' + Style.RESET_ALL) + +mydbconnect() + +def maketable(): + mycursor = mydb.cursor() + for table_name in TABLES: + table_description = TABLES[table_name] + try: + print(Fore.GREEN + "Creating table {}: ".format(table_name), end='') + mycursor.execute(table_description) + if table_name == "events": + eventinsert() + if table_name == "exstats": + exstatinsert() + except mysql.connector.Error as err: + if err.errno == errorcode.ER_TABLE_EXISTS_ERROR: + print(Fore.RED + "already exists." + Style.RESET_ALL) + else: + print(Fore.RED + err.msg + Style.RESET_ALL) + else: + print(Fore.GREEN + "OK" + Style.RESET_ALL) + mycursor.close() + print(Fore.GREEN + "Done" + Style.RESET_ALL) + +def eventinsert(): + print(Fore.GREEN + "Adding events info to table events" + Style.RESET_ALL) + mycursor1 = mydb.cursor() + sql = """INSERT INTO `events` (`id`, `type`, `smessage`, `image`) VALUES (%s, %s, %s, %s)""" + val = [ + (1, 'Skeletons', 'Skeleton Surprise', 'skeleton.png'), + (2, 'Blobs', '..', 'Ooze.png'), + (3, 'Foresttrolls', 'The ground is shaking', 'troll.png'), + (4, 'Wolves', 'You are being hunted', 'wolf.png'), + (5, 'Surtlings', 'There\'s a smell of sulfur in the air', 'surtling.png'), + (6, 'Eikthyrnir', 'Meadows', 'Eikthyr.png'), + (7, 'GDKing', 'Black Forest', 'The_Elder.png'), + (8, 'Bonemass', 'Swamp', 'Bonemass.png'), + (9, 'Dragonqueen', 'Mountain', 'Moder.png'), + (10, 'GoblinKing', 'Plains', 'Yagluth.png'), + (11, 'army_eikthyr', 'Eikthyr rallies the creatures of the forest', 'Boar.png'), + (12, 'army_theelder', 'The forest is moving...', 'Greydwarf.png'), + (13, 'army_bonemass', 'A foul smell from the swamp', 'Draugr.png'), + (14, 'army_moder', 'A cold wind blows from the mountains', 'Drake.png'), + (15, 'army_goblin', 'The horde is attacking', 'Fuling.png') + ] + mycursor1.executemany(sql, val) + mydb.commit() + mycursor1.close() + +def exstatinsert(): + mycursor2 = mydb.cursor() + print(Fore.GREEN + "Adding 1st row to table exstats" + Style.RESET_ALL) + sql = """INSERT INTO `exstats` VALUES (1,'NULL','NULL','NULL','NULL',NULL,NULL,1616448381)""" + mycursor2.execute(sql) + mydb.commit() + mycursor2.close() + + +maketable() +mydb.close() +exit() diff --git a/code/plusbot.py b/code/plusbot.py index 48ded4e..05eb8ae 100644 --- a/code/plusbot.py +++ b/code/plusbot.py @@ -25,6 +25,8 @@ ssaved2 = '^[0-9]{2}\/[0-9]{2}\/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}: World saved sversion = '^[0-9]{2}\/[0-9]{2}\/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}: Valheim version:([\.0-9]+)@([\.0-9]+)$' gdays = '^[0-9]{2}\/[0-9]{2}\/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}: Time [\.0-9]+, day:([0-9]+)\s{1,}nextm:[\.0-9]+\s+skipspeed:[\.0-9]+$' +ploc = '^[0-9]{2}\/[0-9]{2}\/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}: Placed locations in zone ([-,0-9]+) duration ([\.0-9]+) ms$' +tloc = '^[0-9]{2}\/[0-9]{2}\/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}: Loaded ([0-9]+) locations$' bot = commands.Bot(command_prefix=config.BOT_PREFIX) server_name = config.SERVER_NAME @@ -170,6 +172,7 @@ async def mainloop(file): await botsql.botmydb() mycursor.close() await lchannel.send(':skull: **' + pname + '** just died!') + # Announcing of mob events if(re.search(pevent, line)): eventID = re.search(pevent, line).group(1) botsql = bot.get_cog('BotSQL') @@ -184,6 +187,7 @@ async def mainloop(file): embed.set_author(name="📢 Random Mob Event") await lchannel.send(file=image, embed=embed) mycursor.close() + # Announcing when a player joins the server, Announcing if they are a new player on the server, adds player to db if new, updates db with login time if(re.search(pjoin, line)): logJoin = re.search(pjoin, line).group(1) logID = re.search(pjoin, line).group(2) @@ -258,6 +262,7 @@ async def mainloop(file): mycursor.close() # Extra Server Info DB After this point if config.EXSERVERINFO == True: + # Getting and storing how many zdos where saved if(re.search(ssaved1, line)): save1 = re.search(ssaved1, line).group(1) botsql = bot.get_cog('BotSQL') @@ -336,6 +341,43 @@ async def mainloop(file): await botsql.botmydb() await lchannel.send('**INFO:** Server reported in game day as: ' + gamedays + '') mycursor.close() + if config.PLOCINFO == True: + if(re.search(ploc, line)): + zone = re.search(ploc, line).group(1) + duration = re.search(ploc, line).group(2) + botsql = bot.get_cog('BotSQL') + mycursor = await botsql.get_cursor() + sql = """INSERT INTO plocinfo (zone, duration) VALUES ('%s', '%s')""" % (zone, duration) + mycursor.execute(sql) + await botsql.botmydb() + mycursor.close() + if(re.search(tloc, line)): + location = re.search(tloc, line).group(1) + botsql = bot.get_cog('BotSQL') + mycursor = await botsql.get_cursor() + sql = """SELECT id, locations FROM plocinfo WHERE locations IS NOT NULL""" + mycursor.execute(sql) + Info = mycursor.fetchall() + row_count = mycursor.rowcount + if row_count == 0: + sql = """INSERT INTO plocinfo (locations) VALUES ('%s')""" % (location) + mycursor.execute(sql) + await botsql.botmydb() + print(Fore.GREEN + '**INFO:** ' + location + ' Locations Loaded' + Style.RESET_ALL) + if config.USEDEBUGCHAN == True: + buginfo = discord.Embed(title=":white_check_mark: **INFO** :white_check_mark:", description='{} Locations Loaded'.format(location), color=0x7EFF00) + await bugchan.send(embed=buginfo) + else: + Info=Info[0] + if location != Info[1]: + sql = """UPDATE plocinfo SET locations = '%s' WHERE id = '%s'""" % (location, Info[0]) + mycursor.execute(sql) + await botsql.botmydb() + print(Fore.GREEN + '**INFO:** Locations has been updated to: ' + location + '' + Style.RESET_ALL) + if config.USEDEBUGCHAN == True: + buginfo = discord.Embed(title=":white_check_mark: **INFO** :white_check_mark:", description='Locations has been updated to: {}'.format(location), color=0x7EFF00) + await bugchan.send(embed=buginfo) + mycursor.close() await asyncio.sleep(0.2) except IOError: print('No valid log found, event reports disabled. Please check config.py') diff --git a/optional/explorecmds.py b/optional/explorecmds.py new file mode 100644 index 0000000..2ba7537 --- /dev/null +++ b/optional/explorecmds.py @@ -0,0 +1,60 @@ +import discord, typing, config +from discord.ext import commands + +class Explored(commands.Cog): + """ + Explored commands + """ + + def __init__(self, bot): + self.bot = bot + + async def chancheck(ctx): + if ctx.channel.id == config.LOGCHAN_ID or commands.is_owner(): + return True + + @commands.command(name='explored', + brief="Explored stats", + help="Shows total world locations and how many have be explored.", + ) + @commands.has_any_role(config.PLOC_CMD) + @commands.check(chancheck) + async def explored(self, ctx): + ldrembed = discord.Embed(title="World Explored Stats", color=0x33a163) + botsql = self.bot.get_cog('BotSQL') + mycursor = await botsql.get_cursor() + sql = """SELECT COUNT(*) FROM plocinfo WHERE locations IS NULL""" + mycursor.execute(sql) + Info = mycursor.fetchall() + sql1 = """SELECT locations FROM plocinfo WHERE locations IS NOT NULL LIMIT 1""" + mycursor.execute(sql1) + Info1 = mycursor.fetchall() + mycursor.close() + Info=Info[0] + Info1=Info1[0] + ldrembed.add_field(name="Total Locations", + value="{}".format(Info1[0]), + inline=True) + ldrembed.add_field(name="Locations Explored", + value="{}".format(Info[0]), + inline=True) + ldrembed.add_field(name="Percent of World Explored", + value="{}%".format(format(Info[0]/Info1[0]*100, ".2f")), + inline=True) + await ctx.send(embed=ldrembed) + + @explored.error + async def explored_error_handler(self, ctx, error): + if isinstance(error, commands.MissingAnyRole): + if config.USEDEBUGCHAN == True: + bugchan = self.bot.get_channel(config.BUGCHANNEL_ID) + bugerror = discord.Embed(title=":sos: **ERROR** :sos:", description='**{}** Tried to use command: **{}**\n{}'.format(ctx.author, ctx.command, error), color=0xFF001E) + await bugchan.send(embed=bugerror) + if isinstance(error, commands.CheckFailure): + if config.USEDEBUGCHAN == True: + bugchan = self.bot.get_channel(config.BUGCHANNEL_ID) + bugerror = discord.Embed(title=":sos: **ERROR** :sos:", description='**{}** Tried to use command: **{}**\nIn channel **#{}**'.format(ctx.author, ctx.command, ctx.channel), color=0xFF001E) + await bugchan.send(embed=bugerror) + +def setup(bot): + bot.add_cog(Explored(bot)) -- cgit v1.2.3