modified: app.py
new file: emotes.markdown new file: tags.txt
This commit is contained in:
156
app.py
156
app.py
@@ -151,6 +151,21 @@ def find_custom_emoji(ctx: commands.Context, keyword_variants: List[str]) -> Opt
|
||||
return str(e)
|
||||
except Exception:
|
||||
continue
|
||||
# Fallback to markdown-defined emojis if available
|
||||
try:
|
||||
if EMOTE_MAP:
|
||||
for kw in keyword_variants:
|
||||
key = kw.lower()
|
||||
# Exact name match
|
||||
if key in EMOTE_MAP:
|
||||
return EMOTE_MAP[key]
|
||||
# Substring match
|
||||
for name_lower, mention in EMOTE_MAP.items():
|
||||
if key in name_lower:
|
||||
return mention
|
||||
except NameError:
|
||||
# EMOTE_MAP not defined yet
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_t_emoji(ctx: commands.Context, t_level: int) -> str:
|
||||
@@ -180,8 +195,128 @@ def get_team_emoji(ctx: commands.Context, team_name: str) -> str:
|
||||
return custom or "🔴"
|
||||
# Generic HOI4 emoji or fallback
|
||||
custom = find_custom_emoji(ctx, ["hoi4", "hearts_of_iron", "iron"])
|
||||
if not custom:
|
||||
custom = find_custom_emoji(ctx, ["eagle_hoi", "peace_hoi", "navy_hoi", "secretweapon_hoi"])
|
||||
return custom or "🎖️"
|
||||
|
||||
def _flag_from_iso2(code: str) -> Optional[str]:
|
||||
"""Return unicode flag from 2-letter ISO code (e.g., 'DE' -> 🇩🇪)."""
|
||||
if not code or len(code) != 2:
|
||||
return None
|
||||
code = code.upper()
|
||||
base = 0x1F1E6
|
||||
try:
|
||||
return chr(base + ord(code[0]) - ord('A')) + chr(base + ord(code[1]) - ord('A'))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
# Emotes markdown loader and map
|
||||
def load_emote_markdown(path: Optional[str] = None) -> Dict[str, str]:
|
||||
"""Parse emotes.markdown and return a mapping of lowercased emoji names to their mention strings.
|
||||
Expected line format: <:Name:123456789012345678>
|
||||
Lines that don't match are ignored."""
|
||||
if path is None:
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
path = os.path.join(base_dir, 'emotes.markdown')
|
||||
mapping: Dict[str, str] = {}
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
for raw in f:
|
||||
line = raw.strip()
|
||||
if not line or not line.startswith('<:') or ':' not in line[2:]:
|
||||
continue
|
||||
# Format is <:NAME:ID>
|
||||
try:
|
||||
inner = line[2:-1] if line.endswith('>') else line[2:]
|
||||
name, emoji_id = inner.split(':', 1)
|
||||
name = name.strip()
|
||||
mention = f"<:{name}:{emoji_id.strip('>')}>"
|
||||
mapping[name.lower()] = mention
|
||||
except Exception:
|
||||
continue
|
||||
except FileNotFoundError:
|
||||
# Silent if not present
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to load emotes.markdown: {e}")
|
||||
return mapping
|
||||
|
||||
# Load emotes mapping at import
|
||||
EMOTE_MAP: Dict[str, str] = load_emote_markdown()
|
||||
if EMOTE_MAP:
|
||||
print(f"😀 Loaded {len(EMOTE_MAP)} custom emojis from emotes.markdown")
|
||||
|
||||
def load_country_tags(path: Optional[str] = None) -> Dict[str, str]:
|
||||
"""Load HOI4 country tags mapping from tags.txt.
|
||||
Supported formats per line:
|
||||
TAG=Country Name | TAG:Country Name | TAG,Country Name | TAG Country Name
|
||||
Lines starting with # are ignored.
|
||||
Returns dict like { 'GER': 'Germany', ... }"""
|
||||
if path is None:
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
path = os.path.join(base_dir, 'tags.txt')
|
||||
mapping: Dict[str, str] = {}
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
for raw in f:
|
||||
line = raw.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
tag = None
|
||||
name = None
|
||||
for sep in ['=', ';', ',', ':']:
|
||||
if sep in line:
|
||||
left, right = line.split(sep, 1)
|
||||
tag = left.strip().upper()
|
||||
name = right.strip()
|
||||
break
|
||||
if tag is None:
|
||||
parts = line.split(None, 1)
|
||||
if len(parts) == 2:
|
||||
tag = parts[0].strip().upper()
|
||||
name = parts[1].strip()
|
||||
else:
|
||||
tag = line.strip().upper()
|
||||
name = line.strip()
|
||||
if tag and name:
|
||||
mapping[tag] = name
|
||||
except FileNotFoundError:
|
||||
print("ℹ️ tags.txt not found; proceeding without country tag labels")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to load tags.txt: {e}")
|
||||
return mapping
|
||||
|
||||
# Loaded at import
|
||||
COUNTRY_TAGS: Dict[str, str] = load_country_tags()
|
||||
if COUNTRY_TAGS:
|
||||
print(f"🗺️ Loaded {len(COUNTRY_TAGS)} HOI4 country tags")
|
||||
|
||||
def get_country_label(country_tag: Optional[str]) -> Optional[str]:
|
||||
"""Return a display label like "[GER] Germany" if known, or "[GER]" if unknown."""
|
||||
if not country_tag:
|
||||
return None
|
||||
tag = country_tag.strip().upper()
|
||||
name = COUNTRY_TAGS.get(tag)
|
||||
return f"[{tag}] {name}" if name else f"[{tag}]"
|
||||
|
||||
def get_country_emoji(ctx: commands.Context, country: Optional[str]) -> str:
|
||||
"""Prefer custom emoji matching the HOI4 tag (e.g., ger, hoi4_ger). If parameter is ISO2, show unicode flag. Else empty."""
|
||||
if not country:
|
||||
return ""
|
||||
c = country.strip()
|
||||
# Try custom emoji lookups using tag variants
|
||||
variants = [c, c.lower(), f"hoi4_{c.lower()}", f"country_{c.lower()}"]
|
||||
custom = find_custom_emoji(ctx, variants)
|
||||
if custom:
|
||||
return custom
|
||||
# If user passed ISO2, render unicode flag
|
||||
if len(c) == 2:
|
||||
flag = _flag_from_iso2(c)
|
||||
if flag:
|
||||
return flag
|
||||
# Otherwise, no emoji fallback to avoid noisy globes
|
||||
return ""
|
||||
|
||||
# Database Functions
|
||||
# Database Functions
|
||||
async def init_database():
|
||||
@@ -433,7 +568,7 @@ async def hoi4create(ctx, game_type: str, game_name: str):
|
||||
await ctx.send(f"❌ Error creating game: {str(e)}")
|
||||
|
||||
@bot.hybrid_command(name='hoi4setup', description='Add a player to an existing game')
|
||||
async def hoi4setup(ctx, game_name: str, user: discord.Member, team_name: str, t_level: int):
|
||||
async def hoi4setup(ctx, game_name: str, user: discord.Member, team_name: str, t_level: int, country: Optional[str] = None):
|
||||
"""Add a player to an existing game"""
|
||||
if t_level not in [1, 2, 3]:
|
||||
await ctx.send("❌ T-Level must be 1, 2, or 3")
|
||||
@@ -471,7 +606,8 @@ async def hoi4setup(ctx, game_name: str, user: discord.Member, team_name: str, t
|
||||
'username': user.display_name,
|
||||
'team_name': team_name,
|
||||
't_level': t_level,
|
||||
'current_elo': player[f"{game['game_type']}_elo"]
|
||||
'current_elo': player[f"{game['game_type']}_elo"],
|
||||
'country': country.strip() if country else None
|
||||
}
|
||||
players.append(player_data)
|
||||
|
||||
@@ -490,6 +626,11 @@ async def hoi4setup(ctx, game_name: str, user: discord.Member, team_name: str, t
|
||||
embed.add_field(name="Team", value=team_name, inline=True)
|
||||
embed.add_field(name="T-Level", value=f"T{t_level}", inline=True)
|
||||
embed.add_field(name="Current ELO", value=player[f"{game['game_type']}_elo"], inline=True)
|
||||
if country:
|
||||
flag = get_country_emoji(ctx, country)
|
||||
label = get_country_label(country)
|
||||
value = f"{flag} {label}".strip()
|
||||
embed.add_field(name="Country", value=value, inline=True)
|
||||
embed.add_field(name="Players in Game", value=len(players), inline=True)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
@@ -851,7 +992,16 @@ async def hoi4games(ctx):
|
||||
lines = []
|
||||
for m in sorted(members, key=lambda mm: (-mm.get('t_level', 2), mm['username'].lower())):
|
||||
te = get_t_emoji(ctx, int(m.get('t_level', 2)))
|
||||
lines.append(f"{te} {m['username']} ({m['current_elo']})")
|
||||
ctry = m.get('country')
|
||||
flag = get_country_emoji(ctx, ctry) if ctry else ""
|
||||
label = get_country_label(ctry) if ctry else None
|
||||
parts = [te]
|
||||
if flag:
|
||||
parts.append(flag)
|
||||
if label:
|
||||
parts.append(label)
|
||||
parts.append(m['username'])
|
||||
lines.append(f"{' '.join(parts)} ({m['current_elo']})")
|
||||
value = "\n".join(lines) if lines else "No players yet"
|
||||
# Discord field value max ~1024 chars; trim if necessary
|
||||
if len(value) > 1000:
|
||||
|
||||
Reference in New Issue
Block a user