-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Add] TODOリクエスト機能の追加 #3
base: master
Are you sure you want to change the base?
Changes from 2 commits
645304e
feb0807
624a42c
f34922b
e6c17db
4b300f0
eaf6c57
4d73f4e
41a3dd4
6b3fa3a
0ebd49b
ae5c019
8472512
c2d2ddf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,12 +1,25 @@ | ||||||
import discord | ||||||
from discord.ext import commands | ||||||
import json | ||||||
import hashlib | ||||||
|
||||||
|
||||||
class TODOCog(commands.Cog): | ||||||
def __init__(self, bot): | ||||||
self.bot = bot | ||||||
|
||||||
def make_request(self, ctx, to_user, todo): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 見てる感じ内部用メソッドっぽいので、メソッド名は There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. オブジェクト指向のコツの一つは、データごとにロジックを整理すること。 Cog はあくまで Discord とのやり取りを表現するクラス。 ちなみに、 まあ、このへんは設計レベルのリファクタリングであって、重いタスクかつ発展課題なので、「やらなきゃマージできない〜〜〜」とか思わなくていいよ。「ほーん、そうなんや。まあとりあえずマージしちゃお。」でいい。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 分離ですか...ちょっとすぐにはできそうもないので、今は今後の課題、という形で処理させていただこうと思います。 |
||||||
text = f"{ctx.message.id} - {ctx.author.id} -> {to_user.id}" | ||||||
hashed = hashlib.sha256(text.encode()).hexdigest() | ||||||
data = { | ||||||
"author": ctx.author.id, | ||||||
"to": to_user.id, | ||||||
"content": todo | ||||||
} | ||||||
self.bot.data["request"][hashed[:10]] = data | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sha256 の前10文字だけ取ってくるって被らないのかな? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
分かりやすいだけでなくで、修正漏れも防げる。いわゆるDRY原則というやつ。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. てか、ただ一意な ID 振りたいだけなら、UUID とか使えばいい気がする。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このIDを入力してリクエストの承認・拒否を行うので、長すぎると手入力がとても大変になるんですよね... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
大体ダブルクリックして ctrl+C だろうけどね。 てか、いつの間にかメッセージ ID をリクエストの ID にするようになってる。かしこ。
[0-9a-z] で 36 ってわけか。かしこすぎる。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dict 使ってるのは JSON との相互変換しやすいからなんだろうけど、dict でこういうデータ扱うと色々メンテ大変だよ。 e.g.
クラスで作ったオブジェクトでも JSON と相互変換はできる。 |
||||||
self.bot.save_data() | ||||||
return hashed[:10] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メソッド名が
の4つだね。 問題点:
というわけで、内容に沿ってちゃんと分割して、それぞれに内容に即したメソッド名をつけることをオススメする。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここらへんはすぐにはできそうではないので、今後の課題とさせていただきたいと思います、ご指摘ありがとうございます! |
||||||
|
||||||
@commands.command(name="help") | ||||||
async def _help(self, ctx): | ||||||
msg = """ | ||||||
|
@@ -47,13 +60,14 @@ async def on_message(self, message): | |||||
msg = await message.channel.send(msg) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. message(受信したメッセージのオブジェクト) 変数名を |
||||||
await msg.add_reaction("👍") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 突然失礼します ICON_GOOD = "👍" 的な・・・? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 確かに定数を使ったほうがいいですね、ご指摘ありがとうございます! |
||||||
await msg.add_reaction("👎") | ||||||
|
||||||
def check(reac, user): | ||||||
if not user == message.author: | ||||||
return False | ||||||
if not str(reac.emoji) in ["👍", "👎"]: | ||||||
return False | ||||||
return True | ||||||
|
||||||
reac, _ = await self.bot.wait_for("reaction_add", check=check) | ||||||
if str(reac.emoji) == "👍": | ||||||
if not self.bot.data.get(str(message.author.id)): | ||||||
|
@@ -92,14 +106,81 @@ async def delete(self, ctx, num: int): | |||||
return await ctx.send("> そのTODOはありません。`todo!list`で確認してください。") | ||||||
self.bot.save_data() | ||||||
return await ctx.send(f"> TODO`{deleted_todo}`の削除に成功しました。") | ||||||
|
||||||
@delete.error | ||||||
async def error_delete(self, ctx, err): | ||||||
if isinstance(err, commands.errors.BadArgument): | ||||||
return await ctx.send("> 引数は整数で指定してください。") | ||||||
if isinstance(err, commands.errors.MissingRequiredArgument): | ||||||
return await ctx.send(">>> TODOの番号を引数で指定してください。\n番号は`todo!list`で確認できます。") | ||||||
|
||||||
@commands.command() | ||||||
async def request(self, ctx, member: discord.Member, *, todo): | ||||||
text = f""" | ||||||
>>> `{str(member)}`さんにtodoリクエストを送ります。 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なんで全体的に引用メッセージ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 返信遅くなって申し訳ないです There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あ、今思いついたけど、いちいち引用にするのってどこかで忘れそうなので、 async def send_bot_message(ctx, message):
await ctx.send(f">>> `{message}`) みたいな util 関数作ってもいいかもねぇ。 ただ、なまじ共通化しすぎても柔軟性に欠けるから危険なんだよね。例外が色々出てきたりするとまた困ったりする。例外がどれだけ出てきそうかの将来予測次第かな。 |
||||||
内容: | ||||||
・{todo} | ||||||
|
||||||
よろしいですか?""" | ||||||
msg = await ctx.send(text) | ||||||
await msg.add_reaction("👍") | ||||||
await msg.add_reaction("👎") | ||||||
|
||||||
def check(reac, user): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
一番の理由として、脳内で読み辛いんだよね。 まあ個人的意見なので採用するかは自由。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. discord.pyのリファレンスのコード例の中でそんな略し方をしていた気がしたのでそうしていたんですが、今見たら普通に |
||||||
if not user == ctx.author: return | ||||||
if not reac.message == msg: return | ||||||
if not str(reac.emoji) in ["👍", "👎"]: return | ||||||
return True | ||||||
|
||||||
reac, _ = await self.bot.wait_for("reaction_add", check=check) | ||||||
if str(reac.emoji) == "👎": | ||||||
await msg.delete() | ||||||
return await ctx.send("> todoリクエストをキャンセルしました。", delete_after=5) | ||||||
|
||||||
req_id = self.make_request(ctx, member, todo) | ||||||
dm_msg = f""" | ||||||
>>> {ctx.author.mention}さんからTODOリクエストが届きました。 | ||||||
|
||||||
内容: | ||||||
・{todo} | ||||||
|
||||||
リクエストID: `{req_id}` | ||||||
|
||||||
このリクエストを承認する場合は`todo!request_approve {req_id}` | ||||||
拒否する場合は`todo!request_deny {req_id}` | ||||||
とコマンドを実行してください。""" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python の 複数行文字列リテラルってインデント考慮してくれないんだ。 https://stackoverflow.com/a/33924077/12964914 俺だったらこのワークアラウンド採用するかな。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これに関してはtextwrap.dedentという関数を使うことでインデントを治すのが一般的なようです。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
そうなんだ。なるへそ。じゃあそれで |
||||||
try: | ||||||
await member.send(dm_msg) | ||||||
except: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 全ての Exception を握りつぶすんじゃなく、起こりうる Exception のみキャッチすると良いと思う。 |
||||||
await ctx.send(f"{member.mention}\n" + dm_msg) | ||||||
|
||||||
result = f""" | ||||||
>>> リクエストの送信に成功しました。 | ||||||
|
||||||
リクエストID: `{req_id}`""" | ||||||
return await ctx.send(result) | ||||||
|
||||||
@commands.command() | ||||||
async def request_approve(self, ctx, req_id: str): | ||||||
req_todo = self.bot.data["request"].get(req_id) | ||||||
if not req_id: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
ミス? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. deny の方と統一されてないので、何が正しいかわからなくなった |
||||||
return await ctx.send("> そのIDのリクエストは存在しません。もう一度確認してください。") | ||||||
|
||||||
self.bot.data["todo"][str(ctx.author.id)].append(req_todo.content) | ||||||
del self.bot.data["request"][req_id] | ||||||
self.bot.save_data() | ||||||
return await ctx.send(f"> リクエストを承認しました。\n\n追加されたTODO:\n・{req_todo.content}") | ||||||
|
||||||
@commands.command() | ||||||
async def request_deny(self, ctx, req_id: str): | ||||||
req_todo = self.bot.data["request"].get(req_id) | ||||||
if not req_id: | ||||||
return await ctx.send("> そのIDのリクエストは存在しません。もう一度確認してください。") | ||||||
|
||||||
del self.bot.data["request"][req_id] | ||||||
self.bot.save_data() | ||||||
return await ctx.send(f"> リクエストを拒否しました。") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
無意味な f-strings を発見! |
||||||
|
||||||
|
||||||
def setup(bot): | ||||||
bot.add_cog(TODOCog(bot)) | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to_user
、「to」な「user」って意味なんだろうけど、「ユーザーに向けて」みたいに読めちゃうので混乱しちゃうな。俺だったら
user_send_to
とかかな。まあ俺の案もそんなにイケてる感じしなくて微妙なラインなので、別に修正しなくてもまあいいかって感じではある。