aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Xithrius <[email protected]>2021-07-31 00:16:08 -0700
committerGravatar GitHub <[email protected]>2021-07-31 00:16:08 -0700
commit74f0e8632468fb7995366ed4723aeb1f3f27c01b (patch)
treecfd6163777a0aee2dec97e3189f5722d0423d769
parentChange docstring (diff)
parentMerge pull request #790 from python-discord/Remove-user-input-images (diff)
Merge branch 'main' into feature/stackoverflow
-rw-r--r--bot/constants.py16
-rw-r--r--bot/exts/evergreen/avatar_modification/avatar_modify.py44
-rw-r--r--bot/exts/evergreen/issues.py6
-rw-r--r--bot/exts/evergreen/tic_tac_toe.py7
-rw-r--r--bot/exts/evergreen/trivia_quiz.py29
-rw-r--r--bot/exts/halloween/hacktoberstats.py8
-rw-r--r--bot/resources/evergreen/trivia_quiz.json318
-rw-r--r--bot/utils/checks.py5
8 files changed, 355 insertions, 78 deletions
diff --git a/bot/constants.py b/bot/constants.py
index 25545c04..0a3b874a 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -113,7 +113,6 @@ class Channels(NamedTuple):
off_topic_1 = 463035241142026251
off_topic_2 = 463035268514185226
community_bot_commands = int(environ.get("CHANNEL_COMMUNITY_BOT_COMMANDS", 607247579608121354))
- hacktoberfest_2020 = 760857070781071431
voice_chat_0 = 412357430186344448
voice_chat_1 = 799647045886541885
staff_voice = 541638762007101470
@@ -127,6 +126,7 @@ class Categories(NamedTuple):
media = 799054581991997460
staff = 364918151625965579
+codejam_categories_name = "Code Jam" # Name of the codejam team categories
class Client(NamedTuple):
name = "Sir Lancebot"
@@ -190,12 +190,14 @@ class Emojis:
dice_5 = "<:dice_5:755891608091885627>"
dice_6 = "<:dice_6:755891607680843838>"
- issue = "<:IssueOpen:629695470327037963>"
- issue_closed = "<:IssueClosed:629695470570307614>"
- pull_request = "<:PROpen:629695470175780875>"
- pull_request_closed = "<:PRClosed:629695470519713818>"
- pull_request_draft = "<:PRDraft:829755345425399848>"
- merge = "<:PRMerged:629695470570176522>"
+ # These icons are from Github's repo https://github.com/primer/octicons/
+ issue_open = "<:IssueOpen:852596024777506817>"
+ issue_closed = "<:IssueClosed:852596024739758081>"
+ issue_draft = "<:IssueDraft:852596025147523102>" # Not currently used by Github, but here for future.
+ pull_request_open = "<:PROpen:852596471505223781>"
+ pull_request_closed = "<:PRClosed:852596024732286976>"
+ pull_request_draft = "<:PRDraft:852596025045680218>"
+ pull_request_merged = "<:PRMerged:852596100301193227>"
number_emojis = {
1: "\u0031\ufe0f\u20e3",
diff --git a/bot/exts/evergreen/avatar_modification/avatar_modify.py b/bot/exts/evergreen/avatar_modification/avatar_modify.py
index 17f34ed4..bd324f67 100644
--- a/bot/exts/evergreen/avatar_modification/avatar_modify.py
+++ b/bot/exts/evergreen/avatar_modification/avatar_modify.py
@@ -9,7 +9,6 @@ from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
import discord
-from aiohttp import client_exceptions
from discord.ext import commands
from bot.bot import Bot
@@ -236,37 +235,6 @@ class AvatarModify(commands.Cog):
await self.send_pride_image(ctx, image_bytes, pixels, flag, option)
@prideavatar.command()
- async def image(self, ctx: commands.Context, url: str, option: str = "lgbt", pixels: int = 64) -> None:
- """
- This surrounds the image specified by the URL with a border of a specified LGBT flag.
-
- This defaults to the LGBT rainbow flag if none is given.
- The amount of pixels can be given which determines the thickness of the flag border.
- This has a maximum of 512px and defaults to a 64px border.
- The full image is 1024x1024.
- """
- option = option.lower()
- pixels = max(0, min(512, pixels))
- flag = GENDER_OPTIONS.get(option)
- if flag is None:
- await ctx.send("I don't have that flag!")
- return
-
- async with ctx.typing():
- try:
- async with self.bot.http_session.get(url) as response:
- if response.status != 200:
- await ctx.send("Bad response from provided URL!")
- return
- image_bytes = await response.read()
- except client_exceptions.ClientConnectorError:
- raise commands.BadArgument("Cannot connect to provided URL!")
- except client_exceptions.InvalidURL:
- raise commands.BadArgument("Invalid URL!")
-
- await self.send_pride_image(ctx, image_bytes, pixels, flag, option)
-
- @prideavatar.command()
async def flags(self, ctx: commands.Context) -> None:
"""This lists the flags that can be used with the prideavatar command."""
choices = sorted(set(GENDER_OPTIONS.values()))
@@ -283,12 +251,9 @@ class AvatarModify(commands.Cog):
root_aliases=("spookyavatar", "spookify", "savatar"),
brief="Spookify an user's avatar."
)
- async def spookyavatar(self, ctx: commands.Context, member: discord.Member = None) -> None:
- """This "spookifies" the given user's avatar, with a random *spooky* effect."""
- if member is None:
- member = ctx.author
-
- user = await self._fetch_user(member.id)
+ async def spookyavatar(self, ctx: commands.Context) -> None:
+ """This "spookifies" the user's avatar, with a random *spooky* effect."""
+ user = await self._fetch_user(ctx.author.id)
if not user:
await ctx.send(f"{Emojis.cross_mark} Could not get user info.")
return
@@ -296,7 +261,7 @@ class AvatarModify(commands.Cog):
async with ctx.typing():
image_bytes = await user.avatar_url_as(size=1024).read()
- file_name = file_safe_name("spooky_avatar", member.display_name)
+ file_name = file_safe_name("spooky_avatar", ctx.author.display_name)
file = await in_executor(
PfpEffects.apply_effect,
@@ -309,7 +274,6 @@ class AvatarModify(commands.Cog):
title="Is this you or am I just really paranoid?",
colour=Colours.soft_red
)
- embed.set_author(name=member.name, icon_url=member.avatar_url)
embed.set_image(url=f"attachment://{file_name}")
embed.set_footer(text=f"Made by {ctx.author.display_name}.", icon_url=ctx.author.avatar_url)
diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py
index b67aa4a6..00810de8 100644
--- a/bot/exts/evergreen/issues.py
+++ b/bot/exts/evergreen/issues.py
@@ -135,7 +135,7 @@ class Issues(commands.Cog):
# need from the initial API call.
if "issues" in json_data["html_url"]:
if json_data.get("state") == "open":
- emoji = Emojis.issue
+ emoji = Emojis.issue_open
else:
emoji = Emojis.issue_closed
@@ -149,10 +149,10 @@ class Issues(commands.Cog):
if pull_data["draft"]:
emoji = Emojis.pull_request_draft
elif pull_data["state"] == "open":
- emoji = Emojis.pull_request
+ emoji = Emojis.pull_request_open
# When 'merged_at' is not None, this means that the state of the PR is merged
elif pull_data["merged_at"] is not None:
- emoji = Emojis.merge
+ emoji = Emojis.pull_request_merged
else:
emoji = Emojis.pull_request_closed
diff --git a/bot/exts/evergreen/tic_tac_toe.py b/bot/exts/evergreen/tic_tac_toe.py
index 48e8e142..164e056d 100644
--- a/bot/exts/evergreen/tic_tac_toe.py
+++ b/bot/exts/evergreen/tic_tac_toe.py
@@ -318,9 +318,14 @@ class TicTacToe(Cog):
return
game = self.games[game_id - 1]
+ if game.draw:
+ description = f"{game.players[0]} vs {game.players[1]} (draw)\n\n{game.format_board()}"
+ else:
+ description = f"{game.winner} :trophy: vs {game.loser}\n\n{game.format_board()}"
+
embed = discord.Embed(
title=f"Match #{game_id} Game Board",
- description=f"{game.winner} :trophy: vs {game.loser}\n\n{game.format_board()}"
+ description=description,
)
await ctx.send(embed=embed)
diff --git a/bot/exts/evergreen/trivia_quiz.py b/bot/exts/evergreen/trivia_quiz.py
index a8d10afd..28924aed 100644
--- a/bot/exts/evergreen/trivia_quiz.py
+++ b/bot/exts/evergreen/trivia_quiz.py
@@ -17,8 +17,8 @@ from bot.constants import Colours, NEGATIVE_REPLIES, Roles
logger = logging.getLogger(__name__)
DEFAULT_QUESTION_LIMIT = 6
-STANDARD_VARIATION_TOLERANCE = 83
-DYNAMICALLY_GEN_VARIATION_TOLERANCE = 95
+STANDARD_VARIATION_TOLERANCE = 88
+DYNAMICALLY_GEN_VARIATION_TOLERANCE = 97
WRONG_ANS_RESPONSE = [
"No one answered correctly!",
@@ -210,6 +210,8 @@ class TriviaQuiz(commands.Cog):
"retro": "Questions related to retro gaming.",
"math": "General questions about mathematics ranging from grade 8 to grade 12.",
"science": "Put your understanding of science to the test!",
+ "cs": "A large variety of computer science questions.",
+ "python": "Trivia on our amazing language, Python!",
}
@staticmethod
@@ -225,10 +227,12 @@ class TriviaQuiz(commands.Cog):
Start a quiz!
Questions for the quiz can be selected from the following categories:
- - general: Test your general knowledge. (default)
+ - general: Test your general knowledge.
- retro: Questions related to retro gaming.
- math: General questions about mathematics ranging from grade 8 to grade 12.
- science: Put your understanding of science to the test!
+ - cs: A large variety of computer science questions.
+ - python: Trivia on our amazing language, Python!
(More to come!)
"""
@@ -290,7 +294,7 @@ class TriviaQuiz(commands.Cog):
start_embed = self.make_start_embed(category)
await ctx.send(embed=start_embed) # send an embed with the rules
- await asyncio.sleep(1)
+ await asyncio.sleep(5)
done_question = []
hint_no = 0
@@ -430,21 +434,18 @@ class TriviaQuiz(commands.Cog):
"""Generate a starting/introduction embed for the quiz."""
start_embed = discord.Embed(
colour=Colours.blue,
- title="Quiz game starting!",
+ title="A quiz game is starting!",
description=(
- f"This game consists of {self.question_limit + 1} questions.\n"
- "**Rules: **No cheating and have fun!\n"
+ f"This game consists of {self.question_limit + 1} questions.\n\n"
+ "**Rules: **\n"
+ "1. Only enclose your answer in backticks when the question tells you to.\n"
+ "2. If the question specifies an answer format, follow it or else it won't be accepted.\n"
+ "3. You have 30s per question. Points for each question reduces by 25 after 10s or after a hint.\n"
+ "4. No cheating and have fun!\n\n"
f"**Category**: {category}"
),
)
- start_embed.set_footer(
- text=(
- "Points for each question reduces by 25 after 10s or after a hint. "
- "Total time is 30s per question"
- )
- )
-
return start_embed
@staticmethod
diff --git a/bot/exts/halloween/hacktoberstats.py b/bot/exts/halloween/hacktoberstats.py
index b74e680b..50d3aaf6 100644
--- a/bot/exts/halloween/hacktoberstats.py
+++ b/bot/exts/halloween/hacktoberstats.py
@@ -10,15 +10,14 @@ from async_rediscache import RedisCache
from discord.ext import commands
from bot.bot import Bot
-from bot.constants import Channels, Colours, Month, NEGATIVE_REPLIES, Tokens, WHITELISTED_CHANNELS
-from bot.utils.decorators import in_month, whitelist_override
+from bot.constants import Colours, Month, NEGATIVE_REPLIES, Tokens
+from bot.utils.decorators import in_month
log = logging.getLogger(__name__)
CURRENT_YEAR = datetime.now().year # Used to construct GH API query
PRS_FOR_SHIRT = 4 # Minimum number of PRs before a shirt is awarded
REVIEW_DAYS = 14 # number of days needed after PR can be mature
-HACKTOBER_WHITELIST = WHITELISTED_CHANNELS + (Channels.hacktoberfest_2020,)
REQUEST_HEADERS = {"User-Agent": "Python Discord Hacktoberbot"}
# using repo topics API during preview period requires an accept header
@@ -44,7 +43,6 @@ class HacktoberStats(commands.Cog):
@in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER)
@commands.group(name="hacktoberstats", aliases=("hackstats",), invoke_without_command=True)
- @whitelist_override(channels=HACKTOBER_WHITELIST)
async def hacktoberstats_group(self, ctx: commands.Context, github_username: str = None) -> None:
"""
Display an embed for a user's Hacktoberfest contributions.
@@ -72,7 +70,6 @@ class HacktoberStats(commands.Cog):
@in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER)
@hacktoberstats_group.command(name="link")
- @whitelist_override(channels=HACKTOBER_WHITELIST)
async def link_user(self, ctx: commands.Context, github_username: str = None) -> None:
"""
Link the invoking user's Github github_username to their Discord ID.
@@ -96,7 +93,6 @@ class HacktoberStats(commands.Cog):
@in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER)
@hacktoberstats_group.command(name="unlink")
- @whitelist_override(channels=HACKTOBER_WHITELIST)
async def unlink_user(self, ctx: commands.Context) -> None:
"""Remove the invoking user's account link from the log."""
author_id, author_mention = self._author_mention_from_context(ctx)
diff --git a/bot/resources/evergreen/trivia_quiz.json b/bot/resources/evergreen/trivia_quiz.json
index fee1b6d7..8008838c 100644
--- a/bot/resources/evergreen/trivia_quiz.json
+++ b/bot/resources/evergreen/trivia_quiz.json
@@ -371,8 +371,8 @@
},
{
"id": 216,
- "question": "In set builder notation, {p/q | q ≠ 0, p & q ∈ Z} represents what?",
- "answer": "Rational Numbers"
+ "question": "In set builder notation, what does {p/q | q ≠ 0, p & q ∈ Z} represent?",
+ "answer": "Rationals, Rational Numbers"
},
{
"id": 217,
@@ -401,7 +401,7 @@
},
{
"id": 222,
- "question": "In probability, the ________ ______ of an experiment or random trial is the set of all possible outcomes of it.",
+ "question": "In probability, the \\_\\_\\_\\_\\_\\_ \\_\\_\\_\\_\\_ of an experiment or random trial is the set of all possible outcomes of it.",
"answer": "sample space"
},
{
@@ -472,12 +472,12 @@
},
{
"id": 305,
- "question": "The Heisenberg's Uncertainty Principle states that the position and ________ of a quantum object can't be both exactly measured at the same time.",
+ "question": "The Heisenberg's Uncertainty Principle states that the position and \\_\\_\\_\\_\\_\\_\\_\\_ of a quantum object can't be both exactly measured at the same time.",
"answer": "velocity, momentum"
},
{
"id": 306,
- "question": "A ____________ reaction is the one wherein an atom or a set of atoms is/are replaced by another atom or a set of atoms",
+ "question": "A \\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_ reaction is the one wherein an atom or a set of atoms is/are replaced by another atom or a set of atoms",
"answer": "displacement, exchange"
},
{
@@ -521,7 +521,7 @@
},
{
"id": 314,
- "question": "About how many neurons are in the human brain? (A. 1 billion, B. 10 billion, C. 100 billion, D. 300 billion)",
+ "question": "About how many neurons are in the human brain?\n(A. 1 billion, B. 10 billion, C. 100 billion, D. 300 billion)",
"answer": "C, 100 billion, 100 bil"
},
{
@@ -556,7 +556,7 @@
},
{
"id": 321,
- "question": "What range of frequency are the average human ears capable of hearing (A. 10Hz-10kHz, B. 20Hz-20kHz, C. 20Hz-2000Hz, D. 10kHz-20kHz)?",
+ "question": "What range of frequency are the average human ears capable of hearing?\n(A. 10Hz-10kHz, B. 20Hz-20kHz, C. 20Hz-2000Hz, D. 10kHz-20kHz)",
"answer": "B, 20Hz-20kHz"
},
{
@@ -604,5 +604,309 @@
"question": "When DNA is unzipped, two strands are formed. What are they called (separate both answers by the word \"and\")?",
"answer": "leading and lagging, leading strand and lagging strand"
}
+ ],
+ "cs": [
+ {
+ "id": 401,
+ "question": "What does HTML stand for?",
+ "answer": "HyperText Markup Language"
+ },
+ {
+ "id": 402,
+ "question": "What does ASCII stand for?",
+ "answer": "American Standard Code for Information Interchange"
+ },
+ {
+ "id": 403,
+ "question": "What does SASS stand for?",
+ "answer": "Syntactically Awesome Stylesheets, Syntactically Awesome Style Sheets"
+ },
+ {
+ "id": 404,
+ "question": "In neural networks, \\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_ is an algorithm for supervised learning using gradient descent.",
+ "answer": "backpropagation"
+ },
+ {
+ "id": 405,
+ "question": "What is computing capable of performing exaFLOPS called?",
+ "answer": "exascale computing, exascale"
+ },
+ {
+ "id": 406,
+ "question": "In quantum computing, what is the full name of \"qubit\"?",
+ "answer": "quantum binary digit"
+ },
+ {
+ "id": 407,
+ "question": "Given that January 1, 1970 is the starting epoch of time_t in c time, and that time_t is stored as a signed 32-bit integer, when will unix time roll over (year)?",
+ "answer": "2038"
+ },
+ {
+ "id": 408,
+ "question": "What are the components of digital devices that make up logic gates called?",
+ "answer": "transistors"
+ },
+ {
+ "id": 409,
+ "question": "How many possible public IPv6 addresses are there (answer in 2^n)?",
+ "answer": "2^128"
+ },
+ {
+ "id": 410,
+ "question": "A hypothetical point in time at which technological growth becomes uncontrollable and irreversible, resulting in unforeseeable changes to human civilization is termed as...?",
+ "answer": "technological singularity, singularity"
+ },
+ {
+ "id": 411,
+ "question": "In cryptography, the practice of establishing a shared secret between two parties using public keys and private keys is called...?",
+ "answer": "key exchange"
+ },
+ {
+ "id": 412,
+ "question": "How many bits are in a TCP checksum header?",
+ "answer": "16, sixteen"
+ },
+ {
+ "id": 413,
+ "question": "What is the most popular protocol (as of 2021) that handles communication between email servers?",
+ "answer": "SMTP, Simple Mail Transfer Protocol"
+ },
+ {
+ "id": 414,
+ "question": "Which port does SMTP use to communicate between email servers? (assuming its plaintext)",
+ "answer": "25"
+ },
+ {
+ "id": 415,
+ "question": "Which DNS record contains mail servers of a given domain?",
+ "answer": "MX, mail exchange"
+ },
+ {
+ "id": 416,
+ "question": "Which newline sequence does HTTP use?",
+ "answer": "carriage return line feed, CRLF, \\r\\n"
+ },
+ {
+ "id": 417,
+ "question": "What does one call the optimization technique used in CPU design that attempts to guess the outcome of a conditional operation and prepare for the most likely result?",
+ "answer": "branch prediction"
+ },
+ {
+ "id": 418,
+ "question": "Name a universal logic gate.",
+ "answer": "NAND, NOR"
+ },
+ {
+ "id": 419,
+ "question": "What is the mathematical formalism which functional programming was built on?",
+ "answer": "lambda calculus"
+ },
+ {
+ "id": 420,
+ "question": "Why is a DDoS attack different from a DoS attack?\n(A. because the victim's server was indefinitely disrupted from the amount of traffic, B. because it also attacks the victim's confidentiality, C. because the attack had political purposes behind it, D. because the traffic flooding the victim originated from many different sources)",
+ "answer": "D"
+ },
+ {
+ "id": 421,
+ "question": "What is a HTTP/1.1 feature that was superseded by HTTP/2 multiplexing and is unsupported in most browsers nowadays?",
+ "answer": "pipelining"
+ },
+ {
+ "id": 422,
+ "question": "Which of these languages is the oldest?\n(Tcl, Smalltalk 80, Haskell, Standard ML, Java)",
+ "answer": "Smalltalk 80"
+ },
+ {
+ "id": 423,
+ "question": "What is the name for unicode codepoints that do not fit into 16 bits?",
+ "answer": "surrogates"
+ },
+ {
+ "id": 424,
+ "question": "Under what locale does making a string lowercase behave differently?",
+ "answer": "Turkish"
+ },
+ {
+ "id": 425,
+ "question": "What does the \"a\" represent in a HSLA color value?",
+ "answer": "transparency, translucency, alpha value, alpha channel, alpha"
+ },
+ {
+ "id": 426,
+ "question": "What is the section of a GIF that is limited to 256 colors called?",
+ "answer": "image block"
+ },
+ {
+ "id": 427,
+ "question": "What is an interpreter capable of interpreting itself called?",
+ "answer": "metainterpreter"
+ },
+ {
+ "id": 428,
+ "question": "Due to what data storage medium did old programming languages, such as cobol, ignore all characters past the 72nd column?",
+ "answer": "punch cards"
+ },
+ {
+ "id": 429,
+ "question": "Which of these sorting algorithms is not stable?\n(Counting sort, quick sort, insertion sort, tim sort, bubble sort)",
+ "answer": "quick, quick sort"
+ },
+ {
+ "id": 430,
+ "question": "Which of these languages is the youngest?\n(Lisp, Python, Java, Haskell, Prolog, Ruby, Perl)",
+ "answer": "Java"
+ }
+ ],
+ "python": [
+ {
+ "id": 501,
+ "question": "Is everything an instance of the `object` class (y/n)?",
+ "answer": "y, yes"
+ },
+ {
+ "id": 502,
+ "question": "Name the only non-dunder method of the builtin slice object.",
+ "answer": "indices"
+ },
+ {
+ "id": 503,
+ "question": "What exception, other than `StopIteration`, can you raise from a `__getitem__` dunder to indicate to an iterator that it should stop?",
+ "answer": "IndexError"
+ },
+ {
+ "id": 504,
+ "question": "What type does the `&` operator return when given 2 `dict_keys` objects?",
+ "answer": "set"
+ },
+ {
+ "id": 505,
+ "question": "Can you pickle a running `list_iterator` (y/n)?",
+ "answer": "y, yes"
+ },
+ {
+ "id": 506,
+ "question": "What attribute of a closure contains the value closed over?",
+ "answer": "cell_contents"
+ },
+ {
+ "id": 507,
+ "question": "What name does a lambda function have?",
+ "answer": "<lambda>"
+ },
+ {
+ "id": 508,
+ "question": "Which file contains all special site builtins, such as help or credits?",
+ "answer": "_sitebuiltins"
+ },
+ {
+ "id": 509,
+ "question": "Which module when imported opens up a web browser tab that points to the classic 353 XKCD comic mentioning Python?",
+ "answer": "antigravity"
+ },
+ {
+ "id": 510,
+ "question": "Which attribute is the documentation string of a function/method/class stored in (answer should be enclosed in backticks!)?",
+ "answer": "`__doc__`"
+ },
+ {
+ "id": 511,
+ "question": "What is the official name of this operator `:=`, introduced in 3.8?",
+ "answer": "assignment-expression operator"
+ },
+ {
+ "id": 512,
+ "question": "When was Python first released?",
+ "answer": "1991"
+ },
+ {
+ "id": 513,
+ "question": "Where does the name Python come from?",
+ "answer": "Monty Python, Monty Python's Flying Circus"
+ },
+ {
+ "id": 514,
+ "question": "How is infinity represented in Python?",
+ "answer": "float(\"infinity\"), float('infinity'), float(\"inf\"), float('inf')"
+ },
+ {
+ "id": 515,
+ "question": "Which of these characters is valid python outside of string literals in some context?\n(`@`, `$`, `?`)",
+ "answer": "@"
+ },
+ {
+ "id": 516,
+ "question": "Which standard library module is designed for making simple parsers for languages like shell, as well as safe quoting of strings for use in a shell?",
+ "answer": "shlex"
+ },
+ {
+ "id": 517,
+ "question": "Which one of these protocols/abstract base classes does the builtin `range` object NOT implement?\n(`Sequence`, `Iterable`, `Generator`)",
+ "answer": "Generator"
+ },
+ {
+ "id": 518,
+ "question": "What decorator is used to allow a protocol to be checked at runtime?",
+ "answer": "runtime_checkable, typing.runtime_checkable"
+ },
+ {
+ "id": 519,
+ "question": "Does `numbers.Rational` include the builtin object float (y/n)",
+ "answer": "n, no"
+ },
+ {
+ "id": 520,
+ "question": "What is a package that doesn't have a `__init__` file called?",
+ "answer":"namespace package"
+ },
+ {
+ "id": 521,
+ "question": "What file extension is used by the site module to determine what to do at every start?",
+ "answer": ".pth"
+ },
+ {
+ "id": 522,
+ "question": "What is the garbage collection strategy used by cpython to collect everything but reference cycles?",
+ "answer": "reference counting, refcounting"
+ },
+ {
+ "id": 523,
+ "question": "What dunder method is used by the tuple constructor to optimize converting an iterator to a tuple (answer should be enclosed in backticks!)?",
+ "answer": "`__length_hint__`"
+ },
+ {
+ "id": 524,
+ "question": "Which protocol is used to pass self to methods when accessed on classes?",
+ "answer": "Descriptor"
+ },
+ {
+ "id": 525,
+ "question": "Which year was Python 3 released?",
+ "answer": "2008"
+ },
+ {
+ "id": 526,
+ "question": "Which of these is not a generator method?\n(`next`, `send`, `throw`, `close`)",
+ "answer": "next"
+ },
+ {
+ "id": 527,
+ "question": "Is the `__aiter__` method async (y/n)?",
+ "answer": "n, no"
+ },
+ {
+ "id": 528,
+ "question": "How does one call a class who defines the behavior of their instance classes?",
+ "answer": "a metaclass, metaclass"
+ },
+ {
+ "id": 529,
+ "question": "Which of these is a subclass of `Exception`?\n(`NotImplemented`, `asyncio.CancelledError`, `StopIteration`)",
+ "answer": "StopIteration"
+ },
+ {
+ "id": 530,
+ "question": "What type is the attribute of a frame object that contains the current local variables?",
+ "answer": "dict"
+ }
]
}
diff --git a/bot/utils/checks.py b/bot/utils/checks.py
index c06b6870..438ec750 100644
--- a/bot/utils/checks.py
+++ b/bot/utils/checks.py
@@ -75,6 +75,11 @@ def in_whitelist_check(
log.trace(f"{ctx.author} may use the `{ctx.command.name}` command as they are in a whitelisted category.")
return True
+ category = getattr(ctx.channel, "category", None)
+ if category and category.name == constants.codejam_categories_name:
+ log.trace(f"{ctx.author} may use the `{ctx.command.name}` command as they are in a codejam team channel.")
+ return True
+
# Only check the roles whitelist if we have one and ensure the author's roles attribute returns
# an iterable to prevent breakage in DM channels (for if we ever decide to enable commands there).
if roles and any(r.id in roles for r in getattr(ctx.author, "roles", ())):