Implement exclude argument

This commit is contained in:
DevilXD committed 2022-02-16 13:15:53 +01:00
1 parent fdc9dabd49
commit 83b8de11a1
4 files changed
+81 -32

No files matched your search

+1 -1
View File
@@ -51,7 +51,7 @@
"type": "python",
"request": "launch",
"program": "main.py",
"args": ["--wrong"],
"args": ["--excludes", "1", "2", "3"],
"console": "integratedTerminal",
"justMyCode": false
},
+46 -27
View File
@@ -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()
+33 -2
View File
@@ -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
+1 -2
View File
@@ -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: