internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: python-discord/bot

Issue:
Add link to deleted message for message log
Being able to jump immediately back to when it was deleted would be helpful (especially in the case of messages for which the content is no longer available) since this is the default when discord gets a jumplink to a message that does not exist (except for on android, but it would be useful enough on other platforms I think that's worth ignoring.


Discussion:

Resolving patch:
diff --git a/bot/exts/moderation/modlog.py b/bot/exts/moderation/modlog.py
--- a/bot/exts/moderation/modlog.py
+++ b/bot/exts/moderation/modlog.py
@@ -546,6 +546,7 @@ async def on_message_delete(self, message: discord.Message) -> None:
                 f"**Author:** {format_user(author)}\n"
                 f"**Channel:** {channel.category}/#{channel.name} (`{channel.id}`)\n"
                 f"**Message ID:** `{message.id}`\n"
+                f"[Jump to message]({message.jump_url})\n"
                 "\n"
             )
         else:
@@ -553,6 +554,7 @@ async def on_message_delete(self, message: discord.Message) -> None:
                 f"**Author:** {format_user(author)}\n"
                 f"**Channel:** #{channel.name} (`{channel.id}`)\n"
                 f"**Message ID:** `{message.id}`\n"
+                f"[Jump to message]({message.jump_url})\n"
                 "\n"
             )
 


Test patch:
Repository: python-discord/bot

Issue:
Add an `attachments` rule
# Abstract 

We should have an antispam rule filtering small burst of images. 

# Rationale

Currently, when a user posts 4 images in less than 10 seconds without any comment, the `duplicates` rule will trigger. While we still want to be informed when many images are posted, having the `duplicates` rule trigger doesn't make much sense. Besides, if different message content is given for each image, it will only trigger `burst` if more than 9 messages are sent in 10 seconds. 

# Specification

- [ ] Make sure that the `duplicates` filter won't be triggered by messages with images. We can safely skip empty messages with attachments.
- [ ] Create an `images` filter based on `duplicates` that will trigger when more than 3 images are posted in less than 10 seconds. It should ignore the message content. 


Discussion:

Resolving patch:
diff --git a/bot/rules/duplicates.py b/bot/rules/duplicates.py
--- a/bot/rules/duplicates.py
+++ b/bot/rules/duplicates.py
@@ -13,6 +13,7 @@ async def apply(
         if (
             msg.author == last_message.author
             and msg.content == last_message.content
+            and msg.content
         )
     )
 


Test patch:
Repository: python-discord/bot

Issue:
Logic in Source Command's Help Command Check
## Description
<!-- Describe the bug you've found -->
Its impossible to get the source for the HelpChannel cog.

## Steps to Reproduce
<!-- Detail the exact list of steps to be able to encounter the bug -->
`!src HelpChannel`
Due to the logic of the command, all that needs to be said is `!src help` followed by anything.

## Expected Behaviour
<!-- Outline what you expect to occur, include screenshots if relevant -->
Source link to the HelpChannel cog is shown.

## Actual Behaviour
<!-- Outline what occurs instead of the expected behavior, include screenshots if relevant -->
Help command source link is shown.

## Known Impacted Platforms
<!-- Replace [ ] with [x] to mark items -->

- [x] Web
- [x] Desktop
- [x] Android App
- [x] iOS App

## Possible Solutions
<!-- Detail any solutions you might have in mind to be able to resolve the bug -->
These lines are the probable cause.
https://github.com/python-discord/bot/blob/51af1369e0d9c2ad185f0c0920b599b7187ed077/bot/exts/info/source.py#L19-L20
After looking at sir-lancebot, it might even be possible to remove these two lines altogether.
## Would you like to implement a fix?

***Note: For high-priority or critical bugs, fixes may be implemented by staff.***
<!-- Replace [ ] with [x] with your choice -->

- [ ] I'd like to implement the bug fix
- [x] Anyone can implement the bug fix



Discussion:

