Notificação de publicações do TabNews no discord (como fiz essa integração) [discord.py]
Recentemente começei a fazer publicações frequentes no TabNews. Foi ai que tomei uma decisão muito importante.
Tenho uma comunidade de programadores chamada Code Company. E para divulgar ela fazia posts no instagram. Mas depois que conheci o TabNews, percebi o quanto o instagram é inferior no sentido de conteúdo.
A maioria das pessoas (inclusive eu), não estão necessariamente tão interessadas assim em entregar um "conteúdo de qualidade", ele só precisa ser superficial e interessante o suficiente para ganhar uma curtida. Dificilmente você vai ver gente focada em entregar algo profundo mesmo.
Mas vocês sabem que aqui não é assim. Você pode se aprofundar nos assuntos, gerar discussões (com pessoas realmente interessadas em agregar e não só em mandar um parabéns por exemplo, mas fazer críticas construtivas que realmente podem melhorar a publicação).
Isso acabou mudando meu pensamento. E estou disposto a criar um conteúdo denso que realmente agregue na vida dos desenvolvedores.
Mas chega de enrolação... Bora para o conteúdo!
Feature no discord
Bom... Montei uma feature nova no discord da comundade para divulgar os posts. E criei esse post, caso alguem tenha interesse em fazer algo parecido no seu servidor, ou acompanhar nossas postagens.
Vou começar mostrando o resultado final para vocês entederem do que estou falando:
O bot divulga o post e marca o cargo @Notificação TabNews
que pode ser adicionado aqui:
OBS... Também vou ensinar a fazer essa mensagem
Bora para o código!
Primeiro instale as bibliotecas:
pip install discord
pip install requests
pip install beautifulsoup4
pip install python-dotenv
Importação:
import discord
from discord.ext import commands as c
import requests
import os
from bs4 import BeautifulSoup
from dotenv import load_dotenv
Setando o Client do discord
load_dotenv()
bot = c.Bot(command_prefix=".", intents=discord.Intents.all())
reader = TabReader(bot=bot)
Para instanciar a classe TabReader, você deve passar o Client do discord (a variavel bot), e a string do seu perfil. Não passei porque por padrão ele escolhe o codecompanybrasil. Também pode passar o parametro link no caso de ter um link específico
Classe TabReader responsável por pegar o post
class TabReader:
def __init__(self, profile: str="codecompanybrasil", bot: c.Bot=None, link=None):
load_dotenv()
self.profile = f"https://www.tabnews.com.br/{profile}"
self.link = link
self.bot = bot
asyncio.run(TabReader.requesting())
@classmethod
async def requesting(cls):
self.req = requests.get(self.profile)
self.soup = BeautifulSoup(self.req.text, 'html.parser')
async def lastPost(self):
await TabReader.requesting()
elements = []
for element in self.soup.find_all("article"):
if element.find("a", {"class": "Link-sc-hrxz1n-0 bPBLTS"}):
elements.append(element.find("a"))
return f"https://www.tabnews.com.br{elements[0]['href']}"
async def sendPost(self):
if self.link:
self.last = self.link
else:
self.last = await self.lastPost()
guild = self.bot.get_guild(int(os.environ["CODE_COMPANY_ID"]))
channel = guild.get_channel(int(os.environ["TABNEWS_CHANNEL"]))
role = guild.get_role(int(os.environ["TABNEWS_ROLE"]))
m = await channel.send(f"{role.mention}\n{self.last}")
await m.publish()
Para o bot enviar de fato a mensagem eu criei um slash command no discord. E envio assim que termino de postar. De forma que, se eu mando:
/tabnews
- Ele pega o ultimo post que eu fiz
A não ser que o link seja especificado, desse jeito:
/tabnews link=(LINK)
Criando Slash Command
@bot.tree.command(name="tabnews", description="Atualiza o chat Tab News")
@discord.app_commands.describe(link="Especifica o link do post")
async def tabnews(interaction: discord.Interaction, link: str=""):
await interaction.response.defer(ephemeral=True)
tab = TabReader(bot=bot, link=link)
await tab.sendPost()
await interaction.followup.send("Post feito", ephemeral=True)
Fazer uma mensagem como aquela que as pessoas podem reagir e pegar o cargo. Exigem 2 passos
Primeiro você precisa enviar a mensagem, por isso recomendo que crie outro arquivo para não te confundir. Vou deixar o embed do mesmo jeito que enviei lá. Mas você pode fazer como bem entender.
enviarMensagem.py
import discord
from discord.ext import commands as c
import os
from dotenv import load_dotenv
load_dotenv()
bot = c.Bot(command_prefix=".", intents=discord.Intents.all())
@bot.event
async def on_ready():
guild = bot.get_guild(int(os.environ["CODE_COMPANY_ID"]))
cargo_channel = guild.get_channel(int(os.environ["CARGOS_CHANNEL"]))
embed = discord.Embed(
title="Quer o cargo de Tab News?",
description=f'''
Com o cargo de Tab News você será sempre notificado quando tiver posts novos no chat de {tabnews.mention}
Você tambem pode receber as mensagens no seu servidor se quando quiser! É só seguir o canal.
''',
color=discord.Color.dark_gray()
)
embed.set_image(url="https://i.pinimg.com/564x/f9/1a/20/f91a2081360598d2ce68d4a43dfd88a2.jpg")
b1 = discord.ui.Button(
label="Sim",
style=discord.ButtonStyle.success
)
b2 = discord.ui.Button(
label="Não",
style=discord.ButtonStyle.danger
)
view = discord.ui.View()
view.add_item(b1)
view.add_item(b2)
await cargo_channel.send(embed=embed, view=view)
bot.run(str(os.environ["TOKEN"])) #TOKEN do bot
Agora que enviamos a mensagem... Vamos voltar para o nosso arquivo principal e adicionar essas funções para que o botão funcione quando o bot estiver funcionando.
Mas para isso... Você vai precisar do ID da mensagem que acabou de enviar. Ative o modo de desenvolvedor no discord e copie clickando com o botão direito na mensagem e em Copiar ID
.
Ativando o botão e dando o cargo
@bot.event
async def on_ready():
async def givingRole(member, guild, idRole, dontRemove=False):
role = guild.get_role(int(idRole))
if not dontRemove:
for r in member.roles:
if r.id == role.id:
await member.remove_roles(role)
return False
await member.add_roles(role)
return True
async def controleGivingCargo(interaction: discord.Interaction, word, dontRemove=False):
guild = interaction.client.get_guild(int(os.environ["CODE_COMPANY_ID"]))
if dontRemove:
#Não remover
if await givingRole(interaction.user, guild, int(os.environ["TABNEWS_ROLE"]), dontRemove=True):
await interaction.response.send_message(f"Cargo {word} adicionado", ephemeral=True)
else:
await interaction.response.send_message(f"Cargo {word} retirado", ephemeral=True)
else:
#Remover
if await givingRole(interaction.user, guild, int(os.environ["TABNEWS_ROLE"])):
await interaction.response.send_message(f"Cargo {word} adicionado", ephemeral=True)
else:
await interaction.response.send_message(f"Cargo {word} retirado", ephemeral=True)
async def simCallbackTabNews(interaction: discord.Interaction):
await controleGivingCargo(interaction, "Tab news")
async def naoCallbackTabNews(interaction: discord.Interaction):
role = interaction.guild.get_role(int(os.environ["TABNEWS_ROLE"]))
for cargo in interaction.user.roles:
if cargo.id == role.id:
return await controleGivingCargo(interaction, "Tab news")
return await interaction.response.send_message("Sem cargo para retirar", ephemeral=True)
guild = bot.get_guild(int(os.environ["CODE_COMPANY_ID"]))
channel = guild.get_channel(int(os.environ["CARGOS_CHANNEL"]))
message = await channel.fetch_message(int(os.environ["TABNEWS_MESSAGE"]))
view = discord.ui.View.from_message(message)
view.timeout = None
for child in view.children:
print(child)
if str(child.label).lower() == "sim":
child.callback = simCallbackTabNews
elif str(child.label).lower() == "não":
child.callback = naoCallbackTabNews
await message.edit(view=view)
Agora basta ativar o bot
bot.run(str(os.environ["TOKEN"])) #TOKEN do bot
Lembrando que...
Eu fiz desse jeito com um monte de funções porque o Code Bot tem várias mensagens assim. Então com uma estrutura melhor fica mais fácil para adicionar novas mensagens ou editar as que estão ali.
Tanto que no bot ele está em um arquivo separado. Mas se você quiser deixar o código mais simples ou mais bagunçado mesmo, fica a seu critério.
Espero que tenha gostado ❤️
Para quem quiser participar da comunidade Code Company ou seguir o canal tabnews para acompanhar os nossos posts por aqui:
Tentei trazer um conteúdo bem completo para realmente ajudar a galera que tem um servidor no discord. Mas me diz...
O post foi útil para você?
Teve algo que eu esqueci de falar? Comenta ai!
Qual sua opinião da comparação que eu fiz do TabNews e instagram no começo do post? Comenta ai tambem!