1
0
forked from sass/tipibot

Refacor emoijs to use application emoijs

This commit is contained in:
Rene Arumetsa
2026-06-03 18:34:29 +03:00
10 changed files with 244 additions and 127 deletions

View File

@@ -6,10 +6,15 @@ 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."""
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:
return False
@@ -17,11 +22,22 @@ def is_bot_admin(member: discord.abc.User | None) -> bool:
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)

View File

@@ -17,6 +17,7 @@ import aiohttp
from . import pb_client
from .pb_client import DatabaseError
from .emoji import EMOJI as E
import strings
@@ -29,13 +30,9 @@ def _txn(event: str, **fields) -> None:
_txn_log.info("%-16s %s", event, body)
# ---------------------------------------------------------------------------
# Emoji config
# To use your custom Discord emoji replace COIN with the full tag, e.g.:
# COIN = "<:tipicoin:1234567890123456789>"
# ---------------------------------------------------------------------------
COIN = "<:TipiCOIN:1483000209188589628>"
PP_EMOJI = "<:TipiFIRE:1483431381668335687>"
# Per-profile emoji values live in core/emoji.py; add new IDs there.
COIN = E["TipiCOIN"]
PP_EMOJI = E["TipiFIRE"]
PRESTIGE_ROLE = "TipiPRESTIGE"
PRESTIGE_MIN_LEVEL = 30 # minimum level required to prestige
@@ -52,99 +49,99 @@ class ShopItem(TypedDict):
SHOP: dict[str, ShopItem] = {
"gaming_hiir": {
"name": "Mängurihiir",
"emoji": "<:TipiHIIR:1483004306012504128>",
"emoji": E["TipiHIIR"],
"cost": 500,
"description": strings.ITEM_DESCRIPTIONS["gaming_hiir"],
},
"hiirematt": {
"name": "Hiirematt",
"emoji": "<:TipiMATT:1483387697132208128>",
"emoji": E["TipiMATT"],
"cost": 600,
"description": strings.ITEM_DESCRIPTIONS["hiirematt"],
},
"korvaklapid": {
"name": "K\u00f5rvaklapid",
"emoji": "<:TipiKLAPID:1483387694083084349>",
"emoji": E["TipiKLAPID"],
"cost": 1200,
"description": strings.ITEM_DESCRIPTIONS["korvaklapid"],
},
"lan_pass": {
"name": "LAN pilet",
"emoji": "<:TipiPILET:1483004308353060904>",
"emoji": E["TipiPILET"],
"cost": 1200,
"description": strings.ITEM_DESCRIPTIONS["lan_pass"],
},
"energiajook": {
"name": "Red Bull",
"emoji": "<:TipiBULL:1483004310924300409>",
"emoji": E["TipiBULL"],
"cost": 800,
"description": strings.ITEM_DESCRIPTIONS["energiajook"],
},
"gaming_laptop": {
"name": "Bot Farm",
"emoji": "<:TipiLAP:1483004307161874566>",
"emoji": E["TipiLAP"],
"cost": 1500,
"description": strings.ITEM_DESCRIPTIONS["gaming_laptop"],
},
"anticheat": {
"name": "Anticheat",
"emoji": "<:TipiVAC:1483004309510819860>",
"emoji": E["TipiVAC"],
"cost": 1000,
"description": strings.ITEM_DESCRIPTIONS["anticheat"],
},
# ----- Tier 2 -----
"reguleeritav_laud": {
"name": "Reguleeritav laud",
"emoji": "<:TipiLAUD:1483387695576125440>",
"emoji": E["TipiLAUD"],
"cost": 3500,
"description": strings.ITEM_DESCRIPTIONS["reguleeritav_laud"],
},
"jellyfin": {
"name": "Jellyfin server",
"emoji": "<:TipiSERVER:1483387701032910969>",
"emoji": E["TipiSERVER"],
"cost": 4000,
"description": strings.ITEM_DESCRIPTIONS["jellyfin"],
},
"mikrofon": {
"name": "Eraldiseisev mikrofon",
"emoji": "<:TipiMIC:1483387698499551313>",
"emoji": E["TipiMIC"],
"cost": 2800,
"description": strings.ITEM_DESCRIPTIONS["mikrofon"],
},
"klaviatuur": {
"name": "Mehaaniline klaviatuur",
"emoji": "<:TipiKLAVA:1483014339228078140>",
"emoji": E["TipiKLAVA"],
"cost": 1800,
"description": strings.ITEM_DESCRIPTIONS["klaviatuur"],
},
"monitor": {
"name": "Ultralai monitor",
"emoji": "<:TipiMONITOR:1483014340327243908>",
"emoji": E["TipiMONITOR"],
"cost": 2500,
"description": strings.ITEM_DESCRIPTIONS["monitor"],
},
"cat6": {
"name": "Cat6 kaabel",
"emoji": "<:TipiCAT:1483014337663602718>",
"emoji": E["TipiCAT"],
"cost": 3500,
"description": strings.ITEM_DESCRIPTIONS["cat6"],
},
# ----- Tier 3 -----
"monitor_360": {
"name": "360Hz monitor",
"emoji": "<:TipiMONITOR2:1483387699514839162>",
"emoji": E["TipiMONITOR2"],
"cost": 7500,
"description": strings.ITEM_DESCRIPTIONS["monitor_360"],
},
"karikas": {
"name": "TipiLAN karikas",
"emoji": "<:TipiKARIKAS:1483014841148112977>",
"emoji": E["TipiKARIKAS"],
"cost": 6000,
"description": strings.ITEM_DESCRIPTIONS["karikas"],
},
"gaming_tool": {
"name": "Gaming tool",
"emoji": "<:TipiTOOL:1483014341648187613>",
"emoji": E["TipiTOOL"],
"cost": 9000,
"description": strings.ITEM_DESCRIPTIONS["gaming_tool"],
},
@@ -204,7 +201,7 @@ class PrestigeItem(TypedDict):
PRESTIGE_SHOP: dict[str, PrestigeItem] = {
"coin_mult": {
"emoji": "<:TipiCOIN:1483000209188589628>",
"emoji": E["TipiCOIN"],
"max_level": 5,
"pp_cost": 5,
"effect": 0.08,
@@ -1482,21 +1479,21 @@ async def do_rps_pvp_refund(user_id: int, bet: int) -> dict:
# /slots
# ---------------------------------------------------------------------------
_SLOTS_SYMBOLS: list[tuple[str, int]] = [
("<:TipiHEART:1483431377561976853>", 27),
("<:TipiFIRE:1483431381668335687>", 22),
("<:TipiTROLL:1483431380166774895>", 18),
("<:TipICRY:1483431288852709387>", 15),
("<:TipiSKULL:1483431378929451028>", 10),
("<:TipiKARIKAS:1483014841148112977>", 8),
(E["TipiHEART"], 27),
(E["TipiFIRE"], 22),
(E["TipiTROLL"], 18),
(E["TipICRY"], 15),
(E["TipiSKULL"], 10),
(E["TipiKARIKAS"], 8),
]
_SLOTS_JACKPOT = "<:TipiKARIKAS:1483014841148112977>"
_SLOTS_JACKPOT = E["TipiKARIKAS"]
_SLOTS_TRIPLE_MULT: dict[str, int] = {
"<:TipiHEART:1483431377561976853>": 4,
"<:TipiFIRE:1483431381668335687>": 5,
"<:TipiTROLL:1483431380166774895>": 7,
"<:TipICRY:1483431288852709387>": 10,
"<:TipiSKULL:1483431378929451028>": 15,
"<:TipiKARIKAS:1483014841148112977>": 25, # jackpot
E["TipiHEART"]: 4,
E["TipiFIRE"]: 5,
E["TipiTROLL"]: 7,
E["TipICRY"]: 10,
E["TipiSKULL"]: 15,
E["TipiKARIKAS"]: 25, # jackpot
}

66
core/emoji.py Normal file
View File

@@ -0,0 +1,66 @@
"""Custom Discord emoji registry, keyed by symbolic name and resolved per BOT_PROFILE.
Emojis are uploaded as application emojis via the Discord Developer Portal
and are scoped to a single bot application. Dev and production are separate
applications, so the same logical emoji has a different ID in each — hence
two dicts below, selected by BOT_PROFILE.
To add a new emoji: upload it to both applications in the dev portal, grab
the two IDs, and add one line to each dict.
"""
from __future__ import annotations
from config import BOT_PROFILE
_DEV: dict[str, str] = {
"TipiCOIN": "<:TipiCOIN:1483000209188589628>",
"TipiFIRE": "<:TipiFIRE:1483431381668335687>",
"TipiHIIR": "<:TipiHIIR:1483004306012504128>",
"TipiMATT": "<:TipiMATT:1483387697132208128>",
"TipiKLAPID": "<:TipiKLAPID:1483387694083084349>",
"TipiPILET": "<:TipiPILET:1483004308353060904>",
"TipiBULL": "<:TipiBULL:1483004310924300409>",
"TipiLAP": "<:TipiLAP:1483004307161874566>",
"TipiVAC": "<:TipiVAC:1483004309510819860>",
"TipiLAUD": "<:TipiLAUD:1483387695576125440>",
"TipiSERVER": "<:TipiSERVER:1483387701032910969>",
"TipiMIC": "<:TipiMIC:1483387698499551313>",
"TipiKLAVA": "<:TipiKLAVA:1483014339228078140>",
"TipiMONITOR": "<:TipiMONITOR:1483014340327243908>",
"TipiCAT": "<:TipiCAT:1483014337663602718>",
"TipiMONITOR2": "<:TipiMONITOR2:1483387699514839162>",
"TipiKARIKAS": "<:TipiKARIKAS:1483014841148112977>",
"TipiTOOL": "<:TipiTOOL:1483014341648187613>",
"TipiHEART": "<:TipiHEART:1483431377561976853>",
"TipiTROLL": "<:TipiTROLL:1483431380166774895>",
"TipICRY": "<:TipICRY:1483431288852709387>",
"TipiSKULL": "<:TipiSKULL:1483431378929451028>",
"TipiDICE": "<:TipiDICE:1485923107108556950>",
"TipiYKS": "<:TipiYKS:1483103190491856916>",
"TipiKAKS": "<:TipiKAKS:1483103215841972404>",
"TipiKOLM": "<:TipiKOLM:1483103217846980781>",
"TipiNELI": "<:TipiNELI:1483103237585240114>",
"TipiVIIS": "<:TipiVIIS:1483103239036469289>",
"TipiKUUS": "<:TipiKUUS:1483103253163020348>",
"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)
_EMOJI_SETS = {
"dev": _DEV,
"economy": _ECONOMY,
}
EMOJI: dict[str, str] = _EMOJI_SETS[BOT_PROFILE]
_missing = set(_DEV) - set(EMOJI)
if _missing:
raise RuntimeError(f"Emoji set {BOT_PROFILE!r} missing keys: {sorted(_missing)}")