Resolving patch:
diff --git a/bot/exts/info/source.py b/bot/exts/info/source.py
--- a/bot/exts/info/source.py
+++ b/bot/exts/info/source.py
@@ -14,9 +14,10 @@
 class SourceConverter(commands.Converter):
     """Convert an argument into a help command, tag, command, or cog."""
 
-    async def convert(self, ctx: commands.Context, argument: str) -> SourceType:
+    @staticmethod
+    async def convert(ctx: commands.Context, argument: str) -> SourceType:
         """Convert argument into source object."""
-        if argument.lower().startswith("help"):
+        if argument.lower() == "help":
             return ctx.bot.help_command
 
         cog = ctx.bot.get_cog(argument)


Test patch:
Repository: python-discord/bot

Issue:
Default duration for !superstar command if no duration is specified
## Context
The `!superstar` command currently requires a duration to be specified when invoked. 

Often we want to change someone's nickname from something very noisy or that takes up a lot of room until the user can respond and change it themselves. The duration in these cases is not usually that important as we want it to be a quick change.

## Proposal
It would be useful if there was a short default duration for this command. Something like 5 or 15 minutes. It would function similarly to the `!mute` command where if no duration is given, it opts for a 1 hour duration.


Discussion:
I'd be willing to implement this.

Resolving patch:
diff --git a/bot/exts/moderation/infraction/superstarify.py b/bot/exts/moderation/infraction/superstarify.py
--- a/bot/exts/moderation/infraction/superstarify.py
+++ b/bot/exts/moderation/infraction/superstarify.py
@@ -11,7 +11,7 @@
 
 from bot import constants
 from bot.bot import Bot
-from bot.converters import Expiry
+from bot.converters import Duration, Expiry
 from bot.exts.moderation.infraction import _utils
 from bot.exts.moderation.infraction._scheduler import InfractionScheduler
 from bot.utils.messages import format_user
@@ -19,6 +19,7 @@
 
 log = logging.getLogger(__name__)
 NICKNAME_POLICY_URL = "https://pythondiscord.com/pages/rules/#nickname-policy"
+SUPERSTARIFY_DEFAULT_DURATION = "1h"
 
 with Path("bot/resources/stars.json").open(encoding="utf-8") as stars_file:
     STAR_NAMES = json.load(stars_file)
@@ -109,7 +110,7 @@ async def superstarify(
         self,
         ctx: Context,
         member: Member,
-        duration: Expiry,
+        duration: t.Optional[Expiry],
         *,
         reason: str = '',
     ) -> None:
@@ -134,6 +135,9 @@ async def superstarify(
         if await _utils.get_active_infraction(ctx, member, "superstar"):
             return
 
+        # Set to default duration if none was provided.
+        duration = duration or await Duration().convert(ctx, SUPERSTARIFY_DEFAULT_DURATION)
+
         # Post the infraction to the API
         old_nick = member.display_name
         infraction_reason = f'Old nickname: {old_nick}. {reason}'


Test patch:
Repository: python-discord/bot

Issue:
Stop an in-progress stream if a user's role is revoked
If a user's streaming permission is removed via the revoke stream command, we want to stop any stream that may be in-progress.

If a user's video role drops off due to the normal schedule, then we don't need to do this.

`discord.ActivityType.streaming` shows whether a user is streaming.

This implementation should work even if the member don't have the video role anymore.

Concept approved by @MrHemlock 


Discussion:
The only way I can think of doing this is by moving the user to a temporary voice channel and then back to the original voice channel. Discord does not even provide a way to stop stream in their UI, maybe this feature is gonna come up in the future version of discord.
Yea, agreed. My first thought was to move them to #AFK and back.

Resolving patch:
diff --git a/bot/exts/moderation/stream.py b/bot/exts/moderation/stream.py
--- a/bot/exts/moderation/stream.py
+++ b/bot/exts/moderation/stream.py
@@ -70,6 +70,28 @@ async def _reload_tasks_from_redis(self) -> None:
                 self._revoke_streaming_permission(member)
             )
 
