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

Incorrect reserialization on presence sync #765

Open
4 tasks done
outmaneuver opened this issue Nov 28, 2024 · 4 comments
Open
4 tasks done

Incorrect reserialization on presence sync #765

outmaneuver opened this issue Nov 28, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@outmaneuver
Copy link

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

@outmaneuver outmaneuver added the unconfirmed bug Unconfirmed bug label Nov 28, 2024
@dolfies dolfies changed the title streaming activity is done incorrect in this library? Incorrect reserialization on presence sync Dec 1, 2024
@dolfies dolfies added bug Something isn't working and removed unconfirmed bug Unconfirmed bug labels Dec 1, 2024
@dolfies
Copy link
Owner

dolfies commented Dec 1, 2024

Hi! This is what I think is happening here (from a quick glance). User presence is quite complicated.

When user status is updated on a different client, the client modifies user settings to save and propagate the status to other clients. When a user settings update is received, clients are expected to update their gateway session's presence with the new status. The library does this by default.

When the new presence info is being constructed to be sent to Discord, it looks like the streaming activity is being reserialized incorrectly... The activity implementation in the library is in need of a refactor. A temporary mitigation to this would be to disable the syncing behavior by passing sync_presence=False to your client initialization. This causes undefined behavior (different clients for the same user having different presences) but should be fine. My best guess is that the most weirdness you might see is some issues with switching to idle on a different client.

@outmaneuver
Copy link
Author

Hi! This is what I think is happening here (from a quick glance). User presence is quite complicated.

When user status is updated on a different client, the client modifies user settings to save and propagate the status to other clients. When a user settings update is received, clients are expected to update their gateway session's presence with the new status. The library does this by default.

When the new presence info is being constructed to be sent to Discord, it looks like the streaming activity is being reserialized incorrectly... The activity implementation in the library is in need of a refactor. A temporary mitigation to this would be to disable the syncing behavior by passing sync_presence=False to your client initialization. This causes undefined behavior (different clients for the same user having different presences) but should be fine. My best guess is that the most weirdness you might see is some issues with switching to idle on a different client.

well thank you for telling me that cause for a moment I thought I was doing something wrong.. but after talking to a lot of other devs they did point the issue is with the library not my code, I hope this gets fixed soon as I do use it quite often and it's annoying when users tell me they can't see my activity!

@outmaneuver
Copy link
Author

outmaneuver commented Dec 4, 2024

also short update on this cause I forgot to mention it does this only for the streaming activity the whole activity disappears when a user sets his custom status regardless if through selfbot or not, not only assets disappearing

@outmaneuver
Copy link
Author

oh yeah and also your suggestion doesn't fix it either it still persists

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants