lunarflu HF staff commited on
Commit
5a26019
β€’
1 Parent(s): 8bd6cd9

oauth verification update (big)

Browse files
Files changed (1) hide show
  1. app.py +167 -122
app.py CHANGED
@@ -1,41 +1,46 @@
1
- import asyncio
 
2
  import csv
3
- import datetime
4
  import json
 
 
 
 
5
  import logging
6
- import os
7
  import os.path
8
- import random
9
- import re
 
 
10
  import threading
11
- import time
12
-
13
- import discord
14
- import gradio as gr
15
  import gradio_client
16
- import gspread
17
  import numpy as np
18
  import pandas as pd
19
- import requests
20
  import plotly.graph_objects as go
21
 
 
22
  from requests import HTTPError
23
- from apscheduler.executors.pool import ThreadPoolExecutor
24
- from apscheduler.schedulers.background import BackgroundScheduler
25
  from discord import Color, Embed
 
26
  from discord.ext import commands, tasks
27
- from gradio_client import Client
28
- from gspread_dataframe import get_as_dataframe, set_with_dataframe
29
  from gspread_formatting.dataframe import format_with_dataframe
 
 
30
  from huggingface_hub import HfApi, list_liked_repos, list_metrics, list_models
31
- from tabulate import tabulate
32
- from datetime import datetime, timedelta
33
-
34
 
35
  DISCORD_TOKEN = os.environ.get("DISCORD_TOKEN", None)
36
  intents = discord.Intents.all()
37
  bot = commands.Bot(command_prefix='!', intents=intents)
38
 
 
 
 
 
39
 
40
  """"""
41
  XP_PER_MESSAGE = 10 # 100k messages = 1M exp = lvl 100
@@ -60,6 +65,31 @@ community_global_df_gradio = pd.DataFrame()
60
  test_merge = pd.read_csv("https://docs.google.com/spreadsheets/d/1C8aLqgCqLYcMiIFf-P_Aosaa03C_WLIB_UyqvjSdWg8/export?format=csv&gid=0")
61
 
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  @bot.event
64
  async def on_ready():
65
  try:
@@ -67,6 +97,22 @@ async def on_ready():
67
  await asyncio.sleep(1.1)
68
  print(f'Logged in as {bot.user.name}')
