Add Discord Rich Presence detail controls

This commit is contained in:
Dusk-92
2026-09-02 11:26:22 +02:00
parent b2ed9782fc
commit f3aa797317
+192
View File
@@ -18,6 +18,22 @@ class ModernWowSetupTool(WowSetupTool):
self.auction_throttle_enabled = tk.BooleanVar(master=root, value=True)
self.vmmfix_enabled = tk.BooleanVar(master=root, value=False)
self.interact_enabled = tk.BooleanVar(master=root, value=False)
# Discord Rich Presence detail choices are kept independently from the
# main WowPresence checkbox so hiding/disabling the integration never
# destroys the user's selected disclosure preferences.
self.discord_show_character_details = tk.BooleanVar(master=root, value=True)
self.discord_detail_vars = {
"name": tk.BooleanVar(master=root, value=True),
"guild": tk.BooleanVar(master=root, value=True),
"race": tk.BooleanVar(master=root, value=True),
"faction": tk.BooleanVar(master=root, value=True),
"class": tk.BooleanVar(master=root, value=True),
"level": tk.BooleanVar(master=root, value=True),
"zone": tk.BooleanVar(master=root, value=True),
}
self.discord_presence_details_frame = None
self._download_window = None
self._download_label = None
self._download_detail = None
@@ -26,6 +42,167 @@ class ModernWowSetupTool(WowSetupTool):
self._download_indeterminate = False
super().__init__(root)
def _collect_settings(self):
settings = super()._collect_settings()
settings["discord_presence"] = {
"show_character_details": bool(self.discord_show_character_details.get()),
"details": {
name: bool(var.get())
for name, var in self.discord_detail_vars.items()
},
}
return settings
def _apply_settings_dict(self, saved):
super()._apply_settings_dict(saved)
discord = saved.get("discord_presence") if isinstance(saved, dict) else None
if not isinstance(discord, dict):
return
show_details = discord.get("show_character_details")
if isinstance(show_details, bool):
self.discord_show_character_details.set(show_details)
details = discord.get("details")
if isinstance(details, dict):
for name, value in details.items():
var = self.discord_detail_vars.get(name)
if var is not None and isinstance(value, bool):
var.set(value)
def _load_wowpresence_broadcast_preferences(self, target_dir):
"""Migrate the old six-bit mask into the new seven-choice UI."""
mask = remote_packages.read_wowpresence_broadcast_flags(target_dir)
if mask is None:
return
bits = {
"name": remote_packages.WOWPRESENCE_SHARE_NAME,
"guild": remote_packages.WOWPRESENCE_SHARE_GUILD,
"faction": remote_packages.WOWPRESENCE_SHARE_FACTION,
"class": remote_packages.WOWPRESENCE_SHARE_CLASS,
"level": remote_packages.WOWPRESENCE_SHARE_LEVEL,
"zone": remote_packages.WOWPRESENCE_SHARE_ZONE,
}
for name, bit in bits.items():
self.discord_detail_vars[name].set(bool(mask & bit))
# WowPresence versions before the dedicated Race flag always exposed
# race information regardless of the six-bit mask. Treat masks <= 63
# as legacy so the migration preserves exactly that visible behavior.
if mask <= 63:
self.discord_detail_vars["race"].set(True)
else:
self.discord_detail_vars["race"].set(
bool(mask & remote_packages.WOWPRESENCE_SHARE_RACE)
)
# A legacy mask never had a separate master switch. Keeping this on
# preserves the previous display while still allowing all individual
# choices to be edited.
self.discord_show_character_details.set(True)
def _load_legacy_install_state(self, target_dir):
super()._load_legacy_install_state(target_dir)
self._load_wowpresence_broadcast_preferences(target_dir)
def load_settings(self, target_dir):
settings_path = self._settings_path(target_dir)
has_saved_discord_preferences = False
try:
with open(settings_path, "r", encoding="utf-8") as handle:
saved = json.load(handle)
has_saved_discord_preferences = isinstance(
saved.get("discord_presence") if isinstance(saved, dict) else None,
dict,
)
except (OSError, json.JSONDecodeError, ValueError, TypeError):
pass
loaded = super().load_settings(target_dir)
# Existing v2.1 settings.json files predate the detailed controls. Read
# their actual WowPresence mask once so manual choices are not lost.
if os.path.isfile(settings_path) and not has_saved_discord_preferences:
self._load_wowpresence_broadcast_preferences(target_dir)
self.update_discord_presence_controls()
return loaded
def _discord_broadcast_mask(self):
if not self.discord_show_character_details.get():
return 0
bits = {
"name": remote_packages.WOWPRESENCE_SHARE_NAME,
"guild": remote_packages.WOWPRESENCE_SHARE_GUILD,
"race": remote_packages.WOWPRESENCE_SHARE_RACE,
"faction": remote_packages.WOWPRESENCE_SHARE_FACTION,
"class": remote_packages.WOWPRESENCE_SHARE_CLASS,
"level": remote_packages.WOWPRESENCE_SHARE_LEVEL,
"zone": remote_packages.WOWPRESENCE_SHARE_ZONE,
}
mask = 0
for name, bit in bits.items():
var = self.discord_detail_vars.get(name)
if var is not None and var.get():
mask |= bit
return mask
def update_discord_presence_controls(self):
frame = getattr(self, "discord_presence_details_frame", None)
if frame is None:
return
var = self.optional_plugins.get("WowPresence.dll")
visible = bool(var is not None and var.get())
manager = frame.winfo_manager()
if visible and not manager:
frame.pack(fill="x", padx=(22, 8), pady=(0, 4))
elif not visible and manager:
frame.pack_forget()
def _build_discord_presence_details(self, parent):
frame = ttk.Frame(parent)
self.discord_presence_details_frame = frame
show_cb = ttk.Checkbutton(
frame,
text="Show character details",
variable=self.discord_show_character_details,
)
show_cb.pack(anchor="w", padx=6, pady=(1, 2))
ToolTip(
show_cb,
"Controls whether the selected character details are published to Discord. "
"The choices below stay available even when this is unchecked.",
)
labels = {
"name": "Character Name",
"guild": "Guild",
"race": "Race",
"faction": "Faction",
"class": "Class",
"level": "Level",
"zone": "Zone",
}
for name, label in labels.items():
cb = ttk.Checkbutton(
frame,
text=label,
variable=self.discord_detail_vars[name],
)
cb.pack(anchor="w", padx=24, pady=1)
ToolTip(
cb,
f"Choose whether WowPresence may publish your {label.lower()} on Discord.",
)
self.update_discord_presence_controls()
def _show_download_progress(self):
if self._download_window is not None and self._download_window.winfo_exists():
return
@@ -303,14 +480,24 @@ class ModernWowSetupTool(WowSetupTool):
for dll, var in self.optional_plugins.items():
if dll == "no1600x1200.dll":
continue
command = (
self.update_discord_presence_controls
if dll == "WowPresence.dll"
else None
)
self._plugin_row(
right_frame,
optional_display.get(dll, os.path.splitext(dll)[0]),
var,
optional_attribution.get(dll, "by MarcelineVQ"),
self.descriptions.get(dll, ""),
command=command,
)
if dll == "WowPresence.dll":
self._build_discord_presence_details(right_frame)
def clean_unselected_files(self, target):
super().clean_unselected_files(target)
@@ -867,6 +1054,11 @@ class ModernWowSetupTool(WowSetupTool):
os.remove(legacy_path)
except OSError:
pass
remote_packages.write_wowpresence_broadcast_flags(
target,
self._discord_broadcast_mask(),
)
else:
source_dll = os.path.join(payload_weirdu, dll_name)
if os.path.exists(source_dll):