+    async def _suspend_stream(self, ctx: commands.Context, member: discord.Member) -> None:
+        """Suspend a member's stream."""
+        await self.bot.wait_until_guild_available()
+        voice_state = member.voice
+
+        if not voice_state:
+            return
+
+        # If the user is streaming.
+        if voice_state.self_stream:
+            # End user's stream by moving them to AFK voice channel and back.
+            original_vc = voice_state.channel
+            await member.move_to(ctx.guild.afk_channel)
+            await member.move_to(original_vc)
+
+            # Notify.
+            await ctx.send(f"{member.mention}'s stream has been suspended!")
+            log.debug(f"Successfully suspended stream from {member} ({member.id}).")
+            return
+
+        log.debug(f"No stream found to suspend from {member} ({member.id}).")
+
     @commands.command(aliases=("streaming",))
     @commands.has_any_role(*MODERATION_ROLES)
     async def stream(self, ctx: commands.Context, member: discord.Member, duration: Expiry = None) -> None:
@@ -170,10 +192,12 @@ async def revokestream(self, ctx: commands.Context, member: discord.Member) -> N
 
             await ctx.send(f"{Emojis.check_mark} Revoked the permission to stream from {member.mention}.")
             log.debug(f"Successfully revoked streaming permission from {member} ({member.id}).")
-            return
 
-        await ctx.send(f"{Emojis.cross_mark} This member doesn't have video permissions to remove!")
-        log.debug(f"{member} ({member.id}) didn't have the streaming permission to remove!")
+        else:
+            await ctx.send(f"{Emojis.cross_mark} This member doesn't have video permissions to remove!")
+            log.debug(f"{member} ({member.id}) didn't have the streaming permission to remove!")
+
+        await self._suspend_stream(ctx, member)
 
     @commands.command(aliases=('lstream',))
     @commands.has_any_role(*MODERATION_ROLES)


Test patch:
Repository: python-discord/bot

Issue:
Use embed timestamp in reminder
When a user sets a reminder, a confirmation embed is sent, to inform the user that the reminder was successfully saved.

In this reminder, we currently include the time at which it is due to be sent. This time is in UTC.

I propose we refactor this part of the code to instead use the timestamp field in the Embed.
https://github.com/python-discord/bot/blob/f2970481e1cd8950dbbb2d3b871df68e90f5a932/bot/exts/utils/reminders.py#L85-L105
 This would mean that the time would automatically get converted to the user's current time zone by Discord.


Discussion:
Sounds good!
I would like to implement this.

Resolving patch:
diff --git a/bot/exts/utils/reminders.py b/bot/exts/utils/reminders.py
--- a/bot/exts/utils/reminders.py
+++ b/bot/exts/utils/reminders.py
@@ -90,15 +90,18 @@ async def _send_confirmation(
         delivery_dt: t.Optional[datetime],
     ) -> None:
         """Send an embed confirming the reminder change was made successfully."""
-        embed = discord.Embed()
-        embed.colour = discord.Colour.green()
-        embed.title = random.choice(POSITIVE_REPLIES)
-        embed.description = on_success
+        embed = discord.Embed(
+            description=on_success,
+            colour=discord.Colour.green(),
+            title=random.choice(POSITIVE_REPLIES)
+        )
 
         footer_str = f"ID: {reminder_id}"
+
         if delivery_dt:
             # Reminder deletion will have a `None` `delivery_dt`
-            footer_str = f"{footer_str}, Due: {delivery_dt.strftime('%Y-%m-%dT%H:%M:%S')}"
+            footer_str += ', Due'
+            embed.timestamp = delivery_dt
 
         embed.set_footer(text=footer_str)
 


Test patch:
Repository: python-discord/bot

Issue:
Use embed timestamp in mod pings off
When a mods turns off mod pings, a confirmation is sent to inform the user that their pings have successfully been turned off.

In this confirmation, we currently include the time at which it is due to be sent, this time is in UTC.

I propose we refactor this part of the code to instead use an Embed, with a the timestamp field.
https://github.com/python-discord/bot/blob/ce819ade482e82ecbc474bce5fb8ac9dd8b37b40/bot/exts/moderation/modpings.py#L107
This would mean that the time would automatically get converted to the user's current time zone by Discord.


Discussion:
I think this should be done, given that all information is contained within the embed.
Yeah, that sounds useful
I could do this

Resolving patch:
diff --git a/bot/exts/moderation/modpings.py b/bot/exts/moderation/modpings.py
--- a/bot/exts/moderation/modpings.py
+++ b/bot/exts/moderation/modpings.py
@@ -3,11 +3,11 @@
 
 from async_rediscache import RedisCache
 from dateutil.parser import isoparse
-from discord import Member
+from discord import Embed, Member
 from discord.ext.commands import Cog, Context, group, has_any_role
 
 from bot.bot import Bot
-from bot.constants import Emojis, Guild, MODERATION_ROLES, Roles
+from bot.constants import Colours, Emojis, Guild, Icons, MODERATION_ROLES, Roles
 from bot.converters import Expiry
 from bot.utils.scheduling import Scheduler
 
@@ -104,7 +104,9 @@ async def off_command(self, ctx: Context, duration: Expiry) -> None:
             self._role_scheduler.cancel(mod.id)
         self._role_scheduler.schedule_at(duration, mod.id, self.reapply_role(mod))
 
-        await ctx.send(f"{Emojis.check_mark} Moderators role has been removed until {until_date}.")
+        embed = Embed(timestamp=duration, colour=Colours.bright_green)
+        embed.set_footer(text="Moderators role has been removed until", icon_url=Icons.green_checkmark)
+        await ctx.send(embed=embed)
 
     @modpings_group.command(name='on')
     @has_any_role(*MODERATION_ROLES)


Test patch:
Repository: hyperledger/aries-cloudagent-python

Issue:
Credential exchange receiving webhook callback with no "state"
To reproduce:  send a credential using the '/credential_exchange/send' admin method

Callbacks are received with each message state (including 'issued') however additional messages are received by the web hook with no 'state in the message



Discussion:

Resolving patch:
diff --git a/aries_cloudagent/messaging/credentials/manager.py b/aries_cloudagent/messaging/credentials/manager.py
--- a/aries_cloudagent/messaging/credentials/manager.py
+++ b/aries_cloudagent/messaging/credentials/manager.py
@@ -118,6 +118,7 @@ async def prepare_send(
                 auto_issue=True,
                 connection_id=connection_id,
                 initiator=CredentialExchange.INITIATOR_SELF,
+                state=CredentialExchange.STATE_REQUEST_RECEIVED,
                 credential_definition_id=credential_definition_id,
                 schema_id=source_credential_exchange.schema_id,
                 credential_offer=source_credential_exchange.credential_offer,


Test patch:
Repository: hyperledger/aries-cloudagent-python

Issue:
Make the Alice agent accept different format invitations
Currently Alice accepts only a JSON plaintext invitation and we'd like her agent to be able to handle other invitation formats.  We'd like this for a demo at the MyData conference on Sept. 25.

Please update the implementation so that Alice can also accept a URL such as:

```
https://agentbook.vonx.io:10000?c_i=eyJyZWNpcGllbnRLZXlzIjogWyJGWGZEaWRjY3E2VlBFeWl4ZTh6ZnVtUUZ5dmN4RzhZRFFoQWVYeUJiYVd6aSJdLCAicm91dGluZ0tleXMiOiBbXSwgInNlcnZpY2VFbmRwb2ludCI6ICJodHRwczovL2FnZW50Ym9vay52b254LmlvOjEwMDAwIiwgImxhYmVsIjogIkFnZW50Qm9vayIsICJAaWQiOiAiYzJkZjAzODgtYWNkNi00NGI0LTlhZDYtNTE5MDlmNmM2MzVhIiwgIkB0eXBlIjogImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIn0=
```

Or the base64URL encoded argument to the URL:

```
eyJyZWNpcGllbnRLZXlzIjogWyJGWGZEaWRjY3E2VlBFeWl4ZTh6ZnVtUUZ5dmN4RzhZRFFoQWVYeUJiYVd6aSJdLCAicm91dGluZ0tleXMiOiBbXSwgInNlcnZpY2VFbmRwb2ludCI6ICJodHRwczovL2FnZW50Ym9vay52b254LmlvOjEwMDAwIiwgImxhYmVsIjogIkFnZW50Qm9vayIsICJAaWQiOiAiYzJkZjAzODgtYWNkNi00NGI0LTlhZDYtNTE5MDlmNmM2MzVhIiwgIkB0eXBlIjogImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIn0=
```


Discussion:

Resolving patch:
diff --git a/demo/runners/alice.py b/demo/runners/alice.py
--- a/demo/runners/alice.py
+++ b/demo/runners/alice.py
@@ -1,8 +1,11 @@
 import asyncio
+import base64
+import binascii
 import json
 import logging
 import os
 import sys
+from urllib.parse import urlparse
 
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))  # noqa
 
@@ -164,13 +167,33 @@ async def handle_basicmessages(self, message):
 
 async def input_invitation(agent):
     async for details in prompt_loop("Invite details: "):
+        b64_invite = None
+        try:
+            url = urlparse(details)
+            query = url.query
+            if query and "c_i=" in query:
+                pos = query.index("c_i=") + 4
+                b64_invite = query[pos:]
+            else:
+                b64_invite = details
+        except ValueError:
+            b64_invite = details
+
+        if b64_invite:
+            try:
+                invite_json = base64.urlsafe_b64decode(b64_invite)
+                details = invite_json.decode("utf-8")
+            except binascii.Error:
+                pass
+            except UnicodeDecodeError:
+                pass
+
         if details:
             try:
                 json.loads(details)
                 break
             except json.JSONDecodeError as e:
-                log_msg("Invalid JSON:", str(e))
-                pass
+                log_msg("Invalid invitation:", str(e))
 
     with log_timer("Connect duration:"):
         connection = await agent.admin_POST("/connections/receive-invitation", details)


Test patch:
Repository: hyperledger/aries-cloudagent-python

Issue:
Websocket "Webhook" not working
Hi all,

from the code in `server.py` I found that websockets are a way to receive push notifications. I very much like this idea! After playing around with it a little, I could only receive the very first message after I connected to the `/ws` endpoint. 1 message on the "settings" topic. Right after this message, the connection got closed.

After debugging `aca-py` a bit, I can locate the issue now.
I used version 0.4.1, but no change in server.py since then.

`send = loop.create_task(queue.dequeue(timeout=5.0))`
https://github.com/hyperledger/aries-cloudagent-python/blob/master/aries_cloudagent/admin/server.py#L364

The timeout can cause an `asyncio.TimeoutError` exception.
(raised in `basic.py`)

If that happens, it's not detected until this call:
`msg = send.result()`
https://github.com/hyperledger/aries-cloudagent-python/blob/master/aries_cloudagent/admin/server.py#L380

This call re-raises the exception from inside the task and causes the whole loop to stop and jump to the `finally` block and cleans up the websocket queue.
Websocket closed now and it can't be used in `send_webhook` any more.
https://github.com/hyperledger/aries-cloudagent-python/blob/master/aries_cloudagent/admin/server.py#L427


I see a few options:
- catch the `asyncio.TimeoutError` near the `send.result()` call (or somewhere later, still inside the loop) or
- test for `send.exception()` before the `result()` call

Any thoughts on this?

Thanks and have a nice evening,
Matthias



Discussion:
@andrewwhitehead - can you please take a look at this?  Thanks!

