Skip to content

Commit 707322f

Browse files
renzorenzon
authored andcommitted
Created command to collect discord user ids
Partial of #4791
1 parent 47f0dc6 commit 707322f

12 files changed

Lines changed: 191 additions & 10 deletions

File tree

pythonpro/celery.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55

66
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pythonpro.settings')
77
app = Celery('pythonpro.celery')
8-
app.config_from_object('django.conf:settings', namespace='CELERY')
9-
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
8+
app.config_from_object(settings, namespace='CELERY')
9+
app.autodiscover_tasks()

pythonpro/discord/admin.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.contrib import admin
22

3-
from pythonpro.discord.models import DiscordUser
3+
from pythonpro.discord.models import DiscordUser, DiscordLead
44

55

66
@admin.register(DiscordUser)
@@ -18,3 +18,20 @@ def has_change_permission(self, request, obj=None):
1818

1919
def has_delete_permission(self, request, obj=None):
2020
return False
21+
22+
23+
@admin.register(DiscordLead)
24+
class DiscordLeadAdmin(admin.ModelAdmin):
25+
fields = ["discord_id", "status", "created_at", "updated_at"]
26+
list_display = fields
27+
list_filter = ['status']
28+
ordering = ['-updated_at']
29+
30+
def has_add_permission(self, request):
31+
return False
32+
33+
def has_change_permission(self, request, obj=None):
34+
return False
35+
36+
def has_delete_permission(self, request, obj=None):
37+
return False

pythonpro/discord/api_client.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ class DiscordBotClient:
3535
def __init__(self, bot_token: str):
3636
self._bot_token = bot_token
3737

38+
def get_member(self, discord_user_id: str):
39+
headers = {
40+
'Authorization': f'Bot {self._bot_token}'
41+
}
42+
r = requests.get(f'{_BASE_ENDPOINT_URI}/users/{discord_user_id}', headers=headers)
43+
r.raise_for_status()
44+
discord_user_dict = r.json()
45+
return discord_user_dict
46+
3847
def list_guild_members(self, guild_id, limit=100, after=0) -> dict:
3948
"""
4049
:param guild_id: the discord server id
@@ -138,10 +147,3 @@ def generate_api_client(self, autorization_code: str) -> Union[DiscordAppClient,
138147
if self._bot_token is None:
139148
return DiscordAppClient(access_token)
140149
return DiscordAppAndBotClient(access_token, self._bot_token)
141-
142-
143-
if __name__ == '__main__':
144-
import decouple
145-
c = DiscordBotClient(decouple.config('DISCORD_APP_BOT_TOKEN'))
146-
members = c.list_guild_members(971162582624903288)
147-
print(members)

pythonpro/discord/facade.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from django.conf import settings
2+
3+
from pythonpro.discord.api_client import DiscordBotClient
4+
from pythonpro.discord.tasks import clean_discord_user
5+
6+
discord_bot_client = DiscordBotClient(settings.DISCORD_APP_BOT_TOKEN)
7+
8+
9+
def clean_discord_users():
10+
discord_user_id = 0
11+
while True:
12+
discord_members = discord_bot_client.list_guild_members(settings.DISCORD_GUILD_ID, after=discord_user_id)
13+
if len(discord_members) == 0:
14+
break
15+
for member in discord_members:
16+
discord_user = member['user']
17+
discord_user_id = discord_user['id']
18+
is_bot = discord_user.get('bot', False)
19+
if is_bot:
20+
continue
21+
clean_discord_user.delay(discord_user_id)

pythonpro/discord/management/__init__.py

Whitespace-only changes.

pythonpro/discord/management/commands/__init__.py

Whitespace-only changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django.core.management import BaseCommand
2+
3+
from pythonpro.discord import facade
4+
5+
6+
class Command(BaseCommand):
7+
help = 'Sincronizar usuários do Discord com Painel da DevPro'
8+
9+
def add_arguments(self, parser):
10+
pass
11+
12+
def handle(self, *args, **options):
13+
facade.clean_discord_users()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 4.2.10 on 2024-02-28 18:04
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('discord', '0002_discord_user_created_at_desc_index'),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name='DiscordLead',
15+
fields=[
16+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17+
('discord_id', models.CharField(max_length=64, unique=True)),
18+
('created_at', models.DateTimeField(auto_now_add=True)),
19+
('updated_at', models.DateTimeField(auto_now=True)),
20+
('status', models.CharField(choices=[('A', 'Ativa'), ('I', 'Inativa')], default='I', max_length=32)),
21+
],
22+
),
23+
]

pythonpro/discord/models.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,18 @@ class Meta:
1515

1616
def __str__(self):
1717
return self.discord_email
18+
19+
20+
class DiscordLead(models.Model):
21+
class Status(models.TextChoices):
22+
ACTIVE = 'A', 'Ativa'
23+
INACTIVE = 'I', 'Inativa'
24+
25+
discord_id = models.CharField(max_length=64, unique=True)
26+
created_at = models.DateTimeField(auto_now_add=True)
27+
updated_at = models.DateTimeField(auto_now=True)
28+
status = models.CharField(
29+
max_length=32,
30+
choices=Status.choices,
31+
default=Status.INACTIVE
32+
)

pythonpro/discord/tasks.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from celery import shared_task
2+
3+
from pythonpro.discord.models import DiscordLead
4+
from pythonpro.memberkit.models import Subscription
5+
6+
7+
@shared_task(
8+
rate_limit=1,
9+
max_retries=5,
10+
retry_backoff=True,
11+
retry_backoff_max=700,
12+
retry_jitter=True
13+
)
14+
def clean_discord_user(discord_user_id):
15+
has_discord_access = Subscription.objects.filter(
16+
status=Subscription.Status.ACTIVE,
17+
subscription_types__has_discord_access=True,
18+
subscriber__discorduser__discord_id=discord_user_id
19+
).exists()
20+
21+
lead_status = DiscordLead.Status.ACTIVE if has_discord_access else DiscordLead.Status.INACTIVE
22+
DiscordLead.objects.update_or_create(
23+
defaults={'status': lead_status},
24+
discord_id=discord_user_id
25+
)
26+
27+
return print(f'Clean discord user: {discord_user_id}')

0 commit comments

Comments
 (0)