mirror of
https://github.com/aclist/dztui.git
synced 2026-08-30 11:47:17 +02:00
Compare commits
No commits in common. "c97e34c33604f6feba03848c5729912af04ea0bb" and "3b4a736ce6036cdb2acb8cd00930ffea14e93933" have entirely different histories.
c97e34c336
...
3b4a736ce6
40
dzgui/api/bm.py
Normal file
40
dzgui/api/bm.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
from typing import Any, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
from dzgui.const.constants import APP_NAME
|
||||||
|
from dzgui.const.endpoints import BM_SERVERS
|
||||||
|
|
||||||
|
logger = logging.getLogger(APP_NAME)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from dzgui.api.servers import Record
|
||||||
|
|
||||||
|
|
||||||
|
def get_attributes(key: str, uid: int) -> Any:
|
||||||
|
# TODO: handle if key is not set
|
||||||
|
# TODO: tests for malformed IDs/values
|
||||||
|
|
||||||
|
hdr = {"Authorization": "Bearer " + key}
|
||||||
|
payload: dict[str, str] = {
|
||||||
|
"filter[game]": "dayz",
|
||||||
|
"sort": "-players",
|
||||||
|
"filter[ids][whitelist]": str(uid),
|
||||||
|
}
|
||||||
|
res = requests.get(BM_SERVERS, params=payload, headers=hdr)
|
||||||
|
res.raise_for_status()
|
||||||
|
j = res.json()["data"][0]["attributes"]
|
||||||
|
return j
|
||||||
|
|
||||||
|
|
||||||
|
def map_id_to_record(key: str, uid: int) -> Optional["Record"]:
|
||||||
|
from dzgui.api.servers import Record
|
||||||
|
|
||||||
|
try:
|
||||||
|
record = get_attributes(key, uid)
|
||||||
|
ip = record["ip"]
|
||||||
|
port = int(record["port"])
|
||||||
|
qport = int(record["portQuery"])
|
||||||
|
return Record(ip, port, qport)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
@ -41,6 +41,21 @@ def test_ipdb() -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_bm_api(key: str) -> bool:
|
||||||
|
payload: dict[str, str] = {
|
||||||
|
"filter[game]": "dayz",
|
||||||
|
}
|
||||||
|
hdr = {"Authorization": "Bearer " + key}
|
||||||
|
try:
|
||||||
|
res = requests.get(
|
||||||
|
endpoints.BM_SERVERS, params=payload, headers=hdr, timeout=REQUEST_TIMEOUT
|
||||||
|
)
|
||||||
|
return is_remote_up(res)
|
||||||
|
except Exception as e:
|
||||||
|
logger.critical(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_remote_up(res: "Response") -> bool:
|
def is_remote_up(res: "Response") -> bool:
|
||||||
if res.status_code == 200:
|
if res.status_code == 200:
|
||||||
return True
|
return True
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import threading
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Optional, TYPE_CHECKING, Union
|
from typing import Any, Optional, TYPE_CHECKING, Union
|
||||||
|
|
||||||
|
from dzgui.api.bm import map_id_to_record
|
||||||
from dzgui.const.constants import APP_NAME, REQUEST_TIMEOUT
|
from dzgui.const.constants import APP_NAME, REQUEST_TIMEOUT
|
||||||
from dzgui.const.endpoints import STEAM_SERVERS
|
from dzgui.const.endpoints import STEAM_SERVERS
|
||||||
from dzgui.util.format import format_exception
|
from dzgui.util.format import format_exception
|
||||||
@ -477,6 +478,16 @@ def query_by_ip(addr: str) -> A2SInfo:
|
|||||||
return query_by_record(record, update_gameport=True)
|
return query_by_record(record, update_gameport=True)
|
||||||
|
|
||||||
|
|
||||||
|
def query_by_id(server_id: int, key: str) -> A2SInfo:
|
||||||
|
"""
|
||||||
|
Used with numeric Battlemetrics IDs
|
||||||
|
"""
|
||||||
|
record = map_id_to_record(key, server_id)
|
||||||
|
if record is None:
|
||||||
|
return A2SInfo(Record("0", 0, 0), None)
|
||||||
|
return query_by_record(record)
|
||||||
|
|
||||||
|
|
||||||
def query_by_record(record: Record, update_gameport: bool = False) -> A2SInfo:
|
def query_by_record(record: Record, update_gameport: bool = False) -> A2SInfo:
|
||||||
try:
|
try:
|
||||||
info = a2s.info((record.ip, record.qport), 3.0)
|
info = a2s.info((record.ip, record.qport), 3.0)
|
||||||
|
|||||||
@ -42,7 +42,6 @@ def rc2json(file: Path) -> str:
|
|||||||
|
|
||||||
toggles = ["fullscreen"]
|
toggles = ["fullscreen"]
|
||||||
deprecated = [
|
deprecated = [
|
||||||
"api_key",
|
|
||||||
"staging_dir",
|
"staging_dir",
|
||||||
"src_path",
|
"src_path",
|
||||||
"steam_path",
|
"steam_path",
|
||||||
@ -67,6 +66,8 @@ def rc2json(file: Path) -> str:
|
|||||||
value = str2bool(ntok)
|
value = str2bool(ntok)
|
||||||
elif tok == "preferred_client":
|
elif tok == "preferred_client":
|
||||||
tok = "client"
|
tok = "client"
|
||||||
|
elif tok == "api_key":
|
||||||
|
tok = "bm_api"
|
||||||
elif tok == "ip_list":
|
elif tok == "ip_list":
|
||||||
while True:
|
while True:
|
||||||
ntok = lex.get_token()
|
ntok = lex.get_token()
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import textwrap
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from dzgui.const.constants import APP_NAME
|
||||||
from dzgui.util.dirs import copy_dzgui_to_xdg_data, find_icon_resource, make_parents
|
from dzgui.util.dirs import copy_dzgui_to_xdg_data, find_icon_resource, make_parents
|
||||||
|
|
||||||
|
|
||||||
@ -36,8 +37,7 @@ def write_desktop_file(exe_path: Path) -> Path:
|
|||||||
|
|
||||||
def write_desktop_shortcut(desktop_file: Path) -> None:
|
def write_desktop_shortcut(desktop_file: Path) -> None:
|
||||||
# NOTE: necessarily depends on the above (UI blocks creation without XDG entry first)
|
# NOTE: necessarily depends on the above (UI blocks creation without XDG entry first)
|
||||||
link = Path.home().joinpath("Desktop/dzgui.desktop")
|
link = Path.home().joinpath(f"Desktop/{APP_NAME}.desktop")
|
||||||
make_parents(link)
|
|
||||||
if link.exists():
|
if link.exists():
|
||||||
link.unlink()
|
link.unlink()
|
||||||
link.symlink_to(desktop_file)
|
link.symlink_to(desktop_file)
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
Generic defaults used when initializing a config file from scratch
|
Generic defaults used when initializing a config file from scratch
|
||||||
"""
|
"""
|
||||||
config_boilerplate = {
|
config_boilerplate = {
|
||||||
|
"bm_api": "",
|
||||||
"fav_server": "",
|
"fav_server": "",
|
||||||
"fav_label": "",
|
"fav_label": "",
|
||||||
"name": "",
|
"name": "",
|
||||||
|
|||||||
@ -7,6 +7,7 @@ SUB_ENDPOINT = "https://api.steampowered.com/IPublishedFileService/Subscribe/v1"
|
|||||||
UNSUB_ENDPOINT = "https://api.steampowered.com/IPublishedFileService/Unsubscribe/v1"
|
UNSUB_ENDPOINT = "https://api.steampowered.com/IPublishedFileService/Unsubscribe/v1"
|
||||||
APP_DETAILS = "https://store.steampowered.com/api/appdetails?"
|
APP_DETAILS = "https://store.steampowered.com/api/appdetails?"
|
||||||
|
|
||||||
|
BM_SERVERS = "https://api.battlemetrics.com/servers?"
|
||||||
GITHUB = "https://github.com/aclist"
|
GITHUB = "https://github.com/aclist"
|
||||||
GITHUB_RELEASES = "https://api.github.com/repos/aclist/dztui/releases/latest"
|
GITHUB_RELEASES = "https://api.github.com/repos/aclist/dztui/releases/latest"
|
||||||
CODEBERG_RELEASES = "https://codeberg.org/api/v1/repos/aclist/dzgui/releases/latest"
|
CODEBERG_RELEASES = "https://codeberg.org/api/v1/repos/aclist/dzgui/releases/latest"
|
||||||
@ -26,3 +27,5 @@ GITHUB_ISSUES = "https://github.com/aclist/dzgui/issues"
|
|||||||
FORUM = "https://old.reddit.com/r/dzgui"
|
FORUM = "https://old.reddit.com/r/dzgui"
|
||||||
SPONSORS = "https://github.com/sponsors/aclist"
|
SPONSORS = "https://github.com/sponsors/aclist"
|
||||||
STEAM_API_SETUP = "https://steamcommunity.com/dev/apikey"
|
STEAM_API_SETUP = "https://steamcommunity.com/dev/apikey"
|
||||||
|
BM_API_SETUP = "https://www.battlemetrics.com/developers"
|
||||||
|
BM_BROWSE = "https://www.battlemetrics.com/servers/dayz"
|
||||||
|
|||||||
@ -61,6 +61,9 @@ class Preferences(EnumWithAttrs):
|
|||||||
STEAM = {
|
STEAM = {
|
||||||
"key": "steam_api",
|
"key": "steam_api",
|
||||||
}
|
}
|
||||||
|
BM = {
|
||||||
|
"key": "bm_api",
|
||||||
|
}
|
||||||
CLIENT = {
|
CLIENT = {
|
||||||
"key": "client",
|
"key": "client",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -413,7 +413,7 @@ class Controller(GObject.GObject):
|
|||||||
|
|
||||||
def add_by_str(self, addr: str) -> None:
|
def add_by_str(self, addr: str) -> None:
|
||||||
saved_tree = self.get_servers().get_saved()
|
saved_tree = self.get_servers().get_saved()
|
||||||
ServerModelManager(self, saved_tree).add_by_ip(addr)
|
ServerModelManager(self, saved_tree).add_by_str(addr)
|
||||||
|
|
||||||
def add_by_record(self, record: "Record") -> None:
|
def add_by_record(self, record: "Record") -> None:
|
||||||
saved_tree = self.get_servers().get_saved()
|
saved_tree = self.get_servers().get_saved()
|
||||||
@ -437,6 +437,12 @@ class Controller(GObject.GObject):
|
|||||||
ServerModelManager(self, tv).remove_from_history(record)
|
ServerModelManager(self, tv).remove_from_history(record)
|
||||||
|
|
||||||
def connect_by_str(self, addr: str) -> None:
|
def connect_by_str(self, addr: str) -> None:
|
||||||
|
if addr.isdigit():
|
||||||
|
config_man = self.get_config_man()
|
||||||
|
key = config_man.lookup(Preferences.BM)
|
||||||
|
self.connection_man = ConnectionManager(self)
|
||||||
|
self.connection_man.connect_by_id(int(addr), key)
|
||||||
|
else:
|
||||||
self.connection_man = ConnectionManager(self)
|
self.connection_man = ConnectionManager(self)
|
||||||
self.connection_man.connect_by_ip(addr)
|
self.connection_man.connect_by_ip(addr)
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ from dzgui.const.constants import (
|
|||||||
WINDOW_DEFAULT_X,
|
WINDOW_DEFAULT_X,
|
||||||
WINDOW_DEFAULT_Y,
|
WINDOW_DEFAULT_Y,
|
||||||
)
|
)
|
||||||
from dzgui.api.probe import test_steam_api
|
from dzgui.api.probe import test_steam_api, test_bm_api
|
||||||
from dzgui.const.enum import Preferences
|
from dzgui.const.enum import Preferences
|
||||||
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
|
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
|
||||||
from dzgui.views.dialogs.generic import ExceptionDialog
|
from dzgui.views.dialogs.generic import ExceptionDialog
|
||||||
@ -102,6 +102,8 @@ class ConfigManager:
|
|||||||
def update_api_key(self, key: Preferences, text: str) -> None:
|
def update_api_key(self, key: Preferences, text: str) -> None:
|
||||||
if key is Preferences.STEAM:
|
if key is Preferences.STEAM:
|
||||||
res = test_steam_api(text)
|
res = test_steam_api(text)
|
||||||
|
else:
|
||||||
|
res = test_bm_api(text)
|
||||||
if res is True:
|
if res is True:
|
||||||
self.update_config(key, text)
|
self.update_config(key, text)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -103,6 +103,11 @@ class ConnectionManager:
|
|||||||
self.remote_mod_ids: list[str] = []
|
self.remote_mod_ids: list[str] = []
|
||||||
self.missing_mods: list[tuple[str, str, int, int]] = []
|
self.missing_mods: list[tuple[str, str, int, int]] = []
|
||||||
|
|
||||||
|
@call_on_thread(dialog.querying)
|
||||||
|
def connect_by_id(self, _id: int, key: str) -> None:
|
||||||
|
res = Servers.query_by_id(_id, key)
|
||||||
|
self._prepare_connection(res)
|
||||||
|
|
||||||
@call_on_thread(dialog.querying)
|
@call_on_thread(dialog.querying)
|
||||||
def connect_by_ip(self, addr: str) -> None:
|
def connect_by_ip(self, addr: str) -> None:
|
||||||
res = Servers.query_by_ip(addr)
|
res = Servers.query_by_ip(addr)
|
||||||
@ -181,6 +186,7 @@ class ConnectionManager:
|
|||||||
else:
|
else:
|
||||||
allows_downloads = (True, "")
|
allows_downloads = (True, "")
|
||||||
|
|
||||||
|
|
||||||
client_name = self.controller.get_steam_client_name()
|
client_name = self.controller.get_steam_client_name()
|
||||||
client = self.controller.query_config(Preferences.CLIENT)
|
client = self.controller.query_config(Preferences.CLIENT)
|
||||||
running = is_steam_running(client)
|
running = is_steam_running(client)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from typing import Any, TYPE_CHECKING, Union
|
from typing import Any, TYPE_CHECKING, Union
|
||||||
|
from warnings import deprecated
|
||||||
|
|
||||||
from dzgui.const.enum import FilterMode
|
from dzgui.const.enum import FilterMode
|
||||||
from dzgui.model.model_factory import ModelFactory
|
from dzgui.model.model_factory import ModelFactory
|
||||||
|
|||||||
@ -191,6 +191,13 @@ class ServerModelManager:
|
|||||||
parsed = Servers.parse_json(servers)
|
parsed = Servers.parse_json(servers)
|
||||||
self._push_data(parsed)
|
self._push_data(parsed)
|
||||||
|
|
||||||
|
@call_on_thread(dialog.querying)
|
||||||
|
def add_by_id(self, _id: str) -> None:
|
||||||
|
config_man = self.controller.get_config_man()
|
||||||
|
key = config_man.lookup(Preferences.BM)
|
||||||
|
res = Servers.query_by_id(int(_id), key)
|
||||||
|
self._parse_single_record(res)
|
||||||
|
|
||||||
@call_on_thread(dialog.querying)
|
@call_on_thread(dialog.querying)
|
||||||
def add_by_ip(self, addr: str) -> None:
|
def add_by_ip(self, addr: str) -> None:
|
||||||
res = Servers.query_by_ip(addr)
|
res = Servers.query_by_ip(addr)
|
||||||
@ -256,6 +263,12 @@ class ServerModelManager:
|
|||||||
proxy_man.remove_row_from_control(record)
|
proxy_man.remove_row_from_control(record)
|
||||||
self.update_history()
|
self.update_history()
|
||||||
|
|
||||||
|
def add_by_str(self, addr: str) -> None:
|
||||||
|
if addr.isdigit():
|
||||||
|
self.add_by_id(addr)
|
||||||
|
else:
|
||||||
|
self.add_by_ip(addr)
|
||||||
|
|
||||||
@call_on_thread(dialog.querying)
|
@call_on_thread(dialog.querying)
|
||||||
def update_playercount(
|
def update_playercount(
|
||||||
self, treeiter: Gtk.TreeIter, record: Servers.Record
|
self, treeiter: Gtk.TreeIter, record: Servers.Record
|
||||||
|
|||||||
@ -5,9 +5,10 @@ add_tooltip="Add to Saved Servers"
|
|||||||
connect_button="Connect"
|
connect_button="Connect"
|
||||||
connect_tooltip="Connect to this server"
|
connect_tooltip="Connect to this server"
|
||||||
connect_entry_tooltip=(
|
connect_entry_tooltip=(
|
||||||
"- IP: format as IP:Query port\ne.g. 192.168.1.1:27016"
|
"- IP: format as IP:Query port\ne.g. 192.168.1.1:27016\n"
|
||||||
|
"- Battlemetrics: numeric server ID\ne.g. 123456"
|
||||||
)
|
)
|
||||||
connect_entry_placeholder="Enter IP (IP:Query port)"
|
connect_entry_placeholder="Enter IP (IP:Query port) or Battlemetrics ID (numerical id)"
|
||||||
|
|
||||||
fav_heading="Favorite server"
|
fav_heading="Favorite server"
|
||||||
favs_empty="None set. Right click a server and select 'Set favorite' to set."
|
favs_empty="None set. Right click a server and select 'Set favorite' to set."
|
||||||
|
|||||||
@ -46,6 +46,11 @@ You must set up a Steam Web API key in order to browse the global server list.
|
|||||||
\nIf you don't have one already, it can be set up via the page below.
|
\nIf you don't have one already, it can be set up via the page below.
|
||||||
\nPlease refer to the DZGUI documentation for more instructions.
|
\nPlease refer to the DZGUI documentation for more instructions.
|
||||||
"""
|
"""
|
||||||
|
heading_bm_api = "Battlemetrics Web API key"
|
||||||
|
blurb_bm_api = """A Battlemetrics key is <b>optional</b>, but allows you to add/search for servers\n
|
||||||
|
by numeric ID on the web. For example, in the URL https://www.battlemetrics.net/servers/dayz/24819107,\n
|
||||||
|
the ID would be <b>24819107</b>.
|
||||||
|
"""
|
||||||
|
|
||||||
### PreferencesPage
|
### PreferencesPage
|
||||||
heading_prefs = "User preferences"
|
heading_prefs = "User preferences"
|
||||||
|
|||||||
@ -286,8 +286,11 @@ class Thanks:
|
|||||||
class Options:
|
class Options:
|
||||||
header: str
|
header: str
|
||||||
steam_web: str
|
steam_web: str
|
||||||
|
bm_web: str
|
||||||
enter_steam: str
|
enter_steam: str
|
||||||
|
enter_bm: str
|
||||||
steam_placeholder: str
|
steam_placeholder: str
|
||||||
|
bm_placeholder: str
|
||||||
name_placeholder: str
|
name_placeholder: str
|
||||||
last_used: str
|
last_used: str
|
||||||
always_fs: str
|
always_fs: str
|
||||||
@ -375,8 +378,11 @@ thanks = Thanks(
|
|||||||
options = Options(
|
options = Options(
|
||||||
header="Options",
|
header="Options",
|
||||||
steam_web="Steam API page",
|
steam_web="Steam API page",
|
||||||
|
bm_web="Battlemetrics API page",
|
||||||
enter_steam="Enter your Steam API key",
|
enter_steam="Enter your Steam API key",
|
||||||
|
enter_bm="Enter your Battlemetrics API key",
|
||||||
steam_placeholder="Steam API key",
|
steam_placeholder="Steam API key",
|
||||||
|
bm_placeholder="Battlemetrics API key",
|
||||||
name_placeholder="Identifies you to other players in-game",
|
name_placeholder="Identifies you to other players in-game",
|
||||||
last_used="Last used dimensions",
|
last_used="Last used dimensions",
|
||||||
always_fs="Always fullscreen",
|
always_fs="Always fullscreen",
|
||||||
@ -543,9 +549,10 @@ connect_panel = ConnectPanel(
|
|||||||
connect="Connect",
|
connect="Connect",
|
||||||
add="Add",
|
add="Add",
|
||||||
add_con="Add/connect",
|
add_con="Add/connect",
|
||||||
placeholder="Enter IP (IP:Query port)",
|
placeholder="Enter IP (IP:Query port) or Battlemetrics ID (numerical id)",
|
||||||
entry_tooltip=(
|
entry_tooltip=(
|
||||||
"- IP: format as IP:Query port\ne.g. 192.168.1.1:27016"
|
"- IP: format as IP:Query port\ne.g. 192.168.1.1:27016\n"
|
||||||
|
"- Battlemetrics: numeric server ID\ne.g. 123456"
|
||||||
),
|
),
|
||||||
add_tooltip="Add to Saved Servers",
|
add_tooltip="Add to Saved Servers",
|
||||||
connect_tooltip="Connect to this server",
|
connect_tooltip="Connect to this server",
|
||||||
|
|||||||
@ -26,11 +26,14 @@ def validate_port(text: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate_ip_truthy(text: str) -> bool:
|
def validate_ip_or_id(text: str) -> bool:
|
||||||
try:
|
try:
|
||||||
validate_ip(text)
|
validate_ip(text)
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
|
if text.isdigit():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -121,7 +124,7 @@ class IpEntry(ValidatedEntry):
|
|||||||
def __init__(self, controller: "Controller") -> None:
|
def __init__(self, controller: "Controller") -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
controller,
|
controller,
|
||||||
func=validate_ip_truthy,
|
func=validate_ip_or_id,
|
||||||
placeholder_text=connect_panel.placeholder,
|
placeholder_text=connect_panel.placeholder,
|
||||||
tooltip_text=connect_panel.entry_tooltip,
|
tooltip_text=connect_panel.entry_tooltip,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,7 +6,7 @@ from importlib import resources
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Self, TYPE_CHECKING
|
from typing import Any, Callable, Self, TYPE_CHECKING
|
||||||
|
|
||||||
from dzgui.api.probe import test_steam_api
|
from dzgui.api.probe import test_steam_api, test_bm_api
|
||||||
from dzgui.api.shortcuts import add_steam_shortcut
|
from dzgui.api.shortcuts import add_steam_shortcut
|
||||||
from dzgui.api.steam import get_steam_paths
|
from dzgui.api.steam import get_steam_paths
|
||||||
from dzgui.const.constants import (
|
from dzgui.const.constants import (
|
||||||
@ -16,7 +16,7 @@ from dzgui.const.constants import (
|
|||||||
LEGACY_CONFIG_PATH,
|
LEGACY_CONFIG_PATH,
|
||||||
)
|
)
|
||||||
from dzgui.const.boilerplate import config_boilerplate
|
from dzgui.const.boilerplate import config_boilerplate
|
||||||
from dzgui.const.endpoints import STEAM_API_SETUP
|
from dzgui.const.endpoints import BM_API_SETUP, STEAM_API_SETUP
|
||||||
from dzgui.const.enum import Preferences
|
from dzgui.const.enum import Preferences
|
||||||
from dzgui.config import freedesktop
|
from dzgui.config import freedesktop
|
||||||
from dzgui.config.query import lookup
|
from dzgui.config.query import lookup
|
||||||
@ -44,9 +44,10 @@ class PageNum(Enum):
|
|||||||
HAS_CONFIG = 2
|
HAS_CONFIG = 2
|
||||||
STEAM_PATH = 3
|
STEAM_PATH = 3
|
||||||
STEAM_API = 4
|
STEAM_API = 4
|
||||||
USER_PREFS = 5
|
BM_API = 5
|
||||||
SHORTCUTS = 6
|
USER_PREFS = 6
|
||||||
FINAL = 7
|
SHORTCUTS = 7
|
||||||
|
FINAL = 8
|
||||||
|
|
||||||
|
|
||||||
class OptionalPageMixin:
|
class OptionalPageMixin:
|
||||||
@ -222,6 +223,24 @@ class APIValidationPage(ScrolledWizardPage):
|
|||||||
self.spinner.stop()
|
self.spinner.stop()
|
||||||
|
|
||||||
|
|
||||||
|
class BMValidationPage(OptionalPageMixin, APIValidationPage): # type: ignore
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(
|
||||||
|
enum=PageNum.BM_API,
|
||||||
|
heading=wizard.heading_bm_api,
|
||||||
|
description=wizard.blurb_bm_api,
|
||||||
|
link=BM_API_SETUP,
|
||||||
|
func=self._validate,
|
||||||
|
)
|
||||||
|
self.connect("map", self._on_map)
|
||||||
|
|
||||||
|
@call_on_thread("", show_dialog=False)
|
||||||
|
def _validate(self, key: str) -> None:
|
||||||
|
is_valid = test_bm_api(key.strip())
|
||||||
|
cleanup = StoredFunc(self._cleanup, is_valid, key)
|
||||||
|
self.thread_man.set_cleanup_func(cleanup)
|
||||||
|
|
||||||
|
|
||||||
class SteamValidationPage(APIValidationPage):
|
class SteamValidationPage(APIValidationPage):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -446,9 +465,10 @@ class Assistant(Gtk.Assistant):
|
|||||||
self.page2 = ConfigMigrationPage(XDG.config)
|
self.page2 = ConfigMigrationPage(XDG.config)
|
||||||
self.page3 = SteamPathPage()
|
self.page3 = SteamPathPage()
|
||||||
self.page4 = SteamValidationPage()
|
self.page4 = SteamValidationPage()
|
||||||
self.page5 = PreferencesPage()
|
self.page5 = BMValidationPage()
|
||||||
self.page6 = ShortcutCreationPage(XDG.shortcut)
|
self.page6 = PreferencesPage()
|
||||||
self.page7 = CompletionPage()
|
self.page7 = ShortcutCreationPage(XDG.shortcut)
|
||||||
|
self.page8 = CompletionPage()
|
||||||
|
|
||||||
self.set_forward_page_func(self._advance_page)
|
self.set_forward_page_func(self._advance_page)
|
||||||
|
|
||||||
@ -466,6 +486,7 @@ class Assistant(Gtk.Assistant):
|
|||||||
self.page5,
|
self.page5,
|
||||||
self.page6,
|
self.page6,
|
||||||
self.page7,
|
self.page7,
|
||||||
|
self.page8,
|
||||||
):
|
):
|
||||||
# NOTE: skip config migration page if no legacy config file
|
# NOTE: skip config migration page if no legacy config file
|
||||||
if (
|
if (
|
||||||
@ -495,7 +516,7 @@ class Assistant(Gtk.Assistant):
|
|||||||
case ConfigMigrationPage():
|
case ConfigMigrationPage():
|
||||||
if page.is_migrated():
|
if page.is_migrated():
|
||||||
steam_path = lookup(self.config_path, Preferences.DEFAULT)
|
steam_path = lookup(self.config_path, Preferences.DEFAULT)
|
||||||
self.page6.set_steam_path(steam_path)
|
self.page7.set_steam_path(steam_path)
|
||||||
offset = 1 if not self.is_binary else 2
|
offset = 1 if not self.is_binary else 2
|
||||||
self.setup_complete = True
|
self.setup_complete = True
|
||||||
return self.get_n_pages() - offset
|
return self.get_n_pages() - offset
|
||||||
@ -503,14 +524,16 @@ class Assistant(Gtk.Assistant):
|
|||||||
self.config_values["default_steam_path"] = page.get_path_from_radio()
|
self.config_values["default_steam_path"] = page.get_path_from_radio()
|
||||||
case SteamValidationPage():
|
case SteamValidationPage():
|
||||||
self.config_values["steam_api"] = page.get_api_key()
|
self.config_values["steam_api"] = page.get_api_key()
|
||||||
|
case BMValidationPage():
|
||||||
|
self.config_values["bm_api"] = page.get_api_key()
|
||||||
case PreferencesPage():
|
case PreferencesPage():
|
||||||
# NOTE: collects config values before advancing to last page
|
# NOTE: collects config values before advancing to last page
|
||||||
name, use_miles, client = self.page5.get_prefs()
|
name, use_miles, client = self.page6.get_prefs()
|
||||||
self.config_values["name"] = name
|
self.config_values["name"] = name
|
||||||
self.config_values["use_miles"] = use_miles
|
self.config_values["use_miles"] = use_miles
|
||||||
self.config_values["client"] = client
|
self.config_values["client"] = client
|
||||||
self.write_config()
|
self.write_config()
|
||||||
self.page6.set_steam_path(self.config_values["default_steam_path"])
|
self.page7.set_steam_path(self.config_values["default_steam_path"])
|
||||||
self.setup_complete = True
|
self.setup_complete = True
|
||||||
case ShortcutCreationPage():
|
case ShortcutCreationPage():
|
||||||
page.create_shortcuts()
|
page.create_shortcuts()
|
||||||
|
|||||||
@ -15,7 +15,7 @@ from dzgui.const.constants import (
|
|||||||
VIEW_CONCEAL,
|
VIEW_CONCEAL,
|
||||||
VIEW_REVEAL,
|
VIEW_REVEAL,
|
||||||
)
|
)
|
||||||
from dzgui.const.endpoints import STEAM_API_SETUP
|
from dzgui.const.endpoints import STEAM_API_SETUP, BM_API_SETUP
|
||||||
from dzgui.const.enum import Preferences, ServerTab
|
from dzgui.const.enum import Preferences, ServerTab
|
||||||
from dzgui.strings import errors, options
|
from dzgui.strings import errors, options
|
||||||
from dzgui.util import strings, css, open_links
|
from dzgui.util import strings, css, open_links
|
||||||
@ -66,15 +66,23 @@ class Options(Gtk.Box):
|
|||||||
self.add(label)
|
self.add(label)
|
||||||
|
|
||||||
self.steam_entry: Gtk.Entry
|
self.steam_entry: Gtk.Entry
|
||||||
|
self.bm_entry: Gtk.Entry
|
||||||
|
|
||||||
self.steam = WebButton(label=strings.options.steam_web)
|
self.steam = WebButton(label=strings.options.steam_web)
|
||||||
self.steam.connect("clicked", self._on_link_button_clicked, STEAM_API_SETUP)
|
self.steam.connect("clicked", self._on_link_button_clicked, STEAM_API_SETUP)
|
||||||
|
|
||||||
|
self.bm = WebButton(label=strings.options.bm_web)
|
||||||
|
self.bm.connect("clicked", self._on_link_button_clicked, BM_API_SETUP)
|
||||||
|
|
||||||
self.steam_box = self._make_submit_field(
|
self.steam_box = self._make_submit_field(
|
||||||
strings.options.enter_steam, Preferences.STEAM, True
|
strings.options.enter_steam, Preferences.STEAM, True
|
||||||
)
|
)
|
||||||
|
self.bm_box = self._make_submit_field(
|
||||||
|
strings.options.enter_bm, Preferences.BM, True
|
||||||
|
)
|
||||||
api_rows = [
|
api_rows = [
|
||||||
[LeftLabel(strings.options.steam_placeholder), self.steam_box],
|
[LeftLabel(strings.options.steam_placeholder), self.steam_box],
|
||||||
|
[LeftLabel(strings.options.bm_placeholder), self.bm_box],
|
||||||
]
|
]
|
||||||
|
|
||||||
self.player_box = self._make_submit_field(
|
self.player_box = self._make_submit_field(
|
||||||
@ -146,6 +154,7 @@ class Options(Gtk.Box):
|
|||||||
spacing=10,
|
spacing=10,
|
||||||
)
|
)
|
||||||
api_links_box.add(self.steam)
|
api_links_box.add(self.steam)
|
||||||
|
api_links_box.add(self.bm)
|
||||||
api_box.add(api_links_box)
|
api_box.add(api_links_box)
|
||||||
|
|
||||||
prefs_grid = self._make_grid(pref_rows)
|
prefs_grid = self._make_grid(pref_rows)
|
||||||
@ -186,11 +195,13 @@ class Options(Gtk.Box):
|
|||||||
return str(model[ind][0])
|
return str(model[ind][0])
|
||||||
|
|
||||||
def block_text_entry(self) -> None:
|
def block_text_entry(self) -> None:
|
||||||
self.steam_entry.set_position(-1)
|
for entry in self.steam_entry, self.bm_entry:
|
||||||
self.steam_entry.set_can_focus(False)
|
entry.set_position(-1)
|
||||||
|
entry.set_can_focus(False)
|
||||||
|
|
||||||
def unblock_text_entry(self) -> None:
|
def unblock_text_entry(self) -> None:
|
||||||
self.steam_entry.set_can_focus(True)
|
for entry in self.steam_entry, self.bm_entry:
|
||||||
|
entry.set_can_focus(True)
|
||||||
|
|
||||||
def _on_developers_clicked(self, button: Gtk.Button) -> None:
|
def _on_developers_clicked(self, button: Gtk.Button) -> None:
|
||||||
self.controller.show_developers_page()
|
self.controller.show_developers_page()
|
||||||
@ -223,6 +234,8 @@ class Options(Gtk.Box):
|
|||||||
|
|
||||||
if context == Preferences.STEAM:
|
if context == Preferences.STEAM:
|
||||||
self.steam_entry = entry
|
self.steam_entry = entry
|
||||||
|
else:
|
||||||
|
self.bm_entry = entry
|
||||||
|
|
||||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||||
box.add(entry)
|
box.add(entry)
|
||||||
@ -269,7 +282,7 @@ class Options(Gtk.Box):
|
|||||||
case Preferences.NAME:
|
case Preferences.NAME:
|
||||||
value = entry.get_text().strip()
|
value = entry.get_text().strip()
|
||||||
self.controller.update_config(enum, value)
|
self.controller.update_config(enum, value)
|
||||||
case Preferences.STEAM:
|
case Preferences.BM | Preferences.STEAM:
|
||||||
text = "".join(entry.get_text().split())
|
text = "".join(entry.get_text().split())
|
||||||
self.controller.update_api_key(enum, text)
|
self.controller.update_api_key(enum, text)
|
||||||
|
|
||||||
@ -285,6 +298,9 @@ class Options(Gtk.Box):
|
|||||||
def revert(self, mode: Preferences) -> None:
|
def revert(self, mode: Preferences) -> None:
|
||||||
if mode == Preferences.STEAM:
|
if mode == Preferences.STEAM:
|
||||||
self.steam_entry.set_text(self.old_steam)
|
self.steam_entry.set_text(self.old_steam)
|
||||||
|
else:
|
||||||
|
self.bm_entry.set_text(self.old_bm)
|
||||||
|
pass
|
||||||
|
|
||||||
def _on_start_tab_changed(self, combo: Gtk.ComboBoxText) -> None:
|
def _on_start_tab_changed(self, combo: Gtk.ComboBoxText) -> None:
|
||||||
_iter = combo.get_active_iter()
|
_iter = combo.get_active_iter()
|
||||||
@ -320,6 +336,8 @@ class Options(Gtk.Box):
|
|||||||
old = self.old_name
|
old = self.old_name
|
||||||
case Preferences.STEAM:
|
case Preferences.STEAM:
|
||||||
old = self.old_steam
|
old = self.old_steam
|
||||||
|
case Preferences.BM:
|
||||||
|
old = self.old_bm
|
||||||
if text == old:
|
if text == old:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@ -383,13 +401,16 @@ class Options(Gtk.Box):
|
|||||||
name = self.controller.query_config(Preferences.NAME)
|
name = self.controller.query_config(Preferences.NAME)
|
||||||
default_steam_path = self.controller.query_config(Preferences.DEFAULT)
|
default_steam_path = self.controller.query_config(Preferences.DEFAULT)
|
||||||
steam = self.controller.query_config(Preferences.STEAM)
|
steam = self.controller.query_config(Preferences.STEAM)
|
||||||
|
bm = self.controller.query_config(Preferences.BM)
|
||||||
|
|
||||||
steam_path = Path(default_steam_path)
|
steam_path = Path(default_steam_path)
|
||||||
|
|
||||||
self.old_steam = steam
|
self.old_steam = steam
|
||||||
|
self.old_bm = bm
|
||||||
self.old_name = name
|
self.old_name = name
|
||||||
|
|
||||||
self.steam_entry.set_text(steam)
|
self.steam_entry.set_text(steam)
|
||||||
|
self.bm_entry.set_text(bm)
|
||||||
p = self.player_box.get_children()[0]
|
p = self.player_box.get_children()[0]
|
||||||
if hasattr(p, "set_text"):
|
if hasattr(p, "set_text"):
|
||||||
p.set_text(name)
|
p.set_text(name)
|
||||||
@ -407,6 +428,7 @@ class Options(Gtk.Box):
|
|||||||
for field in (
|
for field in (
|
||||||
[name, self.player_box],
|
[name, self.player_box],
|
||||||
[steam, self.steam_box],
|
[steam, self.steam_box],
|
||||||
|
[bm, self.bm_box],
|
||||||
):
|
):
|
||||||
if field[0] == "":
|
if field[0] == "":
|
||||||
field[1].get_children()[1].set_sensitive(False)
|
field[1].get_children()[1].set_sensitive(False)
|
||||||
|
|||||||
@ -21,6 +21,7 @@ def unset_values():
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def keys():
|
def keys():
|
||||||
return [
|
return [
|
||||||
|
"bm_api",
|
||||||
"fav_server",
|
"fav_server",
|
||||||
"fav_label",
|
"fav_label",
|
||||||
"name",
|
"name",
|
||||||
@ -83,6 +84,7 @@ def test_key_conversion(legacy_config):
|
|||||||
j = convert.rc2json(legacy_config)
|
j = convert.rc2json(legacy_config)
|
||||||
j = json.loads(j)
|
j = json.loads(j)
|
||||||
keys = [
|
keys = [
|
||||||
|
"api_key",
|
||||||
"staging_dir",
|
"staging_dir",
|
||||||
"src_path",
|
"src_path",
|
||||||
"steam_path",
|
"steam_path",
|
||||||
|
|||||||
@ -1,24 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from dzgui.api.servers import validate_ip
|
from dzgui.api.servers import validate_ip
|
||||||
from dzgui.views.components.entry import validate_ip_truthy
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"ip",
|
|
||||||
[
|
|
||||||
("foo", False),
|
|
||||||
("999", False),
|
|
||||||
("192.168.1.101", False),
|
|
||||||
("192.168.1.101:", False),
|
|
||||||
(":1", False),
|
|
||||||
("192.168.1.101:27016", True),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_ip_entry(ip) -> None:
|
|
||||||
string, state = ip
|
|
||||||
assert validate_ip_truthy(string) is state
|
|
||||||
|
|
||||||
|
|
||||||
def test_ip_validation() -> None:
|
def test_ip_validation() -> None:
|
||||||
ip = "192.168.1.1:100"
|
ip = "192.168.1.1:100"
|
||||||
@ -33,7 +15,6 @@ def test_invalid_port() -> None:
|
|||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
validate_ip(ip)
|
validate_ip(ip)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("port", [-1, 65536])
|
@pytest.mark.parametrize("port", [-1, 65536])
|
||||||
def test_port_out_of_range(port: int) -> None:
|
def test_port_out_of_range(port: int) -> None:
|
||||||
ip = f"192.168.1.1:{port}"
|
ip = f"192.168.1.1:{port}"
|
||||||
@ -46,7 +27,6 @@ def test_invalid_socket() -> None:
|
|||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
validate_ip(ip)
|
validate_ip(ip)
|
||||||
|
|
||||||
|
|
||||||
# TODO: ?
|
# TODO: ?
|
||||||
def test_ipdb() -> None:
|
def test_ipdb() -> None:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -21,3 +21,9 @@ def test_ipdb():
|
|||||||
def test_steam(config):
|
def test_steam(config):
|
||||||
key = config["steam_api"]
|
key = config["steam_api"]
|
||||||
assert probe.test_steam_api(key)
|
assert probe.test_steam_api(key)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bm(config):
|
||||||
|
# NOTE: see ticket #417; expected to return False
|
||||||
|
key = config["bm_api"]
|
||||||
|
assert probe.test_bm_api(key) is False
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user