Resolving patch:
diff --git a/aries_cloudagent/admin/server.py b/aries_cloudagent/admin/server.py
--- a/aries_cloudagent/admin/server.py
+++ b/aries_cloudagent/admin/server.py
@@ -30,7 +30,7 @@ class AdminModulesSchema(Schema):
     """Schema for the modules endpoint."""
 
     result = fields.List(
-        fields.Str(description="admin module"), description="List of admin modules",
+        fields.Str(description="admin module"), description="List of admin modules"
     )
 
 
@@ -377,7 +377,11 @@ async def websocket_handler(self, request):
                             receive = loop.create_task(ws.receive())
 
                     if send.done():
-                        msg = send.result()
+                        try:
+                            msg = send.result()
+                        except asyncio.TimeoutError:
+                            msg = None
+
                         if msg is None:
                             # we send fake pings because the JS client
                             # can't detect real ones


Test patch:
Repository: hyperledger/aries-cloudagent-python

Issue:
[multitenancy] wallet_id  is not passed correctly in send_webhook
https://github.com/hyperledger/aries-cloudagent-python/blob/5687d287040c2abb4d37999d64fd873ea494a9b8/aries_cloudagent/admin/server.py#L733

In this code, `wallet_id` identifies what this webhook message belongs to.

I checked that `wallet_id` is passed correctly (for newly created wallet) in cases of topic: `connections`, `revocation_registry`.

But, in the case of topic `issue_credential`, `wallet_id` was None.
Although the webhook message belongs to the newly created wallet, I checked that the `profile` passed is for the base wallet (configured when aca-py runs).

Thanks!

@TimoGlastra 



Discussion:
I was able to reproduce the issue. I'll look into it

Resolving patch:
diff --git a/aries_cloudagent/admin/server.py b/aries_cloudagent/admin/server.py
--- a/aries_cloudagent/admin/server.py
+++ b/aries_cloudagent/admin/server.py
@@ -330,17 +330,17 @@ async def setup_context(request: web.Request, handler):
                 except (jwt.InvalidTokenError, StorageNotFoundError):
                     raise web.HTTPUnauthorized()
 
-            # TODO may dynamically adjust the profile used here according to
-            # headers or other parameters
-            admin_context = AdminRequestContext(profile, context=profile.context)
-
             # Create a responder with the request specific context
             responder = AdminResponder(
                 profile,
                 self.outbound_message_router,
                 self.send_webhook,
             )
-            admin_context.injector.bind_instance(BaseResponder, responder)
+            profile.context.injector.bind_instance(BaseResponder, responder)
+
+            # TODO may dynamically adjust the profile used here according to
+            # headers or other parameters
+            admin_context = AdminRequestContext(profile)
 
             request["context"] = admin_context
             request["outbound_message_router"] = responder.send


Test patch:
Repository: hyperledger/aries-cloudagent-python

Issue:
Match returned did:sov doc with uniresolver
Currently the did:sov diddocs assembled in ACA-Py don't include the `assertionMethod` for the key. This means we can't use it for the default VC proof purpose `assertionMethod` and thus we get an error:

"Verification method did:sov:DViYrCMPWfuLiY7LLs8giB#key-1 not authorized by controller for proof purpose assertionMethod"

Uniresolver does include the key in `assertionMethod` so I think we should also do that in ACA-Py. I've modified it in my local branch, but just wanted to check if this is intentional.

@dbluhm 


Discussion:
No particular reason this is missing in the current implementation other than we were focused on representing info needed for DIDComm and overlooked this. Thanks for pointing it out!

Resolving patch:
diff --git a/aries_cloudagent/resolver/default/indy.py b/aries_cloudagent/resolver/default/indy.py
--- a/aries_cloudagent/resolver/default/indy.py
+++ b/aries_cloudagent/resolver/default/indy.py
@@ -57,6 +57,7 @@ async def _resolve(self, profile: Profile, did: str) -> dict:
             ident="key-1", suite=self.SUITE, material=recipient_key
         )
         builder.authentication.reference(vmethod.id)
+        builder.assertion_method.reference(vmethod.id)
         if endpoint:
             # TODO add priority
             builder.services.add_didcomm(


Test patch: