openstudyroom icon indicating copy to clipboard operation
openstudyroom copied to clipboard

user discord online status is not checking everyone

Open climu opened this issue 4 years ago • 8 comments

When we scrape, we update discord users online status:

https://github.com/climu/openstudyroom/blob/d1979e19a4f4b55ff62fbd98baf0ba65e6c683e1/league/views.py#L88-L96

Then we display it like that: image

I just realised that this url only show first 100 users: https://discordapp.com/api/guilds/287487891003932672/widget.json

We should find another way to check who is online.

climu avatar May 25 '20 18:05 climu

So I read this: https://discord.com/developers/docs/resources/guild#guild-object-guild-structure. I try: curl -H 'Authorization: Bot MYBOTTOKEN' https://discordapp.com/api/guilds/287487891003932672/members?/ but it only returns one user. I try curl -H 'Authorization: Bot MYBOTTOKEN' https://discordapp.com/api/guilds/287487891003932672/presences?/ and get a 404 :(

climu avatar May 26 '20 11:05 climu

the question mark after the field means it's optional. those are fields in the responses to /api/guilds/:id, not the member list. I think it's optional because the websocket gateway won't send it to you unless you opt your bot into the presence privileged intent

raylu avatar May 26 '20 16:05 raylu

Thanks for clarification. I still couldn't manage to get the wanted information from discord api.

climu avatar May 28 '20 10:05 climu

@climu @raylu

OK I looked into this today:

  • There's no HTTP endpoint for this https://github.com/discord/discord-api-docs/issues/666 (although they created a websocket endpoint, which isn't that useful)
  • There's a PRESENCE_UPDATE event that gets sent that updates the member's status as expected

so I propose:

  1. Create a new API endpoint /api/discord/online_statuses/ or similar that saves a user's status if they exist in the DB
  2. In the discord bot, create a cog (https://discordpy.readthedocs.io/en/latest/ext/tasks/) that runs the following task every ~5 minutes:
  • gathers all the members in bot: bot.get_guild(guild_id).members
  • builds a status payload of the form: [{user_id: "...", status: "online|offline|etc."}] using member.status
  • POST to the endpoint

EDIT: We could also listen to the event and only send users who’s statuses have changed as a performance improvement

lime-green avatar May 31 '20 20:05 lime-green

Thanks for the investigation! I think this can work.

I have one security wonder: The API endpoint would change our database and I am reluctant to open that to everyone.

Maybe we could do a trick: The bot read a text file /etc/discord_bot_password containing a random string and pass it to the POST request. Then in the view we can open the very same file and check that it matches.

Is my security concern not relevant? Is the suggested security check ok?

climu avatar Jun 01 '20 06:06 climu

the bot and the db are on the same server. no need to post

I think this is pretty overkill and I would personally settle for the discord widget, though

raylu avatar Jun 01 '20 06:06 raylu

the bot and the db are on the same server. no need to post

You mean we could connect the bot to OSR db directly? Isn't it tricky without django ORM?

I think this is pretty overkill and I would personally settle for the discord widget, though

Well discord widget would look like : https://discord.com/widget?id=287487891003932672&theme=light

It just show a global activity count and we have this working allready: image

The idea here is to show users online status on users links. Is it really needed? it's not clear indeed.

climu avatar Jun 01 '20 08:06 climu

the bot and the db are on the same server. no need to post

You mean we could connect the bot to OSR db directly? Isn't it tricky without django ORM?

just install psycopg2 in the bot's venv

raylu avatar Jun 01 '20 17:06 raylu