mirror of
https://github.com/aclist/dztui.git
synced 2026-11-02 16:12:11 +01:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7cef215c6 | ||
|
|
90ef6cbdbb | ||
|
|
0ec1c157f4 | ||
|
|
0cf6439538 | ||
|
|
e3c1ef59ee |
No files matched your search
@@ -2,6 +2,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from warnings import deprecated
|
from warnings import deprecated
|
||||||
@@ -69,6 +70,28 @@ class ACF:
|
|||||||
except StopIteration:
|
except StopIteration:
|
||||||
return acf
|
return acf
|
||||||
|
|
||||||
|
def search_key(self, key: str) -> str:
|
||||||
|
return str(self.dict["AppState"][key])
|
||||||
|
|
||||||
|
def date_to_str(self, epoch: int) -> str | None:
|
||||||
|
if epoch == 0:
|
||||||
|
return None
|
||||||
|
return datetime.fromtimestamp(epoch).isoformat(" ")
|
||||||
|
|
||||||
|
def get_date_by_key(self, key: str) -> str | None:
|
||||||
|
try:
|
||||||
|
stamp = int(self.search_key(key))
|
||||||
|
return self.date_to_str(stamp)
|
||||||
|
except Exception as e:
|
||||||
|
logger.critical(e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_last_updated(self) -> str | None:
|
||||||
|
return self.get_date_by_key("LastUpdated")
|
||||||
|
|
||||||
|
def get_last_played(self) -> str | None:
|
||||||
|
return self.get_date_by_key("LastPlayed")
|
||||||
|
|
||||||
def get_allows_downloads(self) -> int | None:
|
def get_allows_downloads(self) -> int | None:
|
||||||
try:
|
try:
|
||||||
# TODO: consider coercing strs to ints on initial import
|
# TODO: consider coercing strs to ints on initial import
|
||||||
|
|||||||
@@ -389,6 +389,18 @@ def get_running_app() -> int | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_updated(path: Path, appid: int) -> str | None:
|
||||||
|
root_path = get_app_path(path, appid)
|
||||||
|
acf = root_path.joinpath(f"steamapps/appmanifest_{appid}.acf")
|
||||||
|
return ACF(acf).get_last_updated()
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_played(path: Path, appid: int) -> str | None:
|
||||||
|
root_path = get_app_path(path, appid)
|
||||||
|
acf = root_path.joinpath(f"steamapps/appmanifest_{appid}.acf")
|
||||||
|
return ACF(acf).get_last_played()
|
||||||
|
|
||||||
|
|
||||||
def get_app_allows_downloads(path: Path, appid: int) -> bool:
|
def get_app_allows_downloads(path: Path, appid: int) -> bool:
|
||||||
try:
|
try:
|
||||||
root_path = get_app_path(path, appid)
|
root_path = get_app_path(path, appid)
|
||||||
|
|||||||
+3
-102
@@ -3,9 +3,6 @@ import logging
|
|||||||
import re
|
import re
|
||||||
import requests
|
import requests
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
|
||||||
import sqlite3
|
|
||||||
import time
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -25,16 +22,15 @@ def find_download_url(url: str) -> str | None:
|
|||||||
return str(urls[0])
|
return str(urls[0])
|
||||||
|
|
||||||
|
|
||||||
def get_ipdb(db_path: Path) -> None:
|
def get_ipdb(ips_path: Path) -> None:
|
||||||
try:
|
try:
|
||||||
url = find_download_url(DB_IP)
|
url = find_download_url(DB_IP)
|
||||||
if url is None:
|
if url is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
ips_path = db_path.with_suffix(".csv")
|
|
||||||
month_file = db_path.parent / ".month"
|
|
||||||
date = find_date(url)
|
date = find_date(url)
|
||||||
if db_path.exists() and month_file.exists():
|
month_file = ips_path.parent / ".month"
|
||||||
|
if ips_path.exists() and month_file.exists():
|
||||||
old_date = month_file.read_text().rstrip("\n")
|
old_date = month_file.read_text().rstrip("\n")
|
||||||
if old_date == date:
|
if old_date == date:
|
||||||
logger.info(f"IP DB date matches: {date}")
|
logger.info(f"IP DB date matches: {date}")
|
||||||
@@ -49,9 +45,6 @@ def get_ipdb(db_path: Path) -> None:
|
|||||||
logger.info("Stripping IPv6 records")
|
logger.info("Stripping IPv6 records")
|
||||||
strip_ipv6(ips_path)
|
strip_ipv6(ips_path)
|
||||||
|
|
||||||
create_table(db_path, ips_path)
|
|
||||||
ips_path.unlink()
|
|
||||||
|
|
||||||
with open(month_file, "w") as f:
|
with open(month_file, "w") as f:
|
||||||
f.write(date)
|
f.write(date)
|
||||||
logger.info(f"Wrote {date} to {month_file}")
|
logger.info(f"Wrote {date} to {month_file}")
|
||||||
@@ -115,95 +108,3 @@ def strip_ipv6(path: Path) -> None:
|
|||||||
out.write(merged)
|
out.write(merged)
|
||||||
path.unlink()
|
path.unlink()
|
||||||
alt_path.rename(path)
|
alt_path.rename(path)
|
||||||
|
|
||||||
|
|
||||||
def ip_to_int(ip: str) -> int:
|
|
||||||
return int.from_bytes(socket.inet_aton(ip), "big")
|
|
||||||
|
|
||||||
|
|
||||||
def marshal_rows(ip_file: Path) -> list[tuple[int, int, str, str]]:
|
|
||||||
YIELD = 0.003
|
|
||||||
SLEEP = 0.001
|
|
||||||
with open(ip_file, "r") as f:
|
|
||||||
rows: list[tuple[int, int, str, str]] = []
|
|
||||||
# NOTE: yield to GIL periodically to reduce load on spinner
|
|
||||||
last_yield = time.monotonic()
|
|
||||||
for row in f:
|
|
||||||
start, end, lat, lon = row.rstrip("\n").split(",")
|
|
||||||
int_start = ip_to_int(start)
|
|
||||||
int_end = ip_to_int(end)
|
|
||||||
rows.append((int_start, int_end, lat, lon))
|
|
||||||
|
|
||||||
now = time.monotonic()
|
|
||||||
if (now - last_yield) >= YIELD:
|
|
||||||
time.sleep(SLEEP)
|
|
||||||
last_yield = time.monotonic()
|
|
||||||
return rows
|
|
||||||
|
|
||||||
|
|
||||||
def create_table(db_file: Path, ip_file: Path) -> None:
|
|
||||||
create = """
|
|
||||||
CREATE TABLE IF NOT EXISTS ips (
|
|
||||||
start_range INTEGER PRIMARY KEY,
|
|
||||||
end_range INTEGER,
|
|
||||||
latitude REAL,
|
|
||||||
longitude REAL
|
|
||||||
) WITHOUT ROWID;
|
|
||||||
"""
|
|
||||||
insert = """
|
|
||||||
INSERT INTO ips
|
|
||||||
(start_range, end_range, latitude, longitude)
|
|
||||||
values(?, ?, ?, ?)
|
|
||||||
"""
|
|
||||||
|
|
||||||
if db_file.exists():
|
|
||||||
db_file.unlink()
|
|
||||||
|
|
||||||
conn = sqlite3.connect(":memory:")
|
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
try:
|
|
||||||
c.execute(create)
|
|
||||||
rows = marshal_rows(ip_file)
|
|
||||||
c.executemany(insert, rows)
|
|
||||||
logger.info(f"Inserted {len(rows)} IP records into database")
|
|
||||||
conn.commit()
|
|
||||||
with sqlite3.connect(db_file) as dest:
|
|
||||||
conn.backup(dest)
|
|
||||||
logger.info(f"Serialized IP records to database: '{db_file}'")
|
|
||||||
conn.close()
|
|
||||||
except Exception as e:
|
|
||||||
logger.critical(e)
|
|
||||||
|
|
||||||
|
|
||||||
def read_from_table(db_path: Path, ip: str) -> tuple[float, float]:
|
|
||||||
if not db_path.exists():
|
|
||||||
raise FileNotFoundError(f"No file found at the location '{db_path}")
|
|
||||||
|
|
||||||
conn = sqlite3.connect(db_path)
|
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
int_ip = ip_to_int(ip)
|
|
||||||
|
|
||||||
query = """
|
|
||||||
SELECT end_range, latitude, longitude
|
|
||||||
FROM ips
|
|
||||||
WHERE start_range <= ?
|
|
||||||
ORDER BY start_range DESC
|
|
||||||
LIMIT 1
|
|
||||||
"""
|
|
||||||
index = """
|
|
||||||
CREATE INDEX IF NOT EXISTS start_index
|
|
||||||
ON ips(start_range);
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
c.execute(index)
|
|
||||||
conn.commit()
|
|
||||||
c.execute(query, (int_ip,))
|
|
||||||
row = c.fetchone()
|
|
||||||
end, lat, lon = row
|
|
||||||
conn.close()
|
|
||||||
return lat, lon
|
|
||||||
except Exception as e:
|
|
||||||
logger.critical(e)
|
|
||||||
raise e
|
|
||||||
+3
-3
@@ -22,7 +22,7 @@ class Xdg:
|
|||||||
version: Path
|
version: Path
|
||||||
system: Path
|
system: Path
|
||||||
debug: Path
|
debug: Path
|
||||||
db: Path
|
ips: Path
|
||||||
filters: Path
|
filters: Path
|
||||||
shortcut: Path
|
shortcut: Path
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ def parse_filepaths(xdg: dict) -> Xdg:
|
|||||||
resolution = state / "dzg.res.json"
|
resolution = state / "dzg.res.json"
|
||||||
history = state / "dzg.history"
|
history = state / "dzg.history"
|
||||||
versions = state / "dzg.versions"
|
versions = state / "dzg.versions"
|
||||||
db = state / "ips.db"
|
ips = state / "ips.csv"
|
||||||
filters = state / "dzg.filters.json"
|
filters = state / "dzg.filters.json"
|
||||||
|
|
||||||
shortcut = share / APP_NAME_LOWER
|
shortcut = share / APP_NAME_LOWER
|
||||||
@@ -102,7 +102,7 @@ def parse_filepaths(xdg: dict) -> Xdg:
|
|||||||
versions,
|
versions,
|
||||||
system,
|
system,
|
||||||
debug,
|
debug,
|
||||||
db,
|
ips,
|
||||||
filters,
|
filters,
|
||||||
shortcut,
|
shortcut,
|
||||||
)
|
)
|
||||||
@@ -10,10 +10,10 @@ if TYPE_CHECKING:
|
|||||||
logger = logging.getLogger(APP_NAME)
|
logger = logging.getLogger(APP_NAME)
|
||||||
|
|
||||||
|
|
||||||
def get_local_coords(db_path: "Path") -> Coords | None:
|
def get_local_coords(path: "Path") -> Coords | None:
|
||||||
try:
|
try:
|
||||||
my_ip = get_local_ip()
|
my_ip = get_local_ip()
|
||||||
return get_coords(db_path, my_ip)
|
return get_coords(path, my_ip)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn(e)
|
logger.warn(e)
|
||||||
return None
|
return None
|
||||||
+1
-1
Submodule dzgui/lib/dayzquery updated: 07483b88ed...fe413df8e8.
+2
-3
@@ -80,9 +80,8 @@ class CalcDist:
|
|||||||
if local is None:
|
if local is None:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
remote = get_coords(prefs.paths.db, remote_ip)
|
remote = get_coords(prefs.paths.ips, remote_ip)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.critical(e)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
haversine = Haversine(local.lat, local.lon, remote.lat, remote.lon)
|
haversine = Haversine(local.lat, local.lon, remote.lat, remote.lon)
|
||||||
|
|||||||
+43
-12
@@ -1,5 +1,4 @@
|
|||||||
import a2s
|
import a2s
|
||||||
from ipaddress import ip_address
|
|
||||||
import requests
|
import requests
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -8,7 +7,6 @@ from dataclasses import dataclass
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from dzgui.api.servers import Record
|
from dzgui.api.servers import Record
|
||||||
from dzgui.config.ipdb import read_from_table
|
|
||||||
from dzgui.const.constants import REQUEST_TIMEOUT
|
from dzgui.const.constants import REQUEST_TIMEOUT
|
||||||
from dzgui.const.endpoints import IP_ECHO
|
from dzgui.const.endpoints import IP_ECHO
|
||||||
|
|
||||||
@@ -35,20 +33,53 @@ def ip2list(ip: str) -> list:
|
|||||||
return [int(digit) for digit in ip.split(".")]
|
return [int(digit) for digit in ip.split(".")]
|
||||||
|
|
||||||
|
|
||||||
def is_usable(ip: str) -> bool:
|
# TODO: tests
|
||||||
address = ip_address(ip)
|
def is_reserved(digits: list) -> bool:
|
||||||
if address.is_reserved or address.is_private:
|
reserved = [0, 10, 127]
|
||||||
return False
|
|
||||||
|
if digits[0] in reserved:
|
||||||
return True
|
return True
|
||||||
|
if digits[0] == 192 and digits[1] == 168:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_coords(db_path: "Path", ip: str) -> Coords:
|
def get_coords(ips: "Path", ip: str) -> Coords:
|
||||||
if not is_usable(ip):
|
split = ip2list(ip)
|
||||||
|
|
||||||
|
if is_reserved(split):
|
||||||
raise ReservedIPError(f"{ip} is a reserved IP address.")
|
raise ReservedIPError(f"{ip} is a reserved IP address.")
|
||||||
try:
|
|
||||||
lat, lon = read_from_table(db_path, ip)
|
prefix = f"^{split[0]}.{split[1]}."
|
||||||
return Coords(lat, lon)
|
|
||||||
except Exception:
|
if shutil.which("rg") is not None:
|
||||||
|
args = ["/usr/bin/rg", prefix, str(ips)]
|
||||||
|
else:
|
||||||
|
args = ["/usr/bin/grep", "-E", prefix, str(ips)]
|
||||||
|
proc = subprocess.run(args, capture_output=True, text=True)
|
||||||
|
|
||||||
|
if proc.returncode != 0:
|
||||||
|
raise GeolocationError("Failed to split records")
|
||||||
|
|
||||||
|
ip_list = proc.stdout.splitlines()
|
||||||
|
|
||||||
|
for address in ip_list:
|
||||||
|
fields = address.split(",")
|
||||||
|
upper = fields[1]
|
||||||
|
|
||||||
|
upper_digits = ip2list(upper)
|
||||||
|
if ip == upper:
|
||||||
|
return Coords(float(fields[-2]), float(fields[-1]))
|
||||||
|
|
||||||
|
if split[2] > upper_digits[2]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if split[2] == upper_digits[2]:
|
||||||
|
if split[3] > upper_digits[3]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if split[2] <= upper_digits[2]:
|
||||||
|
return Coords(float(fields[-2]), float(fields[-1]))
|
||||||
raise GeolocationError("No matching records found")
|
raise GeolocationError("No matching records found")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ class BootDialog(ColorAwareApp, Gtk.Dialog): # type: ignore
|
|||||||
preboot.signatures,
|
preboot.signatures,
|
||||||
False,
|
False,
|
||||||
),
|
),
|
||||||
(StoredFunc(get_ipdb, self.xdg.db), preboot.geo, False),
|
(StoredFunc(get_ipdb, self.xdg.ips), preboot.geo, False),
|
||||||
# TODO: handle IP DB failure and use coords fallback
|
# TODO: handle IP DB failure and use coords fallback
|
||||||
(StoredFunc(get_local_coords, self.xdg.db), preboot.coords, True),
|
(StoredFunc(get_local_coords, self.xdg.ips), preboot.coords, True),
|
||||||
(StoredFunc(check_updates, self.version), preboot.updates, True),
|
(StoredFunc(check_updates, self.version), preboot.updates, True),
|
||||||
]
|
]
|
||||||
self.results: list[Any] = []
|
self.results: list[Any] = []
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from pathlib import Path
|
|||||||
from typing import Callable, TYPE_CHECKING
|
from typing import Callable, TYPE_CHECKING
|
||||||
|
|
||||||
from dzgui.api import pefile as PeFile
|
from dzgui.api import pefile as PeFile
|
||||||
|
from dzgui.api.steam import get_last_updated
|
||||||
|
|
||||||
from dzgui.config import query
|
from dzgui.config import query
|
||||||
from dzgui.const.constants import (
|
from dzgui.const.constants import (
|
||||||
@@ -340,8 +341,10 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
|
|||||||
[LeftLabel(options.flatpak_label), self.flatpak_toggle],
|
[LeftLabel(options.flatpak_label), self.flatpak_toggle],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.dayz_version_label = Gtk.Label(label=strings.null)
|
self.dayz_version_label = Gtk.Label(label=strings.null, halign=Gtk.Align.START)
|
||||||
self.dayz_exp_version_label = Gtk.Label(label=strings.null)
|
self.dayz_exp_version_label = Gtk.Label(
|
||||||
|
label=strings.null, halign=Gtk.Align.START
|
||||||
|
)
|
||||||
|
|
||||||
version_rows = [
|
version_rows = [
|
||||||
[LeftLabel(APPNAME_DAYZ), self.dayz_version_label],
|
[LeftLabel(APPNAME_DAYZ), self.dayz_version_label],
|
||||||
@@ -467,10 +470,18 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
|
|||||||
dayz_version = PeFile.get_pretty_version(steam_path, APPID_DAYZ)
|
dayz_version = PeFile.get_pretty_version(steam_path, APPID_DAYZ)
|
||||||
if dayz_version is None:
|
if dayz_version is None:
|
||||||
dayz_version = strings.null
|
dayz_version = strings.null
|
||||||
|
else:
|
||||||
|
last_updated = get_last_updated(steam_path, APPID_DAYZ)
|
||||||
|
if last_updated is not None:
|
||||||
|
dayz_version += f" (updated at {last_updated})"
|
||||||
|
|
||||||
dayz_exp_version = PeFile.get_pretty_version(steam_path, APPID_DAYZ_EXP)
|
dayz_exp_version = PeFile.get_pretty_version(steam_path, APPID_DAYZ_EXP)
|
||||||
if dayz_exp_version is None:
|
if dayz_exp_version is None:
|
||||||
dayz_exp_version = strings.null
|
dayz_exp_version = strings.null
|
||||||
|
else:
|
||||||
|
last_updated = get_last_updated(steam_path, APPID_DAYZ_EXP)
|
||||||
|
if last_updated is not None:
|
||||||
|
dayz_exp_version += f" (updated at {last_updated})"
|
||||||
|
|
||||||
self.dayz_version_label.set_text(dayz_version)
|
self.dayz_version_label.set_text(dayz_version)
|
||||||
self.dayz_exp_version_label.set_text(dayz_exp_version)
|
self.dayz_exp_version_label.set_text(dayz_exp_version)
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
"AppState"
|
||||||
|
{
|
||||||
|
"appid" "444"
|
||||||
|
"Universe" "1"
|
||||||
|
"name" "TEST APP"
|
||||||
|
"StateFlags" "4"
|
||||||
|
"installdir" "TESTAPP"
|
||||||
|
"LastUpdated" "1792595373"
|
||||||
|
"LastPlayed" "0"
|
||||||
|
"SizeOnDisk" "0"
|
||||||
|
"StagingSize" "0"
|
||||||
|
"buildid" "0"
|
||||||
|
"LastOwner" "0"
|
||||||
|
"DownloadType" "2"
|
||||||
|
"UpdateResult" "0"
|
||||||
|
"BytesToDownload" "0"
|
||||||
|
"BytesDownloaded" "0"
|
||||||
|
"BytesToStage" "0"
|
||||||
|
"BytesStaged" "0"
|
||||||
|
"TargetBuildID" "0"
|
||||||
|
"AutoUpdateBehavior" "0"
|
||||||
|
"AllowOtherDownloadsWhileRunning" "0"
|
||||||
|
"ScheduledAutoUpdate" "0"
|
||||||
|
"FullValidateAfterNextUpdate" "1"
|
||||||
|
"InstalledDepots"
|
||||||
|
{
|
||||||
|
"3330"
|
||||||
|
{
|
||||||
|
"manifest" "0"
|
||||||
|
"size" "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"SharedDepots"
|
||||||
|
{
|
||||||
|
"228983" "228980"
|
||||||
|
"228985" "228980"
|
||||||
|
"228988" "228980"
|
||||||
|
"228990" "228980"
|
||||||
|
"229004" "228980"
|
||||||
|
}
|
||||||
|
"UserConfig"
|
||||||
|
{
|
||||||
|
"language" "english"
|
||||||
|
"platform_override_dest" "linux"
|
||||||
|
"platform_override_source" "windows"
|
||||||
|
}
|
||||||
|
"MountedConfig"
|
||||||
|
{
|
||||||
|
"language" "english"
|
||||||
|
"platform_override_dest" "linux"
|
||||||
|
"platform_override_source" "windows"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
"AppState"
|
||||||
|
{
|
||||||
|
"appid" "555"
|
||||||
|
"Universe" "1"
|
||||||
|
"name" "TEST APP"
|
||||||
|
"StateFlags" "4"
|
||||||
|
"installdir" "TESTAPP"
|
||||||
|
"LastUpdated" "0"
|
||||||
|
"LastPlayed" "0"
|
||||||
|
"SizeOnDisk" "0"
|
||||||
|
"StagingSize" "0"
|
||||||
|
"buildid" "0"
|
||||||
|
"LastOwner" "0"
|
||||||
|
"DownloadType" "2"
|
||||||
|
"UpdateResult" "0"
|
||||||
|
"BytesToDownload" "0"
|
||||||
|
"BytesDownloaded" "0"
|
||||||
|
"BytesToStage" "0"
|
||||||
|
"BytesStaged" "0"
|
||||||
|
"TargetBuildID" "0"
|
||||||
|
"AutoUpdateBehavior" "0"
|
||||||
|
"AllowOtherDownloadsWhileRunning" "0"
|
||||||
|
"ScheduledAutoUpdate" "0"
|
||||||
|
"FullValidateAfterNextUpdate" "1"
|
||||||
|
"InstalledDepots"
|
||||||
|
{
|
||||||
|
"3330"
|
||||||
|
{
|
||||||
|
"manifest" "0"
|
||||||
|
"size" "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"SharedDepots"
|
||||||
|
{
|
||||||
|
"228983" "228980"
|
||||||
|
"228985" "228980"
|
||||||
|
"228988" "228980"
|
||||||
|
"228990" "228980"
|
||||||
|
"229004" "228980"
|
||||||
|
}
|
||||||
|
"UserConfig"
|
||||||
|
{
|
||||||
|
"language" "english"
|
||||||
|
"platform_override_dest" "linux"
|
||||||
|
"platform_override_source" "windows"
|
||||||
|
}
|
||||||
|
"MountedConfig"
|
||||||
|
{
|
||||||
|
"language" "english"
|
||||||
|
"platform_override_dest" "linux"
|
||||||
|
"platform_override_source" "windows"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import pytest
|
|||||||
from _pytest.monkeypatch import MonkeyPatch
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from dzgui.api.steam import get_app_allows_downloads
|
from dzgui.api.steam import get_app_allows_downloads, get_last_updated
|
||||||
from tests.fixtures import fixture_path
|
from tests.fixtures import fixture_path
|
||||||
|
|
||||||
pytestmark = pytest.mark.apitest
|
pytestmark = pytest.mark.apitest
|
||||||
@@ -43,6 +43,14 @@ def patch_api() -> None:
|
|||||||
mp.undo()
|
mp.undo()
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_last_update(steam_path) -> None:
|
||||||
|
assert get_last_updated(steam_path, 555) is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_last_update(steam_path) -> None:
|
||||||
|
assert get_last_updated(steam_path, 444) == "2026-10-22 00:09:33"
|
||||||
|
|
||||||
|
|
||||||
def test_app_allows_downloads(steam_path) -> None:
|
def test_app_allows_downloads(steam_path) -> None:
|
||||||
assert get_app_allows_downloads(steam_path, 111) is True
|
assert get_app_allows_downloads(steam_path, 111) is True
|
||||||
|
|
||||||
|
|||||||
+7
-44
@@ -1,40 +1,16 @@
|
|||||||
|
from dzgui.config.ipdb import get_ipdb
|
||||||
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
import sqlite3
|
|
||||||
import pytest
|
import pytest
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from dzgui.const.endpoints import DB_IP
|
|
||||||
from dzgui.config.ipdb import (
|
|
||||||
create_table,
|
|
||||||
find_download_url,
|
|
||||||
serialize,
|
|
||||||
strip_ipv6,
|
|
||||||
unzip,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_db_len(path: Path) -> int:
|
|
||||||
conn = sqlite3.connect(path)
|
|
||||||
c = conn.cursor()
|
|
||||||
c.execute("SELECT COUNT(*) from ips")
|
|
||||||
db_len = c.fetchone()[0]
|
|
||||||
return db_len
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def csv() -> Path:
|
|
||||||
csv = Path(tempfile.NamedTemporaryFile().name)
|
|
||||||
url = find_download_url(DB_IP)
|
|
||||||
tmp = serialize(url)
|
|
||||||
unzip(tmp, csv)
|
|
||||||
strip_ipv6(csv)
|
|
||||||
return csv
|
|
||||||
|
|
||||||
@pytest.mark.slow
|
@pytest.mark.slow
|
||||||
def test_stripping(csv):
|
def test_stripping():
|
||||||
with open(csv, "rb") as f:
|
d = tempfile.TemporaryDirectory()
|
||||||
|
path = Path(d.name).joinpath("ips.csv")
|
||||||
|
get_ipdb(path)
|
||||||
|
with open(path, "rb") as f:
|
||||||
first = f.readline().decode().rstrip()
|
first = f.readline().decode().rstrip()
|
||||||
try:
|
try:
|
||||||
f.seek(-2, os.SEEK_END)
|
f.seek(-2, os.SEEK_END)
|
||||||
@@ -49,16 +25,3 @@ def test_stripping(csv):
|
|||||||
|
|
||||||
assert first_els[0] == "0.0.0.0"
|
assert first_els[0] == "0.0.0.0"
|
||||||
assert last_els[0] == "224.0.0.0"
|
assert last_els[0] == "224.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.slow
|
|
||||||
def test_row_parity(csv) -> None:
|
|
||||||
rows = csv.read_text().splitlines()
|
|
||||||
|
|
||||||
db = Path(tempfile.NamedTemporaryFile().name)
|
|
||||||
create_table(db, csv)
|
|
||||||
|
|
||||||
csv_len = len(rows)
|
|
||||||
db_len = get_db_len(db)
|
|
||||||
|
|
||||||
assert csv_len == db_len
|
|
||||||
Reference in new issue
Block a user