Discord.py
discord.py는 현대적이고, 사용하기 쉽고, 많은 기능을 담고 있고, 비동기가 준비된 디스코드를 위한 API 래퍼입니다.
Features
- async/await 구문을 사용한 최신의 Python스러운 API
- 429 에러를 방지하기 위한 타당한 속도 제한
- 모든 디스코드 API의 구현
- 봇 생성에 도움을 주는 확장된 명령어
- 객체 지향 설계로 간편한 사용
- 속도와 메모리에 전부 최적화 됨
Install
Example
# -*- coding: utf-8 -*-
from argparse import Namespace
from discord import Intents
from discord.ext.commands import Bot
from discord.ext.commands.context import Context as CommandContext
from overrides import override
from api.aio.run import aio_run
from api.apps.discord.config import DiscordConfig
from api.arguments import version as version
from api.context.context import CommonContext
from api.logging.logging import logger
class DiscordContext(CommonContext):
def __init__(self, args: Namespace):
self._config = DiscordConfig.from_namespace(args)
super().__init__(self._config)
self._version = version()
self._intents = Intents.default()
self._intents.typing = False
self._intents.presences = False
self._intents.message_content = True
self._bot = bot = Bot(
command_prefix="$",
intents=self._intents,
sync_command=True,
application_id=self._config.discord_application_id,
)
@bot.command(help="Shows version number")
async def version(ctx: CommandContext) -> None:
await self.on_version(ctx)
@override
async def on_mq_connect(self) -> None:
logger.info("Connection to redis was successful!")
@override
async def on_mq_subscribe(self, channel: bytes, data: bytes) -> None:
logger.info(f"Recv sub msg channel: {channel!r} -> {data!r}")
@override
async def on_mq_done(self) -> None:
logger.warning("Redis task is done")
async def on_version(self, ctx: CommandContext) -> None:
await ctx.send(self._version)
async def main(self) -> None:
await self.open_common_context()
try:
await self._bot.start(token=self._config.discord_token)
finally:
await self.close_common_context()
def run(self) -> None:
aio_run(self.main(), self._config.use_uvloop)
Event
- API Reference # Event Reference
- 4. 이벤트에 대하여 - 파이썬으로 디스코드 봇 만들기
- 디스코드봇(파이썬) 06 | discord.py의 이벤트함수를 알아보고 서로 상호작용을 해보자.
- python - How to make Discord.py respond to a single message event twice - Stack Overflow
Example:
@bot.event
async def on_message(message):
if message.author == bot.user:
return
# ignore all channels but the specified one
if message.channel.id == requestsChannelID:
# record request
with open('requests.txt', 'a') as f:
print(repr(message.content), file=f)
reply = await message.channel.send('Got it!')
# wait for 10 seconds, then delete message and reply
await asyncio.sleep(10)
await message.delete()
await reply.delete()
else:
# process other commands (if there are none, delete this line)
await bot.process_commands(message)
파일 다운로드
@client.event
async def on_message(message):
if len(message.attachments) > 0:
attachment = message.attachments[0]
if (
attachment.filename.endswith(".jpg")
or attachment.filename.endswith(".jpeg")
or attachment.filename.endswith(".png")
or attachment.filename.endswith(".webp")
or attachment.filename.endswith(".gif")
):
img_data = requests.get(attachment.url).content
with open("image_name.jpg", "wb") as handler:
handler.write(img_data)
elif (
"https://images-ext-1.discordapp.net" in message.content
or "https://tenor.com/view/" in message.content
):
print(message.content)
Checks
To register a check for a command, we would have two ways of doing so. The first is using the check() decorator. For example:
async def is_owner(ctx):
return ctx.author.id == 316026178463072268
@bot.command(name='eval')
@commands.check(is_owner)
async def _eval(ctx, *, code):
"""A bad example of an eval command"""
await ctx.send(eval(code))
This would only evaluate the command if the function is_owner returns True. Sometimes we re-use a check often and want to split it into its own decorator. To do that we can just add another level of depth: content_copy
def is_owner():
async def predicate(ctx):
return ctx.author.id == 316026178463072268
return commands.check(predicate)
@bot.command(name='eval')
@is_owner()
async def _eval(ctx, *, code):
"""A bad example of an eval command"""
await ctx.send(eval(code))