69
  print(f"XP_PER_MESSAGE: {XP_PER_MESSAGE}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
  """import data from google sheets -> HF Space df (doesn't make API call this way, as it's read-only)"""
72
  global_df = test_merge
@@ -466,7 +512,6 @@ async def add_exp(member_id):
466
 
467
  @bot.event
468
  async def on_message(message):
469
- global global_df
470
  org_link = "https://huggingface.co/organizations/discord-community/share/wPKRAHYbAlaEaCxUxcqVyaaaeZcYagDvqc"
471
  invite_message = "Click to join our community org on the HF Hub!"
472
  try:
@@ -478,109 +523,8 @@ async def on_message(message):
478
  # add check for verification
479
  if message.content.find("!help") != -1:
480
  await message.channel.send(
481
- "To verify your πŸ€— account, message me '!auth <TOKEN>' using your API token found here: https://huggingface.co/settings/token"
482
- )
483
- if message.content.startswith('!auth'):
484
- await asyncio.sleep(3)
485
- lunar = bot.get_user(811235357663297546)
486
- token = message.content.split()[-1].strip()
487
- try:
488
- user = HfApi().whoami(token)
489
- except HTTPError as e:
490
- await message.channel.send(f"Error occured when trying to authenticate. Likely invalid API Token. {e}")
491
- token = "abc" # reset right after we use to be safe
492
-
493
- if user['type'] == 'org':
494
- await message.channel.send(
495
- "Authentication failed because you tried to authenticate with an organization's API token. Please authenticate with your User API token instead."
496
- )
497
- return
498
-
499
- try:
500
- server = bot.get_guild(879548962464493619)
501
- #role = discord.utils.get(server.roles, name="verified")
502
- role = server.get_role(900063512829755413)
503
- member = server.get_member(message.author.id)
504
- verified_date = datetime.now().strftime("%m/%d/%Y, %H:%M:%S")
505
- likes = 0
506
- models = 0
507
- datasets = 0
508
- spaces = 0
509
- discussions = 0
510
- papers = 0
511
- upvotes = 0
512
- # important!-----------------------------------------------------------------------------
513
- # In order to add verification to a discord account, some important checks must ALL pass:
514
- # 1. Discord account should not already have verified role.
515
- # 2. hf_user_name should not already exist in the dataframe.
516
- # -----> If it does, it means we are trying to link 1 HF account to multiple discord accounts. 1->many is disallowed.
517
-
518
- # check if the member has the verified role (prevent duplicate entries in google sheet)
519
- # if users want to change discord / HF accounts, we can deal with that manually
520
- if role in member.roles:
521
- await message.channel.send(f"{member} already has has the '{role}' role and is already verified! To change discord accounts or HF accounts, contact <@811235357663297546> or adam@huggingface.co")
522
- return
523
-
524
- # check if hf_user_name in dataframe:
525
- if user['name'] in global_df['hf_user_name'].values:
526
- await message.channel.send(f"The HF account {user['name']} is already verified! To change discord accounts or HF accounts, contact <@811235357663297546> or adam@huggingface.co")
527
- return
528
-
529
- # check if discord_user_id in dataframe:
530
- altered_member_id = "L" + str(member.id) + "L"
531
- if altered_member_id in global_df['discord_user_id'].values:
532
-
533
- hf_user_name = global_df.loc[global_df['discord_user_id'] == altered_member_id, 'hf_user_name'].iloc[0]
534
-
535
- if pd.isnull(hf_user_name) or hf_user_name == 'n/a':
536
- # empty (no link created yet between discord_user_id and hf_user_name) so we can update
537
- global_df.loc[global_df['discord_user_id'] == altered_member_id, 'hf_user_name'] = user['name']
538
- global_df.loc[global_df['discord_user_id'] == altered_member_id, 'verified_date'] = verified_date
539
- await member.add_roles(role)
540
- if role in member.roles:
541
- print(f"Updated hf_user_name for id {member.id} | discord_user_name {member} | hf_user_name {user['name']}")
542
- await message.channel.send(f"Verification successful! [{member} <---> {user['name']}] πŸ€— {org_link} {invite_message}")
543
- await lunar.send(f"Verification successful! [{member} <---> {user['name']}] \nπŸ€— {org_link} {invite_message}")
544
- print(f"Verification successful! [{member} <---> {user['name']}] πŸ€—")
545
- return
546
- else:
547
- await message.channel.send(f"The Discord account {member} is already verified! To change discord accounts or HF accounts, contact <@811235357663297546> or adam@huggingface.co")
548
- await lunar.send(f"The Discord account {member} is already verified! To change discord accounts or HF accounts, contact <@811235357663297546> or adam@huggingface.co")
549
- print(f"The Discord account {member} is already verified! To change discord accounts or HF accounts, contact <@811235357663297546> or adam@huggingface.co")
550
- return
551
- except Exception as e:
552
- print(f"verification Error: {e}")
553
-
554
- # -----------------------------------------------------------------------------------------
555
- # If creating new record (edge case)
556
- xp = 10
557
- discord_exp = "L10L"
558
- hub_exp = "L0L"
559
- total_exp = "L10L"
560
- current_level = calculate_level(xp)
561
-
562
- row_data = [altered_member_id,
563
- member.name,
564
- discord_exp,
565
- current_level,
566
- user['name'],
567
- "L0L",
568
- hub_exp,
569
- total_exp,
570
- verified_date,
571
- likes,
572
- models,
573
- datasets,
574
- spaces,
575
- discussions,
576
- papers,
577
- upvotes]
578
-
579
- global_df.loc[len(global_df.index)] = row_data
580
- await member.add_roles(role)
581
- if role in member.roles:
582
- print(f"New record created for {member}")
583
- print("------------------------------------------------------------------------")
584
  await bot.process_commands(message)
585
  except Exception as e:
586
  print(f"on_message Error: {e}")
@@ -860,6 +804,85 @@ def create_plot(username, year):
860
 
861
  return fig
862
  #-------------------------------------------------------------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
 
864
 
865
  demo = gr.Blocks()
@@ -898,6 +921,28 @@ with demo:
898
  gr.Markdown("# πŸ“ˆ How to earn Experience!")
899
  with gr.Row():
900
  gr.DataFrame(get_data2, every=5, interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
901
  with gr.TabItem("πŸ“ˆ Activity Heatmap", elem_id="activity-heatmap", id=1):
902
  with gr.Row():
903
  username_input = gr.Textbox(label="Enter Username")
 
1
+ import os
2
+ import re
3
  import csv
 
4
  import json
5
+ import time
6
+ import random
7
+ import asyncio
8
+ import discord
9
  import logging
 
10
  import os.path
11
+ import secrets
12
+ import gspread
13
+ import datetime
14
+ import requests
15
  import threading
 
 
 
 
16
  import gradio_client
17
+
18
  import numpy as np
19
  import pandas as pd
20
+ import gradio as gr
21
  import plotly.graph_objects as go
22
 
23
+ from tabulate import tabulate
24
  from requests import HTTPError
25
+ from gradio_client import Client
 
26
  from discord import Color, Embed
27
+ from discord.ui import Button, View
28
  from discord.ext import commands, tasks
29
+ from datetime import datetime, timedelta
30
+ from apscheduler.executors.pool import ThreadPoolExecutor
31
  from gspread_formatting.dataframe import format_with_dataframe
32
+ from apscheduler.schedulers.background import BackgroundScheduler
33
+ from gspread_dataframe import get_as_dataframe, set_with_dataframe
34
  from huggingface_hub import HfApi, list_liked_repos, list_metrics, list_models
 
 
 
35
 
36
  DISCORD_TOKEN = os.environ.get("DISCORD_TOKEN", None)
37
  intents = discord.Intents.all()
38
  bot = commands.Bot(command_prefix='!', intents=intents)
39
 
40
+ GRADIO_APP_URL = "https://huggingface.co/spaces/discord-community/LevelBot"
41
+ # Dictionary to store user IDs and their corresponding unique strings
42
+ user_tokens = {}
43
+
44
 
45
  """"""
46
  XP_PER_MESSAGE = 10 # 100k messages = 1M exp = lvl 100
 
65
  test_merge = pd.read_csv("https://docs.google.com/spreadsheets/d/1C8aLqgCqLYcMiIFf-P_Aosaa03C_WLIB_UyqvjSdWg8/export?format=csv&gid=0")
66
 
67
 
68
+ class DMButton(Button):
69
+ def __init__(self, label, style):
70
+ super().__init__(label=label, style=style)
71
+
72
+ async def callback(self, interaction: discord.Interaction):
73
+ # await interaction.user.send(self.message) # this is for DMs, but users may have DMs disabled
74
+ user_id = interaction.user.id
75
+ if int(user_id) in user_tokens:
76
+ del user_tokens[int(user_id)] # always delete all past tokens for a given user when creating new link
77
+ unique_string = generate_unique_string()
78
+ user_tokens[user_id] = unique_string
79
+ unique_link = f"<{GRADIO_APP_URL}?user_id={user_id}&token={unique_string}>"
80
+ message = f"Login link generated! To complete the verification process:\n- 1 Visit this link,\n- 2 click the 'πŸ€—Sign in with Hugging Face' button\n\n{unique_link}"
81
+ await interaction.response.send_message(message, ephemeral=True)
82
+
83
+
84
+ @bot.command(name='sendbutton')
85
+ async def send_button(ctx):
86
+ if ctx.author.id == 811235357663297546:
87
+ button = DMButton(label="Verify Discord Account", style=discord.ButtonStyle.primary)
88
+ view = View(timeout=None)
89
+ view.add_item(button)
90
+ await ctx.send("Click the button below to generate your verification link:",view=view) #
91
+
92
+
93
  @bot.event
94
  async def on_ready():
95
  try:
 
97
  await asyncio.sleep(1.1)
98
  print(f'Logged in as {bot.user.name}')
99
  print(f"XP_PER_MESSAGE: {XP_PER_MESSAGE}")
100
+
101
+ channel = bot.get_channel(932563860597121054)
102
+ if channel:
103
+ try:
104
+ message = await channel.fetch_message(1269917762327674974)
105
+ if message:
106
+ button = DMButton(label="Verify Discord Account", style=discord.ButtonStyle.primary)
107
+ view = View(timeout=None)
108
+ view.add_item(button)
109
+ await message.edit(view=view)
110
+ print("message edited")
111
+ except discord.NotFound:
112
+ print(f"Message with ID {KNOWN_MESSAGE_ID} not found.")
113
+ except discord.HTTPException as e:
114
+ print(f"Failed to fetch message with ID {KNOWN_MESSAGE_ID}: {e}")
115
+
116
 
117
  """import data from google sheets -> HF Space df (doesn't make API call this way, as it's read-only)"""
118
  global_df = test_merge
 
512
 
513
  @bot.event
514
  async def on_message(message):
 
515
  org_link = "https://huggingface.co/organizations/discord-community/share/wPKRAHYbAlaEaCxUxcqVyaaaeZcYagDvqc"
516
  invite_message = "Click to join our community org on the HF Hub!"
517
  try:
 
523
  # add check for verification
524
  if message.content.find("!help") != -1:
525
  await message.channel.send(
526
+ "To verify your πŸ€— account, generate a login link in the verification channel! "
527
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  await bot.process_commands(message)
529
  except Exception as e:
530
  print(f"on_message Error: {e}")
 
804
 
805
  return fig
806
  #-------------------------------------------------------------------------------------------------------------------------------
807
+ async def add_verified_role_to_member(member, role):
808
+ await member.add_roles(role)
809
+
810
+
811
+ def add_verified_role(member, role):
812
+ loop = asyncio.get_event_loop()
813
+ loop.run_until_complete(add_role_to_member(member, role))
814
+
815
+
816
+ async def send_lunar_verification_logs(lunar, member, username)
817
+ org_link = "https://huggingface.co/organizations/discord-community/share/wPKRAHYbAlaEaCxUxcqVyaaaeZcYagDvqc"
818
+ invite_message = "Click to join our community org on the HF Hub!"
819
+ await lunar.send(f"Verification successful! [{member} <---> {username}] \nπŸ€— {invite_message}\n{org_link} ")
820
+
821
+ def send_lunar_verification_logs_def(lunar, member, username)
822
+ loop = asyncio.get_event_loop()
823
+ loop.run_until_complete(send_lunar_verification_logs(lunar, member, username))
824
+
825
+ def verify_button(profile: gr.OAuthProfile | None, request: gr.Request) -> str:
826
+ url_str = str(request.url)
827
+ query_params = parse_qs(urlparse(url_str).query)
828
+ user_id = query_params.get('user_id', [None])[0]
829
+ token = query_params.get('token', [None])[0]
830
+
831
+ print(f"||| token:{token}||| user_id:{user_id}||| profile:{profile}||| user_tokens:{user_tokens}")
832
+
833
+ if user_id is None or token is None:
834
+ return "# ❌ Invalid link. Generate a new link [here](https://discord.com/channels/879548962464493619/900125909984624713) !"
835
+
836
+ if int(user_id) not in user_tokens or user_tokens[int(user_id)] != token:
837
+ return "# ❌ Invalid or expired link. Generate a new link [here](https://discord.com/channels/879548962464493619/900125909984624713) !"
838
+
839
+ if profile is None:
840
+ return f"# ❌ Not logged in with Hugging Face yet."
841
+
842
+ server = bot.get_guild(879548962464493619)
843
+ role = server.get_role(900063512829755413)
844
+ member = server.get_member(user_id)
845
+ verified_date = datetime.now().strftime("%m/%d/%Y, %H:%M:%S")
846
+ likes = 0
847
+ models = 0
848
+ datasets = 0
849
+ spaces = 0
850
+ discussions = 0
851
+ papers = 0
852
+ upvotes = 0
853
+
854
+ # do they have the verified role already?
855
+ if role in member.roles:
856
+ return (f" ❌ {member} already has has the '{role}' role! To change discord accounts or HF accounts, contact @lunarflu on discord or adam@huggingface.co")
857
+
858
+
859
+ # check if hf_user_name in dataframe:
860
+ if profile.username in global_df['hf_user_name'].values:
861
+ return (f"The HF account {profile.username} is already verified! To change discord accounts or HF accounts, contact @lunarflu or adam@huggingface.co")
862
+
863
+ # check if discord_user_id in dataframe:
864
+ lunar = bot.get_user(811235357663297546)
865
+ altered_member_id = "L" + str(member.id) + "L"
866
+ if altered_member_id in global_df['discord_user_id'].values:
867
+
868
+ hf_user_name = global_df.loc[global_df['discord_user_id'] == altered_member_id, 'hf_user_name'].iloc[0]
869
+
870
+ if pd.isnull(hf_user_name) or hf_user_name == 'n/a':
871
+ # empty (no link created yet between discord_user_id and hf_user_name) so we can update
872
+ global_df.loc[global_df['discord_user_id'] == altered_member_id, 'hf_user_name'] = profile.username
873
+ global_df.loc[global_df['discord_user_id'] == altered_member_id, 'verified_date'] = verified_date
874
+ add_verified_role(member, role)
875
+ if role in member.roles:
876
+ print(f"Updated hf_user_name for id {member.id} | discord_user_name {member} | hf_user_name {user['name']}")
877
+ return (f" βœ… Verification successful! [{member} <---> {profile.username}] πŸ€—\n{invite_message}\n{org_link} ")
878
+ send_lunar_verification_logs_def(lunar, member, profile.username)
879
+ print(f" βœ… Verification successful! [{member} <---> {profile.username}] πŸ€—")
880
+ else:
881
+ return (f" ❌ The Discord account {member} is already verified! To change discord accounts or HF accounts, contact @lunarflu or adam@huggingface.co")
882
+ print(f"The Discord account {member} is already verified! To change discord accounts or HF accounts, contact @lunarflu or adam@huggingface.co")
883
+
884
+ # Remove the token after successful verification
885
+ del user_tokens[int(user_id)]
886
 
887
 
888
  demo = gr.Blocks()
 
921
  gr.Markdown("# πŸ“ˆ How to earn Experience!")
922
  with gr.Row():
923
  gr.DataFrame(get_data2, every=5, interactive=False)
924
+ #------------------------------------------------------------------------------
925
+ with gr.TabItem(" Discord Verification", elem_id="verify-tab", id=2):
926
+ with gr.Row():
927
+ login_button = gr.LoginButton()
928
+ m1 = gr.Markdown()
929
+ demo.load(verify_button, inputs=None, outputs=m1)
930
+
931
+ def check_login_status():
932
+ try:
933
+ return login_button.get_session().get("oauth_info", None)
934
+ except AttributeError:
935
+ return None
936
+
937
+ def check_login_wrapper():
938
+ session = check_login_status()
939
+ if session is None:
940
+ return "Not logged in."
941
+ else:
942
+ return f"Logged in as {session.get('username', 'Unknown')}"
943
+
944
+ login_button.click(check_login_wrapper, inputs=None, outputs=m1)
945
+ #------------------------------------------------------------------------------
946
  with gr.TabItem("πŸ“ˆ Activity Heatmap", elem_id="activity-heatmap", id=1):
947
  with gr.Row():
948
  username_input = gr.Textbox(label="Enter Username")