Implement exclude argument
This commit is contained in:
1 parent
fdc9dabd49
commit
83b8de11a1
4 files changed
+81
-32
No files matched your search
Vendored
+1
-1
@@ -51,7 +51,7 @@
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "main.py",
|
||||
"args": ["--wrong"],
|
||||
"args": ["--excludes", "1", "2", "3"],
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": false
|
||||
},
|
||||
|
||||
@@ -262,6 +262,7 @@ class GameSelector:
|
||||
self._list.pack(fill="both", expand=True)
|
||||
self._selection: Optional[str] = self._manager._twitch.options.game
|
||||
self._games: OrderedDict[str, Game] = OrderedDict()
|
||||
self._excluded: Set[int] = set()
|
||||
self._list.bind("<<ListboxSelect>>", self._on_select)
|
||||
|
||||
def set_games(self, games: Iterable[Game]):
|
||||
@@ -270,30 +271,42 @@ class GameSelector:
|
||||
self._list.delete(0, "end")
|
||||
self._list.insert("end", *self._games.keys())
|
||||
self._list.config(width=0) # autoadjust listbox width
|
||||
if self._selection is not None:
|
||||
selected_index: Optional[int] = next(
|
||||
(
|
||||
i
|
||||
for i, str_game in enumerate(self._games.keys())
|
||||
if str_game == self._selection
|
||||
),
|
||||
None,
|
||||
)
|
||||
# process excluded games and relink the selection
|
||||
self._excluded.clear()
|
||||
selected_index: Optional[int] = None
|
||||
exclude = self._manager._twitch.options.exclude
|
||||
for i, game_name in enumerate(self._list.get(0, "end")):
|
||||
if game_name in exclude:
|
||||
self._excluded.add(i)
|
||||
self._list.itemconfig(i, foreground="gray60")
|
||||
elif game_name == self._selection:
|
||||
selected_index = i
|
||||
self._list.selection_clear(0, "end")
|
||||
if selected_index is not None:
|
||||
# reselect the currently selected item
|
||||
self._list.selection_clear(0, "end")
|
||||
self._list.selection_set(selected_index)
|
||||
else:
|
||||
elif self._selection is not None:
|
||||
# the game we've had selected isn't there anymore - clear selection
|
||||
self._selection = None
|
||||
|
||||
def _on_select(self, event):
|
||||
current = self._list.curselection()
|
||||
current: Tuple[int, ...] = self._list.curselection()
|
||||
if not current:
|
||||
# can happen when the user clicks on an empty list
|
||||
new_selection = None
|
||||
return
|
||||
idx: int = current[0]
|
||||
if idx in self._excluded:
|
||||
# user clicked on an excluded game - reselect the previous one if possible
|
||||
self._list.selection_clear(0, "end")
|
||||
if self._selection is not None:
|
||||
for i, game_name in enumerate(self._list.get(0, "end")):
|
||||
if game_name == self._selection:
|
||||
self._list.selection_set(i)
|
||||
break
|
||||
else:
|
||||
new_selection = self._list.get(current[0])
|
||||
self._selection = None
|
||||
return
|
||||
new_selection: str = self._list.get(idx)
|
||||
if new_selection != self._selection:
|
||||
self._selection = new_selection
|
||||
self._manager._twitch.change_state(State.GAME_SELECT)
|
||||
@@ -303,15 +316,15 @@ class GameSelector:
|
||||
return None
|
||||
return self._games[self._selection]
|
||||
|
||||
def set_first(self) -> Game:
|
||||
# select and return the first game from the list
|
||||
def set_first(self) -> Optional[Game]:
|
||||
# select and return the first non-excluded game from the list
|
||||
self._list.selection_clear(0, "end")
|
||||
self._list.selection_set(0)
|
||||
for game_name, first_game in self._games.items():
|
||||
# just one iteration to get, set and return the first game
|
||||
for i, game_name in enumerate(self._list.get(0, "end")):
|
||||
if i not in self._excluded:
|
||||
self._selection = game_name
|
||||
return first_game
|
||||
raise RuntimeError("No games to select from")
|
||||
self._list.selection_set(i)
|
||||
return self._games[game_name]
|
||||
return None
|
||||
|
||||
|
||||
class _BaseVars(TypedDict):
|
||||
@@ -1028,7 +1041,9 @@ if __name__ == "__main__":
|
||||
|
||||
async def main(exit_event: asyncio.Event):
|
||||
# Initialize GUI debug
|
||||
mock = SimpleNamespace(options=SimpleNamespace(game=None, tray=False), channels={})
|
||||
mock = SimpleNamespace(
|
||||
options=SimpleNamespace(game=None, tray=False, exclude={"Lit Game"}), channels={}
|
||||
)
|
||||
mock.change_state = lambda state: mock.gui.print(f"State change: {state.value}")
|
||||
mock.state_change = lambda state: partial(mock.change_state, state)
|
||||
gui = GUIManager(mock) # type: ignore
|
||||
@@ -1041,19 +1056,21 @@ if __name__ == "__main__":
|
||||
gui.login.update("Login required", None)
|
||||
# Game selector
|
||||
gui.games.set_games([
|
||||
create_game(420690, "Lit Game"),
|
||||
create_game(123456, "Best Game"),
|
||||
# create_game(654321, "My Game Very Long Name"),
|
||||
create_game(654321, "My Game Very Long Name"),
|
||||
])
|
||||
# Channel list
|
||||
gui.channels.display(
|
||||
create_channel(
|
||||
name="Thomus", status=0, game=None, drops=False, viewers=0, points=0, priority=True
|
||||
)
|
||||
),
|
||||
add=True,
|
||||
)
|
||||
channel = create_channel(
|
||||
name="Traitus", status=1, game=None, drops=False, viewers=0, points=0, priority=True
|
||||
)
|
||||
gui.channels.display(channel)
|
||||
gui.channels.display(channel, add=True,)
|
||||
gui.channels.set_watching(channel)
|
||||
gui.channels.display(
|
||||
create_channel(
|
||||
@@ -1064,7 +1081,8 @@ if __name__ == "__main__":
|
||||
viewers=42,
|
||||
points=1234567,
|
||||
priority=False,
|
||||
)
|
||||
),
|
||||
add=True,
|
||||
)
|
||||
gui.channels.display(
|
||||
create_channel(
|
||||
@@ -1075,7 +1093,8 @@ if __name__ == "__main__":
|
||||
viewers=69,
|
||||
points=1234567,
|
||||
priority=False,
|
||||
)
|
||||
),
|
||||
add=True,
|
||||
)
|
||||
gui._root.update()
|
||||
gui.channels.get_selection()
|
||||
|
||||
@@ -9,10 +9,12 @@ import logging
|
||||
import argparse
|
||||
import traceback
|
||||
import tkinter as tk
|
||||
from copy import copy
|
||||
from pathlib import Path
|
||||
from tkinter import messagebox
|
||||
from typing import Optional, NoReturn
|
||||
from typing import Optional, Union, Set, NoReturn, Generic
|
||||
|
||||
from utils import _T
|
||||
from twitch import Twitch
|
||||
from version import __version__
|
||||
from exceptions import CaptchaRequired
|
||||
@@ -41,12 +43,40 @@ class Parser(argparse.ArgumentParser):
|
||||
messagebox.showerror("Argument Parser Error", self._message.getvalue())
|
||||
|
||||
|
||||
class SetCollectAction(argparse.Action, Generic[_T]):
|
||||
def __init__(
|
||||
self,
|
||||
option_strings,
|
||||
dest,
|
||||
*,
|
||||
nargs: Optional[Union[int, str]] = None,
|
||||
const: Optional[_T] = None,
|
||||
default: Optional[Set[_T]] = None,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
if nargs is not None and nargs in ('?', '*') or isinstance(nargs, int) and nargs <= 0:
|
||||
raise ValueError("'nargs' has to be '+' or an integer greater than zero")
|
||||
if default is None:
|
||||
default = set()
|
||||
elif not isinstance(default, set):
|
||||
raise TypeError("'default' has to be of 'set' type")
|
||||
super().__init__(option_strings, dest, nargs, const, default, **kwargs)
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
items: Set[_T] = getattr(namespace, self.dest, self.default)
|
||||
items = copy(items)
|
||||
for value in values:
|
||||
items.add(value)
|
||||
setattr(namespace, self.dest, items)
|
||||
|
||||
|
||||
class ParsedArgs(argparse.Namespace):
|
||||
_verbose: int
|
||||
_debug_ws: bool
|
||||
_debug_gql: bool
|
||||
log: bool
|
||||
tray: bool
|
||||
exclude: Set[str]
|
||||
no_run_check: bool
|
||||
game: Optional[str]
|
||||
|
||||
@@ -90,9 +120,10 @@ parser = Parser(
|
||||
)
|
||||
parser.add_argument("--version", action="version", version=f"v{__version__}")
|
||||
parser.add_argument("-v", dest="_verbose", action="count", default=0)
|
||||
parser.add_argument("-g", "--game", default=None)
|
||||
parser.add_argument("--tray", action="store_true")
|
||||
parser.add_argument("--log", action="store_true")
|
||||
parser.add_argument("-g", "--game", default=None)
|
||||
parser.add_argument("--exclude", action=SetCollectAction, nargs='+', metavar="GAME")
|
||||
# undocumented debug args
|
||||
parser.add_argument(
|
||||
"--no-run-check", dest="no_run_check", action="store_true", help=argparse.SUPPRESS
|
||||
|
||||
@@ -180,7 +180,6 @@ class Twitch:
|
||||
WebsocketTopic("User", "CommunityPoints", self._user_id, self.process_points),
|
||||
])
|
||||
first_select: bool = True
|
||||
games: List[Game] = []
|
||||
full_cleanup: bool = False
|
||||
channels: Final[OrderedDict[int, Channel]] = self.channels
|
||||
self.change_state(State.INVENTORY_FETCH)
|
||||
@@ -193,7 +192,7 @@ class Twitch:
|
||||
self.change_state(State.GAMES_UPDATE)
|
||||
elif self._state is State.GAMES_UPDATE:
|
||||
# Figure out which games to watch, and claim the drops we can
|
||||
games.clear()
|
||||
games: List[Game] = []
|
||||
for game, campaigns in self.inventory.items():
|
||||
add_game = False
|
||||
for campaign in campaigns:
|
||||
|
||||
Reference in new issue
Block a user