Skip to content

Commit

Permalink
fix: update audit log filtering & sorting (#2371)
Browse files Browse the repository at this point in the history
* fix: either i'm high and it won't work, or i'm god and this works

* Update iterators.py

* Update iterators.py

Signed-off-by: Lala Sabathil <lala@pycord.dev>

* chore: clean code

Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>

* chore: add changelog entry

Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>

* chore: add changelog entry

Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>

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

* Update guild.py

Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>

---------

Signed-off-by: Lala Sabathil <lala@pycord.dev>
Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jul 5, 2024
1 parent ec3cf16 commit d1702cf
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 54 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ These changes are available on the `master` branch, but have not yet been releas
to `None`. ([#2464](https://github.com/Pycord-Development/pycord/pull/2464))
- Fixed `remove_application_command` causing issues while reloading extensions.
([#2480](https://github.com/Pycord-Development/pycord/pull/2480))
- Fixed outdated logic for filtering and sorting audit log entries.
([#2371](https://github.com/Pycord-Development/pycord/pull/2371))

### Changed

Expand Down Expand Up @@ -103,6 +105,9 @@ These changes are available on the `master` branch, but have not yet been releas
- Removed the `delete_message_days` parameter from ban methods. Please use
`delete_message_seconds` instead.
([#2421](https://github.com/Pycord-Development/pycord/pull/2421))
- Removed the `oldest_first` parameter from `Guild.audit_logs` in favor of the `before`
and `after` parameters.
([#2371](https://github.com/Pycord-Development/pycord/pull/2371))

## [2.5.0] - 2024-03-02

Expand Down
8 changes: 3 additions & 5 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -3266,14 +3266,16 @@ def audit_logs(
limit: int | None = 100,
before: SnowflakeTime | None = None,
after: SnowflakeTime | None = None,
oldest_first: bool | None = None,
user: Snowflake = None,
action: AuditLogAction = None,
) -> AuditLogIterator:
"""Returns an :class:`AsyncIterator` that enables receiving the guild's audit logs.
You must have the :attr:`~Permissions.view_audit_log` permission to use this.
See `API documentation <https://discord.com/developers/docs/resources/audit-log#get-guild-audit-log>`_
for more information about the `before` and `after` parameters.
Parameters
----------
limit: Optional[:class:`int`]
Expand All @@ -3286,9 +3288,6 @@ def audit_logs(
Retrieve entries after this date or entry.
If a datetime is provided, it is recommended to use a UTC aware datetime.
If the datetime is naive, it is assumed to be local time.
oldest_first: :class:`bool`
If set to ``True``, return entries in oldest->newest order. Defaults to ``True`` if
``after`` is specified, otherwise ``False``.
user: :class:`abc.Snowflake`
The moderator to filter entries from.
action: :class:`AuditLogAction`
Expand Down Expand Up @@ -3333,7 +3332,6 @@ def audit_logs(
before=before,
after=after,
limit=limit,
oldest_first=oldest_first,
user_id=user_id,
action_type=action,
)
Expand Down
60 changes: 11 additions & 49 deletions discord/iterators.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ def __init__(
limit=None,
before=None,
after=None,
oldest_first=None,
user_id=None,
action_type=None,
):
Expand All @@ -485,7 +484,6 @@ def __init__(
if isinstance(after, datetime.datetime):
after = Object(id=time_snowflake(after, high=True))

self.reverse = after is not None if oldest_first is None else oldest_first
self.guild = guild
self.loop = guild._state.loop
self.request = guild._state.http.get_audit_logs
Expand All @@ -496,51 +494,28 @@ def __init__(
self.after = after or OLDEST_OBJECT
self._users = {}
self._state = guild._state

self._filter = None # entry dict -> bool

self.entries = asyncio.Queue()

if self.reverse:
self._strategy = self._after_strategy
if self.before:
self._filter = lambda m: int(m["id"]) < self.before.id
else:
self._strategy = self._before_strategy
if self.after and self.after != OLDEST_OBJECT:
self._filter = lambda m: int(m["id"]) > self.after.id

async def _before_strategy(self, retrieve):
async def _retrieve_entries(self, retrieve):
before = self.before.id if self.before else None
data: AuditLogPayload = await self.request(
self.guild.id,
limit=retrieve,
user_id=self.user_id,
action_type=self.action_type,
before=before,
)

entries = data.get("audit_log_entries", [])
if len(data) and entries:
if self.limit is not None:
self.limit -= retrieve
self.before = Object(id=int(entries[-1]["id"]))
return data.get("users", []), entries

async def _after_strategy(self, retrieve):
after = self.after.id if self.after else None
data: AuditLogPayload = await self.request(
self.guild.id,
limit=retrieve,
user_id=self.user_id,
action_type=self.action_type,
before=before,
after=after,
)

entries = data.get("audit_log_entries", [])
if len(data) and entries:
if self.limit is not None:
self.limit -= retrieve
self.after = Object(id=int(entries[0]["id"]))
if self.before or not self.after:
self.before = Object(id=int(entries[-1]["id"]))
if self.after or not self.before:
self.after = Object(id=int(entries[0]["id"]))
return data.get("users", []), entries

async def next(self) -> AuditLogEntry:
Expand All @@ -553,36 +528,23 @@ async def next(self) -> AuditLogEntry:
raise NoMoreItems()

def _get_retrieve(self):
l = self.limit
if l is None or l > 100:
r = 100
else:
r = l
self.retrieve = r
return r > 0
limit = self.limit or 100
self.retrieve = min(limit, 100)
return self.retrieve > 0

async def _fill(self):
from .user import User

if self._get_retrieve():
users, data = await self._strategy(self.retrieve)
users, data = await self._retrieve_entries(self.retrieve)
if len(data) < 100:
self.limit = 0 # terminate the infinite loop

if self.reverse:
data = reversed(data)
if self._filter:
data = filter(self._filter, data)

for user in users:
u = User(data=user, state=self._state)
self._users[u.id] = u

for element in data:
# TODO: remove this if statement later
if element["action_type"] is None:
continue

await self.entries.put(
AuditLogEntry(data=element, users=self._users, guild=self.guild)
)
Expand Down

0 comments on commit d1702cf

Please sign in to comment.