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:
|
||||
|
||||
30
emotes.markdown
Normal file
30
emotes.markdown
Normal file
@@ -0,0 +1,30 @@
|
||||
<:Civilian_Economy:1432372408941154325>
|
||||
<:Disarmed_Nation:1432372405669724362>
|
||||
<:Anarchism:1432372205647298672>
|
||||
<:Communism:1432372203860525149>
|
||||
<:Communism:1432372203860525149>
|
||||
<:Democracy:1432372201943994368>
|
||||
<:Fascism:1432372200756740281>
|
||||
<:Neutrality:1432372199469355039>
|
||||
<:Unknown_Ideology:1432372192879972353>
|
||||
<:Nuclear_Strike:1432371908615213148>
|
||||
<:Construction:1432371608806490132>
|
||||
<:Decision:1432371606537109576>
|
||||
<:Deployment:1432371605065044029>
|
||||
<:Diplomacy:1432371603911606315>
|
||||
<:Intelligence:1432371602531680337>
|
||||
<:Logistics:1432371601168535582>
|
||||
<:Production:1432371599524495540>
|
||||
<:Research:1432371597989380258>
|
||||
<:Trade:1432371596558991412>
|
||||
<:navy_hoi:1432370988426985642>
|
||||
<:peace_hoi:1432370987076423780>
|
||||
<:secretweapon_hoi:1432370981607051397>
|
||||
<:Eagle_hoi:1432370708771770509>
|
||||
<:Cadet_hoi:1432370649053270140>
|
||||
<:FreshRecruit:1432370967652335736>
|
||||
<:ExperiencedRegular:1432370968818352191>
|
||||
<:HardenedVeteran:1432370970135625748>
|
||||
<:SkilledCaptain:1432370971792117810>
|
||||
<:CommanderinChief:1432370973176238161>
|
||||
<:WarHero:1432370974212489226>
|
||||
105
tags.txt
Normal file
105
tags.txt
Normal file
@@ -0,0 +1,105 @@
|
||||
Kingdom of Afghanistan AFG
|
||||
Albanian Kingdom ALB
|
||||
Argentina ARG
|
||||
Sultanate of Aussa AFA
|
||||
Australia AST
|
||||
Austria AUS
|
||||
Belgian Congo COG
|
||||
Belgium BEL
|
||||
Bhutan BHU
|
||||
Bolivian Republic BOL
|
||||
Second Brazilian Republic BRA
|
||||
British Burma BRM
|
||||
British Malaya MAL
|
||||
British Raj RAJ
|
||||
Bulgaria BUL
|
||||
BUZ
|
||||
BUF
|
||||
Dominion of Canada CAN
|
||||
Chile CHL
|
||||
China CHI
|
||||
Colombia COL
|
||||
Communist China PRC
|
||||
Costa Rica COS
|
||||
Cuba CUB
|
||||
Czechoslovakia CZE
|
||||
Denmark DEN
|
||||
Dominican Republic DOM
|
||||
Dutch East Indies INS
|
||||
Ecuador ECU
|
||||
El Salvador ELS
|
||||
Estonia EST
|
||||
Ethiopia ETH
|
||||
Finland FIN
|
||||
France FRA
|
||||
VIC
|
||||
German Reich GER
|
||||
Kingdom of Greece GRE
|
||||
Guangxi Clique GXC
|
||||
Guatemala GUA
|
||||
Haiti HAI
|
||||
Honduras HON
|
||||
Kingdom of Hungary HUN
|
||||
Iceland ICE
|
||||
Iran PER
|
||||
Iraq IRQ
|
||||
Ireland IRE
|
||||
Italy ITA
|
||||
RSI
|
||||
RDS
|
||||
Japan JAP
|
||||
Sheikhdom of Kuwait KUW
|
||||
Latvia LAT
|
||||
Lebanese Republic LEB
|
||||
Liberia LIB
|
||||
Lithuania LIT
|
||||
Luxembourg LUX
|
||||
Manchukuo MAN
|
||||
Mengkukuo MEN
|
||||
Mexico MEX
|
||||
Mongolian People's Republic MON
|
||||
Sultanate of Muscat and Oman OMA
|
||||
Nepal NEP
|
||||
Netherlands HOL
|
||||
New Zealand NZL
|
||||
Nicaragua NIC
|
||||
Norway NOR
|
||||
Mandatory Palestine PAL
|
||||
Panama PAN
|
||||
Republic of Paraguay PAR
|
||||
Peru PRU
|
||||
Philippines PHI
|
||||
Poland POL
|
||||
Portugal POR
|
||||
Romania ROM
|
||||
Saudi Arabia SAU
|
||||
Shanxi SHX
|
||||
Kingdom of Siam SIA
|
||||
Sinkiang SIK
|
||||
South Africa SAF
|
||||
Soviet Union SOV
|
||||
SOS
|
||||
SOT
|
||||
SOB
|
||||
SOP
|
||||
SOU
|
||||
Spain SPR
|
||||
SPA
|
||||
SPB
|
||||
SPC
|
||||
SPD
|
||||
Sweden SWE
|
||||
Switzerland SWI
|
||||
Republic of Syria SYR
|
||||
Tannu Tuva TAN
|
||||
Tibet TIB
|
||||
Emirate of Transjordan JOR
|
||||
Turkey TUR
|
||||
United Kingdom ENG
|
||||
United States USA
|
||||
Uruguay URG
|
||||
Venezuela VEN
|
||||
Xibei San Ma XSM
|
||||
Yemen YEM
|
||||
Yugoslavia YUG
|
||||
Yunnan YUN
|
||||
Reference in New Issue
Block a user