aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Xithrius <[email protected]>2021-08-22 16:16:00 -0700
committerGravatar GitHub <[email protected]>2021-08-22 16:16:00 -0700
commitabef38e09431e27a079af5a84d914a02b75c108e (patch)
treee16e57365d99a6976fbcf605faff1bb8c687cfe7
parentMerge pull request #1742 from python-discord/remove-redundant-converters (diff)
parentMerge branch 'main' into metabase-sharing (diff)
Merge pull request #1762 from python-discord/metabase-sharing
Metabase sharing
-rw-r--r--bot/constants.py2
-rw-r--r--bot/exts/moderation/metabase.py109
-rw-r--r--config-default.yml10
3 files changed, 70 insertions, 51 deletions
diff --git a/bot/constants.py b/bot/constants.py
index 500803f33..12b5c02e5 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -568,7 +568,7 @@ class Metabase(metaclass=YAMLGetter):
username: Optional[str]
password: Optional[str]
- url: str
+ base_url: str
max_session_age: int
diff --git a/bot/exts/moderation/metabase.py b/bot/exts/moderation/metabase.py
index e9faf7240..3b454ab18 100644
--- a/bot/exts/moderation/metabase.py
+++ b/bot/exts/moderation/metabase.py
@@ -42,6 +42,25 @@ class Metabase(Cog):
self.init_task = self.bot.loop.create_task(self.init_cog())
+ async def cog_command_error(self, ctx: Context, error: Exception) -> None:
+ """Handle ClientResponseError errors locally to invalidate token if needed."""
+ if not isinstance(error.original, ClientResponseError):
+ return
+
+ if error.original.status == 403:
+ # User doesn't have access to the given question
+ log.warning(f"Failed to auth with Metabase for {error.original.url}.")
+ await ctx.send(f":x: {ctx.author.mention} Failed to auth with Metabase for that question.")
+ elif error.original.status == 404:
+ await ctx.send(f":x: {ctx.author.mention} That question could not be found.")
+ else:
+ # User credentials are invalid, or the refresh failed.
+ # Delete the expiry time, to force a refresh on next startup.
+ await self.session_info.delete("session_expiry")
+ log.exception("Session token is invalid or refresh failed.")
+ await ctx.send(f":x: {ctx.author.mention} Session token is invalid or refresh failed.")
+ error.handled = True
+
async def init_cog(self) -> None:
"""Initialise the metabase session."""
expiry_time = await self.session_info.get("session_expiry")
@@ -65,7 +84,7 @@ class Metabase(Cog):
"username": MetabaseConfig.username,
"password": MetabaseConfig.password
}
- async with self.bot.http_session.post(f"{MetabaseConfig.url}/session", json=data) as resp:
+ async with self.bot.http_session.post(f"{MetabaseConfig.base_url}/api/session", json=data) as resp:
json_data = await resp.json()
self.session_token = json_data.get("id")
@@ -86,7 +105,7 @@ class Metabase(Cog):
"""A group of commands for interacting with metabase."""
await ctx.send_help(ctx.command)
- @metabase_group.command(name="extract")
+ @metabase_group.command(name="extract", aliases=("export",))
async def metabase_extract(
self,
ctx: Context,
@@ -106,48 +125,50 @@ class Metabase(Cog):
Valid extensions are: csv and json.
"""
- async with ctx.typing():
-
- # Make sure we have a session token before running anything
- await self.init_task
-
- url = f"{MetabaseConfig.url}/card/{question_id}/query/{extension}"
- try:
- async with self.bot.http_session.post(url, headers=self.headers, raise_for_status=True) as resp:
- if extension == "csv":
- out = await resp.text(encoding="utf-8")
- # Save the output for use with int e
- self.exports[question_id] = list(csv.DictReader(StringIO(out)))
-
- elif extension == "json":
- out = await resp.json(encoding="utf-8")
- # Save the output for use with int e
- self.exports[question_id] = out
-
- # Format it nicely for human eyes
- out = json.dumps(out, indent=4, sort_keys=True)
- except ClientResponseError as e:
- if e.status == 403:
- # User doesn't have access to the given question
- log.warning(f"Failed to auth with Metabase for question {question_id}.")
- await ctx.send(f":x: {ctx.author.mention} Failed to auth with Metabase for that question.")
- else:
- # User credentials are invalid, or the refresh failed.
- # Delete the expiry time, to force a refresh on next startup.
- await self.session_info.delete("session_expiry")
- log.exception("Session token is invalid or refresh failed.")
- await ctx.send(f":x: {ctx.author.mention} Session token is invalid or refresh failed.")
- return
-
- paste_link = await send_to_paste_service(out, extension=extension)
- if paste_link:
- message = f":+1: {ctx.author.mention} Here's your link: {paste_link}"
- else:
- message = f":x: {ctx.author.mention} Link service is unavailible."
- await ctx.send(
- f"{message}\nYou can also access this data within internal eval by doing: "
- f"`bot.get_cog('Metabase').exports[{question_id}]`"
- )
+ await ctx.trigger_typing()
+
+ # Make sure we have a session token before running anything
+ await self.init_task
+
+ url = f"{MetabaseConfig.base_url}/api/card/{question_id}/query/{extension}"
+
+ async with self.bot.http_session.post(url, headers=self.headers, raise_for_status=True) as resp:
+ if extension == "csv":
+ out = await resp.text(encoding="utf-8")
+ # Save the output for use with int e
+ self.exports[question_id] = list(csv.DictReader(StringIO(out)))
+
+ elif extension == "json":
+ out = await resp.json(encoding="utf-8")
+ # Save the output for use with int e
+ self.exports[question_id] = out
+
+ # Format it nicely for human eyes
+ out = json.dumps(out, indent=4, sort_keys=True)
+
+ paste_link = await send_to_paste_service(out, extension=extension)
+ if paste_link:
+ message = f":+1: {ctx.author.mention} Here's your link: {paste_link}"
+ else:
+ message = f":x: {ctx.author.mention} Link service is unavailible."
+ await ctx.send(
+ f"{message}\nYou can also access this data within internal eval by doing: "
+ f"`bot.get_cog('Metabase').exports[{question_id}]`"
+ )
+
+ @metabase_group.command(name="publish", aliases=("share",))
+ async def metabase_publish(self, ctx: Context, question_id: int) -> None:
+ """Publically shares the given question and posts the link."""
+ await ctx.trigger_typing()
+ # Make sure we have a session token before running anything
+ await self.init_task
+
+ url = f"{MetabaseConfig.base_url}/api/card/{question_id}/public_link"
+
+ async with self.bot.http_session.post(url, headers=self.headers, raise_for_status=True) as resp:
+ response_json = await resp.json(encoding="utf-8")
+ sharing_url = f"{MetabaseConfig.base_url}/public/question/{response_json['uuid']}"
+ await ctx.send(f":+1: {ctx.author.mention} Here's your sharing link: {sharing_url}")
# This cannot be static (must have a __func__ attribute).
async def cog_check(self, ctx: Context) -> bool:
diff --git a/config-default.yml b/config-default.yml
index 881a7df76..79828dd77 100644
--- a/config-default.yml
+++ b/config-default.yml
@@ -432,14 +432,12 @@ anti_spam:
max: 3
-
metabase:
- username: !ENV "METABASE_USERNAME"
- password: !ENV "METABASE_PASSWORD"
- url: "http://metabase.default.svc.cluster.local/api"
+ username: !ENV "METABASE_USERNAME"
+ password: !ENV "METABASE_PASSWORD"
+ base_url: "http://metabase.default.svc.cluster.local"
# 14 days, see https://www.metabase.com/docs/latest/operations-guide/environment-variables.html#max_session_age
- max_session_age: 20160
-
+ max_session_age: 20160
big_brother: