Skip to content

Commit

Permalink
Add manager, improve logging
Browse files Browse the repository at this point in the history
  • Loading branch information
hannilo committed May 5, 2020
1 parent 86e2d93 commit 479db81
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 56 deletions.
9 changes: 6 additions & 3 deletions bot.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os
import discord
import logging

import rollbot.log_config
from dotenv import load_dotenv

import rollbot.config.log_config

from rollbot.Bot import Bot
from rollbot.CommandManager import CommandManager
from rollbot.config.BotConfig import BotConfig

logger = logging.getLogger('bot')

Expand All @@ -14,5 +16,6 @@
PREFIX = os.getenv('PREFIX')
BUILD = os.getenv('BUILD')

bot = Bot(commandPrefix=PREFIX, build=BUILD)
botConfig = BotConfig(PREFIX, BUILD)
bot = Bot(botConfig, CommandManager(botConfig))
bot.run(TOKEN)
61 changes: 15 additions & 46 deletions rollbot/Bot.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import logging
from typing import Dict, List

import discord

from rollbot import roller
from rollbot.model.DiceRoll import DiceRoll
from rollbot.CommandManager import CommandManager, ReplyResult
from rollbot.config.BotConfig import BotConfig


class Bot(discord.Client):
"""
The base of the Bot. Only concerns itself with discord.Client events and delegates handling
"""
logger = logging.getLogger(__name__)
prefix: str
build: str
previousRoll: Dict[discord.User, DiceRoll] = {}

def __init__(self, commandPrefix='!', build='dev'):
manager: CommandManager

def __init__(self, config: BotConfig, commandManager: CommandManager):
super(Bot, self).__init__()
self.prefix = commandPrefix
self.build = build
self.prefix = config.prefix
self.build = config.build
self.manager = commandManager
self.logger.info(f"Will be reacting to '{self.prefix}'")

async def on_ready(self):
Expand All @@ -27,41 +29,8 @@ async def on_ready(self):
async def on_message(self, message: discord.Message):
if message.author == self.user:
return
if str(message.content).startswith(self.prefix + 'roll'): # todo add command manager, enumerate
self.logger.info(f"Command {message.content} from {message.author} at {message.guild}.{message.channel}")
args = str(message.content).split(' ')
self.logger.info(f"Command args: {args}")
args.pop(0)
if not args:
await message.channel.send(f"{message.author.mention}, mkm")
elif len(args) > 1:
await message.channel.send(f"{message.author.mention}, 1 korraga atm")
else:
if len(args[0]) > 100:
await message.channel.send(f"{message.author.mention}, that command is too long")
return

result = roller.roll(args[0])
self.logger.debug(f"{result}")

if not result.valid:
await message.channel.send(f"{message.author.mention}, invalid roll [{result.command}]")
return

self.previousRoll[message.author] = result
await message.channel.send(self.buildResultMessage(result, message))
if str(message.content).startswith(self.prefix + 'reroll'): # todo add command manager, enumerate
result = roller.reroll(self.previousRoll[message.author])
await message.channel.send(self.buildResultMessage(result, message))
if str(message.content).startswith(self.prefix + 'help'): # todo add command manager, enumerate
await message.channel.send(f"`{self.prefix}roll 2d4+1` - roll 2 d4 dice and add 1\n"
f"`{self.prefix}reroll` - reroll your last roll\n"
f"`{self.prefix}about` - general info")
if str(message.content).startswith(self.prefix + 'about'): # todo add command manager, enumerate
await message.channel.send(f"Build: **{self.build}**\n"
f"Source: https://github.com/hannilo/rollbot-py")

def buildResultMessage(self, roll: DiceRoll, message: discord.Message):
return f"{message.author.mention}\n" \
f"result: {roll}\n" \
f"sum ({roll.sum()} {'+' if roll.modifier >= 0 else '-'} {abs(roll.modifier)}) : **{roll.sum() + roll.modifier}**"
if str(message.content).startswith(self.prefix):
result = self.manager.handle(message)
if isinstance(result, ReplyResult):
await message.channel.send(result.reply)
105 changes: 103 additions & 2 deletions rollbot/CommandManager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,106 @@
import logging
from dataclasses import dataclass
from enum import Enum
from typing import Dict

import discord

from rollbot import roller
from rollbot.config.BotConfig import BotConfig
from rollbot.model.DiceRoll import DiceRoll


class Command(Enum):
ABOUT = 'about'
HELP = 'help'
REROLL = 'reroll'
ROLL = 'roll'


@dataclass
class CommandResult:
command: str
successful: bool


@dataclass
class VoidResult(CommandResult):
pass


@dataclass
class ReplyResult(CommandResult):
reply: str


class CommandManager:
logger = logging.getLogger(__name__)

prefix: str
config: BotConfig

previousRoll: Dict[discord.User, DiceRoll] = {}

def __init__(self, botConfig: BotConfig):
self.prefix = botConfig.prefix
self.config = botConfig

def handle(self, message: discord.Message) -> CommandResult:
messageContent = str(message.content)

self.logger.info(f"Command {message.content} from {message.author} at {message.guild}.{message.channel}")
args = str(message.content).split(' ')

userCommand = args.pop(0)
botCommand = self.parseBotCommand(userCommand)
if not botCommand:
return VoidResult(messageContent, False)

self.logger.debug(f"Got {userCommand} [{botCommand}]")
if args:
self.logger.debug(f"Command args: {args}")

if botCommand == Command.ROLL:
if not args:
return ReplyResult(messageContent, False, f"{message.author.mention}, mkm")
elif len(args) > 1:
return ReplyResult(messageContent, False, f"{message.author.mention}, 1 korraga atm")
elif len(args[0]) > 100:
return ReplyResult(messageContent, False, f"{message.author.mention}, that command is too long")

result = roller.roll(args[0])
self.logger.debug(f"{result}")

if not result.valid:
return ReplyResult(messageContent, False, f"{message.author.mention}, invalid roll [{result.command}]")

self.previousRoll[message.author] = result
return ReplyResult(messageContent, True, _buildResultMessage(result, message))

if botCommand == Command.REROLL:
previous = self.previousRoll.get(message.author)
if previous is None:
self.logger.info(f"No previous roll for {message.author}")
return VoidResult(userCommand, False)
result = roller.reroll(previous)
return ReplyResult(messageContent, True, _buildResultMessage(result, message))

if botCommand == Command.HELP:
return ReplyResult(messageContent, True, f"`{self.prefix}roll 2d4+1` - roll 2 d4 dice and add 1\n"
f"`{self.prefix}reroll` - reroll your last roll\n"
f"`{self.prefix}about` - general info")

if botCommand == Command.ABOUT:
return ReplyResult(messageContent, True, f"Build: **{self.config.build}**\n"
f"Source: https://github.com/hannilo/rollbot-py")

def parseBotCommand(self, userCommand: str) -> Command:
for cmd in Command:
if userCommand == f"{self.prefix}{cmd.value}":
return cmd

def about(self):
return "wasd"

def _buildResultMessage(roll: DiceRoll, message: discord.Message):
return f"{message.author.mention}\n" \
f"result: {roll}\n" \
f"sum ({roll.sum()} {'+' if roll.modifier >= 0 else '-'} {abs(roll.modifier)}) : **{roll.sum() + roll.modifier}**"
7 changes: 7 additions & 0 deletions rollbot/config/BotConfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from dataclasses import dataclass


@dataclass
class BotConfig:
prefix: str = '!'
build: str = 'dev'
Empty file added rollbot/config/__init__.py
Empty file.
9 changes: 7 additions & 2 deletions rollbot/log_config.py → rollbot/config/log_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

logging_config = dict(
version=1,
disable_existing_loggers=True,
formatters={
'f': {'format':
'%(levelname)-8s %(asctime)s %(name)-18s %(message)s'}
Expand All @@ -16,13 +17,13 @@
'console': {
'class': 'logging.StreamHandler',
'formatter': 'f',
'level': LOGLEVEL
'level': LOGLEVEL,
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'formatter': 'f',
'filename': 'bot.log',
'level': LOGLEVEL
'level': LOGLEVEL,
}
},
root={
Expand All @@ -33,5 +34,9 @@

dictConfig(logging_config)

logging.getLogger('discord').setLevel(logging.WARNING)
logging.getLogger('websockets').setLevel(logging.ERROR)
logging.getLogger('asyncio').setLevel(logging.ERROR)

logger = logging.getLogger()
logger.info(f"Logging level: {LOGLEVEL}")
7 changes: 4 additions & 3 deletions rollbot/roller.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import logging
import re
import random
from typing import List

from rollbot.model.DiceRoll import DiceRoll

logger = logging.getLogger(__name__)


def roll(rollCommand: str):
def roll(rollCommand: str) -> DiceRoll:
if not re.fullmatch('\\d+d\\d+([+-]\\d+)?', rollCommand):
logger.error(f"Failed to parse {rollCommand}")
return DiceRoll(rollCommand, valid=False)
Expand All @@ -29,15 +30,15 @@ def roll(rollCommand: str):
modifier=modifier)


def reroll(roll: DiceRoll):
def reroll(roll: DiceRoll) -> DiceRoll:
return DiceRoll(command=roll.command,
diceCount=roll.diceCount,
diceFaces=roll.diceFaces,
resultList=getResults(roll.diceCount, roll.diceFaces),
modifier=roll.modifier)


def getResults(diceCount: int, diceFaces: int):
def getResults(diceCount: int, diceFaces: int) -> List[int]:
results = []
for i in range(0, diceCount):
results.append(random.randint(1, diceFaces)) # todo inject random function
Expand Down

0 comments on commit 479db81

Please sign in to comment.