From e86e87368e898425017846824d263016666864cc Mon Sep 17 00:00:00 2001 From: Gorialis Date: Tue, 16 Jan 2018 03:43:16 +0900 Subject: [PATCH] Transition to using YAML for configs --- .circleci/config.yml | 5 ++- .circleci/queuebot_config.py | 37 ------------------- .circleci/queuebot_config.yaml | 8 +++++ .flake8 | 2 ++ .gitignore | 1 + .travis.yml | 2 +- README.rst | 10 +++--- config.example.py | 36 ------------------- config.example.yaml | 58 ++++++++++++++++++++++++++++++ queuebot/bot.py | 9 ++--- queuebot/checks.py | 3 +- queuebot/cog.py | 1 + queuebot/cogs/emoji_list.py | 3 +- queuebot/cogs/queue/__init__.py | 44 +++++++++++------------ queuebot/cogs/queue/suggestion.py | 34 ++++++++---------- queuebot/configuration.py | 32 +++++++++++++++++ queuebot/default_config.yaml | 60 +++++++++++++++++++++++++++++++ requirements.txt | 1 + run.py | 5 +-- tests/init_test.py | 24 +++++++------ tests/travis_config.py | 37 ------------------- tests/travis_config.yaml | 8 +++++ 22 files changed, 238 insertions(+), 182 deletions(-) delete mode 100644 .circleci/queuebot_config.py create mode 100644 .circleci/queuebot_config.yaml delete mode 100644 config.example.py create mode 100644 config.example.yaml create mode 100644 queuebot/configuration.py create mode 100644 queuebot/default_config.yaml delete mode 100644 tests/travis_config.py create mode 100644 tests/travis_config.yaml diff --git a/.circleci/config.yml b/.circleci/config.yml index 8673fd8..489d962 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -68,7 +68,7 @@ jobs: name: run tests command: | . .venv/bin/activate - cp .circleci/queuebot_config.py config.py + cp .circleci/queuebot_config.yaml config.yaml export PYTHONPATH=$PYTHONPATH:$(pwd) pytest -vs @@ -163,7 +163,7 @@ jobs: name: run tests command: | . .venv/bin/activate - cp .circleci/queuebot_config.py config.py + cp .circleci/queuebot_config.yaml config.yaml export PYTHONPATH=$PYTHONPATH:$(pwd) pytest -vs @@ -214,5 +214,4 @@ workflows: build: jobs: - "build and install 3.6" - - "build and install 3.7" - "flake8" diff --git a/.circleci/queuebot_config.py b/.circleci/queuebot_config.py deleted file mode 100644 index 3ff55f8..0000000 --- a/.circleci/queuebot_config.py +++ /dev/null @@ -1,37 +0,0 @@ -token = "" - -pg_credentials = { - "host": "localhost", - "port": 5432, - "user": "qbotsql", - "database": "qbottest", - "timeout": 60 -} - -bot_log = 123456789012345678 # replace this with the ID of your bot logging channel - -admins = [234567890123456789, 345678901234567890] # add IDs of anyone who needs admin perms on this bot - -authority_roles = [456789012345678901, - 567890123456789012] # IDs of roles that have authority over this bot (Blob Police, etc) - -council_roles = [678901234567890123, - 789012345678901234] # IDs of roles considered Council (Blob Council, Blob Council Lite, etc) - -blob_guilds = [890123456789012345] # IDs of all guilds the bot updates an emoji list in - -approve_emoji_id = 901234567890123456 # ID of the approval emoji -deny_emoji_id = 876543210987654321 # ID of the denial emoji - -approve_emoji = "ok:901234567890123456" # representation of the approval emoji -deny_emoji = "notok:876543210987654321" # representation of the denial emoji - -suggestions_channel = 987654321098765432 # ID of the suggestions channel -council_queue = 98765432109876543 # ID of the council queue channel -approval_queue = 109876543210987654 # ID of the approval queue channel - -suggestions_log = 210987654321098765 # ID of the suggestions log channel -council_changelog = 321098765432109876 # ID of the council changelog channel - -required_difference = 5 # The majority required to reach a conclusive council vote. -required_votes = 15 # The minimum amount of votes required to make a conclusive council vote. diff --git a/.circleci/queuebot_config.yaml b/.circleci/queuebot_config.yaml new file mode 100644 index 0000000..88042da --- /dev/null +++ b/.circleci/queuebot_config.yaml @@ -0,0 +1,8 @@ +token: "" + +pg_credentials: + host: localhost + port: 5432 + user: "qbotsql" + database: "qbottest" + timeout: 60 diff --git a/.flake8 b/.flake8 index 162d775..da5f35b 100644 --- a/.flake8 +++ b/.flake8 @@ -13,6 +13,8 @@ exclude = .git, __pycache__, config.example.py, config.py, + config.example.yaml, + config.yaml, .env, .venv, env, diff --git a/.gitignore b/.gitignore index 4e9b4d3..777b7d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # QueueBot queuebot.log config.py +config.yaml /data # IDEA diff --git a/.travis.yml b/.travis.yml index f44549d..b8165c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ addons: before_script: - psql -c 'create database travis_testdb;' -U postgres - psql travis_testdb < schema.sql - - cp tests/travis_config.py config.py + - cp tests/travis_config.yaml config.yaml - "export PYTHONPATH=$PYTHONPATH:$(pwd)" install: "pip install -r requirements.txt" script: pytest -vs \ No newline at end of file diff --git a/README.rst b/README.rst index 8ac91fb..26e0bac 100644 --- a/README.rst +++ b/README.rst @@ -33,7 +33,7 @@ This project has a number of requirements for deployment: - ``git``, for acquiring ``discord.py@rewrite`` - A PostgreSQL >=9.6 server to store suggestion data -- A ``config.py`` file containing configuration data +- A ``config.yaml`` file containing configuration data - ``libuv`` to enable ``uvloop`` - Python requirements as in `requirements.txt `__ @@ -140,12 +140,12 @@ In Linux you can do this quickly by doing ``psql -d mydb -U myuser < schema.sql` Your setup for PostgreSQL is now done and you can log out of psql by typing ``\q``. -config.py -######### +config.yaml +########### -A ``config.py`` file should be placed in the project root, alongside ``run.py``. +A ``config.yaml`` file should be placed in the project root, alongside ``run.py``. -You can find an example of how to create this config by referencing `config.example.py `__. +You can find an example of how to create this config by referencing `config.example.yaml `__. libuv ##### diff --git a/config.example.py b/config.example.py deleted file mode 100644 index a085d9c..0000000 --- a/config.example.py +++ /dev/null @@ -1,36 +0,0 @@ -token = "mytoken" - -pg_credentials = { - "host": "localhost", - "port": 5432, - "user": "myuser", - "database": "mydb", - "password": "mypassword", - "timeout": 60 -} - -bot_log = 1234567890 # replace this with the ID of your bot logging channel - -admins = [1234567890, 9876543210] # add IDs of anyone who needs admin perms on this bot - -authority_roles = [1234567890, 9876543210] # IDs of roles that have authority over this bot (Blob Police, etc) - -council_roles = [1234567890, 9876543210] # IDs of roles considered Council (Blob Council, Blob Council Lite, etc) - -blob_guilds = [37428175841, ] # IDs of all guilds the bot updates an emoji list in - -approve_emoji_id = 1234567890 # ID of the approval emoji -deny_emoji_id = 1234567890 # ID of the denial emoji - -approve_emoji = "name:1234567890" # representation of the approval emoji -deny_emoji = "name:1234567890" # representation of the denial emoji - -suggestions_channel = 1234567890 # ID of the suggestions channel -council_queue = 1234567890 # ID of the council queue channel -approval_queue = 1234567890 # ID of the approval queue channel - -suggestions_log = 1234567890 # ID of the suggestions log channel -council_changelog = 1234567890 # ID of the council changelog channel - -required_difference = 5 # The majority required to reach a conclusive council vote. -required_votes = 15 # The minimum amount of votes required to make a conclusive council vote. diff --git a/config.example.yaml b/config.example.yaml new file mode 100644 index 0000000..55e5e2f --- /dev/null +++ b/config.example.yaml @@ -0,0 +1,58 @@ + +token: 'token' + +pg_credentials: + host: localhost + port: 5432 + user: 'myuser' + database: 'mydb' + password: 'mypassword' + timeout: 60 + + +# IDs of users who should have admin tool access (eval, reload, etc) +admins: + - 1234567890 + - 9876543210 + + +# Roles which possess extra authority over this bot (Blob Police, etc) +authority_roles: + - 1234567890 + - 9876543210 + + +# List of roles considered council (Blob Council, Council Lite, etc) +council_roles: + - 1234567890 + - 9876543210 + + +# ID of guilds in which the bot should update the emoji list +blob_guilds: + - 1234567890 + - 9876543210 + + +# Emoji info +approve_emoji_id: 1234567890 +deny_emoji_id: 9876543210 + +approve_emoji: 'green_tick:1234567890' +deny_emoji: 'red_tick:9876543210' + + +# Channel IDs +bot_log: 1234567890 + +suggestions_channel: 1234567890 +council_queue: 1234567890 +approval_queue: 1234567890 + +suggestions_log: 1234567890 +council_changelog: 1234567890 + + +# Voting parameters +required_difference: 5 # Majority required for this blob to move into the next stage +required_votes: 15 # Minimum amount of total votes before moving to next stage diff --git a/queuebot/bot.py b/queuebot/bot.py index 417ee06..a3fbd54 100644 --- a/queuebot/bot.py +++ b/queuebot/bot.py @@ -12,7 +12,6 @@ import discord from discord.ext import commands -import config from queuebot.cog import Cog logger = logging.getLogger(__name__) @@ -31,6 +30,8 @@ def __init__(self, *args, **kwargs): #: List of extension names to load. We store this because `self.extensions` is volatile during reload. self.to_load: typing.List[str] = None + self.config = kwargs.pop('config') + # Database connection to PostgreSQL self.db: Pool = kwargs.pop('db') @@ -50,18 +51,18 @@ async def on_ready(self): async def log(self, content, **kwargs) -> typing.Union[discord.Message, None]: timestamp = f'`[{datetime.datetime.utcnow().strftime("%H:%M")}]`' - channel = self.get_channel(config.bot_log) + channel = self.get_channel(self.config.bot_log) if not channel: return None return await channel.send(f'{timestamp} {content}', **kwargs) @property def admins(self): - return set([self.owner.id] + getattr(config, 'admins', [])) + return set([self.owner.id] + self.config.get('admins', [])) @property def council_roles(self): - return set(getattr(config, 'council_roles', [])) + return set(self.config.get('council_roles', [])) async def on_message(self, msg: discord.Message): # Ignore messages from bots. diff --git a/queuebot/checks.py b/queuebot/checks.py index 8164a22..e7c70b4 100644 --- a/queuebot/checks.py +++ b/queuebot/checks.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import config from discord.ext import commands @@ -14,7 +13,7 @@ def predicate(ctx: commands.Context) -> bool: if not ctx.guild: return False - return any(role.id in config.authority_roles for role in ctx.author.roles) + return any(role.id in ctx.bot.config.authority_roles for role in ctx.author.roles) return commands.check(predicate) diff --git a/queuebot/cog.py b/queuebot/cog.py index 853906c..e31cb59 100644 --- a/queuebot/cog.py +++ b/queuebot/cog.py @@ -2,4 +2,5 @@ class Cog: def __init__(self, bot: 'queuebot.bot.Queuebot'): self.bot = bot + self.config = bot.config self.db = bot.db diff --git a/queuebot/cogs/emoji_list.py b/queuebot/cogs/emoji_list.py index d2c7de1..01a2f55 100644 --- a/queuebot/cogs/emoji_list.py +++ b/queuebot/cogs/emoji_list.py @@ -3,7 +3,6 @@ import discord -from config import blob_guilds from queuebot.cog import Cog @@ -31,7 +30,7 @@ def format_emoji_list(guild: discord.Guild) -> List[str]: class EmojiList(Cog): async def on_guild_emojis_update(self, guild: discord.Guild, *_): - if guild.id not in blob_guilds: + if guild.id not in self.config.blob_guilds: return formatted = format_emoji_list(guild) diff --git a/queuebot/cogs/queue/__init__.py b/queuebot/cogs/queue/__init__.py index 1f815ea..bd46294 100644 --- a/queuebot/cogs/queue/__init__.py +++ b/queuebot/cogs/queue/__init__.py @@ -13,7 +13,6 @@ from PIL import Image from discord.ext import commands -import config from queuebot.checks import is_bot_admin, is_council from queuebot.cog import Cog from queuebot.cogs.queue.converters import SuggestionConverter, PartialSuggestionConverter, PublicQueueOrEmojiConverter @@ -31,17 +30,6 @@ logger = logging.getLogger(__name__) -def is_vote(emoji: discord.PartialEmoji, channel_id: int) -> bool: - """Checks whether an emoji is the approve or deny emoji and a channel is a suggestion processing channel.""" - if emoji.id is None: - return False # not a custom emoji - - if emoji.id not in [config.approve_emoji_id, config.deny_emoji_id]: - return False - - return channel_id in [config.council_queue, config.approval_queue] - - class BlobQueue(Cog): """Processing blob suggestions on the Blob Emoji server.""" @@ -54,8 +42,18 @@ def __init__(self, bot): self.voting_lock = asyncio.Lock() self.vs_lock = asyncio.Lock() + def is_vote(self, emoji: discord.PartialEmoji, channel_id: int) -> bool: + """Checks whether an emoji is the approve or deny emoji and a channel is a suggestion processing channel.""" + if emoji.id is None: + return False # not a custom emoji + + if emoji.id not in [self.config.approve_emoji_id, self.config.deny_emoji_id]: + return False + + return channel_id in [self.config.council_queue, self.config.approval_queue] + async def on_message(self, message: discord.Message): - if message.channel.id != config.suggestions_channel or message.author == self.bot.user: + if message.channel.id != self.config.suggestions_channel or message.author == self.bot.user: return async def respond(response): @@ -88,7 +86,7 @@ async def respond(response): except discord.HTTPException: await message.delete() - log = self.bot.get_channel(config.bot_log) + log = self.bot.get_channel(self.config.bot_log) logger.info(f"A suggestion by {message.author.id} was not processed due to lack of emoji or guild slots.") await log.send('Couldn\'t process suggestion due to having no free emoji or guild slots!') @@ -119,10 +117,10 @@ async def respond(response): animated = queue_file.filename.endswith(".gif") - queue = self.bot.get_channel(config.council_queue) + queue = self.bot.get_channel(self.config.council_queue) msg = await queue.send(emoji, file=queue_file) - await msg.add_reaction(config.approve_emoji) - await msg.add_reaction(config.deny_emoji) + await msg.add_reaction(self.config.approve_emoji) + await msg.add_reaction(self.config.deny_emoji) record = await self.db.fetchrow( """ @@ -153,7 +151,7 @@ async def respond(response): buffer.seek(0) file_hash = hashlib.sha256(buffer.read()).hexdigest() buffer.seek(0) - log = self.bot.get_channel(config.suggestions_log) + log = self.bot.get_channel(self.config.suggestions_log) await log.send( (f'**Submission #{record["idx"]}**\n\n:{name}: by `{name_id(message.author)}`\n' f'Filename: {attachment.filename}\nHash: `{file_hash}`').replace('@', '@\u200b'), @@ -165,7 +163,7 @@ async def respond(response): async def on_raw_reaction_add(self, emoji: discord.PartialEmoji, message_id: int, channel_id: int, user_id: int): - if user_id == self.bot.user.id or not is_vote(emoji, channel_id): + if user_id == self.bot.user.id or not self.is_vote(emoji, channel_id): return logger.debug('Received reaction add.') @@ -176,7 +174,7 @@ async def on_raw_reaction_add(self, emoji: discord.PartialEmoji, message_id: int async def on_raw_reaction_remove(self, emoji: discord.PartialEmoji, message_id: int, channel_id: int, user_id: int): - if user_id == self.bot.user.id or not is_vote(emoji, channel_id): + if user_id == self.bot.user.id or not self.is_vote(emoji, channel_id): return logger.debug('Received reaction remove.') @@ -227,7 +225,7 @@ async def approve(self, ctx, suggestion: SuggestionConverter, *, reason=None): reason = reason or None # do not push empty strings await suggestion.reset_votes() await suggestion.move_to_public_queue(who=ctx.author.id, reason=reason) - await self.bot.log(f"<:{config.approve_emoji}> Suggestion #{suggestion.idx} force approved by " + await self.bot.log(f"<:{self.config.approve_emoji}> Suggestion #{suggestion.idx} force approved by " f"{ctx.author.mention} ({ctx.author.id})\n" f"{'Reason: ' + reason if reason else 'No reason provided.'}") await ctx.send(f"Successfully moved #{suggestion.idx}.") @@ -239,7 +237,7 @@ async def deny(self, ctx, suggestion: SuggestionConverter, *, reason=None): logger.info('%s: Denying %s.', ctx.author, suggestion) reason = reason or None # do not push empty strings await suggestion.deny(who=ctx.author.id, reason=reason) - await self.bot.log(f"<:{config.deny_emoji}> Suggestion #{suggestion.idx} force denied by " + await self.bot.log(f"<:{self.config.deny_emoji}> Suggestion #{suggestion.idx} force denied by " f"{ctx.author.mention} ({ctx.author.id})\n" f"{'Reason: ' + reason if reason else 'No reason provided.'}") await ctx.send(f"Successfully denied #{suggestion.idx}.") @@ -306,7 +304,7 @@ def wait_check(msg): return - queue = self.bot.get_channel(config.approval_queue) + queue = self.bot.get_channel(self.config.approval_queue) vs_message = await queue.send(emote_sequence) for this_emoji in temp_emotes: diff --git a/queuebot/cogs/queue/suggestion.py b/queuebot/cogs/queue/suggestion.py index c535c32..573111e 100644 --- a/queuebot/cogs/queue/suggestion.py +++ b/queuebot/cogs/queue/suggestion.py @@ -5,14 +5,10 @@ import discord -import config - # Can these messages be set in the config? Or at least channels/mentions/whatever from queuebot.utils import SUBMITTER_NOT_FOUND, UPLOADED_EMOJI_NOT_FOUND, SUGGESTION_APPROVED, SUGGESTION_DENIED, \ name_id -from config import suggestions_channel, required_votes, required_difference - log = logging.getLogger(__name__) @@ -143,7 +139,7 @@ async def process_vote(self, vote_emoji: discord.PartialEmoji, vote_type: VoteTy ) # Calculate the column to modify depending on which emoji was reacted with. - approval = vote_emoji.id == config.approve_emoji_id + approval = vote_emoji.id == self.bot.config.approve_emoji_id vote_target = 'upvotes' if approval else 'downvotes' await self.db.execute( @@ -189,7 +185,7 @@ async def process_vote(self, vote_emoji: discord.PartialEmoji, vote_type: VoteTy async def delete_from_council_queue(self): """Deletes the voting message for this suggestion from the council queue.""" log.debug('Removing %s from council queue.', self) - council_queue = self.bot.get_channel(config.council_queue) + council_queue = self.bot.get_channel(self.bot.config.council_queue) # Delete the message in the council queue (cleanup). council_message = await council_queue.get_message(self.record['council_message_id']) @@ -224,16 +220,16 @@ async def move_to_public_queue(self, *, who=None, reason=None): await self.bot.log(UPLOADED_EMOJI_NOT_FOUND.format(action='move to PQ', suggestion=self.record)) return - changelog = self.bot.get_channel(config.council_changelog) - queue = self.bot.get_channel(config.approval_queue) + changelog = self.bot.get_channel(self.bot.config.council_changelog) + queue = self.bot.get_channel(self.bot.config.approval_queue) await changelog.send( - f'<:{config.approve_emoji}> moved to {queue.mention}: {emoji} (by <@{user_id}>)' + f'<:{self.bot.config.approve_emoji}> moved to {queue.mention}: {emoji} (by <@{user_id}>)' ) msg = await queue.send(emoji) - await msg.add_reaction(config.approve_emoji) - await msg.add_reaction(config.deny_emoji) + await msg.add_reaction(self.bot.config.approve_emoji) + await msg.add_reaction(self.bot.config.deny_emoji) await emoji.delete() await self.delete_from_council_queue() @@ -264,7 +260,7 @@ async def move_to_public_queue(self, *, who=None, reason=None): async def remove_from_public_queue(self): """Removes an entry from the public queue.""" - public_queue = self.bot.get_channel(config.approval_queue) + public_queue = self.bot.get_channel(self.bot.config.approval_queue) try: msg = await public_queue.get_message(self.record["public_message_id"]) except discord.NotFound: @@ -315,10 +311,10 @@ async def deny(self, *, who=None, reason=None, revoke=False): await self.update_inplace() - changelog = self.bot.get_channel(config.council_changelog) + changelog = self.bot.get_channel(self.bot.config.council_changelog) action = 'revoked' if revoke else 'denied' - await changelog.send(f'<:{config.deny_emoji}> {action}: {emoji} (by <@{user_id}>)') + await changelog.send(f'<:{self.bot.config.deny_emoji}> {action}: {emoji} (by <@{user_id}>)') await emoji.delete() await self.delete_from_council_queue() await self.delete_from_suggestions_channel() @@ -345,16 +341,16 @@ async def check_council_votes(self): upvotes = self.record['upvotes'] downvotes = self.record['downvotes'] - if upvotes + downvotes < required_votes: + if upvotes + downvotes < self.bot.config.required_votes: # Total number of votes doesn't meet the threshold, no point taking any further action. return - if upvotes - downvotes >= required_difference: + if upvotes - downvotes >= self.bot.config.required_difference: # Since we don't track internal queue/public queue votes separately, we'll have to reset the upvotes # and downvotes columns. await self.reset_votes() await self.move_to_public_queue() - elif downvotes - upvotes >= required_difference: + elif downvotes - upvotes >= self.bot.config.required_difference: await self.deny() async def delete_from_suggestions_channel(self): @@ -365,7 +361,7 @@ async def delete_from_suggestions_channel(self): log.debug('No suggestions_message_id associated with this suggestion.') return - channel = self.bot.get_channel(suggestions_channel) + channel = self.bot.get_channel(self.bot.config.suggestions_channel) try: message = await channel.get_message(message_id) @@ -374,7 +370,7 @@ async def delete_from_suggestions_channel(self): except discord.HTTPException: await self.bot.log( f"\N{WARNING SIGN} Failed to delete suggestion #{self.idx}'s message in " - f"<#{suggestions_channel}>." + f"<#{self.bot.config.suggestions_channel}>." ) log.exception("Failed to delete %s\'s suggestion message ID:", self) diff --git a/queuebot/configuration.py b/queuebot/configuration.py new file mode 100644 index 0000000..57f3052 --- /dev/null +++ b/queuebot/configuration.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +import os as _os + +from yaml import safe_load as _safe_load + +with open(_os.path.join(_os.path.dirname(__file__), "default_config.yaml"), "rb") as default_config_file: + default_config = _safe_load(default_config_file) + + +class Configuration: + __slots__ = ('_dict', ) + + def __init__(self, config_dict: dict): + self._dict = {**default_config, **config_dict} + + def __getattr__(self, item): + return self._dict.get(item) + + @property + def get(self): + return self._dict.get + + +def config_from_file(file_path: str): + with open(file_path, "rb") as config_file: + configuration = _safe_load(config_file) + + if isinstance(configuration, str): + configuration = {"token": configuration} + + return Configuration(configuration) diff --git a/queuebot/default_config.yaml b/queuebot/default_config.yaml new file mode 100644 index 0000000..cbd5b08 --- /dev/null +++ b/queuebot/default_config.yaml @@ -0,0 +1,60 @@ + +token: null + +pg_credentials: + host: localhost + port: 5432 + user: 'postgres' + database: 'db' + timeout: 60 + + +# IDs of users who should have admin tool access (eval, reload, etc) +admins: + - 69198249432449024 # FrostLuma#0005 /gh/FrostLuma + - 97104885337575424 # slice#4274 /gh/slice + - 122122926760656896 # devon#4089 /gh/Gorialis + + +# Roles which possess extra authority over this bot (Blob Police, etc) +authority_roles: + - 295476842935353345 # Blob Police + + +# List of roles considered council (Blob Council, Council Lite, etc) +council_roles: + - 294928463536586754 # Blob Council + - 300509002520068097 # Council Lite + + +# ID of guilds in which the bot should update the emoji list +blob_guilds: + - 272885620769161216 # Blob Emoji + - 356869031870988309 # Blob Emoji 2 + - 356876866952364032 # Blob Emoji 3 + - 356876897403011072 # Blob Emoji 4 + - 396144014128054275 # Blob Emoji 5 + + +# Emoji info +approve_emoji_id: 341056297921150976 +deny_emoji_id: 341056297703178242 + +approve_emoji: 'green_tick:341056297921150976' +deny_emoji: 'red_tick:341056297703178242' + + +# Channel IDs +bot_log: 382995510287663104 + +suggestions_channel: 295012914564169728 +council_queue: 294924110130184193 +approval_queue: 289847856033169409 + +suggestions_log: 382306839859036161 +council_changelog: 298920394751082507 + + +# Voting parameters +required_difference: 5 # Majority required for this blob to move into the next stage +required_votes: 15 # Minimum amount of total votes before moving to next stage diff --git a/requirements.txt b/requirements.txt index b5316e4..8848eb0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ asyncpg git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py uvloop pillow +PyYAML diff --git a/run.py b/run.py index df1e901..07ddbdf 100644 --- a/run.py +++ b/run.py @@ -7,7 +7,7 @@ import asyncpg import uvloop -import config +from queuebot.configuration import config_from_file from queuebot.bot import Queuebot @@ -30,6 +30,7 @@ async def main(): + config = config_from_file("config.yaml") while True: try: db = await asyncpg.create_pool(**config.pg_credentials) @@ -39,7 +40,7 @@ async def main(): else: break - bot = Queuebot(command_prefix='q!', db=db) + bot = Queuebot(command_prefix='q!', config=config, db=db) bot.discover_exts('queuebot/cogs') await bot.start(config.token) diff --git a/tests/init_test.py b/tests/init_test.py index abe6d95..364d774 100644 --- a/tests/init_test.py +++ b/tests/init_test.py @@ -7,7 +7,7 @@ import discord -import config +from queuebot.configuration import config_from_file from queuebot.bot import Queuebot if os.name != "nt": @@ -16,9 +16,11 @@ async def main(): + config = config_from_file("config.yaml") + db = await asyncpg.create_pool(**config.pg_credentials) - bot = Queuebot(command_prefix='q!', db=db) + bot = Queuebot(command_prefix='q!', config=config, db=db) bot.discover_exts('queuebot/cogs') @@ -47,12 +49,12 @@ async def main(): ) RETURNING idx """, - 123456789012345678, - 234567890123456789, - 345678901234567890, - "test", + 122122926760656896, + 294924538062569492, + 396521731440771085, + "blobsmile", datetime.datetime.utcnow(), - 456789012345678901, + 312640412474933248, False ) @@ -63,16 +65,16 @@ async def main(): suggestion = await Suggestion.get_from_id(idx) assert repr(suggestion) == \ - f"" + f"" queuecog = bot.get_cog("BlobQueue") - await queuecog.on_raw_reaction_add(discord.PartialEmoji(animated=False, name="ok", id=901234567890123456), - 234567890123456789, 98765432109876543, 234567890123456789) + await queuecog.on_raw_reaction_add(discord.PartialEmoji(animated=False, name="green_tick", id=341056297921150976), + 294924538062569492, 294924110130184193, 69198249432449024) await suggestion.update_inplace() assert repr(suggestion) == \ - f"" + f"" await bot.close() diff --git a/tests/travis_config.py b/tests/travis_config.py deleted file mode 100644 index 745888f..0000000 --- a/tests/travis_config.py +++ /dev/null @@ -1,37 +0,0 @@ -token = "" - -pg_credentials = { - "host": "localhost", - "port": 5432, - "user": "postgres", - "database": "travis_testdb", - "timeout": 60 -} - -bot_log = 123456789012345678 # replace this with the ID of your bot logging channel - -admins = [234567890123456789, 345678901234567890] # add IDs of anyone who needs admin perms on this bot - -authority_roles = [456789012345678901, - 567890123456789012] # IDs of roles that have authority over this bot (Blob Police, etc) - -council_roles = [678901234567890123, - 789012345678901234] # IDs of roles considered Council (Blob Council, Blob Council Lite, etc) - -blob_guilds = [890123456789012345] # IDs of all guilds the bot updates an emoji list in - -approve_emoji_id = 901234567890123456 # ID of the approval emoji -deny_emoji_id = 876543210987654321 # ID of the denial emoji - -approve_emoji = "ok:901234567890123456" # representation of the approval emoji -deny_emoji = "notok:876543210987654321" # representation of the denial emoji - -suggestions_channel = 987654321098765432 # ID of the suggestions channel -council_queue = 98765432109876543 # ID of the council queue channel -approval_queue = 109876543210987654 # ID of the approval queue channel - -suggestions_log = 210987654321098765 # ID of the suggestions log channel -council_changelog = 321098765432109876 # ID of the council changelog channel - -required_difference = 5 # The majority required to reach a conclusive council vote. -required_votes = 15 # The minimum amount of votes required to make a conclusive council vote. diff --git a/tests/travis_config.yaml b/tests/travis_config.yaml new file mode 100644 index 0000000..1988f3f --- /dev/null +++ b/tests/travis_config.yaml @@ -0,0 +1,8 @@ +token: "" + +pg_credentials: + host: localhost + port: 5432 + user: "postgres" + database: "travis_testdb" + timeout: 60