Skip to content

Commit

Permalink
j (#4)
Browse files Browse the repository at this point in the history
* feat: add once kwarg to Cog.listener (Pycord-Development#2403)

* add once kwarg to Cog.listener

* clarify

* style(pre-commit): auto fixes from pre-commit.com hooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Lala Sabathil <lala@pycord.dev>

* chore(pre-commit): pre-commit autoupdate (Pycord-Development#2410)

updates:
- [github.com/asottile/pyupgrade: v3.15.1 → v3.15.2](asottile/pyupgrade@v3.15.1...v3.15.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* fix: pass proper state to interaction._guild (Pycord-Development#2411)

* fix: option and BridgeOption adjustments (Pycord-Development#2417)

* chore(pre-commit): pre-commit autoupdate (Pycord-Development#2416)

updates:
- [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](pre-commit/pre-commit-hooks@v4.5.0...v4.6.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* feat: implement Guild.search_members (Pycord-Development#2418)

* implement guild member search

* clarification.

* style(pre-commit): auto fixes from pre-commit.com hooks

* cl

* undo iteration

* style(pre-commit): auto fixes from pre-commit.com hooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* ci(deps): bump ribtoks/tdg-github-action from 0.4.7.pre.beta to 0.4.10.pre.beta (Pycord-Development#2420)

ci(deps): bump ribtoks/tdg-github-action

Bumps [ribtoks/tdg-github-action](https://github.com/ribtoks/tdg-github-action) from 0.4.7.pre.beta to 0.4.10.pre.beta.
- [Release notes](https://github.com/ribtoks/tdg-github-action/releases)
- [Commits](ribtoks/tdg-github-action@v0.4.7-beta...v0.4.10-beta)

---
updated-dependencies:
- dependency-name: ribtoks/tdg-github-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: plun1331 <plun1331@gmail.com>

* fix: Added member data to the raw_reaction_remove event (Pycord-Development#2412)

* fix: Added member data to the raw_reaction_remove event

* style(pre-commit): auto fixes from pre-commit.com hooks

* Added changelog.md for adding member data to raw reaction remove

* Update CHANGELOG.md

Signed-off-by: plun1331 <plun1331@gmail.com>

* doc: Updated documentation for the RawReactionActionEvent.member field

---------

Signed-off-by: plun1331 <plun1331@gmail.com>
Co-authored-by: root <root@DESKTOP-U7KGUE3>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: plun1331 <plun1331@gmail.com>

* chore(pre-commit): pre-commit autoupdate (Pycord-Development#2422)

updates:
- [github.com/psf/black: 24.3.0 → 24.4.0](psf/black@24.3.0...24.4.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* docs: remove false optional (Pycord-Development#2424)

docs: not optional

* fix: Guild.query_members may accept empty query and limit (Pycord-Development#2419)

Signed-off-by: UK <41271523+NeloBlivion@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: JustaSqu1d <89910983+JustaSqu1d@users.noreply.github.com>
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
Co-authored-by: plun1331 <plun1331@gmail.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: plun1331 <plun1331@gmail.com>
Signed-off-by: UK <41271523+NeloBlivion@users.noreply.github.com>
Co-authored-by: UK <41271523+NeloBlivion@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Lala Sabathil <lala@pycord.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jordan-day <47164307+jordan-day@users.noreply.github.com>
Co-authored-by: root <root@DESKTOP-U7KGUE3>
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
Co-authored-by: JustaSqu1d <89910983+JustaSqu1d@users.noreply.github.com>
  • Loading branch information
9 people committed Apr 21, 2024
1 parent 8bd4e8f commit 51be093
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/todo.yml
Expand Up @@ -6,7 +6,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Run tdg-github-action
uses: ribtoks/tdg-github-action@v0.4.7-beta
uses: ribtoks/tdg-github-action@v0.4.10-beta
with:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Expand Up @@ -4,7 +4,7 @@ ci:

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Expand All @@ -19,7 +19,7 @@ repos:
# - --remove-duplicate-keys
# - --remove-unused-variables
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.1
rev: v3.15.2
hooks:
- id: pyupgrade
args: [--py38-plus]
Expand All @@ -28,7 +28,7 @@ repos:
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 24.3.0
rev: 24.4.0
hooks:
- id: black
args: [--safe, --quiet]
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Expand Up @@ -16,6 +16,12 @@ These changes are available on the `master` branch, but have not yet been releas
([#2396](https://github.com/Pycord-Development/pycord/pull/2396))
- Added `user` argument to `Paginator.edit`.
([#2390](https://github.com/Pycord-Development/pycord/pull/2390))
- Added `bridge_option` decorator. Required for `bridge.Bot` in 2.7.
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
- Added `Guild.search_members`.
([#2418](https://github.com/Pycord-Development/pycord/pull/2418))
- Added `member` data to the `raw_reaction_remove` event.
([#2412](https://github.com/Pycord-Development/pycord/pull/2412))
- Added support for user-installable applications.
([#2409](https://github.com/Pycord-Development/pycord/pull/2409))

Expand All @@ -34,6 +40,10 @@ These changes are available on the `master` branch, but have not yet been releas
([#2400](https://github.com/Pycord-Development/pycord/pull/2400))
- Fixed `ScheduledEvent.subscribers` behavior with `limit=None`.
([#2407](https://github.com/Pycord-Development/pycord/pull/2407))
- Fixed invalid data being passed to `Interaction._guild` in certain cases.
([#2411](https://github.com/Pycord-Development/pycord/pull/2411))
- Fixed option typehints being ignored when using `parameter_name`.
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
- Fixed an issue with `Interaction` that would cause bots to crash if a guild was not
cached. ([#2409](https://github.com/Pycord-Development/pycord/pull/2409))

Expand All @@ -43,6 +53,12 @@ These changes are available on the `master` branch, but have not yet been releas
([#2387](https://github.com/Pycord-Development/pycord/pull/2387))
- HTTP requests that fail with a 503 status are now re-tried.
([#2395](https://github.com/Pycord-Development/pycord/pull/2395))
- `option` decorator now accepts `input_type`.
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
- `Option` may be used instead of `BridgeOption` until 2.7.
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
- `Guild.query_members` now accepts `limit=None` to retrieve all members.
([#2419](https://github.com/Pycord-Development/pycord/pull/2419))
- `ApplicationCommand.guild_only` is now deprecated in favor of
`ApplicationCommand.contexts`.
([#2409](https://github.com/Pycord-Development/pycord/pull/2409))
Expand Down
8 changes: 7 additions & 1 deletion discord/cog.py
Expand Up @@ -379,7 +379,9 @@ def _get_overridden_method(cls, method: FuncT) -> FuncT | None:
)

@classmethod
def listener(cls, name: str = MISSING) -> Callable[[FuncT], FuncT]:
def listener(
cls, name: str = MISSING, once: bool = False
) -> Callable[[FuncT], FuncT]:
"""A decorator that marks a function as a listener.
This is the cog equivalent of :meth:`.Bot.listen`.
Expand All @@ -389,6 +391,9 @@ def listener(cls, name: str = MISSING) -> Callable[[FuncT], FuncT]:
name: :class:`str`
The name of the event being listened to. If not provided, it
defaults to the function's name.
once: :class:`bool`
If this listener should only be called once after each cog load.
Defaults to false.
Raises
------
Expand All @@ -411,6 +416,7 @@ def decorator(func: FuncT) -> FuncT:
raise TypeError("Listener function must be a coroutine function.")
actual.__cog_listener__ = True
to_assign = name or actual.__name__
actual._once = once
try:
actual.__cog_listener_names__.append(to_assign)
except AttributeError:
Expand Down
15 changes: 8 additions & 7 deletions discord/commands/options.py
Expand Up @@ -395,7 +395,7 @@ def to_dict(self) -> dict[str, str | int | float]:
return as_dict


def option(name, type=None, **kwargs):
def option(name, input_type=None, **kwargs):
"""A decorator that can be used instead of typehinting :class:`.Option`.
.. versionadded:: 2.0
Expand All @@ -408,12 +408,13 @@ def option(name, type=None, **kwargs):
"""

def decorator(func):
nonlocal type
type = type or func.__annotations__.get(name, str)
if parameter := kwargs.get("parameter_name"):
func.__annotations__[parameter] = Option(type, name=name, **kwargs)
else:
func.__annotations__[name] = Option(type, **kwargs)
resolved_name = kwargs.pop("parameter_name", None) or name
itype = (
kwargs.pop("type", None)
or input_type
or func.__annotations__.get(resolved_name, str)
)
func.__annotations__[resolved_name] = Option(itype, name=name, **kwargs)
return func

return decorator
38 changes: 37 additions & 1 deletion discord/ext/bridge/core.py
Expand Up @@ -40,7 +40,7 @@
SlashCommandOptionType,
)

from ...utils import MISSING, find, get
from ...utils import MISSING, find, get, warn_deprecated
from ..commands import BadArgument
from ..commands import Bot as ExtBot
from ..commands import (
Expand All @@ -63,6 +63,7 @@
"BridgeCommandGroup",
"bridge_command",
"bridge_group",
"bridge_option",
"BridgeExtCommand",
"BridgeSlashCommand",
"BridgeExtGroup",
Expand Down Expand Up @@ -627,3 +628,38 @@ async def convert(self, ctx, argument: str) -> Any:
return converted
except ValueError as exc:
raise BadArgument() from exc


def bridge_option(name, input_type=None, **kwargs):
"""A decorator that can be used instead of typehinting :class:`.BridgeOption`.
.. versionadded:: 2.6
Attributes
----------
parameter_name: :class:`str`
The name of the target parameter this option is mapped to.
This allows you to have a separate UI ``name`` and parameter name.
"""

def decorator(func):
resolved_name = kwargs.pop("parameter_name", None) or name
itype = (
kwargs.pop("type", None)
or input_type
or func.__annotations__.get(resolved_name, str)
)
func.__annotations__[resolved_name] = BridgeOption(itype, name=name, **kwargs)
return func

return decorator


discord.commands.options.Option = BridgeOption
discord.Option = BridgeOption
warn_deprecated(
"Option",
"BridgeOption",
"2.5",
reference="https://github.com/Pycord-Development/pycord/pull/2417",
)
65 changes: 50 additions & 15 deletions discord/guild.py
Expand Up @@ -2027,6 +2027,36 @@ def fetch_members(

return MemberIterator(self, limit=limit, after=after)

async def search_members(self, query: str, *, limit: int = 1000) -> list[Member]:
"""Search for guild members whose usernames or nicknames start with the query string. Unlike :meth:`fetch_members`, this does not require :meth:`Intents.members`.
.. note::
This method is an API call. For general usage, consider filtering :attr:`members` instead.
.. versionadded:: 2.6
Parameters
----------
query: :class:`str`
Searches for usernames and nicknames that start with this string, case-insensitive.
limit: :class:`int`
The maximum number of members to retrieve, up to 1000.
Returns
-------
List[:class:`Member`]
The list of members that have matched the query.
Raises
------
HTTPException
Getting the members failed.
"""

data = await self._state.http.search_members(self.id, query, limit)
return [Member(data=m, guild=self, state=self._state) for m in data]

async def fetch_member(self, member_id: int, /) -> Member:
"""|coro|
Expand Down Expand Up @@ -3354,7 +3384,7 @@ async def query_members(
self,
query: str | None = None,
*,
limit: int = 5,
limit: int | None = 5,
user_ids: list[int] | None = None,
presences: bool = False,
cache: bool = True,
Expand All @@ -3372,22 +3402,22 @@ async def query_members(
----------
query: Optional[:class:`str`]
The string that the username's start with.
limit: :class:`int`
The maximum number of members to send back. This must be
a number between 5 and 100.
presences: :class:`bool`
user_ids: Optional[List[:class:`int`]]
List of user IDs to search for. If the user ID is not in the guild then it won't be returned.
.. versionadded:: 1.4
limit: Optional[:class:`int`]
The maximum number of members to send back. If no query is passed, passing ``None`` returns all members.
If a ``query`` or ``user_ids`` is passed, must be between 1 and 100. Defaults to 5.
presences: Optional[:class:`bool`]
Whether to request for presences to be provided. This defaults
to ``False``.
.. versionadded:: 1.6
cache: :class:`bool`
Whether to cache the members internally. This makes operations
such as :meth:`get_member` work for those that matched.
user_ids: Optional[List[:class:`int`]]
List of user IDs to search for. If the user ID is not in the guild then it won't be returned.
.. versionadded:: 1.4
such as :meth:`get_member` work for those that matched. Defaults to ``True``.
Returns
-------
Expand All @@ -3407,20 +3437,25 @@ async def query_members(
if presences and not self._state._intents.presences:
raise ClientException("Intents.presences must be enabled to use this.")

if query is None:
if query == "":
raise ValueError("Cannot pass empty query string.")
if not limit or limit > 100 or limit < 1:
if query or user_ids:
raise ValueError(
"limit must be between 1 and 100 when using query or user_ids"
)
if not limit:
query = ""
limit = 0

if query is None:
if user_ids is None:
raise ValueError("Must pass either query or user_ids")
raise ValueError("Must pass query or user_ids, or set limit to None")

if user_ids is not None and query is not None:
raise ValueError("Cannot pass both query and user_ids")

if user_ids is not None and not user_ids:
raise ValueError("user_ids must contain at least 1 value")

limit = min(100, limit or 5)
return await self._state.query_members(
self,
query=query,
Expand Down
14 changes: 14 additions & 0 deletions discord/http.py
Expand Up @@ -1636,6 +1636,20 @@ def get_members(
r = Route("GET", "/guilds/{guild_id}/members", guild_id=guild_id)
return self.request(r, params=params)

def search_members(
self,
guild_id: Snowflake,
query: str,
limit: int,
) -> Response[list[member.MemberWithUser]]:
params: dict[str, Any] = {
"query": query,
"limit": limit,
}

r = Route("GET", "/guilds/{guild_id}/members/search", guild_id=guild_id)
return self.request(r, params=params)

def get_member(
self, guild_id: Snowflake, member_id: Snowflake
) -> Response[member.MemberWithUser]:
Expand Down
3 changes: 1 addition & 2 deletions discord/raw_models.py
Expand Up @@ -205,8 +205,7 @@ class RawReactionActionEvent(_RawReprMixin):
emoji: :class:`PartialEmoji`
The custom or unicode emoji being used.
member: Optional[:class:`Member`]
The member who added the reaction. Only available if `event_type` is `REACTION_ADD`
and the reaction is inside a guild.
The member who added the reaction. Only available if the reaction occurs within a guild.
.. versionadded:: 1.3
Expand Down
11 changes: 11 additions & 0 deletions discord/state.py
Expand Up @@ -781,6 +781,17 @@ def parse_message_reaction_remove(self, data) -> None:
emoji_id = utils._get_as_snowflake(emoji, "id")
emoji = PartialEmoji.with_state(self, id=emoji_id, name=emoji["name"])
raw = RawReactionActionEvent(data, emoji, "REACTION_REMOVE")

member_data = data.get("member")
if member_data:
guild = self._get_guild(raw.guild_id)
if guild is not None:
raw.member = Member(data=member_data, guild=guild, state=self)
else:
raw.member = None
else:
raw.member = None

self.dispatch("raw_reaction_remove", raw)

message = self._get_message(raw.message_id)
Expand Down

0 comments on commit 51be093

Please sign in to comment.