From 3fea7d1f52c31e7445fb11ba4911be65d4ba65ef Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 21 Mar 2024 22:03:38 +0900 Subject: [PATCH] feat: refresh player count --- CHANGELOG.md | 8 +++++++ dzgui.sh | 6 ++--- helpers/funcs | 17 +++++++++++--- helpers/ui.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 81 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c25ff9..8bfc35b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [5.2.0] 2024-03-21 +### Added +- Refresh player count for active row: invoke via right-click context meu or directly with the Ctrl-r hotkey. This feature has a 30 second global cooldown to prevent throttling. + +### Fixed +- Improve case-insensitive keyword search to be portable across awk versions (previous version required gawk) +- Fixed a dialog string from being shown twice when adding a server to favorites via context menus + ## [5.1.1] 2024-03-18 ### Fixed - Hotfix for remote helper files not being fetched correctly diff --git a/dzgui.sh b/dzgui.sh index 3d25e6c..0d7b247 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -o pipefail -version=5.1.1 +version=5.2.0 #CONSTANTS aid=221100 @@ -537,10 +537,10 @@ fetch_helpers_by_sum(){ source "$config_file" declare -A sums sums=( - ["ui.py"]="7ffd38571285a92fea00faea8027612b" + ["ui.py"]="05a84408e1d375a38a899b715c38da6e" ["query_v2.py"]="1822bd1769ce7d7cb0d686a60f9fa197" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" - ["funcs"]="e56b8da82177ff6e6269701229bd6442" + ["funcs"]="80f1740a56e0b81d8c811ef9ac749c36" ) local author="aclist" local repo="dztui" diff --git a/helpers/funcs b/helpers/funcs index 0802284..de540a5 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -o pipefail -version=5.1.1 +version=5.2.0 #CONSTANTS aid=221100 @@ -121,8 +121,20 @@ declare -A funcs=( ["Remove from history"]="remove_from_history" ["force_update"]="force_update" ["Handshake"]="final_handshake" +["get_player_count"]="get_player_count" ) +get_player_count(){ + shift + local res + local ip="$1" + local qport="$2" + res=$(a2s $ip $qport info) + [[ ! $? -eq 0 ]] && return 1 + local players="$(<<< $res jq -r '.[].players')" + printf "%s" "$players" +} + validate_and_connect(){ local context="$1" local addr="$2" @@ -447,7 +459,7 @@ filter_servers(){ } filter_keyword(){ keyword=$(sanitize "$keyword") - <<< "$filtered" KEYWORD="$keyword" awk -F$separator 'BEGIN{IGNORECASE=1} $0 ~ ENVIRON["KEYWORD"] {print $0}' + <<< "$filtered" awk -F$separator -v keyword="$keyword" 'tolower($0) ~ tolower(keyword)' } filter_duplicates(){ if [[ ${filters[*]} =~ Duplicate ]]; then @@ -787,7 +799,6 @@ update_favs_from_table(){ echo "Removed $record from saved servers" else add_to_favs "$record" - echo "Added $record to saved servers" fi return 0 } diff --git a/helpers/ui.py b/helpers/ui.py index 7414b1a..ded35c8 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -3,10 +3,11 @@ import gi import json import locale import logging -import os -import signal +import math import multiprocessing +import os import re +import signal import subprocess import sys import textwrap @@ -17,9 +18,11 @@ locale.setlocale(locale.LC_ALL, '') gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GLib, Gdk, GObject, Pango -# 5.1.1 +# 5.2.0 app_name = "DZGUI" +start_time = 0 + cache = {} config_vals = [] stored_keys = [] @@ -691,6 +694,8 @@ class TreeView(Gtk.TreeView): ip = addr.split(':')[0] record = "%s:%s" %(ip, qport) self.clipboard.set_text(record, -1) + case "Refresh player count": + self.refresh_player_count() case "Show server-side mods": record = "%s:%s" %(self.get_column_at_index(6), self.get_column_at_index(7)) dialog = ModDialog(parent, "Enter/double click a row to open in Steam Workshop. ESC exits this dialog", "Modlist", record) @@ -729,9 +734,9 @@ class TreeView(Gtk.TreeView): self.menu = Gtk.Menu() mod_context_items = ["Open in Steam Workshop", "Delete mod"] - subcontext_items = {"Server browser": ["Add to my servers", "Copy IP to clipboard", "Show server-side mods"], - "My saved servers": ["Remove from my servers", "Copy IP to clipboard", "Show server-side mods"], - "Recent servers": ["Remove from history", "Copy IP to clipboard", "Show server-side mods"], + subcontext_items = {"Server browser": ["Add to my servers", "Copy IP to clipboard", "Show server-side mods", "Refresh player count"], + "My saved servers": ["Remove from my servers", "Copy IP to clipboard", "Show server-side mods", "Refresh player count"], + "Recent servers": ["Remove from history", "Copy IP to clipboard", "Show server-side mods", "Refresh player count"], } # submenu hierarchy https://stackoverflow.com/questions/52847909/how-to-add-a-sub-menu-to-a-gtk-menu if context == "Mod": @@ -760,6 +765,22 @@ class TreeView(Gtk.TreeView): else: self.menu.popup_at_pointer(event) + def refresh_player_count(self): + parent = self.get_outer_window() + + global start_time + then = start_time + now = time.monotonic() + diff = now - then + cooldown = 30 - math.floor(diff) + if ((start_time > 0) and (now - then) < 30): + spawn_dialog(parent, "Global refresh cooldown not met. Wait %s second(s)." %(str(cooldown)), "NOTIFY") + return + start_time = now + + thread = threading.Thread(target=self._background_player_count, args=()) + thread.start() + def get_outer_window(self): win = self.get_parent().get_parent().get_parent() return win @@ -844,6 +865,8 @@ class TreeView(Gtk.TreeView): debug.set_active(True) case Gdk.KEY_l: self._on_button_release(self, event) + case Gdk.KEY_r: + self.refresh_player_count() case Gdk.KEY_f: if self.get_first_col() == "Mod": return @@ -874,6 +897,32 @@ class TreeView(Gtk.TreeView): value = model.get_value(tree_iter, index) return value + def _background_player_count(self): + def _load(): + server_store[path][4] = int(data.stdout) + wait_dialog.destroy() + + parent = self.get_outer_window() + wait_dialog = GenericDialog(parent, "Refreshing player count", "WAIT") + wait_dialog.show_all() + select = self.get_selection() + sels = select.get_selected_rows() + (model, pathlist) = sels + if len(pathlist) < 1: + return + path = pathlist[0] + tree_iter = model.get_iter(path) + addr = server_store[path][6] + qport = server_store[path][7] + ip = addr.split(':')[0] + qport = str(qport) + + data = call_out(self, "get_player_count", ip, qport) + if data.returncode == 1: + wait_dialog.destroy() + return + GLib.idle_add(_load) + def _background(self, dialog, mode): def loadTable(): for map in maps: @@ -1330,6 +1379,7 @@ def KeysDialog(parent, text, mode): Ctrl-f: jump to keyword field Ctrl-m: jump to maps dropdown Ctrl-d: toggle dry run (debug) mode + Ctrl-r: refresh player count for active row 1-9: toggle filter ON/OFF ESC: jump back to main view from keyword/maps """