Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Now using Embeds
Browse files Browse the repository at this point in the history
  • Loading branch information
Retzudo committed May 10, 2017
1 parent bce08c3 commit 939fb2c
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 29 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ If you want to change the default command prefix `!` to something else, add anot

## Extending the command list

All commands must either return `None`, a `str` or an `discord.Embed` object.

### Regular command

A regular command is a command that does *something* and optionally returns a string. Create a new class in `regular.py`, inherit from `Command` and override the `execute` method where you can do anything. If you want the bot respond with a message, just return a string. Finally add your new class to the dictionary at the bottom of the file.
Expand All @@ -52,4 +54,4 @@ A sound command is a command that requires the bot to be connected to a voice ch

### Passive command

A passive command is a command that can be triggered by any message the bot can listen to. Create a new class in `passive.py`, inherit from `PassiveCommand` and override `is_triggered` as well as `execute`. If somebody writes a message in Discord, the bot listens to it and uses the `is_triggered` method to check if it should call the class's `execute` method. Finally add your new class to the list at the bottom of the file.
A passive command is a command that can be triggered by any message the bot can listen to. Create a new class in `passive.py`, inherit from `PassiveCommand` and override `is_triggered` as well as `execute`. If somebody writes a message in Discord, the bot listens to it and uses the `is_triggered` method to check if it should call the class's `execute` method. Finally add your new class to the list at the bottom of the file.
2 changes: 1 addition & 1 deletion servoskull/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import datetime

__version__ = 'v1.6.0'
__version__ = 'v1.7.0'

start_time = datetime.now()

Expand Down
5 changes: 4 additions & 1 deletion servoskull/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ async def execute_command(command, arguments, message):
if response:
# Only respond if there's actually a response.
# Some commands don't need to respond with text.
await client.send_message(message.channel, response)
if isinstance(response, str):
await client.send_message(message.channel, content=response)
if isinstance(response, discord.Embed):
await client.send_message(message.channel, embed=response)
logger.info(response)


Expand Down
41 changes: 21 additions & 20 deletions servoskull/commands/regular.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import random

import aiohttp
from discord import Embed
from imperialdate import ImperialDate

from servoskull.skulllogging import logger
Expand All @@ -17,7 +18,7 @@ def __init__(self, **kwargs):
self.message = kwargs.get('message')
self.client = kwargs.get('client')

async def execute(self) -> str:
async def execute(self):
raise NotImplementedError()

def _get_mentions(self):
Expand All @@ -39,7 +40,7 @@ class CommandGif(Command):

GIFS_URL = 'https://gifs.retzudo.com/gifs.json'

async def execute(self) -> str:
async def execute(self):
"""Respond with a gif that matches a title or a tag of a gif
at https://gifs.retzudo.com."""
if not self.arguments or len(self.arguments) < 1:
Expand All @@ -58,7 +59,9 @@ async def execute(self) -> str:
haystack = '{} {}'.format(haystack, ' '.join([tag.lower() for tag in gif['tags']]))

if all(arg.lower() in haystack for arg in self.arguments):
return gif['url']
response = Embed()
response.set_image(url=gif['url'])
return response

return 'No gif found'

Expand All @@ -74,7 +77,7 @@ async def execute(self) -> str:
class CommandIdentify(Command):
help_text = 'Identifies the servo-skull'

async def execute(self) -> str:
async def execute(self) -> Embed:
"""Respond with some info and a little RP text."""
from datetime import datetime
from dateutil.relativedelta import relativedelta
Expand All @@ -88,23 +91,19 @@ async def execute(self) -> str:
"or cybernetic components that utilise embedded anti-gravity field generators to allow them to hover "
"and drift bodiless through the air. They are fashioned from the skulls of loyal Adepts of the Adeptus "
"Terra and other pious Imperial servants to which robotic components and an antigravitic impeller have "
"been added.This is so that they may continue their work for the Emperor of Mankind even after death. To "
"have one's; skull chosen to serve as a; Servo-skull is a great honour in the Imperium, for it implies "
"one\'s service in life has been satisfactory enough to warrant continuation beyond death."
"been added. This is so that they may continue their work for the Emperor of Mankind even after death. To "
"have one's skull chosen to serve as a Servo-skull is a great honour in the Imperium, for it implies "
"one's service in life has been satisfactory enough to warrant continuation beyond death."
)

return (
'Servo-skull active. Vox module operational.\n'
'Version: **{}**\n'
'Uptime: **{}**\n'
'\n'
'*{}*'
.format(
servoskull.__version__,
uptime,
flavour_text
)
)
response = Embed()
response.set_thumbnail(url='http://vignette3.wikia.nocookie.net/warhammer40k/images/c/c3/Servo-Skull-Front2.jpg/revision/latest?cb=20120711230906')
response.title = 'Servo-skull active. Vox module operational.'
response.add_field(name='Version', value=servoskull.__version__)
response.add_field(name='Uptime', value=uptime)
response.set_footer(text=flavour_text)

return response


class CommandNextHoliday(Command):
Expand Down Expand Up @@ -162,12 +161,14 @@ async def execute(self) -> str:
data = await response.json()

try:
url = data['results'][0]['image']
url = data['results'][0]['url']
except (KeyError, TypeError) as e:
logger.error(e, exc_info=True)
return 'No relevant comic found.'

logger.info('Returning xkcd {}'.format(url))
if not url.startswith('https://') or not url.startswith('http://'):
url = 'https://' + url
return url


Expand Down
14 changes: 8 additions & 6 deletions test/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import discord
import pytest

import servoskull.commands.regular as commands
Expand All @@ -19,7 +20,8 @@ async def test_cmd_gif():

command = commands.CommandGif(arguments=['worf'])
response = await command.execute()
assert response.startswith('https://')
assert isinstance(response, discord.Embed)
assert response.image.url.startswith('https://')


@pytest.mark.asyncio
Expand All @@ -36,8 +38,8 @@ async def test_cmd_identify():
command = commands.CommandIdentify()
response = await command.execute()

assert len(response) > 100
assert response.startswith('Servo-skull active.')
assert isinstance(response, discord.Embed)
assert response.title.startswith('Servo-skull active.')


@pytest.mark.asyncio
Expand All @@ -46,7 +48,7 @@ async def test_cmd_next_holiday():
command = commands.CommandNextHoliday()
response = await command.execute()

assert re.match('^The next holiday is "\w+" .* \(\d{4}-\d{2}-\d{2}\)$', response)
assert re.match('^The next holiday is "[\w ]+" .* \(\d{4}-\d{2}-\d{2}\)$', response) is not None


@pytest.mark.asyncio
Expand Down Expand Up @@ -97,9 +99,9 @@ async def test_cmd_xkcd():
command = commands.CommandXkcd(arguments=['standard'])
response = await command.execute()

assert response.startswith('https://imgs.xkcd.com/comics/')
assert response.startswith('https://xkcd.com/')

command = commands.CommandXkcd(arguments=['meaning', 'of', 'life'])
response = await command.execute()

assert response.startswith('https://imgs.xkcd.com/comics/')
assert response.startswith('https://xkcd.com/')

0 comments on commit 939fb2c

Please sign in to comment.