2018-07-24 22:47:57 +02:00
|
|
|
import asyncio
|
2018-12-05 11:44:10 +01:00
|
|
|
import sys
|
2018-07-24 22:47:57 +02:00
|
|
|
|
2018-12-05 11:44:10 +01:00
|
|
|
import asyncpg
|
2018-07-24 22:47:57 +02:00
|
|
|
import discord
|
2018-12-05 11:44:10 +01:00
|
|
|
import logging
|
|
|
|
|
import os
|
2018-10-27 23:30:12 +02:00
|
|
|
import traceback
|
2018-07-24 22:47:57 +02:00
|
|
|
|
2018-09-01 19:12:33 +02:00
|
|
|
from pluralkit import db
|
2018-10-27 23:30:12 +02:00
|
|
|
from pluralkit.bot import commands, proxy, channel_logger, embeds
|
2018-07-24 22:47:57 +02:00
|
|
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO, format="[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s")
|
2018-09-15 14:52:24 +02:00
|
|
|
|
|
|
|
|
|
2019-03-07 16:29:46 +01:00
|
|
|
def connect_to_database(uri: str) -> asyncpg.pool.Pool:
|
|
|
|
|
return asyncio.get_event_loop().run_until_complete(db.connect(uri))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run(token: str, db_uri: str, log_channel_id: int):
|
|
|
|
|
pool = connect_to_database(db_uri)
|
2018-07-24 22:47:57 +02:00
|
|
|
|
2018-10-27 23:30:12 +02:00
|
|
|
async def create_tables():
|
|
|
|
|
async with pool.acquire() as conn:
|
|
|
|
|
await db.create_tables(conn)
|
2018-07-24 22:47:57 +02:00
|
|
|
|
2018-10-27 23:30:12 +02:00
|
|
|
asyncio.get_event_loop().run_until_complete(create_tables())
|
2018-07-24 22:47:57 +02:00
|
|
|
|
2018-10-27 22:00:41 +02:00
|
|
|
client = discord.Client()
|
2018-10-27 23:30:12 +02:00
|
|
|
logger = channel_logger.ChannelLogger(client)
|
|
|
|
|
|
2018-10-27 22:00:41 +02:00
|
|
|
@client.event
|
|
|
|
|
async def on_ready():
|
|
|
|
|
print("PluralKit started.")
|
|
|
|
|
print("User: {}#{} (ID: {})".format(client.user.name, client.user.discriminator, client.user.id))
|
|
|
|
|
print("{} servers".format(len(client.guilds)))
|
|
|
|
|
print("{} shards".format(client.shard_count or 1))
|
|
|
|
|
|
2018-11-08 16:43:09 +01:00
|
|
|
await client.change_presence(activity=discord.Game(name="pk;help"))
|
|
|
|
|
|
2018-10-27 22:00:41 +02:00
|
|
|
@client.event
|
|
|
|
|
async def on_message(message: discord.Message):
|
|
|
|
|
# Ignore messages from bots
|
2018-07-24 22:47:57 +02:00
|
|
|
if message.author.bot:
|
|
|
|
|
return
|
2018-09-01 19:16:42 +02:00
|
|
|
|
2018-10-27 22:00:41 +02:00
|
|
|
# Grab a database connection from the pool
|
|
|
|
|
async with pool.acquire() as conn:
|
|
|
|
|
# First pass: do command handling
|
|
|
|
|
did_run_command = await commands.command_dispatch(client, message, conn)
|
|
|
|
|
if did_run_command:
|
2018-09-15 14:52:24 +02:00
|
|
|
return
|
2018-07-24 22:47:57 +02:00
|
|
|
|
2018-10-27 22:00:41 +02:00
|
|
|
# Second pass: do proxy matching
|
2018-11-30 20:39:10 +01:00
|
|
|
await proxy.try_proxy_message(conn, message, logger, client.user)
|
2018-10-27 23:30:12 +02:00
|
|
|
|
|
|
|
|
@client.event
|
|
|
|
|
async def on_raw_message_delete(payload: discord.RawMessageDeleteEvent):
|
|
|
|
|
async with pool.acquire() as conn:
|
|
|
|
|
await proxy.handle_deleted_message(conn, client, payload.message_id, None, logger)
|
|
|
|
|
|
|
|
|
|
@client.event
|
|
|
|
|
async def on_raw_bulk_message_delete(payload: discord.RawBulkMessageDeleteEvent):
|
|
|
|
|
async with pool.acquire() as conn:
|
|
|
|
|
for message_id in payload.message_ids:
|
|
|
|
|
await proxy.handle_deleted_message(conn, client, message_id, None, logger)
|
|
|
|
|
|
|
|
|
|
@client.event
|
|
|
|
|
async def on_raw_reaction_add(payload: discord.RawReactionActionEvent):
|
|
|
|
|
if payload.emoji.name == "\u274c": # Red X
|
|
|
|
|
async with pool.acquire() as conn:
|
|
|
|
|
await proxy.try_delete_by_reaction(conn, client, payload.message_id, payload.user_id, logger)
|
|
|
|
|
|
|
|
|
|
@client.event
|
|
|
|
|
async def on_error(event_name, *args, **kwargs):
|
2019-03-07 16:29:46 +01:00
|
|
|
# Print it to stderr
|
|
|
|
|
logging.getLogger("pluralkit").exception("Exception while handling event {}".format(event_name))
|
|
|
|
|
|
|
|
|
|
# Then log it to the given log channel
|
|
|
|
|
# TODO: replace this with Sentry or something
|
2018-10-27 23:30:12 +02:00
|
|
|
if not log_channel_id:
|
2018-09-15 14:52:24 +02:00
|
|
|
return
|
2019-03-07 16:29:46 +01:00
|
|
|
log_channel = client.get_channel(log_channel_id)
|
2018-10-27 23:30:12 +02:00
|
|
|
|
|
|
|
|
# If this is a message event, we can attach additional information in an event
|
|
|
|
|
# ie. username, channel, content, etc
|
|
|
|
|
if args and isinstance(args[0], discord.Message):
|
|
|
|
|
message: discord.Message = args[0]
|
|
|
|
|
embed = embeds.exception_log(
|
|
|
|
|
message.content,
|
|
|
|
|
message.author.name,
|
|
|
|
|
message.author.discriminator,
|
|
|
|
|
message.author.id,
|
|
|
|
|
message.guild.id if message.guild else None,
|
|
|
|
|
message.channel.id
|
2018-08-22 19:50:32 +02:00
|
|
|
)
|
2018-10-27 23:30:12 +02:00
|
|
|
else:
|
|
|
|
|
# If not, just post the string itself
|
|
|
|
|
embed = None
|
|
|
|
|
|
|
|
|
|
traceback_str = "```python\n{}```".format(traceback.format_exc())
|
2018-11-13 14:01:24 +01:00
|
|
|
if len(traceback.format_exc()) >= (2000 - len("```python\n```")):
|
|
|
|
|
traceback_str = "```python\n...{}```".format(traceback.format_exc()[- (2000 - len("```python\n...```")):])
|
2018-10-27 23:30:12 +02:00
|
|
|
await log_channel.send(content=traceback_str, embed=embed)
|
2019-03-07 16:29:46 +01:00
|
|
|
client.run(token)
|