mirror of
https://github.com/rangermix/TwitchDropsMiner.git
synced 2026-05-26 23:19:39 +00:00
145 lines
4.4 KiB
Python
Executable File
145 lines
4.4 KiB
Python
Executable File
# -*- mode: python ; coding: utf-8 -*-
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import platform
|
|
import fnmatch
|
|
from pathlib import Path
|
|
from collections import abc
|
|
from traceback import format_exc
|
|
from typing import Any, TypeAlias, TYPE_CHECKING
|
|
|
|
SELF_PATH = str(Path(".").resolve())
|
|
if SELF_PATH not in sys.path:
|
|
sys.path.insert(0, SELF_PATH)
|
|
|
|
from constants import WORKING_DIR, SITE_PACKAGES_PATH, DEFAULT_LANG
|
|
|
|
if TYPE_CHECKING:
|
|
from PyInstaller.building.splash import Splash
|
|
from PyInstaller.building.build_main import Analysis
|
|
from PyInstaller.building.datastruct import _TOCTuple
|
|
from PyInstaller.building.api import PYZ, EXE, COLLECT
|
|
|
|
|
|
PYZTypeCOLLECT: TypeAlias = "abc.Iterable[_TOCTuple] | PYZ"
|
|
PYZTypeEXE: TypeAlias = "abc.Iterable[_TOCTuple] | PYZ | Splash"
|
|
|
|
|
|
# Simple configuration
|
|
upx: bool = False # Use UPX compression (reduces file size, may increase AV detections)
|
|
console: bool = False # True if you'd want to add a console window (useful for debugging)
|
|
one_dir: bool = False # True for one-dir, False for one-file
|
|
optimize: int | None = None # -1/None/0=none, 1=remove asserts, 2=also remove docstrings
|
|
app_name: str = "Twitch Drops Miner (by DevilXD)"
|
|
|
|
|
|
# (source_path, dest_path, required)
|
|
to_add: list[tuple[Path, str, bool]] = [
|
|
# icon files
|
|
(Path("icons/pickaxe.ico"), "./icons", True),
|
|
(Path("icons/active.ico"), "./icons", True),
|
|
(Path("icons/idle.ico"), "./icons", True),
|
|
(Path("icons/error.ico"), "./icons", True),
|
|
(Path("icons/maint.ico"), "./icons", True),
|
|
# SeleniumWire HTTPS/SSL cert file and key
|
|
(Path(SITE_PACKAGES_PATH, "seleniumwire/ca.crt"), "./seleniumwire", False),
|
|
(Path(SITE_PACKAGES_PATH, "seleniumwire/ca.key"), "./seleniumwire", False),
|
|
]
|
|
for lang_filepath in WORKING_DIR.joinpath("lang").glob("*.json"):
|
|
if lang_filepath.stem != DEFAULT_LANG:
|
|
to_add.append((lang_filepath, "lang", True))
|
|
|
|
# Ensure the required to-be-added data exists
|
|
datas: list[tuple[Path, str]] = []
|
|
for source_path, dest_path, required in to_add:
|
|
if source_path.exists():
|
|
datas.append((source_path, dest_path))
|
|
elif required:
|
|
raise FileNotFoundError(str(source_path))
|
|
|
|
hooksconfig: dict[str, Any] = {}
|
|
binaries: list[tuple[Path, str]] = []
|
|
hiddenimports: list[str] = [
|
|
"PIL._tkinter_finder",
|
|
"setuptools._distutils.log",
|
|
"setuptools._distutils.dir_util",
|
|
"setuptools._distutils.file_util",
|
|
"setuptools._distutils.archive_util",
|
|
]
|
|
|
|
if sys.platform == "linux":
|
|
# Needed files for better system tray support on Linux via pystray (AppIndicator backend).
|
|
arch: str = platform.machine()
|
|
libraries_path: Path = Path(f"/usr/lib/{arch}-linux-gnu")
|
|
if not libraries_path.exists():
|
|
libraries_path = Path("/usr/lib64")
|
|
datas.append(
|
|
(libraries_path / "girepository-1.0/AyatanaAppIndicator3-0.1.typelib", "gi_typelibs")
|
|
)
|
|
binaries.append((libraries_path / "libayatana-appindicator3.so.1", "."))
|
|
|
|
hiddenimports.extend([
|
|
"gi.repository.Gtk",
|
|
"gi.repository.GObject",
|
|
])
|
|
hooksconfig = {
|
|
"gi": {
|
|
"icons": [],
|
|
"themes": [],
|
|
"languages": ["en_US"]
|
|
}
|
|
}
|
|
|
|
a = Analysis(
|
|
["main.py"],
|
|
datas=datas,
|
|
binaries=binaries,
|
|
hooksconfig=hooksconfig,
|
|
hiddenimports=hiddenimports,
|
|
)
|
|
|
|
# Exclude unneeded Linux libraries (supports globbing)
|
|
excluded_binaries = [
|
|
"libicudata.so.*",
|
|
"libicuuc.so.*",
|
|
"librsvg-*.so.*"
|
|
]
|
|
a.binaries = [
|
|
b for b in a.binaries
|
|
if not any(fnmatch.fnmatch(b[0], pattern) for pattern in excluded_binaries)
|
|
]
|
|
if one_dir:
|
|
exe_args: PYZTypeEXE = tuple()
|
|
collect_args: PYZTypeCOLLECT = (a.datas, a.binaries)
|
|
else:
|
|
exe_args = (a.datas, a.binaries)
|
|
collect_args = tuple()
|
|
|
|
pyz = PYZ(a.pure)
|
|
try:
|
|
exe = EXE(
|
|
pyz,
|
|
a.scripts,
|
|
*exe_args,
|
|
upx=upx,
|
|
debug=False,
|
|
name=app_name,
|
|
console=console,
|
|
optimize=optimize,
|
|
exclude_binaries=one_dir,
|
|
icon="icons/pickaxe.ico",
|
|
)
|
|
except PermissionError as exc:
|
|
exc_text: str = format_exc()
|
|
if any(t in exc_text for t in ("os.remove", "os.unlink")):
|
|
raise PermissionError("Ensure the executable isn't running when rebuilding.") from exc
|
|
raise
|
|
if one_dir:
|
|
coll = COLLECT(
|
|
exe,
|
|
*collect_args,
|
|
upx=upx,
|
|
name=app_name,
|
|
)
|