Skip to content

Incorrect reserialization on presence sync #765

Open
@outmaneuver

Description

@outmaneuver

Summary

assets breaking

Reproduction Steps

pass a streaming type activity using change_presence method with assets url name and details, go on discord edit your custom status through the profile no need to even touch the selfbot just use it to run the presence, wait a bit and your activity's assets are now gone but at least the activity will remain (sometimes it does disappear probably discord's fault though)

I'm including my method for creating the presence below, other activities do work fine (i think, haven't tested extensively) it's just the streaming one for some odd reason P.S ignore the custom_status method yes it happens when i use it too but it also happens without using it so it's quite irrelevant

Code

async def update_presence(self, status=None):
        try:
            config = self.load_config()
            presence_config = config.get('presence', {})
            
            # Determine status
            status_str = status.name.lower() if status else presence_config.get('status', 'dnd').lower()
            status = getattr(discord.Status, status_str, discord.Status.dnd)
            
            activities = []
    
            # Add rich presence if enabled
            if presence_config.get('enabled') and presence_config.get('application_id'):
                app_id = presence_config['application_id']
                await self.fetch_application_assets(app_id)


                activity_type = str(presence_config.get('type', 'playing')).lower()
                activity_kwargs = {
                    'application_id': presence_config['application_id'],
                    'type': self.ACTIVITY_TYPES.get(activity_type.lower()) or self.ACTIVITY_TYPES.get(activity_type) or discord.ActivityType.playing,
                    'name': presence_config.get('name', ''),
                    # don't pass if streaming type
                    'state': presence_config.get('state') if activity_type not in ['streaming', '1'] else None,
                    'details': presence_config.get('details'),
                }

                # Only add URL if type is streaming (either by name or number)
                if (activity_type == 'streaming' or activity_type == '1') and presence_config.get('url'):
                    activity_kwargs['url'] = presence_config['url']
    
                # Handle assets
                assets = {}
                if app_assets := self.application_assets.get(app_id):
                    if large_image := presence_config.get('large_image'):
                        assets['large_image'] = app_assets.get(large_image, large_image)
                        if large_text := presence_config.get('large_text'):
                            assets['large_text'] = large_text
                    if small_image := presence_config.get('small_image'):
                        assets['small_image'] = app_assets.get(small_image, small_image)
                        if small_text := presence_config.get('small_text'):
                            assets['small_text'] = small_text
    
                if assets:
                    activity_kwargs['assets'] = assets
    
                # Add timestamps
                if self.start_time:
                    activity_kwargs['timestamps'] = {'start': int(self.start_time * 1000)}
    
                # Handle buttons
                buttons = []
                if button1 := presence_config.get('button1'):
                    buttons.append(button1)
                if button2 := presence_config.get('button2'):
                    buttons.append(button2)
                if buttons:
                    activity_kwargs['buttons'] = buttons
    
                # Add party info
                if presence_config.get('party_id') or (presence_config.get('party_size') and presence_config.get('party_max')):
                    party = {}
                    if party_id := presence_config.get('party_id'):
                        party['id'] = party_id
                    if party_size := presence_config.get('party_size'):
                        party['size'] = [int(party_size), int(presence_config.get('party_max', party_size))]
                    activity_kwargs['party'] = party
    
                activities.append(discord.Activity(**activity_kwargs))
    
            # Add custom status if configured
            if custom_status := presence_config.get('custom_status', {}):
                if text := custom_status.get('text'):
                    custom_activity = discord.CustomActivity(name=text)
                    if emoji := custom_status.get('emoji'):
                        custom_activity.emoji = discord.PartialEmoji.from_dict(emoji)
                    activities.append(custom_activity)
    
            # Update presence with all activities
            await self.bot.change_presence(status=status, activities=activities)
    
        except Exception as e:
            print(f"Error updating presence: {e}")
            import traceback
            traceback.print_exc()

Expected Results

the assets not to disappear from the activity lmao?
6eLOypZ

Actual Results

the activity continues running with broken assets
8J8Htlg

and just in case you didn't understand that break happens when i play with this little fella :)
v7xPgBg

System Information

root@red-owl-04917:~# python3 -m discord -v

Checklist

  • I have confirmed I am using unmodified discord.py-self and not the upstream discord.py.
  • I have searched the open issues for duplicates.
  • I have shared the entire traceback.
  • I am using a user token (and it isn't visible in the code).

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions