kheina-com / Blue-Blocker

Blocks all Twitter Blue verified users on twitter.com
Mozilla Public License 2.0
343 stars 28 forks source link

Check notifications #259

Open rougetimelord opened 5 months ago

rougetimelord commented 5 months ago

Description + behavior research

I wonder if there's a way to implement checking the accounts that get sent to the verified notifications tab? From some preliminary research on a fresh load i/api/2/notifications/verified.json?... gets fetched and the response has the structure (simplified to just focus on what we care about):

{
  "globalObjects": {
    "users": {
      "<user_id>": "<user object>",
      ...
    },
    "notifications": {
      "<notification_id>": {
        "message":  {
          "entities": [
            {
              "ref": {
                "user": {
                  "id": "<user_id that's found in globalObjects.users>"
                },
              },
            },
          ],
        },
      },
    },
    ...
  },
  "timeline": {
    "instructions": [
      {
        "addEntries": {
          "entries": [
            {
              "entryId": "cursor-top-<number higher than the sortIndex of the notification>",
              "sortIndex": "<same number>",
              ...
            },
            {
              "entryId": "notification-<notification_id found in globalObjects.notifications>",
              "sortIndex": "<a number>"
              ...
            },
            {
              "entryId": "cursor-bottom-<number lower than the sortIndex of the notification>",
              "sortIndex": "<same number>",
              ...
            },
            ...
          ]
        },
        ...
      }
    ]
  }
}

After the first load there seems to be some caching going on? This part might not matter, I'm not sure if verified notification also get received from calls to i/api/2/notifications/all.json?.... If they do there might be some more complicated cursor ranges. In general, the same verified endpoint gets fetched but responds with an object that looks like:

{
    "globalObjects": {},
    "timeline": {
        "instructions": [
            {
                "addEntries": {
                    "entries": [
                        {
                            "entryId": "cursor-top-<number higher than the sortIndex of the notification>",
                            "sortIndex": "<same number>",
                            ...
                        },
                        {
                            "entryId": "cursor-bottom-<number lower than the sortIndex of the notification>",
                            "sortIndex": "<same number>",
                            ...
                        },
                        ...
                    ]
                },
                ...
            },
            ...
        ]
    }
}

So I think it's grabbing the notification entries between/below the cursor sort indexes. If there's more than one cursor range it repeats fetches from the verified endpoint until there's only a top cursor.

How to implement

Assuming that verified notifications are not included in responses from i/api/2/notifications/all.json?... all we would need to do is add i/api/2/notifications/verified.json?... to the list of endpoints we handle. Then do:

for (const notification of Object.values(obj.notifications)) {
    const users: BlueBlockerUser[] = [];
    for (const id of notification.message.entities.map(
        entity => entity.ref.user.id)
    ) {
        // Have to do some shit here because we get a different user interface than BlueBlockerUser
        // I think it's the same shape as the search user objects?
        let user = obj.users[id];
        user.is_blue_verified = true;
        QueuePush(user);
    }
}
rougetimelord commented 5 months ago

I should mention that for now, this also adds another check that addresses #195