polyhattrick 0.1.0__py3-none-any.whl

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.
File without changes
@@ -0,0 +1,86 @@
1
+ from urllib.parse import parse_qs
2
+ import requests
3
+ import configparser
4
+ import logging
5
+ from pathlib import Path
6
+
7
+ auth_secrets_path = Path.home() / ".config/polyhattrick/auth"
8
+ auth_secrets_path.parent.mkdir(parents=True, exist_ok=True)
9
+
10
+ environments = {"local": "http://localhost:8000", "prod": "http://161.35.142.18"}
11
+
12
+
13
+ def host(env):
14
+ return environments[env]
15
+
16
+
17
+ class PolyhattrickClient:
18
+ def __init__(self, env):
19
+ self.env = env
20
+
21
+ def authenticate(self):
22
+ headers = {
23
+ "User-Agent": "polyhattrick_client/0.1",
24
+ }
25
+
26
+ response = requests.post(
27
+ f"{host(self.env)}/login/authenticate", headers=headers
28
+ )
29
+ json = response.json()
30
+
31
+ config = configparser.ConfigParser()
32
+ config["auth"] = {
33
+ "resource_owner_key": json["resource_owner_key"],
34
+ "resource_owner_secret": json["resource_owner_secret"],
35
+ }
36
+ with auth_secrets_path.open("w") as configfile:
37
+ config.write(configfile)
38
+
39
+ return json["auth_url"]
40
+
41
+ def exchange_tokens(self, pin):
42
+ config = configparser.ConfigParser()
43
+ config.read(auth_secrets_path)
44
+
45
+ if "auth" not in config:
46
+ logging.warning("Auth section not found in config")
47
+ print(
48
+ "Looks like you haven't initiated the authentication flow yet. Please run `TODO`"
49
+ )
50
+
51
+ headers = {
52
+ "User-Agent": "polyhattrick_client/0.1",
53
+ "Content-Type": "application/json",
54
+ }
55
+
56
+ data = {
57
+ "verification_code": pin,
58
+ "resource_owner_key": config["auth"]["resource_owner_key"],
59
+ "resource_owner_secret": config["auth"]["resource_owner_secret"],
60
+ }
61
+
62
+ response = requests.post(
63
+ f"{host(self.env)}/login/exchange_tokens", headers=headers, json=data
64
+ ).json()
65
+ config.set("auth", "secret", response["secret"])
66
+
67
+ with auth_secrets_path.open("w") as configfile:
68
+ config.write(configfile)
69
+
70
+ def get_live_result(self):
71
+ config = configparser.ConfigParser()
72
+ config.read(auth_secrets_path)
73
+
74
+ if "auth" not in config or "secret" not in config["auth"]:
75
+ logging.warning("Auth secret not found.")
76
+ print("Not authenticated. Please authenticate first, then try again.")
77
+ return
78
+
79
+ headers = {
80
+ "Authorization": "Bearer " + config["auth"]["secret"],
81
+ "User-Agent": "polyhattrick_client/0.1",
82
+ }
83
+
84
+ response = requests.get(f"{host(self.env)}/watch/live", headers=headers)
85
+
86
+ return response.text
@@ -0,0 +1,58 @@
1
+ from typing import Annotated
2
+ from pathlib import Path
3
+ import typer
4
+ import logging
5
+
6
+ from polyhattrick.client import polyhattrick_client
7
+
8
+ app = typer.Typer()
9
+ login_app = typer.Typer()
10
+ app.add_typer(login_app, name="login")
11
+
12
+ match_app = typer.Typer()
13
+ app.add_typer(match_app, name="match")
14
+ live_app = typer.Typer()
15
+ match_app.add_typer(live_app, name="live")
16
+
17
+ LOG_DIR = Path("logs")
18
+ LOG_DIR.mkdir(exist_ok=True)
19
+
20
+ logging.basicConfig(
21
+ filename=LOG_DIR / "client.log",
22
+ level=logging.INFO,
23
+ format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
24
+ )
25
+
26
+ client = polyhattrick_client.PolyhattrickClient("prod")
27
+
28
+
29
+ @login_app.command("authenticate")
30
+ def authenticate():
31
+ response = client.authenticate()
32
+ print(
33
+ f"Please follow this URL to grant polyhattrick access to read your data. Then, run `login exchange [TOKEN]`:\n{response}"
34
+ )
35
+
36
+
37
+ @login_app.command("exchange")
38
+ def exchange(pin: Annotated[str, typer.Argument()]):
39
+ client.exchange_tokens(pin)
40
+
41
+
42
+ @live_app.command("watch")
43
+ def watch():
44
+ try:
45
+ res = client.get_live_result()
46
+ if res:
47
+ print(res)
48
+ except Exception as e:
49
+ logging.error("Unable to get live result.", exc_info=True)
50
+ return ""
51
+
52
+
53
+ def main():
54
+ app()
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: polyhattrick
3
+ Version: 0.1.0
4
+ Summary: Live Hattrick scores in your terminal and polybar
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Author: Peter Toth
8
+ Author-email: work@petertoth.de
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: anyio (==4.12.0)
15
+ Requires-Dist: black (==25.12.0)
16
+ Requires-Dist: build (==1.3.0)
17
+ Requires-Dist: cachecontrol (==0.14.4)
18
+ Requires-Dist: certifi (==2025.11.12)
19
+ Requires-Dist: cffi (==2.0.0)
20
+ Requires-Dist: charset-normalizer (==3.4.4)
21
+ Requires-Dist: cleo (==2.1.0)
22
+ Requires-Dist: click (==8.3.1)
23
+ Requires-Dist: crashtest (==0.4.1)
24
+ Requires-Dist: cryptography (==46.0.3)
25
+ Requires-Dist: distlib (==0.4.0)
26
+ Requires-Dist: dulwich (==0.24.10)
27
+ Requires-Dist: fastjsonschema (==2.21.2)
28
+ Requires-Dist: filelock (==3.20.0)
29
+ Requires-Dist: findpython (==0.7.1)
30
+ Requires-Dist: h11 (==0.16.0)
31
+ Requires-Dist: httpcore (==1.0.9)
32
+ Requires-Dist: httpx (==0.28.1)
33
+ Requires-Dist: idna (==3.11)
34
+ Requires-Dist: installer (==0.7.0)
35
+ Requires-Dist: jaraco-classes (==3.4.0)
36
+ Requires-Dist: jaraco-context (==6.0.1)
37
+ Requires-Dist: jaraco-functools (==4.3.0)
38
+ Requires-Dist: jeepney (==0.9.0)
39
+ Requires-Dist: keyring (==25.7.0)
40
+ Requires-Dist: markdown-it-py (==4.0.0)
41
+ Requires-Dist: mdurl (==0.1.2)
42
+ Requires-Dist: more-itertools (==10.8.0)
43
+ Requires-Dist: msgpack (==1.1.2)
44
+ Requires-Dist: mypy-extensions (==1.1.0)
45
+ Requires-Dist: packaging (==25.0)
46
+ Requires-Dist: pathspec (==0.12.1)
47
+ Requires-Dist: pbs-installer (==2025.12.5)
48
+ Requires-Dist: pkginfo (==1.12.1.2)
49
+ Requires-Dist: platformdirs (==4.5.0)
50
+ Requires-Dist: poetry (==2.2.1)
51
+ Requires-Dist: poetry-core (==2.2.1)
52
+ Requires-Dist: pycparser (==2.23)
53
+ Requires-Dist: pygments (==2.19.2)
54
+ Requires-Dist: pyproject-hooks (==1.2.0)
55
+ Requires-Dist: pytokens (==0.3.0)
56
+ Requires-Dist: rapidfuzz (==3.14.3)
57
+ Requires-Dist: requests (==2.32.5)
58
+ Requires-Dist: requests-toolbelt (==1.0.0)
59
+ Requires-Dist: rich (==14.2.0)
60
+ Requires-Dist: secretstorage (==3.5.0)
61
+ Requires-Dist: shellingham (==1.5.4)
62
+ Requires-Dist: tomlkit (==0.13.3)
63
+ Requires-Dist: trove-classifiers (==2025.12.1.14)
64
+ Requires-Dist: typer (==0.20.0)
65
+ Requires-Dist: typing-extensions (==4.15.0)
66
+ Requires-Dist: urllib3 (==2.5.0)
67
+ Requires-Dist: virtualenv (==20.35.4)
68
+ Requires-Dist: zstandard (==0.25.0)
69
+ Description-Content-Type: text/markdown
70
+
71
+ # polyhattrick
72
+
73
+ `polyhattrick` is a simple command-line utility for fetching live match scores from [Hattrick](https://www.hattrick.org). It can be easily integrated into `polybar`, allowing you to see how your team is performing live directly on your desktop.
74
+
75
+ ---
76
+
77
+ ## Installation
78
+
79
+ Install `polyhattrick` using `pip`:
80
+
81
+ ```bash
82
+ pip install polyhattrick
83
+ ```
84
+
85
+ ## Authentication
86
+
87
+ Before you can display match results in your terminal or in polybar, you need to authorize polyhattrick to access your match data on Hattrick.
88
+
89
+ First, start the authentication process:
90
+
91
+ ```bash
92
+ polyhattrick login authenticate
93
+ ```
94
+
95
+ This command will generate a login link. Open it in your browser to log in to Hattrick and authorize polyhattrick. Once authorized, Hattrick will display a token. Copy this token and complete the authorization process:
96
+
97
+ ```bash
98
+ polyhattrick login exchange [TOKEN]
99
+ ```
100
+
101
+ ## Usage
102
+
103
+ After authentication, you can start fetching live match results.
104
+
105
+ To display the score of the first match in your live ticker on Hattrick, run:
106
+
107
+ ```bash
108
+ polyhattrick match live watch
109
+ ```
110
+
111
+ If you want to see the result of a different match, reorder your live ticker on the Hattrick website so that the desired match appears first.
112
+
113
+ ## Integration with polybar
114
+
115
+ To display live match results in polybar, add the following module to your polybar configuration:
116
+
117
+ ```
118
+ [module/hattrick]
119
+ type = custom/script
120
+ exec = polyhattrick match live watch
121
+ ```
122
+
123
+ Then place the module wherever you want it to appear in your bar.
124
+
125
+ ## Notes
126
+
127
+ - This tool is intended for Linux systems.
128
+
129
+ - Make sure polyhattrick is available in your PATH when used with polybar.
130
+
@@ -0,0 +1,8 @@
1
+ polyhattrick/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ polyhattrick/client/polyhattrick_client.py,sha256=JQgVTdGNG_M9CipAWCwmfVzmC_ASnd2klgqeNJs5wPc,2623
3
+ polyhattrick/polyhattrick.py,sha256=LjXHwJp-p1urQpNJ-94iQh1SafQ6h8wQLko_VzAGf_I,1281
4
+ polyhattrick-0.1.0.dist-info/METADATA,sha256=XRIrD6MR4ypOZvQ8ouLBu5-kCbO_3J7EbO6JPR0Dvu4,4096
5
+ polyhattrick-0.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
6
+ polyhattrick-0.1.0.dist-info/entry_points.txt,sha256=63-6OGV0pGT4ioT-5h7yPZL-TLSubSKJewDxpE0C6mU,63
7
+ polyhattrick-0.1.0.dist-info/licenses/LICENSE,sha256=AXL4D-FQaXIb7JFfPuhYT4wqV4Nsu63MtMEMTlrm9u0,1066
8
+ polyhattrick-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ polyhattrick=polyhattrick.polyhattrick:main
3
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Peter Toth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.