async def new_book(self,inter,book_title: str,book_author:str, *,
book_description: str):
await inter.response.defer(ephemeral=True)
embed = disnake.Embed(
color = disnake.Colour.random(),
title = f"{self.bot.user.name}'s Book Notifications",
description = f"{inter.author.name} Has Suggested A New Book"
).add_field(
name = book_title + " " + book_author,
value = book_description,
inline = False
).set_thumbnail(url = inter.author.avatar)
book_channel = disnake.utils.get(inter.guild.text_channels, id=1112524159239589898)
await book_channel.send(embed=embed)
return await inter.edit_original_message(f"{inter.author.mention} Your Book Has Been Suggested")
```This is a first time trying to do this sort of situation for me. I'm wanting to adjust this command to where when the embed is sent to the desired channel, it comes with a π and a π reaction. The reactions won't do anything, but I've never tried to add reactions to an embed through a command before, so I'm not sure how to proceed from here. Thanks
#Setting a command to have reactions
1 messages Β· Page 1 of 1 (latest)
-d Messageable.send
await send(content=None, *, tts=False, embed=None, embeds=None, file=None, files=None, stickers=None, delete_after=None, nonce=None, suppress_embeds=None, flags=None, ...)```
This function is a [*coroutine*](https://docs.python.org/3/library/asyncio-task.html#coroutine).
Sends a message to the destination with the content given.
The content must be a type that can convert to a string through `str(content)`.
At least one of `content`, `embed`/`embeds`, `file`/`files`, `stickers`, `components`, or `view` must be provided.
To upload a single file, the `file` parameter should be used with a single [`File`](https://docs.disnake.dev/en/latest/api/messages.html#disnake.File "disnake.File") object. To upload multiple files, the `files` parameter should be used with a [`list`](https://docs.python.org/3/library/stdtypes.html#list "(in Python v3.11)") of [`File`](https://docs.disnake.dev/en/latest/api/messages.html#disnake.File "disnake.File") objects. **Specifying both parameters will lead to an exception**.
To upload a single embed, the `embed` parameter should be used with a single [`Embed`](https://docs.disnake.dev/en/latest/api/messages.html#disnake.Embed "disnake.Embed") object. To upload multiple embeds, the `embeds` parameter should be used with a [`list`](https://docs.python.org/3/library/stdtypes.html#list "(in Python v3.11)") of [`Embed`](https://docs.disnake.dev/en/latest/api/messages.html#disnake.Embed "disnake.Embed") objects. **Specifying both parameters will lead to an exception**.
-d disnake.Message
class disnake.Message```
Represents a message from Discord.
x == y Checks if two messages are equal.
x != y Checks if two messages are not equal.
hash(x) Returns the messageβs hash.
ok give me a moment to look at these.
so then I would do
msg = await book_channel.send(embed=embed)
msg.add_reaction(":thumbsup:")
msg.add_reaction(":thumbsdown:")
```?
I believe I'm reading that right
or instead of the strings, it would be the universal emoji
Yup. You can actually copy and paste the emoji π and π .
Just don't forget await
msg = await book_channel.send(embed=embed)
await msg.add_reaction(π)
await msg.add_reaction(π)
```the only problem I'm getting from this is that the thumbsup line is telling me that I forgot a `(`
you need quotes
await message.add_reaction("π")
haha yeet tyvm!
Solved!
Marked the thread as solved. If your question has not been answered, please open a new thread in #1019642966526140566.
one more question if that's alright.
@commands.Cog.listener()
async def on_thread_join(self,thread):
announce_channel = disnake.utils.get(thread.guild.text_channels, id=1112533230483148882)
book_members = [member for member in thread.guild.members if member.top_role.name == "Book Club Member"]
book_capts = [member for member in thread.guild.members if member.top_role.name == "Book Club Captain"]
return await announce_channel.send_message(
f"{', '.join([m.mention for m in book_capts])}, {', '.join([m.mention for m in book_members])} A New Book Thread Has Been Started." +
f" Please Click {thread.mention} To View This Thread."
)
```when running events within a cog, do I need to do the decorator like this
```python
@commands.Cog.listener()
```or does it need to be
```python
@commands.Cog.listener("thread")
```? I'm a little confused with the docs
commands.Cog.listener() is basically bot.listen()
You can pass on the event name on_thread_join as a string, then call your callback function whatever you want, or don't pass anything to it and make sure the function name matches the expected event
so how I have it in the code block is appropriate?
And again..
announce_channel = disnake.utils.get(thread.guild.text_channels, id=1112533230483148882)
is inefficient and so much more typing thanthread.guild.get_channel(1112533230483148882)
It's fine.
does this need to be awaited?
I know that's a stupid question
No. It relies on cache
ok bet. tyvm
ok so I have to tweak it a little bit so that it only does announcements for book club threads that are created. According to the docs, it would be thread.parent but parent is an Optional(Union[ForumChannel,TextChannel]) so how would I write an early return if the threads parent (forum channel) wasn't "open_books"?
if thread.parent[0].name != "open_books":
pass
```?
or would I just call thread.forum_channel.name?
and also, if a new "open_book" thread is created via the discord ui, is it going to trigger my cog listener?
async def on_thread_join(self,thread):
# if the new thread does not belong to the open_books forum, pass
if thread.forum_channel.name != "open_books":
pass
announce_channel = thread.guild.get_channel(1112533230483148882)
embed = disnake.Embed(
color = disnake.Colour.random(),
title = "A New Book Has Been Created!",
description = f"Click Here To View This Thread {thread.jump_url}"
).add_field(
name = "Book Name",
value = thread.name,
inline = False
).add_field(
name = "Book Details",
value = thread.starter_message,
inline = False
).add_field(
name = "Book Genre",
value = [tag.name for tag in thread.applied_tags]
)
return await announce_channel.send_message("@here A New Book Thread Has Been Started.", embed=embed)
```this is what I'm trying to do, but I don't know a couple of things
1) If the thread is created via the discord UI "New Post" button, will it trigger this bot event
2) if I called the thread forum channel name correctly to check which forum it was created in
nevermind. I found a work around
on_thread_join is when the bot is added to a thread
so it needs to be on_thread_create not join
between the command https://pastebin.com/4vkD2SFN and the event https://pastebin.com/F4sKaHZ3, everything works except getting the newly created threads jump url (command) and getting the event to send the announcement when the thread is created. I'm not sure what I'm doing wrong as I'm following the docs when doing this
if thread.category.name != "Book Club":
pass
you'd probably want to return
pass just means, don't do anything and continue through the function
ok I changed that, but when the thread is created, it's still not sending the notification
unless I need to put the rest of the code in an else statement
You need to look back at the create_thread method.
It returns a NamedTuple
Tuple[Thread, Message]
so it should look like:
thread, message = await forum_channel.create_thread(...)
new_thread, message = await forum_channel.create_thread(
name = f"{book_title} - {book_author}",
applied_tags = [tag_to_apply,],
content = book_description
)
```and I have to unpack it
yep lol gotcha. ok so now why isn't the event sending the notification when the thread is created?
and jump_thread is unnecesary.
because :
1 get_thread take an ID, not a thread object
2. you already have the thread object
right. I slipped on that part
return await inter.edit_original_response(f'{inter.author.mention} You new Book Thread has been created. {thread.jump_url}')
right.
that should send the message to the user that used the command.
correct
So the on_thread_create isn't working?
Make sure the bot has access to the forum channel, otherwise has the manage_threads permission
it is now except it doesn't like where I'm trying to get the threads first message thread.starter_message. I was doing this because the first message that is sent to the thread is the books description and I'm trying to obtain that message for the announcement embed
thread.starter_message doesn't exist.
its supposed to be thread.thread_start_message isn't it
Yeah, that's not part of Thread
i mispelled this
oh
so then how can I get that first message for the books description?
That's to see if a channel message started a thread.
use the message history?
not the case for forum threads.
ok so then how would I get that first message or is what you're saying is that it's not possible?
You'll have to use thread.history
-d thread.last_message
property last_message```
Gets the last message in this channel from the cache.
The message might not be valid or point to an existing message.
Reliable Fetching
For a slightly more reliable method of fetching the last message, consider using either [`history()`](https://docs.disnake.dev/en/latest/api/channels.html#disnake.Thread.history "disnake.Thread.history") or [`fetch_message()`](https://docs.disnake.dev/en/latest/api/channels.html#disnake.Thread.fetch_message "disnake.Thread.fetch_message") with the [`last_message_id`](https://docs.disnake.dev/en/latest/api/channels.html#disnake.Thread.last_message_id "disnake.Thread.last_message_id") attribute.
could I get away with the last message?
last_message was None for me. Same with last_message_id
I just tested with last_message, tried to fetch with last_message_id, but the only success was with history()
async for message in thread.history(limit=1):
...
ok so then it would look like
announce_channel = thread.guild.get_channel()
message_history = await thread.history(limit=None).flatten()
embed.add_field(
name = "Book Details",
value = message_history[0],
inline = False
)
```right?
that would be value=Message
I'd suggest setting the limit to 1.
But realistically..
why not just have the announcement in the command callback where you already have the thread, message, and tags.
I mean. you're not wrong. I didn't think of that honestly. I was just thinking about expanding the bot past commands by using events.