Skip to content
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

feat(polls): implement Polls #1176

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open

Conversation

Snipy7374
Copy link
Contributor

@Snipy7374 Snipy7374 commented Mar 25, 2024

Summary

Notes:

  • Emojis in PollMedia doesn't work yet... idk if this is an issue on my code or on the API
  • I still haven't tested sending Poll(s) on interaction responses and on Webhook(s) because that still returns 403 (Forbidden)
  • I followed the discord api docs to name things, but if you have suggestions they are welcome, for example i feel like the new events names may be too long
  • In the future the question field on Poll will be able to accept a PollMedia too, and PollMedia will likely supports new things
  • Messages that contain a Poll can't be edited after sending (yet), tho in the future this shouldn't require much code changes
  • Rn sending messages that contains Poll(s) can't have any other field set, this will not require any code change in the future since i'm not doing any check

Doubts:
I feel like i'm passing way too many arguments for the new events? What's your opinion? Solved

  • Should we check for the number of answers the user is passing to construct the Poll? The maximum allowed is 10 answers per poll

I have a typing (skill) issue at poll.py/PollAnswer#245 what am i supposed to do there? Solved

Should we make answers and polls be EQ comparable in some way? (we could use the internal message object, if set, to check if two polls are equals) Doesn't make sense on second thought

Checklist

  • If code changes were made, then they have been tested
    • I have updated the documentation to reflect the changes
    • I have formatted the code properly by running pdm lint
    • I have type-checked the code by running pdm pyright
  • This PR fixes an issue
  • This PR adds something new (e.g. new method or parameters)
  • This PR is a breaking change (e.g. methods or parameters removed/renamed)
  • This PR is not a code change (e.g. documentation, README, ...)

@shiftinv shiftinv added t: enhancement New feature t: api support Support of Discord API features labels Mar 25, 2024
@shiftinv shiftinv added this to the disnake v2.10 milestone Mar 25, 2024
@Victorsitou Victorsitou added the s: waiting for api/docs Issue/PR is waiting for API support/documentation label Mar 25, 2024
disnake/poll.py Outdated Show resolved Hide resolved
disnake/poll.py Outdated Show resolved Hide resolved
@@ -0,0 +1,426 @@
# SPDX-License-Identifier: MIT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to have two separate objects for what the user can construct vs what the api returns; there's a bunch of fields the user constructible version won't have populated until some magic event, and you made accessing them throw AttributeError

I think you'd agree that physically restricting what the user can do with their object is better than merely mentioning it in the docstring (which seem to often grow large enough a good part of it won't be seen unless scrolled down)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this. Something similar to what I did in the Onboarding PR could be implemented.

Copy link
Member

@shiftinv shiftinv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First off, thanks for implementing this, and sorry the review took so long! A bunch of other things unfortunately got in the way.

Many of these comments are simple documentation adjustments and can be committed as-is, some other parts are a bit more complex (as usual, coming up with a good developer interface is tricky).
There's still a bunch of bikeshedding to be done as you mentioned, so i've left out comments about a couple things that only make sense to talk about once everything else is taken care of, for now.

That said, a new permission and poll intents have been added to the api since, would be great to have them implemented here too.

disnake/abc.py Outdated Show resolved Hide resolved
disnake/http.py Outdated Show resolved Hide resolved
changelog/1175.feature.rst Outdated Show resolved Hide resolved
disnake/enums.py Show resolved Hide resolved
disnake/enums.py Outdated Show resolved Hide resolved
disnake/raw_models.py Show resolved Hide resolved
disnake/raw_models.py Outdated Show resolved Hide resolved
disnake/state.py Outdated Show resolved Hide resolved
disnake/types/poll.py Outdated Show resolved Hide resolved
disnake/types/poll.py Outdated Show resolved Hide resolved
@shiftinv shiftinv removed the s: waiting for api/docs Issue/PR is waiting for API support/documentation label Apr 23, 2024
Snipy7374 and others added 15 commits April 23, 2024 23:07
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
disnake/http.py Outdated Show resolved Hide resolved
disnake/poll.py Outdated Show resolved Hide resolved
disnake/poll.py Outdated Show resolved Hide resolved
disnake/poll.py Outdated Show resolved Hide resolved
disnake/permissions.py Show resolved Hide resolved
disnake/flags.py Show resolved Hide resolved
disnake/flags.py Show resolved Hide resolved
disnake/poll.py Outdated Show resolved Hide resolved
Co-authored-by: shiftinv <[email protected]>
Signed-off-by: Snipy7374 <[email protected]>
@Snipy7374
Copy link
Contributor Author

Ty for the reviews and sorry if this is taking longer than expected, it's my first API feature so i'm quite inexperienced. I still have the same typing (skill) issue at poll.py/PollAnswer#273, should i just type ignore it? It doesn't seem like our fault.

@shiftinv
Copy link
Member

Ty for the reviews and sorry if this is taking longer than expected, it's my first API feature so i'm quite inexperienced.

No worries, it's a pretty substantial feature and this is already really good c:
I feel like many of the issues here boil down to the API structure being somewhat weird in the name of extensibility, and avoiding possible breaking changes in the lib while also making things developer-friendly isn't really trivial.

I still have the same typing (skill) issue at poll.py/PollAnswer#273, should i just type ignore it? It doesn't seem like our fault.

Hm, seems that HTTPClient.get_poll_answer_voters should return a {users: List[User]} typeddict?

Copy link
Member

@Victorsitou Victorsitou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far 👍

@@ -1344,6 +1361,11 @@ class EntitlementType(Enum):
application_subscription = 8


class PollLayoutType(Enum):
default = 1
"""The default poll layout type."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be documented in the respective .rst file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already documented in disnake.Event page and in the messages API reference section too. Is there somewhere else this should be documented?

@@ -22,7 +22,7 @@
overload,
)

from . import utils
from . import poll, utils
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so insignificant, but the Poll class should be imported instead of doing this

@@ -0,0 +1,426 @@
# SPDX-License-Identifier: MIT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this. Something similar to what I did in the Onboarding PR could be implemented.

The message ID that got or lost a vote.
user_id: :class:`int`
The user ID who added the vote or whose vote was removed.
member: Optional[:class:`Member`]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this is not consistent across all raw models, changing this to cached_member would be more descriptive.

Comment on lines +937 to +955
member_id = raw.user_id
guild = self._get_guild(raw.guild_id)
if guild is not None:
member = guild.get_member(member_id)
if (message := self._get_message(raw.message_id)) and message.poll:
answer = utils.get(message.poll.answers, id=raw.answer_id)
else:
answer = None
if member is not None:
raw.member = member
else:
raw.member = None
else:
raw.member = None
answer = None
self.dispatch(f"raw_message_poll_vote_{event_type}", raw)

if raw.member and answer:
self.dispatch(f"message_poll_vote_{event_type}", raw.member, answer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
member_id = raw.user_id
guild = self._get_guild(raw.guild_id)
if guild is not None:
member = guild.get_member(member_id)
if (message := self._get_message(raw.message_id)) and message.poll:
answer = utils.get(message.poll.answers, id=raw.answer_id)
else:
answer = None
if member is not None:
raw.member = member
else:
raw.member = None
else:
raw.member = None
answer = None
self.dispatch(f"raw_message_poll_vote_{event_type}", raw)
if raw.member and answer:
self.dispatch(f"message_poll_vote_{event_type}", raw.member, answer)
guild = self._get_guild(raw.guild_id)
answer = None
if guild is not None:
member = guild.get_member(raw.user_id)
message = self._get_message(raw.message_id)
if message is not None and message.poll is not None:
answer = utils.get(message.poll.answers, id=raw.answer_id)
if member is not None:
raw.member = member
self.dispatch(f"raw_message_poll_vote_{event_type}", raw)
if raw.member is not None and answer is not None:
self.dispatch(f"message_poll_vote_{event_type}", raw.member, answer)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
t: api support Support of Discord API features t: enhancement New feature
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

implement new Poll discord API feature
4 participants