forked from sass/tipibot
Compare commits
5 Commits
3939c879c9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cdd8dac63 | ||
|
|
6101a278e7 | ||
|
|
1e9ec56761 | ||
|
|
a96488fe9e | ||
|
|
25cf60d2e1 |
5
bot.py
5
bot.py
@@ -594,12 +594,7 @@ class HelpSelect(discord.ui.Select):
|
||||
|
||||
@tree.command(name="help", description=S.CMD["help"])
|
||||
async def cmd_help(interaction: discord.Interaction):
|
||||
<<<<<<< HEAD
|
||||
is_admin = is_bot_admin(interaction.user)
|
||||
=======
|
||||
member = interaction.user
|
||||
is_admin = isinstance(member, discord.Member) and is_bot_admin(member)
|
||||
>>>>>>> 42f7bae68124fa6a9824780ba17b46d00f3f2b36
|
||||
await interaction.response.send_message(
|
||||
embed=_help_embed("üldine"), view=HelpView(is_admin), ephemeral=True
|
||||
)
|
||||
|
||||
52
config.py
52
config.py
@@ -43,21 +43,28 @@ BIRTHDAY_WINDOW_DAYS = int(os.getenv("BIRTHDAY_WINDOW_DAYS", "7"))
|
||||
BASE_ROLE_IDS: list[int] = [1478304631930228779, 1478302278862766190]
|
||||
|
||||
|
||||
def _parse_admin_roles(raw: str) -> dict[int, int]:
|
||||
"""Parse BOT_ADMIN_ROLES env var as "guild_id:role_id,guild_id:role_id"."""
|
||||
result: dict[int, int] = {}
|
||||
for pair in raw.split(","):
|
||||
pair = pair.strip()
|
||||
if not pair:
|
||||
def _parse_admin_roles(raw: str) -> dict[int, set[int]]:
|
||||
"""Parse DISCORD_ADMIN_ROLES env var as "guild_id:role_id[:role_id...],guild_id:role_id...".
|
||||
|
||||
Multiple admin roles per guild are colon-separated; guild entries are comma-separated.
|
||||
Repeating a guild_id across entries merges its roles.
|
||||
"""
|
||||
result: dict[int, set[int]] = {}
|
||||
for entry in raw.split(","):
|
||||
entry = entry.strip()
|
||||
if not entry:
|
||||
continue
|
||||
guild_str, _, role_str = pair.partition(":")
|
||||
if not role_str:
|
||||
raise SystemExit(f"BOT_ADMIN_ROLES: expected 'guild_id:role_id', got {pair!r}")
|
||||
result[int(guild_str)] = int(role_str)
|
||||
parts = entry.split(":")
|
||||
if len(parts) < 2 or not all(p.strip() for p in parts):
|
||||
raise SystemExit(
|
||||
f"DISCORD_ADMIN_ROLES: expected 'guild_id:role_id[:role_id...]', got {entry!r}"
|
||||
)
|
||||
guild_id = int(parts[0].strip())
|
||||
result.setdefault(guild_id, set()).update(int(p.strip()) for p in parts[1:])
|
||||
return result
|
||||
|
||||
|
||||
BOT_ADMIN_ROLES: dict[int, int] = _parse_admin_roles(os.getenv("BOT_ADMIN_ROLES", ""))
|
||||
BOT_ADMIN_ROLES: dict[int, set[int]] = _parse_admin_roles(os.getenv("DISCORD_ADMIN_ROLES", ""))
|
||||
|
||||
PB_URL = os.getenv("PB_URL", "http://127.0.0.1:8090")
|
||||
PB_ADMIN_EMAIL = os.getenv("PB_ADMIN_EMAIL", "")
|
||||
@@ -75,26 +82,3 @@ PB_ECONOMY_COLLECTION_ECONOMY = (
|
||||
PB_ECONOMY_COLLECTION = (
|
||||
PB_ECONOMY_COLLECTION_ECONOMY if BOT_PROFILE == "economy" else PB_ECONOMY_COLLECTION_DEV
|
||||
)
|
||||
|
||||
|
||||
def _parse_admin_roles() -> dict[int, int]:
|
||||
"""Parse BOT_ADMIN_ROLES env var (format: guild_id:role_id,guild_id:role_id)."""
|
||||
raw = os.getenv("BOT_ADMIN_ROLES", "").strip()
|
||||
if not raw:
|
||||
return {}
|
||||
result: dict[int, int] = {}
|
||||
for pair in raw.split(","):
|
||||
pair = pair.strip()
|
||||
if not pair:
|
||||
continue
|
||||
parts = pair.split(":")
|
||||
if len(parts) != 2:
|
||||
continue
|
||||
try:
|
||||
result[int(parts[0].strip())] = int(parts[1].strip())
|
||||
except ValueError:
|
||||
continue
|
||||
return result
|
||||
|
||||
|
||||
BOT_ADMIN_ROLES: dict[int, int] = _parse_admin_roles()
|
||||
|
||||
@@ -6,38 +6,22 @@ from discord import app_commands
|
||||
import config
|
||||
|
||||
|
||||
<<<<<<< HEAD
|
||||
def is_bot_admin(member: discord.abc.User | None) -> bool:
|
||||
"""True when the member has the configured admin role for their guild."""
|
||||
"""True when the member has any of the configured admin roles for their guild."""
|
||||
if not isinstance(member, discord.Member) or member.guild is None:
|
||||
return False
|
||||
=======
|
||||
def is_bot_admin(member: discord.Member) -> bool:
|
||||
"""Return True if the member has the configured bot-admin role for their guild."""
|
||||
>>>>>>> 42f7bae68124fa6a9824780ba17b46d00f3f2b36
|
||||
role_id = config.BOT_ADMIN_ROLES.get(member.guild.id)
|
||||
if role_id is None:
|
||||
admin_role_ids = config.BOT_ADMIN_ROLES.get(member.guild.id)
|
||||
if not admin_role_ids:
|
||||
return False
|
||||
return any(r.id == role_id for r in member.roles)
|
||||
return any(r.id in admin_role_ids for r in member.roles)
|
||||
|
||||
|
||||
def bot_admin_check():
|
||||
<<<<<<< HEAD
|
||||
"""Slash-command decorator that gates execution behind ``is_bot_admin``."""
|
||||
|
||||
async def predicate(interaction: discord.Interaction) -> bool:
|
||||
if is_bot_admin(interaction.user):
|
||||
return True
|
||||
raise app_commands.MissingPermissions(["bot_admin_role"])
|
||||
=======
|
||||
"""Slash-command check decorator: raises MissingPermissions if not a bot admin."""
|
||||
def predicate(interaction: discord.Interaction) -> bool:
|
||||
member = interaction.user
|
||||
if not isinstance(member, discord.Member):
|
||||
raise app_commands.MissingPermissions(["bot_admin"])
|
||||
if not is_bot_admin(member):
|
||||
raise app_commands.MissingPermissions(["bot_admin"])
|
||||
return True
|
||||
>>>>>>> 42f7bae68124fa6a9824780ba17b46d00f3f2b36
|
||||
|
||||
return app_commands.check(predicate)
|
||||
|
||||
@@ -37,7 +37,7 @@ _DEV: dict[str, str] = {
|
||||
"TipiTROLL": "<:TipiTROLL:1483431380166774895>",
|
||||
"TipICRY": "<:TipICRY:1483431288852709387>",
|
||||
"TipiSKULL": "<:TipiSKULL:1483431378929451028>",
|
||||
"TipiDICE": "<:TipiDICE:1485923107108556950>",
|
||||
"TipiDICE": "<a:TipiDICE:1485923107108556950>",
|
||||
"TipiYKS": "<:TipiYKS:1483103190491856916>",
|
||||
"TipiKAKS": "<:TipiKAKS:1483103215841972404>",
|
||||
"TipiKOLM": "<:TipiKOLM:1483103217846980781>",
|
||||
@@ -47,11 +47,42 @@ _DEV: dict[str, str] = {
|
||||
"TipiSLOTS": "<a:TipiSLOTS:1483444233863037101>",
|
||||
}
|
||||
|
||||
# Production application emoji IDs. Replace each ID with the one from the
|
||||
# prod application in the dev portal. The dev IDs below are placeholders so
|
||||
# this dict is structurally complete — they will NOT render in prod because
|
||||
# they belong to a different application.
|
||||
_ECONOMY: dict[str, str] = dict(_DEV)
|
||||
# Production application emoji IDs (from the TipiBOT application's dev-portal
|
||||
# Emojis tab). The display name in <:name:id> is cosmetic — Discord resolves
|
||||
# by ID — so we keep the same logical names as _DEV even when the prod portal
|
||||
# uses a different upload name (e.g. prod's "TipiFIVE" → key "TipiVIIS").
|
||||
_ECONOMY: dict[str, str] = {
|
||||
"TipiCOIN": "<:TipiCOIN:1511754551747940485>",
|
||||
"TipiFIRE": "<:TipiFIRE:1511754615761272862>",
|
||||
"TipiHIIR": "<:TipiHIIR:1511754556105822218>",
|
||||
"TipiMATT": "<:TipiMATT:1511754595448131665>",
|
||||
"TipiKLAPID": "<:TipiKLAPID:1511754589798666433>",
|
||||
"TipiPILET": "<:TipiPILET:1511754560593727652>",
|
||||
"TipiBULL": "<:TipiBULL:1511754564179595264>",
|
||||
"TipiLAP": "<:TipiLAP:1511754558970269907>",
|
||||
"TipiVAC": "<:TipiVAC:1511754562413924442>",
|
||||
"TipiLAUD": "<:TipiLAUD:1511754592759713985>",
|
||||
"TipiSERVER": "<:TipiSERVER:1511754601186066534>",
|
||||
"TipiMIC": "<:TipiMIC:1511754597016801310>",
|
||||
"TipiKLAVA": "<:TipiKLAVA:1511754567648542780>",
|
||||
"TipiMONITOR": "<:TipiMONITOR:1511754570722971868>",
|
||||
"TipiCAT": "<:TipiCAT:1511754566092193853>",
|
||||
"TipiMONITOR2": "<:TipiMONITOR2:1511754598732402689>",
|
||||
"TipiKARIKAS": "<:TipiKARIKAS:1511754574405435502>",
|
||||
"TipiTOOL": "<:TipiTOOL:1511754572522061874>",
|
||||
"TipiHEART": "<:TipiHEART:1511754608299737139>",
|
||||
"TipiTROLL": "<:TipiTROLL:1511754612775063832>",
|
||||
"TipICRY": "<:TipICRY:1511754603308515368>",
|
||||
"TipiSKULL": "<:TipiSKULL:1511754610195566622>",
|
||||
"TipiDICE": "<a:TipiDICE:1511753607119376504>",
|
||||
"TipiYKS": "<:TipiYKS:1511754576368373951>",
|
||||
"TipiKAKS": "<:TipiKAKS:1511754577928523997>",
|
||||
"TipiKOLM": "<:TipiKOLM:1511754581078442005>",
|
||||
"TipiNELI": "<:TipiNELI:1511754582571880509>",
|
||||
"TipiVIIS": "<:TipiVIIS:1511754584182227005>",
|
||||
"TipiKUUS": "<:TipiKUUS:1511754586262736977>",
|
||||
"TipiSLOTS": "<a:TipiSLOTS:1511754521188106431>",
|
||||
}
|
||||
|
||||
|
||||
_EMOJI_SETS = {
|
||||
|
||||
Reference in New Issue
Block a user