lunarflu's picture
lunarflu HF staff
disable notification triggers for now, fix monday
568a224 verified
raw
history blame
9.96 kB
import discord
import threading
import os
import gradio as gr
from discord.ext import commands
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
import aiojobs
import asyncio
from datetime import datetime, timedelta
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.schedulers.background import BackgroundScheduler
DISCORD_TOKEN = os.getenv('DISCORD_TOKEN')
SLACK_BOT_TOKEN = os.getenv('BOT_USER_OAUTH_TOKEN_HF')
# real = os.getenv('SLACK_CHANNEL_ID_HF')
# test = 'C07B4KNU5BQ'
SLACK_CHANNEL_ID = os.getenv('SLACK_CHANNEL_ID_HF')
SLACK_CHANNEL_ID_TEST = 'C07B4KNU5BQ'
# 1259415803879751700 = test forum
# 1019883044724822016 = ask for help
ASK_FOR_HELP_CHANNEL_ID = 1019883044724822016
GRADIO_CHANNEL_ID = 1025174734427656283
ARGILLA_HELP_CHANNEL_ID = 1253640751481356330
DATA_DISCUSSIONS_CHANNEL_ID = 1217179426002047076
TRIGGERS = {
("discord bot",): "<@U051DB2754M>", # adam
("autotrain",): "<@U01E3LEC2N7>", # abhishek
("auto train",): "<@U01E3LEC2N7>", # abhishek
("competition",): "<@U01E3LEC2N7>", # abhishek
("competitions",): "<@U01E3LEC2N7>", # abhishek
("text to speech",): "<@U039C2GANMV>", # VB
("tts",): "<@U039C2GANMV>", # VB
("asr",): "<@U039C2GANMV>", # VB
("musicgen",): "<@U039C2GANMV>", # VB
("whisper",): "<@U039C2GANMV>", # VB
("speech recognition",): "<@U039C2GANMV>", # VB
("bark",): "<@U039C2GANMV>", # VB
("sentence-transformers",): "<@U04E4DNPWG7>", # tom aarsen
("sentence_transformers",): "<@U04E4DNPWG7>", # tom aarsen
("setfit",): "<@U04E4DNPWG7>", # tom aarsen
("sentence transformers",): "<@U04E4DNPWG7>", # tom aarsen
("argilla",): "<@U076B8C7G3E>", # david berenstein
("distilabel",): "<@U076B8C7G3E>", # david berenstein
("argilla",): "<@U0766H30T7F>", # natalia elvira
("dataset",): "<@U0766H30T7F>", # natalia elvira
("docs",): "<@U02DATT4C5B>", # steven liu
("documentation",): "<@U02DATT4C5B>", # steven liu
("gradio",): "<@U02NMK75F1V>", # abubakar abid
("gradio",): "<@U04FLGQ26PQ>", # yuvraj sharma
("argilla",): "<@U076MF65WEM>", # sara han diaz lorenzo
("distilabel",): "<@U076MF65WEM>", # sara han diaz lorenzo
("argilla",): "<@U0765RENPNZ>", # sara han diaz lorenzo
("distilabel",): "<@U0765RENPNZ>", # sara han diaz lorenzo
("dataset", "feedback"): "<@U0768RCHCRY>", # ben burtenshaw
("distilabel",): "<@U0768QEN0LA>", # Gabriel Martín Blázquez
("distilabel",): "<@U076271MBUN>", # Agustín Piqueres
}
daily_pings = []
intents = discord.Intents.all()
intents.messages = True
bot = commands.Bot(command_prefix='!', intents=intents)
slack_client = WebClient(token=SLACK_BOT_TOKEN)
thread_mapping = {}
@bot.event
async def on_ready():
print(f'Logged in as {bot.user}')
@bot.event
async def on_message(message):
if message.author == bot.user:
return
# notification bot
print("on_message")
"""
huggingfolks_role = discord.utils.get(message.guild.roles, id=897376942817419265)
bots_role = discord.utils.get(message.guild.roles, id=1258328471609016341)
if huggingfolks_role not in message.author.roles: # no need for ping if we're already discussing
if bots_role not in message.author.roles: # bots shouldn't trigger pings for this
print(" not bot ")
content = message.content.lower()
for trigger, slack_mention in TRIGGERS.items():
if all(word in content for word in trigger):
daily_pings.append({
'author': str(message.author),
'content': message.content,
'channel': message.channel.name,
'url': message.jump_url,
'mention': slack_mention,
'trigger': trigger
})
print(f"daily pings:{daily_pings}")
break
"""
# Check if the message is in a thread
if isinstance(message.channel, discord.Thread):
discord_thread_id = message.channel.id
# Check if there's an existing Slack thread for this Discord thread
# (the only Slack threads created should be for forum channel threads, not just any thread)
if discord_thread_id in thread_mapping:
slack_thread_ts = thread_mapping[discord_thread_id]
# post to slack only if thread already exists
post_to_slack_forum_version(message, SLACK_CHANNEL_ID, message.content, message.author, thread_ts=slack_thread_ts)
await bot.process_commands(message)
@bot.event
async def on_thread_create(thread):
# (discord) must be the child thread of the CORRECT forum channel(s) (not just any thread, or any forum channel)
if isinstance(thread.parent, discord.ForumChannel) and thread.parent.id in {ASK_FOR_HELP_CHANNEL_ID, GRADIO_CHANNEL_ID, ARGILLA_HELP_CHANNEL_ID, DATA_DISCUSSIONS_CHANNEL_ID}:
discord_thread_id = thread.id
slack_thread_ts = post_to_slack_create_thread(
SLACK_CHANNEL_ID,
f"New forum thread started in {thread.parent.name} by {thread.owner}: *{thread.name}*\n"
f"{thread.jump_url}"
)
if slack_thread_ts:
thread_mapping[discord_thread_id] = slack_thread_ts
def post_to_slack_forum_version(message, channel, text, author, thread_ts=None):
if message.attachments:
for attachment in message.attachments:
attachment_url = attachment.url
text += f"\nAttachment: {attachment_url}"
text = f"{author}" + ": " + text
try:
response = slack_client.chat_postMessage(
channel=channel,
text=text,
thread_ts=thread_ts
)
return response['ts'] # Return the Slack message timestamp (thread ID)
except SlackApiError as e:
print(f"Error posting to Slack: {e.response['error']}")
return None
def post_to_slack_create_thread(channel, text, thread_ts=None):
try:
response = slack_client.chat_postMessage(
channel=channel,
text=text,
thread_ts=thread_ts,
unfurl_links=False,
unfurl_media=False
)
return response['ts'] # Return the Slack message timestamp (thread ID)
except SlackApiError as e:
print(f"Error posting to Slack: {e.response['error']}")
return None
@bot.command()
async def list_tags(ctx, forum_channel_id: int):
if ctx.author.id == 811235357663297546:
forum_channel = bot.get_channel(forum_channel_id)
if isinstance(forum_channel, discord.ForumChannel):
tags = forum_channel.available_tags
tag_list = [f"{tag.name} (ID: {tag.id})" for tag in tags]
await ctx.send(f'Available tags: {", ".join(tag_list)}')
# react with ✅ on slack if marked with solved tag on discord
SOLVED_TAG_IDS = {1026743978026094664, 1025179659215847575, 1263095032328753174, 1253641354312155208}
@bot.event
async def on_thread_update(before, after):
if isinstance(after.parent, discord.ForumChannel) and after.parent.id in {ASK_FOR_HELP_CHANNEL_ID, GRADIO_CHANNEL_ID, ARGILLA_HELP_CHANNEL_ID, DATA_DISCUSSIONS_CHANNEL_ID}:
before_tag_ids = {tag.id for tag in before.applied_tags}
after_tag_ids = {tag.id for tag in after.applied_tags}
added_tags = after_tag_ids - before_tag_ids
removed_tags = before_tag_ids - after_tag_ids
discord_thread_id = after.id
if discord_thread_id in thread_mapping:
slack_thread_ts = thread_mapping[discord_thread_id]
if any(tag_id in SOLVED_TAG_IDS for tag_id in added_tags):
react_to_slack_message(slack_thread_ts, 'white_check_mark')
if any(tag_id in SOLVED_TAG_IDS for tag_id in removed_tags):
unreact_to_slack_message(slack_thread_ts, 'white_check_mark')
def react_to_slack_message(thread_ts, emoji):
try:
response = slack_client.reactions_add(
channel=SLACK_CHANNEL_ID,
name=emoji,
timestamp=thread_ts
)
except SlackApiError as e:
print(f"Error reacting to Slack message: {e.response['error']}")
def unreact_to_slack_message(thread_ts, emoji):
try:
response = slack_client.reactions_remove(
channel=SLACK_CHANNEL_ID,
name=emoji,
timestamp=thread_ts
)
except SlackApiError as e:
print(f"Error removing reaction from Slack message: {e.response['error']}")
#----------------------------------------------------------------------------------------------
def send_daily_pings():
global daily_pings
if daily_pings:
print("sending daily pings...")
# combine into one message
combined_message = '\n'.join(f"{ping['mention']} (for the keyword -> '{ping['trigger']}')\nFrom {ping['author']} in channel #{ping['channel']}: {ping['content']}\n{ping['url']}" for ping in daily_pings)
response = slack_client.chat_postMessage(
channel=SLACK_CHANNEL_ID,
text=combined_message,
unfurl_links=False,
unfurl_media=False
)
daily_pings = [] # reset after posting
# pings -------------------------------------------------------------------------------------------
"""
executor = ThreadPoolExecutor(max_workers=1)
scheduler = BackgroundScheduler(executors={'default': executor})
scheduler.add_job(send_daily_pings, trigger='interval', days=1)
scheduler.start()
"""
# runs discord bot in thread = helps avoid blocking calls
def run_bot():
bot.run(DISCORD_TOKEN)
threading.Thread(target=run_bot).start()
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()