Skip to content

Commit

Permalink
team-cinnamon
Browse files Browse the repository at this point in the history
  • Loading branch information
asleep-cult committed Nov 17, 2020
1 parent 9f39f7e commit abb9be1
Show file tree
Hide file tree
Showing 32 changed files with 1,185 additions and 0 deletions.
1 change: 1 addition & 0 deletions team-cinnamon/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
website/scripts/jquery.js
23 changes: 23 additions & 0 deletions team-cinnamon/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import logging
import asyncio
from hata.ext.commands import setup_ext_commands
from importlib import import_module
from bot.client import Client
from bot.logger import Logger
from website.server import Server
from bot import constants
from database.database import Database

client = Client(constants.Auth.BOT_TOKEN)
setup_ext_commands(client, client._get_prefix)
client.server = Server(client=client)
client.database = Database(client=client)
client.logger = Logger(client=client)

logging.basicConfig(level=logging.DEBUG)

client.load_extension(import_module('.extensions.main', package='bot').Main())
client.load_extension(import_module('.extensions.fun', package='bot').Fun())
client.load_extension(import_module('.extensions.moderation', package='bot').Moderation())

client.login()
Empty file added team-cinnamon/bot/__init__.py
Empty file.
112 changes: 112 additions & 0 deletions team-cinnamon/bot/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import asyncio
import json
from logging import getLogger
from importlib import import_module
import hata
from hata.discord import client_core
from hata import discord
from hata.ext import commands
from database import utils
from . import constants

log = getLogger(__name__)


@hata.backend.KeepType(discord.Client)
class Client:
ready_event = asyncio.Event()
_asyncio_event_loop = asyncio.get_event_loop()
extensions = []
cached_guild_setups = {}

def load_extension(self, ext):
for method in ext._methods:
method._load(ext, self)
ext.__init__(self, *ext._args_, **ext._kwargs_)
self.extensions.append(ext)
return ext

async def _ready_set(self, _):
self._asyncio_event_loop.call_soon_threadsafe(self.ready_event.set)

async def _add_guild_on_create(self, _, guild):
asyncio.run_coroutine_threadsafe(self.get_fetch_or_create(guild.id), loop=self._asyncio_event_loop)

async def _get_guild_setups(self):
execute = """
SELECT * FROM guilds
"""
conn = self.database.conn
setups = await conn.fetch(execute)
for setup in setups:
self._add_guild_setup(dict(setup))

def _add_guild_setup(self, setup):
setup['guild_id'] = int(setup['guild_id'])
if setup['log_channel_id'] is not None:
setup['log_channel_id'] = int(setup['log_channel_id'])
if setup['muted_role_id'] is not None:
setup['muted_role_id'] = int(setup['muted_role_id'])
setup['disabled_commands'] = json.loads(setup['disabled_commands'])
setup['prefixes'] = json.loads(setup['prefixes'])
setup['level_roles'] = json.loads(setup['level_roles'])
setup['join_roles'] = json.loads(setup['join_roles'])
self.cached_guild_setups[setup['guild_id']] = setup

async def _create_guild_setups(self, get_after=True):
await self.database.wait_until_ready()
await self.ready_event.wait()
await self._get_guild_setups()
for guild in hata.discord.GUILDS:
if guild not in self.cached_guild_setups:
await utils.post_guild_setup(self, guild_id=guild)
await self._get_guild_setups()

def get_guild_setup(self, guild_id):
return self.cached_guild_setups.get(int(guild_id))

async def fetch_guild_setup(self, guild_id):
data = await utils.get_guild_setup(self, guild_id=guild_id)
if data:
self._add_guild_setup(data)
return data

async def get_fetch_or_create(self, guild_id):
data = self.get_guild_setup(guild_id)
if data:
return data
data = await self.fetch_guild_setup(guild_id)
if data:
return data
await utils.post_guild_setup(self, guild_id=guild_id)
data = await self.fetch_guild_setup(guild_id)
return data

async def _get_prefix(self, message):
if message.guild is None:
return '!'
data = await self.get_fetch_or_create(message.guild.id)
for prefix in data['prefixes']:
if message.content.startswith(prefix):
return prefix
return data['prefixes'][0]

def login(self, *, db=True, client=True, server=True):
if client:
self.events(self._ready_set, name='ready')
self.events(self._add_guild_on_create, name='guild_create')
self.start()
if server:
self._asyncio_event_loop.create_task(self.server.start())
if db:
self._asyncio_event_loop.create_task(self.database.connect())
if db and client:
self._asyncio_event_loop.create_task(self._create_guild_setups())
try:
log.debug('Logged in, starting asyncio event loop')
self._asyncio_event_loop.run_forever()
except KeyboardInterrupt:
log.debug('Received KeyboardInterrupt, stopping processes')
self.stop()
discord.client_core.KOKORO.stop()
exit()
16 changes: 16 additions & 0 deletions team-cinnamon/bot/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os
from typing import Dict, Tuple, Union
from hata import discord
import json


with open("config.json") as fp:
config = json.load(fp)

class Auth:
BOT_TOKEN: str = os.environ.get("BOT_TOKEN") or config.get("BOT_TOKEN")

class Colors:
RED = 0xe85133
GREEN = 0x2cc95e
BLUE = 0x2cb1c9
Empty file.
47 changes: 47 additions & 0 deletions team-cinnamon/bot/extensions/extension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# simple extensions built on classes

class Wrapped:
def __init__(self, func, load):
self.func = func
self._load = load

def __get__(self, instance, owner):
return self.func.__get__(instance, owner)
# binds the method to the instance ensuring that the
# `self` argument is always passed implicitly


def event(func):
def load(instance, client):
bound = func.__get__(instance, instance.__class__)
client.events(bound)
return Wrapped(func, load)


def command(func):
def load(instance, client):
bound = func.__get__(instance, instance.__class__)
client.commands(bound)
return Wrapped(func, load)


class ExtensionMeta(type):
def __new__(cls, name, bases, dict_):
klass = super().__new__(cls, name, bases, dict_)
klass._methods = []
for value in dict_.values():
if isinstance(value, Wrapped):
klass._methods.append(value)
return klass

def __call__(cls, *args, **kwargs):
obj = object.__new__(cls)
obj._args_ = args
obj._kwargs_ = kwargs
return obj


class Extension(metaclass=ExtensionMeta):
def remove_event(self, func):
self._methods.remove(func)
self.client.events.remove(func)
77 changes: 77 additions & 0 deletions team-cinnamon/bot/extensions/fun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from . import extension
from .. import utils, constants
from hata.discord import client_core
from hata import backend, discord
from time import time

class Fun(extension.Extension):
def __init__(self, client):
self.client = client
self.chat_grabbers = []

async def send_start_message(self, chat_grabber: utils.ChatGrabber):
embed = discord.Embed(color=constants.Colors.BLUE, description='Say hi, you\'re talking to people in **{}**'.format(chat_grabber.destination.guild))
await self.client.message_create(chat_grabber.origin, embed=embed)
embed = discord.Embed(color=constants.Colors.BLUE, description='Say hi, you\'re talking to people in **{}**'.format(chat_grabber.origin.guild))
await self.client.message_create(chat_grabber.destination, embed=embed)

async def send_stop_message(self, chat_grabber: utils.ChatGrabber):
embed = discord.Embed(color=constants.Colors.BLUE, description='You\'re no longer talking to people in **{}**'.format(chat_grabber.destination.guild))
await self.client.message_create(chat_grabber.origin, embed=embed)
embed = discord.Embed(color=constants.Colors.BLUE, description='You\'re no longer talking to people in **{}**'.format(chat_grabber.origin.guild))
await self.client.message_create(chat_grabber.destination, embed=embed)

async def create_chat(self, message):
if any(message.channel in (c.origin, c.destination) for c in self.chat_grabbers):
await self.client.message_create(message.channel, 'This channel is already chatting.')
return
try:
chat_grabber = next(c for c in self.chat_grabbers if not c.started)
chat_grabber.set_destination(message.channel)
await chat_grabber.start()
except StopIteration:
embed = discord.Embed(color=constants.Colors.BLUE, description='**Looking for someone who wants to talk to you**')
await self.client.message_create(message.channel, content=message.author.mention, embed=embed)
chat_grabber = utils.ChatGrabber(
self.client,
message.channel,
timeout=30,
start_hook=self.send_start_message,
stop_hook=self.send_stop_message,
destination_to_origin=True
)
self.chat_grabbers.append(chat_grabber)
backend.future_or_timeout(chat_grabber.destination_future, 30)
try:
await chat_grabber.destination_future
except TimeoutError:
embed = discord.Embed(color=constants.Colors.RED, description=':x: **No one wants to talk to you**')
await self.client.message_create(message.channel, content=message.author.mention, embed=embed)
self.chat_grabbers.remove(chat_grabber)
return

async def close_chat(self, message):
try:
chat_grabber = next(c for c in self.chat_grabbers if message.channel in (c.origin, c.destination))
except StopIteration:
await self.client.message_create(message.channel, 'This channel isn\'t chatting')
return
if message.author in chat_grabber.cancellation_votes:
await self.client.message_create(message.channel, 'You\'ve already voted to close this chat.')
return
users = list(filter((lambda key: time() - chat_grabber.users[key]['time'] < 30), chat_grabber.users))
if message.author.id not in users:
return
elif len(chat_grabber.cancellation_votes) >= len(users) - 1:
await chat_grabber.stop()
self.chat_grabbers.remove(chat_grabber)
else:
chat_grabber.cancellation_votes.append(message.author)
await self.client.message_create(message.channel, '{}/{} votes required to close this chat.'.format(chat_grabber.cancellation_votes, len(users)))

@extension.command
async def chat(self, client, message, arg=None):
if arg is None:
await self.create_chat(message)
elif arg.lower() == 'close':
await self.close_chat(message)
42 changes: 42 additions & 0 deletions team-cinnamon/bot/extensions/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from . import extension
from .. import constants
from .. import utils
from hata import discord
from database import utils as dutils


class Main(extension.Extension):
def __init__(self, client):
self.client = client

@extension.event
async def ready(self, client):
print('Logged in as {}'.format(self.client.full_name))

@extension.command
async def ping(self, client, message):
embed = discord.Embed(
color=constants.Colors.BLUE,
title='Pong',
description=':ping_pong: **WebSocket:**'
' {:.4f}ms'.format(self.client.gateway.latency * 1000)
)
await self.client.message_create(message.channel, embed=embed)

@extension.command
async def setlog(self, client, message, channel: discord.ChannelText):
data = await utils.hata_fut_from_asyncio_task(
self.client,
self.client.get_fetch_or_create(message.guild.id)
)
data['log_channel_id'] = channel.id
await utils.hata_fut_from_asyncio_task(
self.client,
dutils.update_guild_setup(
self.client,
guild_id=message.guild.id,
log_channel_id=channel.id
)
)
embed = discord.Embed(color=constants.Colors.GREEN, description='Changed log channel to {}'.format(channel.mention))
await self.client.message_create(message.channel, embed=embed)
Loading

0 comments on commit abb9be1

Please sign in to comment.