climu / openstudyroom

Website for the Open Study Room online go/baduk/weiqi community.
https://openstudyroom.org
GNU General Public License v3.0
67 stars 33 forks source link

user discord online status is not checking everyone #405

Open climu opened 4 years ago

climu commented 4 years ago

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 commented 4 years ago

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 :(

raylu commented 4 years ago

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

climu commented 4 years ago

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

lime-green commented 4 years ago

@climu @raylu

OK I looked into this today:

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

climu commented 4 years ago

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?

raylu commented 4 years ago

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

climu commented 4 years ago

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.

raylu commented 4 years ago

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