From eff057da8c9d77255c3a324dc1f3ea657ad2e1c6 Mon Sep 17 00:00:00 2001 From: bibin Date: Mon, 13 Jul 2020 23:47:56 +0200 Subject: [PATCH] lot's of refactoring and packaging --- .../__pycache__/developer.cpython-37.pyc | Bin 0 -> 2695 bytes .../__pycache__/send_message.cpython-37.pyc | Bin 0 -> 1068 bytes src/{ => package}/developer.py | 6 +- .../games/__pycache__/game.cpython-37.pyc | Bin 0 -> 751 bytes .../games/__pycache__/game_cog.cpython-37.pyc | Bin 0 -> 4787 bytes src/package/games/game.py | 18 +++ src/package/games/game_cog.py | 90 +++++++++++ .../werewolf/__pycache__/cog.cpython-37.pyc | Bin 0 -> 1597 bytes .../werewolf/__pycache__/game.cpython-37.pyc | Bin 0 -> 10956 bytes .../__pycache__/players.cpython-37.pyc | Bin 0 -> 5114 bytes .../werewolf/__pycache__/roles.cpython-37.pyc | Bin 0 -> 8612 bytes src/package/games/werewolf/cog.py | 34 ++++ .../games/werewolf/game.py} | 8 +- .../games/werewolf/players.py} | 0 .../games/werewolf/roles.py} | 2 +- src/package/send_message.py | 18 +++ src/werewolf_bot.py | 148 +++--------------- 17 files changed, 190 insertions(+), 134 deletions(-) create mode 100644 src/package/__pycache__/developer.cpython-37.pyc create mode 100644 src/package/__pycache__/send_message.cpython-37.pyc rename src/{ => package}/developer.py (88%) create mode 100644 src/package/games/__pycache__/game.cpython-37.pyc create mode 100644 src/package/games/__pycache__/game_cog.cpython-37.pyc create mode 100644 src/package/games/game.py create mode 100644 src/package/games/game_cog.py create mode 100644 src/package/games/werewolf/__pycache__/cog.cpython-37.pyc create mode 100644 src/package/games/werewolf/__pycache__/game.cpython-37.pyc create mode 100644 src/package/games/werewolf/__pycache__/players.cpython-37.pyc create mode 100644 src/package/games/werewolf/__pycache__/roles.cpython-37.pyc create mode 100644 src/package/games/werewolf/cog.py rename src/{werewolf_game.py => package/games/werewolf/game.py} (96%) rename src/{werewolf_players.py => package/games/werewolf/players.py} (100%) rename src/{werewolf_roles.py => package/games/werewolf/roles.py} (99%) create mode 100644 src/package/send_message.py diff --git a/src/package/__pycache__/developer.cpython-37.pyc b/src/package/__pycache__/developer.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96d4ba4c2155bcf82fb38466472a322b1847f2b1 GIT binary patch literal 2695 zcmZuzPj4GV6yMo@UMEiCrY%%ZU_l_&h&C;ue^{XkDA0nCIRvP%gjVaFiM`Hx$DJ7` z&ElNW6H;%83##NCx$zx1aNrxvl~cb$FXg>i$8oBzHM6rbZ{EE3e((LppRcSeS@8Vy zZzKNQx2*s0*K1*5TWyHS@hR`wnQ`d@s`_x(quT)jaeotZ_tWgRbB@Xjpw=WtFbYR@T_sph=tb zjL~$4u7d|>b^Qyr%W^(qqWtFjekQ{-PoxZCkQIs*l+lnE`F^;~MX35Lq{rePgu^78 zuP~{yq8Eon$$IwL zMxPJaMmOtb#m3fmUtj)~C6tMcUZytom|%N6-({C!_l6Yd#wba5k{;Wbn|EcjuY)+w zicH0EfTtUiNVz_D_{#BeN?;uye0$LTh9*CPZek6r0Z{<{z*Y7XV25DakL|C)gL@#Z zeCkYVD0KwECzW4ryL|n-f`#p@*H_^Wxypu#V&VPD=xy-Umnud{*>0xx%Qx<` zu%GO*Fz3A<#5^m)M25dyy)u?e9JB%x8oieGlcLAskzkS)DbqEY$&?GK{jEx)4`5{l z)9&45$h0>SfTH#RJTRd}1UhHJTXi+~)B!JI0kPd*Mz0Y9%MMS)=~&Kx2TT(InmA(m=tLDgJ#ve*3GIV=UKpMl0*dOAYtI zPpHJ#K(oZ!vq*!uq)E!=iSd=lDU=XNV?O$f=1<8nHnY+K%CM_2`%ox+4AfEO^h?4g zLePS($`EJq@M`n?@H$AXLHh@#|AJ1L$RSNXwh!P6H~@k^0O~&gVm_!%oPn(z8XS^| z`-e5DLGxyB7}GkmrHK#yvgsS9UwN`Zfs7wRl0kC06Nfe*&(jIg%cW;duzC1CCg8yT z!ut8mg8)}2!O5zsO@aZOPOJyN-mf@ky$HDBR=4+u8Hym|NOYnaY6(Ql4{B z29Xkc)ZdRvKT<&1(KAvnU;iYMK%XqSdG-3O8=F@*H*ej%cH_q8wOiM3Yqt%B_!RT1 zY((7zYEH#n{xB+61Vi zgwKY2kjbhH--J!D*Ki%?g?1Cslj0H#J9P+7Y=k>Y6iBZcYeywr?U^v3EuibgTJ$LE zj(hKc4v8*U&MIVd_4|~plcv3j`Mp3wMn1*J;e&5%e?yZdy@4?&_6er*8?mY@XTf}r z3BkpS1}&QdVzYJ~wa$3({7H!|NVHq)cpW0G#<5(shvB#r-M9`@OJ=CTgSQD?Ej9qfMRc8_ZH53X`iJ#rt$>-sS=ym;Z3?=zF|4M zdIUxUVKN~Nh-(MVy4Q4@e&GA$oC|Hu$ebcMv=2cLcHIvk0vKq77a z1C;y?_zP5SsrU;tVP-ET7m)%n*1Wv4v)?znkNW)%LwWtZC%oW8(OvQ-lgJ29;)9siVq8|SSNm4y6GN=OFcYBr^(5IZXF3^Y+}#K0S5?2O@^m>XCY3kSrP}xeYkkE4IEtgR?9@2>HWSPlQwb~nf8J>f; zm@6kX!#~U2jYysfdLwce*6?uL$;H4;uCfp+NSN76>H*RVS;fLIt@V#*j6)wY8=XncG?0 z*|wT(`}*EE-FJR0WKiDpUmUY_DZx*0Ihm(rc{^-Ox$f4TEpI-5Jo{v7G_GvBvAi?R z+ztJAb4Fh%y=%&C-F&TEQ?@j-k9fYl54qNz?MAJ+qh|myiO<7=*_|Krjo=&!Th?Es zo@a`5#465I2$xYP`UiMM$B?>VXYn~#@PoC=NGvKagf3EenUETl7D7KFOIX7dNGw@zcfH^t7Zl)iXmM1F7C%KH#6+EHTg9d1?+zop=WWKl%;jGa_m{T- literal 0 HcmV?d00001 diff --git a/src/package/games/__pycache__/game_cog.cpython-37.pyc b/src/package/games/__pycache__/game_cog.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b663aaef0710c1a22afa4513f4559cd9f6fd7c43 GIT binary patch literal 4787 zcmcIoOK;rP73Omuni;(;JF$(pbQ-{(z#gSYfdqlu+L0UEKr#s+BZX&Cg5tfBIO34g zOO6#0la-C`40O{~8^BujclbASQEt1+w##nP?;LVo@>nU*W&~c|7wUDji|bZs_iXgpVP#P5 zRnb=w)vz|G_v)zEL_J&?GzUbGMSE4O zp}ofKHMG~o2HG3kUKiG`*51sXJU$E(=cc!pq{{Qtwlj#uD3lI5JtvieVd$mO*^iZT zKS=yo31=rhxRG$rfj5v&GL(L>ANY=c=tYqX9X}onyhtS91F+WCbMxM(J9t_513&Ge zQkzaNiV4kK83}hFlf*la-|I!E^#F_ew8Z3RqH-5cLWR_NI<#pBy=O{G+Wm^G?i-gi zVf+<371ndBR};3VJlA@4Q57}3S43T`;N1`nAaCY1+QIeXgY4V0I`Bg;NmvC+GM+ec z_D7MQ22_DA(nIOc=cO`kCNdojZ<9W5IYTAOS`cxieajhmK@^@ihh73TN&iTy>3RuN zvPxgNL6oFk{G1mLqSnKOY zRdsEwy)?$U&`*s=aE^zXJ{zq7ozczSc??xgObbRC#i_&Ec1~p40pMym$Z+$Ogly?p z#nD0AP)%%?n|}HYE1@XhpjzJGC0ss>%OqF@g{C+4O+DM1Vwsz?9L@*$2vA69{j%0K zlmkHK89;O6O*%4wa&}{-POdxm9MUiwTBvX!Cyp9LQ2^O3hNI}r^J>|tHqa_jsZG?+ zqS}CR+;Vb(?HXp4*j5SKl_|E@rY=X=!2lWb*^``6oVdRD7NY!;k?7OZa7t5=nh;4b}vHT|8DFT_Q zk(6sxT%dw1UR|PsJZi2Wi&AwIbS4S;VNJJ;x2>98v$@|#*Yrml-o=yr62)Q|n+slc z8N4de;$8}2R}g>3;XJ_z&V@U&93r3 z<;RYX^`rRML1sMp#A#R9Neg!+lg=$NF^<4_i=)xL3J{dSleWnLsc>EL%riEW+r0lR z(jVELW;FF{#wA3g#pCYqv;}`9qhh_kjSBPz-Jj}etJJ0OD=-c6%q2<;0y1w#d|n{3m4u9B;6;isR$d3eQ>Mm48G@)1gZLvVDa?SV5+(B& z=C|h9>>I+Kn1ZOh(2*<5zD3EM68j6YY&SrI=G!gMp!xP1Xwa-}iw&{KYw7*U*c2CD z=*UD{WR_wJD!Z6{NbCfPLE0a9OaQ#Sc$BivlF{CT%uHzk=`m|Qgn^_n+sJRSKR<~_ z&T$ZiP9&wEerRXnPONwEB_~KhIp(&38F~|og-r_wN27{;`5PRXk{##Xek#?mr$lj# zWR+kSCE*An41(5S_wb`c)GV2%FbsnBKjt`pL*d)<`s~l zAd=bIWQjufB)hf?{S0J8vOr;@L@Ky-!YiRV+f&7%OtLF9ootw!6TLI$*;LkEw)z#x zj#V*t6p5_<(0dAcJBqGTJWCP%@wVk)Pl|54s;;uMzojNoi`4Z-=^=7Aqo{jAxch+& z%d!19hPH`;MFI(&$j6+ox2ZYH985zjI`2;~z~oLd*7Yqs#a~m;E&$hDnD5Z+Zo8)5 zqNT{w6>%4Jg$hnq*Qxd{728zIcH+{|4rX2kmcpO@Gv_*9eSv5{EEBsRvI zs3FgsQd}ewJXxpNSIc|Sc~Vx($)C^3xV0c-IblJC1EM<8}I4a<^md?K<>KC zF@Av$)rVAkM8z_nAR7Mw&%`J6npray^)B}b2P5bE1dOVhHy%ZWD;&grcKDOIf*2`c zXOkShaHb|CeT66aFKnNv?K$V5NReODTBX%roP+lUqo0}-MUk1&_l=k4Dc$w7mmq!f zw?8(2T##B1h>alE_+TiaZO^QR%_XlCL(0Lr=g5p$oW{c^By?dqxB{)ui%r8_P`Ec5 z4h83>HuEtC9@D}^c@alpGm84!8yt^w)7$eEX)3RzCqo<%-!zJZ(kQPR9i$sYg5^yn zilu8ST9R>cRL{+w_<-*b9H!YWd8=h|<+VG-jpx_&e-u7;%WUdRvxWz6d+V+BYwNB5 E0M2EN=Kufz literal 0 HcmV?d00001 diff --git a/src/package/games/game.py b/src/package/games/game.py new file mode 100644 index 0000000..69d7c84 --- /dev/null +++ b/src/package/games/game.py @@ -0,0 +1,18 @@ +from abc import ABC + + +class Game(ABC): + + name = "Game" + + def __init__(self, bot, channel): + self.bot = bot + self.channel = channel + self.running = False + self.player_list = [] + + async def round(self): + pass + + async def set_players(self): + pass diff --git a/src/package/games/game_cog.py b/src/package/games/game_cog.py new file mode 100644 index 0000000..b530cff --- /dev/null +++ b/src/package/games/game_cog.py @@ -0,0 +1,90 @@ +"""This (abstract) module is a template for Discord Cog's for game specific channel commands""" + +# standard library imports +from typing import Dict + +# discord imports +import discord +from discord.ext import commands + +# local imports +from ..send_message import Send_message +from .game import Game + + +# TODO: take group as argument to add subcommands + +class Game_cog(Send_message, commands.Cog): + """This (abstract) class is are common function for the Game Cog's (setup-game, pre-game, in-game), mainly has checker functions""" + + def __init__(self, bot, game_instances: Dict[discord.TextChannel, Game]): + self.bot = bot + self.game_instances = game_instances + + async def setup_check(self, ctx): + if ctx.channel not in self.game_instances: + await self.send_wrong(ctx, f"The channel is not setup yet.") + return ctx.channel in self.game_instances + + async def not_running_check(self, ctx): + if self.game_instances[ctx.channel].running: + await self.send_wrong(ctx, "Sorry! A game is already running") + return not self.game_instances[ctx.channel].running + + async def running_check(self, ctx): + if not self.game_instances[ctx.channel].running: + await self.send_wrong(ctx, "No game is running") + return self.game_instances[ctx.channel].running + + +class Setup_game_cog(Game_cog): + """This (abstract) class is a template for Discord Cog's for game specific channel commands for setting up the channel""" + + async def setup(self, ctx, game: Game): + """This function creates an game instance for this channel""" + if ctx.channel in self.game_instances: + await self.send_wrong(ctx, f"A game '{game.name}' is already setup in this channel") + else: + self.game_instances[ctx.channel] = game(self.bot, ctx.channel) + await self.send_friendly(ctx, f"This channel can now play: {game.name}") + + async def reset(self, ctx): + """This function deletes the game instance for this channel""" + if self.setup_check(ctx): + del self.game_instances[ctx.channel] + + # TODO: better info message + async def info(self, ctx, game: Game): + """Send information about the subcommands for the game""" + embed = discord.Embed(title="How to play?", description="You will need to set up the game and its information in a channel and start the game there. Afterwards the player mainly interact with the bot in DM.", color=0x00ffff) + embed.set_author(name=f"With this bot you can play {game.name}") + # embed.set_thumbnail(url="https://images-na.ssl-images-amazon.com/images/I/717GrDtFKCL._AC_SL1000_.jpg") + embed.add_field(name="$w game setup", value="Make this channel playable.", inline=False) + embed.add_field(name="$w game players", value="Set mentioned users as players", inline=False) + embed.add_field(name="$w game roles", value="Set the roles to play with", inline=False) + embed.add_field(name="$w game start", value="Play one round", inline=False) + embed.set_footer(text="Have fun!") + await ctx.send(embed=embed) + + +class Pre_game_cog(Game_cog): + """This (abstract) class is a template for Discord Cog's for game specific channel commands for setting up the game rounds""" + async def cog_check(self, ctx): + return self.setup_check(ctx) and self.not_running_check(ctx) + + async def players(self, ctx): + await self.game_instances[ctx.channel].set_players(ctx.message) + + async def start(self, ctx): + self.game_instances[ctx.channel].game = self.bot.loop.create_task(self.game_instances[ctx.channel].round()) + await self.game_instances[ctx.channel].game + + +class In_game_goc(Game_cog): + """This (abstract) class is a template for Discord Cog's for game specific channel commands during the game""" + async def cog_check(self, ctx): + return self.setup_check(ctx) and self.running_check(ctx) + + async def stop(self, ctx): + self.game_instances[ctx.channel].game.cancel() + await self.send_friendly(ctx, "Game canceled") diff --git a/src/package/games/werewolf/__pycache__/cog.cpython-37.pyc b/src/package/games/werewolf/__pycache__/cog.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3673ed4b1c9e330168b7b486239048bf91f7941 GIT binary patch literal 1597 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 literal 0 HcmV?d00001 diff --git a/src/package/games/werewolf/cog.py b/src/package/games/werewolf/cog.py new file mode 100644 index 0000000..87618b2 --- /dev/null +++ b/src/package/games/werewolf/cog.py @@ -0,0 +1,34 @@ +# discord imports +from discord.ext import commands + +# local imports +from ..game_cog import Game_cog +from .game import Werewolf_game + + +class Werewolf_cog(Game_cog): + """This singleton class is a Discord Cog for the interaction in the werewolf game""" + + @commands.group(invoke_without_command=True) + async def werewolf(self, ctx): + # TODO: isn't there a better way to have a default subcommand? + await ctx.invoke(self.bot.get_command('werewolf info')) + + @werewolf.command() + async def info(self, ctx): + """Send information about the subcommands for the game""" + await super().info(ctx, Werewolf_game) + + @werewolf.command() + async def setup(self, ctx): + """This function creates an game instance for this channel""" + await super().setup(ctx, Werewolf_game) + + @werewolf.command() + async def reset(self, ctx): + """This function deletes the game instance for this channel""" + await super().reset(ctx) + + +def setup(bot): + bot.add_cog(Werewolf_cog(bot, None)) diff --git a/src/werewolf_game.py b/src/package/games/werewolf/game.py similarity index 96% rename from src/werewolf_game.py rename to src/package/games/werewolf/game.py index 53ccf39..4526027 100644 --- a/src/werewolf_game.py +++ b/src/package/games/werewolf/game.py @@ -2,11 +2,13 @@ from random import shuffle import time import asyncio import discord -from werewolf_roles import Role, Doppelganger, Werewolf, Minion, Mason, Seer, Robber, Troublemaker, Drunk, Insomniac, Tanner, Hunter, No_role -from werewolf_players import Player, No_player +from .roles import Role, Doppelganger, Werewolf, Minion, Mason, Seer, Robber, Troublemaker, Drunk, Insomniac, Tanner, Hunter, No_role +from .players import Player, No_player -class Game: +class Werewolf_game: + + name = "One Night Ultimate Werewolf" def __init__(self, bot, channel): self.running = False diff --git a/src/werewolf_players.py b/src/package/games/werewolf/players.py similarity index 100% rename from src/werewolf_players.py rename to src/package/games/werewolf/players.py diff --git a/src/werewolf_roles.py b/src/package/games/werewolf/roles.py similarity index 99% rename from src/werewolf_roles.py rename to src/package/games/werewolf/roles.py index f7cf685..8e9b867 100644 --- a/src/werewolf_roles.py +++ b/src/package/games/werewolf/roles.py @@ -1,6 +1,6 @@ import functools from fuzzywuzzy import fuzz -from werewolf_players import No_player +from .players import No_player class Role: diff --git a/src/package/send_message.py b/src/package/send_message.py new file mode 100644 index 0000000..136f7de --- /dev/null +++ b/src/package/send_message.py @@ -0,0 +1,18 @@ +# discord import +import discord + + +class Send_message: + """This (abstract) class for sending formatted messages""" + + def __init__(self, bot): + self.bot = bot + + async def send_embed(self, ctx, desc, color): + await ctx.send(embed=discord.Embed(description=desc, color=color)) + + async def send_friendly(self, ctx, desc): + await self.send_embed(ctx, desc, 0x00ff00) + + async def send_wrong(self, ctx, desc): + await self.send_embed(ctx, desc, 0xff8000) diff --git a/src/werewolf_bot.py b/src/werewolf_bot.py index 4bcd478..c4b0ca0 100644 --- a/src/werewolf_bot.py +++ b/src/werewolf_bot.py @@ -1,124 +1,43 @@ +""" +This is the main module of the Discord Bot + +Mainly loads the Cog's and starts the bot +""" + +__version__ = '0.3' +__author__ = 'Bibin Muttappillil' + +# standard library imports import os from dotenv import load_dotenv -import functools -import asyncio -import discord + +# discord imports from discord.ext import commands -from werewolf_game import Game as Werewolf_Game +# Token stuff load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN') if TOKEN is None: print("Missing discord token!") exit(1) +bot = commands.Bot(command_prefix=commands.when_mentioned_or('$w ')) -PREFIX = '$w ' -bot = commands.Bot(command_prefix=commands.when_mentioned_or(PREFIX)) -bot.remove_command('help') - -bot.load_extension('developer') - - -@bot.command() -async def load(ctx, extension): - bot.load_extension(f'{extension}') - - -@bot.command() -async def unload(ctx, extension): - bot.unload_extension(f'{extension}') +bot.load_extension('package.developer') +bot.load_extension('package.games.werewolf.cog') @bot.command() +@commands.is_owner() async def reload(ctx, extension): bot.reload_extension(f'{extension}') -# TODO: better help message -@bot.command() -async def help(ctx): - embed = discord.Embed(title="How to play?", description="You will need to set up the game and its information in a channel and start the game there. Afterwards the player mainly interact with the bot in DM.", color=0x00ffff) - embed.set_author(name="With this bot you can play One Night Ultimate Werewolf") - # embed.set_thumbnail(url="https://images-na.ssl-images-amazon.com/images/I/717GrDtFKCL._AC_SL1000_.jpg") - embed.add_field(name="$w game setup", value="Make this channel playable.", inline=False) - embed.add_field(name="$w game players", value="Set mentioned users as players", inline=False) - embed.add_field(name="$w game roles", value="Set the roles to play with", inline=False) - embed.add_field(name="$w game start", value="Play one round", inline=False) - embed.set_footer(text="Have fun!") - await ctx.send(embed=embed) - - -# TODO: interaction COG -async def send_embed(ctx, desc, color): - await ctx.send(embed=discord.Embed(description=desc, color=color)) - - -async def send_friendly(ctx, desc): - await send_embed(ctx, desc, 0x00ff00) - - -async def send_wrong(ctx, desc): - await send_embed(ctx, desc, 0xff8000) - - -# TODO: (general) game COG -# game commands - -game_instances = {} - - -@bot.group() -async def game(ctx): - if ctx.invoked_subcommand is None: - await send_wrong(ctx, 'Invalid sub command passed...') - - -@game.command() -async def setup(ctx): - if ctx.channel in game_instances: - await send_wrong(ctx, "Game already setup in this channel") - else: - game_instances[ctx.channel] = Werewolf_Game(bot, ctx.channel) - await send_friendly(ctx, "This channel can now play Werewolf") - - # checker annotations # TODO: replace with discord.py error handling? -def channel_setup(command): - @functools.wraps(command) - async def wrapper(ctx, *args, **kwargs): - if ctx.channel not in game_instances: - await send_wrong(ctx, f"No game setup yet. Use {PREFIX}game setup") - else: - await command(ctx, *args, **kwargs) - return wrapper - - -def game_not_running(command): - @functools.wraps(command) - @channel_setup - async def wrapper(ctx, *args, **kwargs): - if game_instances[ctx.channel].running: - await send_wrong(ctx, "Sorry! A game is already running") - else: - await command(ctx, *args, **kwargs) - return wrapper - - -def game_running(command): - @functools.wraps(command) - @channel_setup - async def wrapper(ctx, *args, **kwargs): - if not game_instances[ctx.channel].running: - await send_wrong(ctx, "No game is running") - else: - await command(ctx, *args, **kwargs) - return wrapper - - +''' def error_handling(command): @functools.wraps(command) async def wrapper(ctx, *args, **kwargs): @@ -129,30 +48,9 @@ def error_handling(command): except asyncio.TimeoutError: await send_wrong(ctx, "Error: I got bored waiting for your input") return wrapper +''' - -@game.command() -@game_not_running -@error_handling -async def start(ctx): - game_instances[ctx.channel].game = bot.loop.create_task(game_instances[ctx.channel].round()) - await game_instances[ctx.channel].game - - -@game.command() -@game_running -@channel_setup -async def stop(ctx): - game_instances[ctx.channel].game.cancel() - await send_friendly(ctx, "Game canceled") - - -@game.command() -@game_not_running -@error_handling -async def players(ctx): - await game_instances[ctx.channel].set_players(ctx.message) - +''' # TODO: (specifig game) werewolf COG @@ -175,10 +73,6 @@ async def minutes(ctx, i): @error_handling async def time(ctx): await send_friendly(ctx, game_instances[ctx.channel].remaining_time_string()) - - -# TODO: developer COG -# smaller commands - +''' bot.run(TOKEN)