forked from rougeth/pybr2021-discord-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fe1c676
commit 70fc6ef
Showing
27 changed files
with
1,506 additions
and
928 deletions.
There are no files selected for viewing
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
worker: python pybr2021/bot.py | ||
worker: python bot.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,23 @@ | ||
# Robô no Discord da Python Brasil 2021 | ||
# Robô do Discord da Scipy Latin America 2021 | ||
|
||
### Fazendo o Bot Funcionar | ||
|
||
```bash | ||
$ poetry install | ||
$ poetry run python bot.py | ||
``` | ||
|
||
### Comandos disponíveis | ||
|
||
#### Config | ||
|
||
- `pybr!config roles` | ||
- Cria os roles/perfis | ||
- `pybr!config canais` | ||
- Cria as categories e os canais de texto e voz e atribui as permissões corretas | ||
|
||
### Adicionando novos canais e roles | ||
|
||
#### Roles | ||
Adicione uma tupla na lista [new_roles](https://github.com/rougeth/pybr2021-discord-bot/blob/main/pybr2021/bot.py#L50-L54), exemplo: | ||
|
||
```python | ||
new_roles = [ | ||
("root", discord.Permissions.all(), 90), | ||
("Organização", org_permissions, 80), | ||
("Voluntariado", None, 70), | ||
("Novo Role", None, 60), | ||
] | ||
``` | ||
- `scibot!config info`: - Retorna informações do canal | ||
- `scibot!config roles`: - Cria as roles descritas em src/roles.py | ||
- `scibot!config canais`: - Cria os canaos descritos em src/channels.py | ||
- `scibot!config reset-roles`: - Deleta roles criadas pelo bot. | ||
- `scibot!config reset-canais`: - Deleta canais criadas pelo bot. | ||
|
||
Os elementos da tupla devem ser, em ordem: | ||
1. Nome do novo perfil/role. | ||
2. As permissões do novo perfil. Deve ser uma instância de `discord.Permissions` ([doc](https://discordpy.readthedocs.io/en/stable/api.html?highlight=permissionoverwrite#discord.Permissions)) ou `None`. | ||
3. A posição do novo perfil em relação aos demais. Quanto maior o número, maior na hierarquia. | ||
|
||
|
||
#### Canais | ||
Para criar novos canais, a mudança é um pouco maior. Siga os exemplos no [próprio código](https://github.com/rougeth/pybr2021-discord-bot/blob/main/pybr2021/bot.py#L97-L143) e consulte a documentação do [discord.py](https://discordpy.readthedocs.io/). | ||
#### Agradecimentos | ||
|
||
Referências: | ||
- https://support.discord.com/hc/en-us/articles/214836687-Role-Management-101 | ||
Código totalmente baseado no bot do discord da Python Brasil. | ||
https://github.com/rougeth/pybr2021-discord-bot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
# snake.bot | ||
|
||
import asyncio | ||
import discord | ||
import logging | ||
import sentry_sdk | ||
import sys | ||
from decouple import config | ||
from discord.ext import commands | ||
from src.roles import ROLES, get_or_create_role, roles_msg | ||
from src.channels import CHANNELS, create_channel | ||
from src.icons import icon_check, icon_1, icon_2, icon_3, icon_time | ||
from src.helpers import get_destination | ||
|
||
logger = logging.getLogger('discord') | ||
log_level = logging.INFO | ||
logger.setLevel(log_level) | ||
log_formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s') | ||
terminal_handler = logging.StreamHandler() | ||
file_handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w') | ||
terminal_handler.setLevel(log_level) | ||
file_handler.setLevel(log_level) | ||
terminal_handler.setFormatter(log_formatter) | ||
file_handler.setFormatter(log_formatter) | ||
logger.addHandler(terminal_handler) | ||
logger.addHandler(file_handler) | ||
|
||
|
||
DISCORD_TOKEN = config("DISCORD_TOKEN") | ||
SENTRY_TOKEN = config("SENTRY_TOKEN", default=None) | ||
|
||
if SENTRY_TOKEN: | ||
sentry_sdk.init(SENTRY_TOKEN, traces_sample_rate=1.0) | ||
|
||
bot = commands.Bot(command_prefix="scibot!", intents=discord.Intents.all()) | ||
|
||
# bot.add_cog(cogs.Reminders(bot)) | ||
# bot.add_cog(cogs.Greetings(bot)) | ||
# bot.add_cog(cogs.Greetings2(bot)) | ||
# bot.add_cog(cogs.Schedules(bot)) | ||
|
||
|
||
@bot.event | ||
async def on_error(event, *args, **kwargs): | ||
"""Don't ignore the error, causing Sentry to capture it.""" | ||
logger.exception("Exception while handling event. event={event!r}, args={args!r}, kwargs={kwargs!r}") | ||
if SENTRY_TOKEN: | ||
_, e, traceback = sys.exc_info() | ||
sentry_sdk.capture_exception(e) | ||
logger.info(f"Exception sent to Sentry. e={e!r}") | ||
|
||
|
||
@bot.event | ||
async def on_message(message): | ||
if not message.author.bot and message.content.lower() == "ping": | ||
await message.channel.send("pong") | ||
await bot.process_commands(message) | ||
|
||
|
||
@bot.group(name="config", invoke_without_command=True) | ||
async def config_group(ctx, *args): | ||
await ctx.channel.send( | ||
"Comandos Disponíveis:\n" | ||
"**info**\n - Mostrar informações dos canais\n" | ||
"**roles**\n - Cria todos os roles necessários\n" | ||
"**canais**\n - Cria todos os canais necessários\n" | ||
"**reset-roles**\n - Deleta todos os roles criados pelo bot\n" | ||
"**reset-canais**\n - Deleta todos os canais criados pelo bot\n" | ||
) | ||
|
||
|
||
@config_group.command(name="info") | ||
@commands.has_role("Moderator") | ||
async def info(ctx: commands.Context): | ||
await ctx.channel.send( | ||
content=(f"Guild ID: `{ctx.guild.id}`\nChannel ID: `{ctx.channel.id}`\n") | ||
) | ||
|
||
|
||
@config_group.command(name="roles") | ||
@commands.has_role("Moderator") | ||
async def config_roles(ctx: commands.Context): | ||
logger.info("Configurando roles") | ||
tracking_message = await ctx.channel.send(roles_msg.format(icon_1, icon_2, icon_3)) | ||
|
||
roles = await ctx.guild.fetch_roles() | ||
roles = {role.name: role for role in roles} | ||
logger.info(f"{len(roles)} roles encontrados. roles={','.join(roles.keys())!r}") | ||
|
||
await tracking_message.edit(content=(roles_msg.format(icon_check, icon_2, icon_3))) | ||
|
||
logger.info("Criando roles") | ||
for role in ROLES: | ||
try: | ||
roles[role.name] = await get_or_create_role(name=role.name, guild=ctx.guild, | ||
permissions=role.permissions, colour=role.colour) | ||
logger.info(f"Role {role.name} created.") | ||
except Exception as e: | ||
logger.info(f"Problem while creating role {role.name}. Skipping it for now.") | ||
logger.exception(f"Exception sent to Sentry. e={e!r}") | ||
|
||
await tracking_message.edit(content=(roles_msg.format(icon_check, icon_check, icon_3))) | ||
|
||
logger.info("Configurando permissões") | ||
positions = {roles[role.name]: role.position for role in ROLES} | ||
positions[ctx.guild.me.top_role] = 999 | ||
await ctx.guild.edit_role_positions(positions) | ||
|
||
await tracking_message.edit(content=(roles_msg.format(icon_check, icon_check, icon_check))) | ||
|
||
|
||
@config_group.command(name="canais") | ||
@commands.has_role("Moderator") | ||
async def config_channels(ctx: commands.Context): | ||
|
||
track_message = await ctx.channel.send("""Criando Categorias e Canais""") | ||
|
||
for channel in CHANNELS: | ||
channel_message = await ctx.channel.send( | ||
"""Channel {} being created. {}""".format(channel.name, icon_time) | ||
) | ||
await create_channel(channel, ctx) | ||
await channel_message.edit( | ||
content=( | ||
"""Channel {} being created. {}""".format(channel.name, icon_check) | ||
) | ||
) | ||
|
||
await track_message.edit(content=("""Criando Categorias e Canais {}""".format(icon_check))) | ||
|
||
|
||
@bot.command(name="msg", brief="Send a msg to a channel [#channel] [msg]") | ||
@commands.has_role("Moderator") | ||
async def sendmsg(ctx, *args): | ||
|
||
if len(args) < 2: | ||
logger.warning("Missing destination channel and message") | ||
return | ||
|
||
destination, destination_type = get_destination(ctx, args[0]) | ||
|
||
if not destination: | ||
logger.warning( | ||
f"Destination not found. args={args!r}" | ||
) | ||
return | ||
|
||
message = " ".join(args[1:]) | ||
|
||
logger.info(f"Message sent. Destination={destination}, message={message}") | ||
await destination.send(message) | ||
|
||
|
||
@config_group.command(name="reset-canais") | ||
@commands.has_role("Moderator") | ||
async def reset_channels(ctx: commands.Context): | ||
guild = ctx.guild | ||
|
||
channels = await guild.fetch_channels() | ||
managed_channels = [channel.name for channel in CHANNELS] + [channel.category for channel in CHANNELS] | ||
managed_channels = list(set(managed_channels)) | ||
channels_to_be_deleted = [channel for channel in channels if channel.name in managed_channels] | ||
await asyncio.gather(*[ | ||
channel.delete() for channel in channels_to_be_deleted | ||
]) | ||
logger.info(f"Channels deleted: {channels_to_be_deleted}") | ||
|
||
|
||
@config_group.command(name="reset-roles") | ||
@commands.has_role("Moderator") | ||
async def reset_roles(ctx: commands.Context): | ||
guild = ctx.guild | ||
|
||
roles = await guild.fetch_roles() | ||
managed_roles = [role.name for role in ROLES] | ||
roles_to_be_deleted = [role for role in roles if role.name in managed_roles] | ||
await asyncio.gather(*[ | ||
role.delete() for role in roles_to_be_deleted | ||
]) | ||
logger.info(f"Roles deleted: {roles_to_be_deleted}") | ||
|
||
|
||
@bot.event | ||
async def on_ready(): | ||
print('Show is starting!') | ||
print('We have logged in as {0.user}'.format(bot)) | ||
|
||
|
||
if __name__ == '__main__': | ||
bot.run(DISCORD_TOKEN) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# snake.bot | ||
|
||
import discord | ||
from decouple import config | ||
DISCORD_TOKEN = config("DISCORD_TOKEN") | ||
client = discord.Client() | ||
|
||
|
||
@client.event | ||
async def on_ready(): | ||
print('We have logged in as {0.user}'.format(client)) | ||
|
||
|
||
@client.event | ||
async def on_message(message): | ||
if message.author == client.user: | ||
return | ||
|
||
if message.content.startswith('$hello'): | ||
await message.channel.send('Hello!') | ||
|
||
|
||
if __name__ == '__main__': | ||
client.run(DISCORD_TOKEN) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import sentry_sdk | ||
from decouple import config | ||
|
||
sentry_sdk.init( | ||
config("SENTRY_TOKEN"), | ||
|
||
# Set traces_sample_rate to 1.0 to capture 100% | ||
# of transactions for performance monitoring. | ||
# We recommend adjusting this value in production. | ||
traces_sample_rate=1.0 | ||
) | ||
|
||
division_by_zero = 1 / 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import gspread | ||
from oauth2client.service_account import ServiceAccountCredentials | ||
|
||
scope = ['https://spreadsheets.google.com/feeds'] | ||
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope) | ||
client = gspread.authorize(creds) | ||
|
||
wks = client.open_by_key('1R0fYLV32a4TpDL0AxO-pxgjEI0XToRu9tU-lw0wL51A') | ||
|
||
all_emails = [] | ||
for i in range(3): | ||
worksheet = wks.get_worksheet(i) | ||
emails = worksheet.col_values(4)[1:] | ||
all_emails.extend(emails) | ||
|
||
assert "[email protected]" in all_emails |
Oops, something went wrong.