Compare commits

..

No commits in common. "interactive" and "master" have entirely different histories.

4 changed files with 167 additions and 262 deletions

View file

@ -1,47 +1,41 @@
import discord import discord
from discord.ext import commands from discord.ext import commands
from utils import jisho, interactive from utils import jisho
class KanjiEmbed(interactive.InteractiveEmbed): class JishoKanjiObject():
REACTIONS = { def __init__(self, query, owner):
"prev_kanji": "⬅️", self.response = jisho.JishoKanji(query)
"next_kanji": "➡️" self.total_pages = self.response.entries
} self.page = 0
self.owner = owner
def __init__(self, parent, ctx, response): def prev(self):
super(KanjiEmbed, self).__init__(parent.bot, ctx, 60.0) self.page -= 1
self.parent = parent if self.page < 0:
self.owner = self.ctx.author self.page = self.total_pages - 1
self.response = response
self.current_kanji = 0 def next(self):
self.page += 1
if self.page >= self.total_pages:
self.page = 0
def prev_kanji(self):
self.current_kanji -= 1
if self.current_kanji < 0:
self.current_kanji = self.response.entries - 1
def next_kanji(self): class Kanji(commands.Cog):
self.current_kanji += 1 def __init__(self, bot):
if self.current_kanji >= self.response.entries: self.bot = bot
self.current_kanji = 0 self.activeObject = None
self.latestMessage = 0
async def on_reaction(self, reaction, user): async def createEmbed(self):
if reaction.emoji == KanjiEmbed.REACTIONS["prev_kanji"]: if self.activeObject.total_pages == 0:
self.prev_kanji() embed = discord.Embed(
await reaction.remove(user) title = "No search results",
description = "The search returned nothing. Did you make a typo?",
if reaction.emoji == KanjiEmbed.REACTIONS["next_kanji"]: colour = 0x56d926
self.next_kanji() )
await reaction.remove(user) else:
response = self.activeObject.response
async def add_navigation(self, message): node = response.nodes[self.activeObject.page]
if self.response.entries > 1:
await message.add_reaction(KanjiEmbed.REACTIONS["prev_kanji"])
await message.add_reaction(KanjiEmbed.REACTIONS["next_kanji"])
def make_embed(self):
node = self.response.nodes[self.current_kanji]
embed = discord.Embed( embed = discord.Embed(
title = node.meaning, title = node.meaning,
@ -56,30 +50,41 @@ class KanjiEmbed(interactive.InteractiveEmbed):
embed.add_field(name="On", value="".join(node.on), inline=False) embed.add_field(name="On", value="".join(node.on), inline=False)
embed.add_field(name=f"Radical: {node.radical[0]}", value=node.radical[1], inline=False) embed.add_field(name=f"Radical: {node.radical[0]}", value=node.radical[1], inline=False)
embed.set_thumbnail(url=node.image_url) embed.set_thumbnail(url=node.image_url)
embed.set_footer(text=f"Jōyō kanji (Grade {node.grade}) | JLPT level {node.jlpt}\t\t{self.current_kanji + 1}/{self.response.entries}")
embed.set_footer(text=f"Jōyō kanji (Grade {node.grade}) | JLPT level {node.jlpt}\t\t{self.activeObject.page + 1}/{self.activeObject.total_pages}")
return embed return embed
async def on_close(self): @commands.Cog.listener()
self.parent.activeObjects.pop(self.ctx.channel.id) async def on_reaction_add(self, reaction, user):
message = reaction.message
if message.id != self.latestMessage:
return
if user == self.bot.user:
return
class Kanji(commands.Cog): if user.id != self.activeObject.owner:
def __init__(self, bot): return
self.bot = bot
self.activeObjects = {} if reaction.me:
if reaction.emoji == "⬅️":
self.activeObject.prev()
await reaction.remove(user)
if reaction.emoji == "➡️":
self.activeObject.next()
await reaction.remove(user)
embed = await self.createEmbed()
await message.edit(embed=embed)
@commands.command(name="kanji", description="Performs a Kanji search", usage="<kanji>", aliases=["k"]) @commands.command(name="kanji", description="Performs a Kanji search", usage="<kanji>", aliases=["k"])
@commands.cooldown(1, 5) @commands.cooldown(1, 5)
async def kanji(self, ctx, *, kanji: str = None): async def kanji(self, ctx, *, kanji: str = None):
if kanji is None: if kanji is None:
embed = discord.Embed(
title = "No search results",
description = "The search returned nothing. Did you make a typo?",
colour = 0x56d926
)
await ctx.send(embed=embed)
return return
embed = discord.Embed( embed = discord.Embed(
@ -87,23 +92,19 @@ class Kanji(commands.Cog):
description = "This might take a few seconds", description = "This might take a few seconds",
colour = 0x56d926 colour = 0x56d926
) )
message = await ctx.send(embed=embed) message = await ctx.send(embed=embed)
kanji = kanji[:5] kanji = kanji[:5]
response = jisho.JishoKanji(kanji)
if response.entries < 1: self.activeObject = JishoKanjiObject(kanji, ctx.author.id)
embed = discord.Embed( embed = await self.createEmbed()
title = "No search results",
description = "The search returned nothing. Did you make a typo?",
colour = 0x56d926
)
await message.edit(embed=embed) await message.edit(embed=embed)
return self.latestMessage = message.id
await message.delete() if self.activeObject.total_pages > 1:
self.activeObjects[ctx.channel.id] = KanjiEmbed(self, ctx, response) await message.add_reaction("⬅️")
await self.activeObjects[ctx.channel.id].show_embed() await message.add_reaction("➡️")
def setup(bot): def setup(bot):
bot.add_cog(Kanji(bot)) bot.add_cog(Kanji(bot))

View file

@ -1,47 +1,40 @@
from inspect import currentframe
import discord import discord
from discord.ext import commands from discord.ext import commands
from utils import jisho, interactive from utils import jisho
class SearchEmbed(interactive.InteractiveEmbed): class JishoObject():
REACTIONS = { def __init__(self, query, owner):
"prev_page": "⬅️", self.response = jisho.JishoResponse(query)
"next_page": "➡️" self.total_pages = self.response.entries
} self.page = 0
self.owner = owner
def __init__(self, parent, ctx, response): def prev(self):
super(SearchEmbed, self).__init__(parent.bot, ctx, 60.0) self.page -= 1
self.parent = parent if self.page < 0:
self.owner = self.ctx.author self.page = self.total_pages - 1
self.response = response
self.current_page = 0 def next(self):
self.page += 1
if self.page >= self.total_pages:
self.page = 0
def prev_page(self): class Search(commands.Cog):
self.current_page -= 1 def __init__(self, bot: commands.Bot):
if self.current_page < 0: self.bot = bot
self.current_page = self.response.size - 1 self.activeObject = None
self.latestMessage = 0
def next_page(self): async def createEmbed(self):
self.current_page += 1 if self.activeObject.total_pages == 0:
if self.current_page >= self.response.size: embed = discord.Embed(
self.current_page = 0 title = "No search results",
description = "The search returned nothing. Did you make a typo?",
async def on_reaction(self, reaction, user): colour = 0x56d926
if reaction.emoji == SearchEmbed.REACTIONS["prev_page"]: )
self.prev_page() else:
await reaction.remove(user) response = self.activeObject.response
node = response.nodes[self.activeObject.page]
if reaction.emoji == SearchEmbed.REACTIONS["next_page"]:
self.next_page()
await reaction.remove(user)
async def add_navigation(self, message):
await message.add_reaction(SearchEmbed.REACTIONS["prev_page"])
await message.add_reaction(SearchEmbed.REACTIONS["next_page"])
def make_embed(self):
node = self.response.nodes[self.current_page]
embed = discord.Embed( embed = discord.Embed(
title = node.japanese[0][0], title = node.japanese[0][0],
url = f"https://jisho.org/word/{node.slug}", url = f"https://jisho.org/word/{node.slug}",
@ -65,43 +58,49 @@ class SearchEmbed(interactive.InteractiveEmbed):
embed.set_footer( embed.set_footer(
text = f"{node.ftags} \t\t {self.current_page + 1}/{self.response.size}" text = f"{node.ftags} \t\t {self.activeObject.page + 1}/{self.activeObject.total_pages}"
) )
return embed return embed
async def on_close(self): @commands.Cog.listener()
self.parent.activeObjects.pop(self.ctx.channel.id) async def on_reaction_add(self, reaction, user):
message = reaction.message
if message.id != self.latestMessage:
return
if user == self.bot.user:
return
if user.id != self.activeObject.owner:
return
if reaction.me:
if reaction.emoji == "⬅️":
self.activeObject.prev()
await reaction.remove(user)
if reaction.emoji == "➡️":
self.activeObject.next()
await reaction.remove(user)
embed = await self.createEmbed()
await message.edit(embed=embed)
class Search(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
self.activeObjects = {}
@commands.command(name="search", description="Searches Jisho", usage="<query>", aliases=["s"]) @commands.command(name="search", description="Searches Jisho", usage="<query>", aliases=["s"])
@commands.cooldown(1, 5) @commands.cooldown(1, 5)
async def search(self, ctx: commands.Context, *, query: str = None): async def search(self, ctx: commands.Context, *, query: str = None):
if query is None: if query is None:
embed = discord.Embed(
title = "No search results",
description = "The search returned nothing. Did you make a typo?",
colour = 0x56d926
)
await ctx.send(embed=embed)
return return
result = jisho.JishoResponse(query) self.activeObject = JishoObject(query, ctx.author.id)
if result.size == 0: embed = await self.createEmbed()
embed = discord.Embed( message = await ctx.send(embed=embed)
title = "No search results", self.latestMessage = message.id
description = "The search returned nothing. Did you make a typo?", if self.activeObject.total_pages > 0:
colour = 0x56d926 await message.add_reaction("⬅️")
) await message.add_reaction("➡️")
await ctx.send(embed=embed)
return
self.activeObjects[ctx.channel.id] = SearchEmbed(self, ctx, result)
await self.activeObjects[ctx.channel.id].show_embed()
@search.error @search.error
async def search_error(self, ctx, error): async def search_error(self, ctx, error):

View file

@ -1,93 +0,0 @@
import discord
from discord.ext import commands
from abc import ABC, abstractmethod
import asyncio
class InteractiveEmbed(ABC):
"""
This abstract base class can be used to create interactive embeds
"""
def __init__(self, bot, ctx, timeout):
"""
Sets up the embed with needed parameters
bot: The bot hosting this embed
ctx: The context that caused this embed
timeuout: The time until the embed times out (in seconds)
"""
self.bot = bot
self.ctx = ctx
self.message = None
self.timeout = timeout
@abstractmethod
async def on_reaction(self, reaction, user):
"""
Gets called when the user interacted with the embed
"""
pass
@abstractmethod
def make_embed(self):
"""
Creates and returns a new embed
"""
pass
@abstractmethod
async def add_navigation(self, message):
"""
Adds the navigational emotes to the embed
"""
pass
async def on_close(self):
"""
Can be overridden. Gets called when the embed is closed
"""
pass
def additional_checks(self, reaction, user):
"""
Can be overridden. Additional checks to do before calling on_reaction()
"""
return True
async def show_embed(self):
"""
Displays an embed / Creates an embed
"""
if self.message is None:
self.message = await self.ctx.send(embed=self.make_embed())
await self.add_navigation(self.message)
else:
await self.message.edit(embed=self.make_embed())
def check(reaction, user):
if self.message is None:
return False
if user.id != self.ctx.author.id:
return False
if reaction.message.id != self.message.id:
return False
if not reaction.me:
return False
return self.additional_checks(reaction, user)
try:
reaction, user = await self.bot.wait_for("reaction_add", check=check, timeout=self.timeout)
await self.on_reaction(reaction, user)
await self.show_embed()
except asyncio.TimeoutError:
await self.close_embed()
async def close_embed(self):
"""
Close this embed
"""
await self.message.clear_reactions()
await self.on_close()

View file

@ -64,8 +64,6 @@ class JishoResponse():
self.nodes = [] self.nodes = []
self.disassemble() self.disassemble()
self.size = len(self.nodes)
def query(self): def query(self):
url = TEMPLATE_URL.format(urllib.parse.quote_plus(self.query_string)) url = TEMPLATE_URL.format(urllib.parse.quote_plus(self.query_string))
r = requests.get(url, headers=HEADER) r = requests.get(url, headers=HEADER)