polyhattrick 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/PKG-INFO +1 -8
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/README.md +0 -7
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/pyproject.toml +1 -1
- polyhattrick-0.2.1/src/polyhattrick/__init__.py +1 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/api/client.py +4 -4
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/interactive/application.py +13 -2
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/polyhattrick.py +0 -1
- polyhattrick-0.2.1/src/polyhattrick/tips.py +65 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/views.py +36 -1
- polyhattrick-0.2.0/src/polyhattrick/__init__.py +0 -1
- polyhattrick-0.2.0/src/polyhattrick/tips.py +0 -37
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/LICENSE +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/api/__init__.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/commands/__init__.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/commands/common.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/commands/data.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/commands/live.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/commands/login.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/commands/support.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/interactive/__init__.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/output.py +0 -0
- {polyhattrick-0.2.0 → polyhattrick-0.2.1}/src/polyhattrick/settings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polyhattrick
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Live Hattrick scores in your terminal and polybar
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -159,17 +159,10 @@ Optional, in `~/.config/polyhattrick/configuration.toml`:
|
|
|
159
159
|
|
|
160
160
|
```toml
|
|
161
161
|
server = "https://api.polyhattrick.sesamemonster.de" # the polyhattrick server to use
|
|
162
|
-
tips = false # never show the support reminder
|
|
163
162
|
```
|
|
164
163
|
|
|
165
164
|
`POLYHATTRICK_SERVER` overrides `server` for a single run.
|
|
166
165
|
|
|
167
|
-
## Support
|
|
168
|
-
|
|
169
|
-
polyhattrick is free. `polyhattrick support` tells you how to support it.
|
|
170
|
-
Now and then, after a command, one line reminds you of that; it never shows
|
|
171
|
-
in scripts, and `tips = false` turns it off.
|
|
172
|
-
|
|
173
166
|
## Notes
|
|
174
167
|
|
|
175
168
|
- Made for Linux.
|
|
@@ -88,17 +88,10 @@ Optional, in `~/.config/polyhattrick/configuration.toml`:
|
|
|
88
88
|
|
|
89
89
|
```toml
|
|
90
90
|
server = "https://api.polyhattrick.sesamemonster.de" # the polyhattrick server to use
|
|
91
|
-
tips = false # never show the support reminder
|
|
92
91
|
```
|
|
93
92
|
|
|
94
93
|
`POLYHATTRICK_SERVER` overrides `server` for a single run.
|
|
95
94
|
|
|
96
|
-
## Support
|
|
97
|
-
|
|
98
|
-
polyhattrick is free. `polyhattrick support` tells you how to support it.
|
|
99
|
-
Now and then, after a command, one line reminds you of that; it never shows
|
|
100
|
-
in scripts, and `tips = false` turns it off.
|
|
101
|
-
|
|
102
95
|
## Notes
|
|
103
96
|
|
|
104
97
|
- Made for Linux.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.1"
|
|
@@ -60,8 +60,8 @@ class Client:
|
|
|
60
60
|
|
|
61
61
|
# Data
|
|
62
62
|
|
|
63
|
-
def about(self):
|
|
64
|
-
return self._request("GET", "/v1/about", authenticated=False)
|
|
63
|
+
def about(self, timeout=TIMEOUT_SECONDS):
|
|
64
|
+
return self._request("GET", "/v1/about", authenticated=False, timeout=timeout)
|
|
65
65
|
|
|
66
66
|
def my_teams(self):
|
|
67
67
|
return self._request("GET", "/v1/me/teams")
|
|
@@ -102,13 +102,13 @@ class Client:
|
|
|
102
102
|
headers["Authorization"] = f"Bearer {self.secret}"
|
|
103
103
|
return headers
|
|
104
104
|
|
|
105
|
-
def _send(self, method, path, headers, **arguments):
|
|
105
|
+
def _send(self, method, path, headers, timeout=TIMEOUT_SECONDS, **arguments):
|
|
106
106
|
try:
|
|
107
107
|
return requests.request(
|
|
108
108
|
method,
|
|
109
109
|
f"{self.server}{path}",
|
|
110
110
|
headers=headers,
|
|
111
|
-
timeout=
|
|
111
|
+
timeout=timeout,
|
|
112
112
|
**arguments,
|
|
113
113
|
)
|
|
114
114
|
except requests.RequestException as error:
|
|
@@ -80,6 +80,7 @@ class PolyhattrickApplication(App):
|
|
|
80
80
|
Binding("r", "refresh", "Refresh"),
|
|
81
81
|
Binding("t", "switch_team", "Next team"),
|
|
82
82
|
Binding("q", "quit", "Quit"),
|
|
83
|
+
Binding("escape", "focus_sections", "Sections", show=False),
|
|
83
84
|
]
|
|
84
85
|
|
|
85
86
|
def __init__(self, client=None):
|
|
@@ -131,11 +132,21 @@ class PolyhattrickApplication(App):
|
|
|
131
132
|
view.display = True
|
|
132
133
|
view.update(f"[red]{error.message}[/red]")
|
|
133
134
|
|
|
134
|
-
@on(OptionList.OptionSelected, "#sections")
|
|
135
135
|
@on(OptionList.OptionHighlighted, "#sections")
|
|
136
|
-
def
|
|
136
|
+
def _section_highlighted(self, event):
|
|
137
|
+
if event.option.id != self.section:
|
|
138
|
+
self.show_section(event.option.id)
|
|
139
|
+
|
|
140
|
+
@on(OptionList.OptionSelected, "#sections")
|
|
141
|
+
def _section_entered(self, event):
|
|
142
|
+
"""Enter moves the cursor into the section, so arrows and Enter act there."""
|
|
137
143
|
if event.option.id != self.section:
|
|
138
144
|
self.show_section(event.option.id)
|
|
145
|
+
target = "#squad" if event.option.id == "squad" else "#content"
|
|
146
|
+
self.query_one(target).focus()
|
|
147
|
+
|
|
148
|
+
def action_focus_sections(self):
|
|
149
|
+
self.query_one("#sections", OptionList).focus()
|
|
139
150
|
|
|
140
151
|
def show_section(self, section):
|
|
141
152
|
self.section = section
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""The occasional line asking for support.
|
|
2
|
+
|
|
3
|
+
Never in the first `INTERVAL_DAYS` after the first use, then at most once
|
|
4
|
+
every `INTERVAL_DAYS`, after a command succeeded, and only to a person:
|
|
5
|
+
never with `--json`, never when stderr is not a terminal (pipes, scripts,
|
|
6
|
+
polybar). `tips = false` in the configuration file turns it off for good.
|
|
7
|
+
|
|
8
|
+
It only appears when the server announces a funding link: a reminder with
|
|
9
|
+
nowhere to send support is just noise. The server is asked only when a
|
|
10
|
+
reminder is due, and at most once a day while it has no link.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
from datetime import date, timedelta
|
|
15
|
+
|
|
16
|
+
from polyhattrick import output, settings
|
|
17
|
+
from polyhattrick.api.client import ApiError, Client
|
|
18
|
+
|
|
19
|
+
INTERVAL_DAYS = 14
|
|
20
|
+
ABOUT_TIMEOUT_SECONDS = 3
|
|
21
|
+
LINE = (
|
|
22
|
+
"Enjoying polyhattrick? See `polyhattrick support` for how to help keep it running."
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _day(state, key):
|
|
27
|
+
value = state.get(key)
|
|
28
|
+
return date.fromisoformat(value) if value else None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def due(state, today):
|
|
32
|
+
"""Whether `INTERVAL_DAYS` have passed since the first use and the last reminder."""
|
|
33
|
+
starts = [
|
|
34
|
+
day for day in (_day(state, "first_used"), _day(state, "tip_shown")) if day
|
|
35
|
+
]
|
|
36
|
+
return bool(starts) and max(starts) + timedelta(days=INTERVAL_DAYS) <= today
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _funding_url():
|
|
40
|
+
try:
|
|
41
|
+
return Client().about(timeout=ABOUT_TIMEOUT_SECONDS).get("funding_url")
|
|
42
|
+
except ApiError:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def maybe_show(as_json, today=None):
|
|
47
|
+
if as_json or not sys.stderr.isatty() or not settings.configuration().tips:
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
today = today or date.today()
|
|
51
|
+
state = settings.read_state()
|
|
52
|
+
if "first_used" not in state:
|
|
53
|
+
state["first_used"] = today.isoformat()
|
|
54
|
+
settings.write_state(state)
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
if not due(state, today) or _day(state, "funding_checked") == today:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
if _funding_url():
|
|
61
|
+
output.error_output.print(f"\n[dim]{LINE}[/dim]", highlight=False)
|
|
62
|
+
state["tip_shown"] = today.isoformat()
|
|
63
|
+
else:
|
|
64
|
+
state["funding_checked"] = today.isoformat()
|
|
65
|
+
settings.write_state(state)
|
|
@@ -309,6 +309,41 @@ def club(club):
|
|
|
309
309
|
)
|
|
310
310
|
|
|
311
311
|
|
|
312
|
+
# Short labels for the server's match types; `--json` keeps the server's values.
|
|
313
|
+
MATCH_TYPE_LABELS = {
|
|
314
|
+
"league": "League",
|
|
315
|
+
"qualification": "Qualification",
|
|
316
|
+
"cup": "Cup",
|
|
317
|
+
"friendly": "Friendly",
|
|
318
|
+
"friendly_cup_rules": "Friendly (cup)",
|
|
319
|
+
"international_friendly": "Friendly (int)",
|
|
320
|
+
"international_friendly_cup_rules": "Friendly (int) (cup)",
|
|
321
|
+
"hattrick_masters": "Masters",
|
|
322
|
+
"national_teams_competition": "National team",
|
|
323
|
+
"national_teams_competition_cup_rules": "National team (cup)",
|
|
324
|
+
"national_teams_friendly": "National team friendly",
|
|
325
|
+
"tournament_league": "Tournament",
|
|
326
|
+
"tournament_playoff": "Tournament (playoff)",
|
|
327
|
+
"duel": "Duel",
|
|
328
|
+
"ladder": "Ladder",
|
|
329
|
+
"preparation": "Preparation",
|
|
330
|
+
"youth_league": "Youth league",
|
|
331
|
+
"youth_friendly": "Youth friendly",
|
|
332
|
+
"youth_friendly_cup_rules": "Youth friendly (cup)",
|
|
333
|
+
"youth_international_friendly": "Youth friendly (int)",
|
|
334
|
+
"youth_international_friendly_cup_rules": "Youth friendly (int) (cup)",
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def match_type(value):
|
|
339
|
+
"""`international_friendly` → `Friendly (int)`; `unknown_63` → `Other (63)`."""
|
|
340
|
+
if value is None:
|
|
341
|
+
return "-"
|
|
342
|
+
if value.startswith("unknown_"):
|
|
343
|
+
return f"Other ({value.removeprefix('unknown_')})"
|
|
344
|
+
return MATCH_TYPE_LABELS.get(value, words(value))
|
|
345
|
+
|
|
346
|
+
|
|
312
347
|
def matches(matches):
|
|
313
348
|
table = Table(title="Matches")
|
|
314
349
|
table.add_column("Date")
|
|
@@ -324,7 +359,7 @@ def matches(matches):
|
|
|
324
359
|
)
|
|
325
360
|
table.add_row(
|
|
326
361
|
date(match["date"]),
|
|
327
|
-
|
|
362
|
+
match_type(match["match_type"]),
|
|
328
363
|
match["home_team"] and match["home_team"]["name"],
|
|
329
364
|
score,
|
|
330
365
|
match["away_team"] and match["away_team"]["name"],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.0"
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"""The occasional line asking for support.
|
|
2
|
-
|
|
3
|
-
Shown at most once every `INTERVAL_DAYS`, after a command succeeded, and
|
|
4
|
-
only to a person: never with `--json`, never when stderr is not a terminal
|
|
5
|
-
(pipes, scripts, polybar). `tips = false` in the configuration file turns
|
|
6
|
-
it off for good.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import sys
|
|
10
|
-
from datetime import date, timedelta
|
|
11
|
-
|
|
12
|
-
from polyhattrick import output, settings
|
|
13
|
-
|
|
14
|
-
INTERVAL_DAYS = 30
|
|
15
|
-
LINE = (
|
|
16
|
-
"Enjoying polyhattrick? See `polyhattrick support` for how to help keep it running."
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def due(today=None):
|
|
21
|
-
today = today or date.today()
|
|
22
|
-
last = settings.read_state().get("tip_shown")
|
|
23
|
-
return (
|
|
24
|
-
last is None
|
|
25
|
-
or date.fromisoformat(last) + timedelta(days=INTERVAL_DAYS) <= today
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def maybe_show(as_json, today=None):
|
|
30
|
-
if as_json or not sys.stderr.isatty() or not settings.configuration().tips:
|
|
31
|
-
return
|
|
32
|
-
if not due(today):
|
|
33
|
-
return
|
|
34
|
-
output.error_output.print(f"\n[dim]{LINE}[/dim]", highlight=False)
|
|
35
|
-
state = settings.read_state()
|
|
36
|
-
state["tip_shown"] = (today or date.today()).isoformat()
|
|
37
|
-
settings.write_state(state)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|