akipy 0.1.0__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.
akipy-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 advnpzn
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.
akipy-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.1
2
+ Name: akipy
3
+ Version: 0.1.0
4
+ Summary: A Python library wrapper for Akinator
5
+ Author: advnpzn
6
+ Author-email: adenosinetp10@protonmail.com
7
+ Requires-Python: >=3.12,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Requires-Dist: httpx (>=0.27.0,<0.28.0)
11
+ Description-Content-Type: text/markdown
12
+
13
+ # akipy [WIP]
14
+ Python library wrapper for [akinator.com](https://akinator.com)
15
+
16
+ Wrapper is still in development.
17
+ Some things are not present or partially present.
18
+
19
+ Such as,
20
+ * Exception Handling
21
+ * Docs
22
+ * Better error Handling
23
+ * Custom Exceptions
24
+
25
+ These are the things I'll be working on trying to improve. If you want to help,
26
+ the above is the main priority for now.
27
+
28
+ # Why ?
29
+ I already used to use a wrapper library for Akinator ([akinator.py](https://github.com/Ombucha/akinator.py)) before.
30
+ But suddenly it seems to be not working. I debugged and made
31
+ sure the problem is because of API changes from Akinator themselves.
32
+ There were so many changes making me think I would have to change a lot of things.
33
+ So instead of doing that, I just made it from scratch. Obviously I took a lot
34
+ of inspiration from the old Python wrapper I was using thus the code structure
35
+ would look very similar. In fact, I'm trying to replicate the same interface that
36
+ was present in the old wrapper. Because I don't want to make changes to any piece
37
+ of software that may depend on this library (which isn't working now).
38
+
39
+ I hope there isn't any interface breaking changes here. If there are any, please
40
+ contact me either through Telegram or raise an issue here on GitHub or if you want
41
+ to help, raise a Pull Request.
42
+
43
+ # Installation
44
+
45
+ `pip install akipy`
46
+
47
+ # Usage
48
+
49
+ There is both synchronous and asynchronous variants of `akipy` available.
50
+
51
+ Synchronous: `from akipy import Akinator`
52
+
53
+ Asynchronous: `from akipy.async_akipy import Akinator`
54
+
55
+ I'll provide a sample usage for synchronous usage of `Akinator`.
56
+ All the examples are also in the project's examples folder. So please check them out as well.
57
+
58
+ ```python
59
+ import akipy
60
+
61
+ aki = akipy.Akinator()
62
+ aki.start_game()
63
+
64
+ while not aki.win:
65
+ ans = input(aki.question + "\n\t")
66
+ if ans == "b":
67
+ try:
68
+ aki.back()
69
+ except akipy.CantGoBackAnyFurther:
70
+ pass
71
+ else:
72
+ aki.answer(ans)
73
+
74
+ print(aki.name_proposition)
75
+ print(aki.description_proposition)
76
+ print(aki.pseudo)
77
+ print(aki.photo)
78
+ ```
79
+
80
+
81
+
82
+
83
+
84
+
85
+
akipy-0.1.0/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # akipy [WIP]
2
+ Python library wrapper for [akinator.com](https://akinator.com)
3
+
4
+ Wrapper is still in development.
5
+ Some things are not present or partially present.
6
+
7
+ Such as,
8
+ * Exception Handling
9
+ * Docs
10
+ * Better error Handling
11
+ * Custom Exceptions
12
+
13
+ These are the things I'll be working on trying to improve. If you want to help,
14
+ the above is the main priority for now.
15
+
16
+ # Why ?
17
+ I already used to use a wrapper library for Akinator ([akinator.py](https://github.com/Ombucha/akinator.py)) before.
18
+ But suddenly it seems to be not working. I debugged and made
19
+ sure the problem is because of API changes from Akinator themselves.
20
+ There were so many changes making me think I would have to change a lot of things.
21
+ So instead of doing that, I just made it from scratch. Obviously I took a lot
22
+ of inspiration from the old Python wrapper I was using thus the code structure
23
+ would look very similar. In fact, I'm trying to replicate the same interface that
24
+ was present in the old wrapper. Because I don't want to make changes to any piece
25
+ of software that may depend on this library (which isn't working now).
26
+
27
+ I hope there isn't any interface breaking changes here. If there are any, please
28
+ contact me either through Telegram or raise an issue here on GitHub or if you want
29
+ to help, raise a Pull Request.
30
+
31
+ # Installation
32
+
33
+ `pip install akipy`
34
+
35
+ # Usage
36
+
37
+ There is both synchronous and asynchronous variants of `akipy` available.
38
+
39
+ Synchronous: `from akipy import Akinator`
40
+
41
+ Asynchronous: `from akipy.async_akipy import Akinator`
42
+
43
+ I'll provide a sample usage for synchronous usage of `Akinator`.
44
+ All the examples are also in the project's examples folder. So please check them out as well.
45
+
46
+ ```python
47
+ import akipy
48
+
49
+ aki = akipy.Akinator()
50
+ aki.start_game()
51
+
52
+ while not aki.win:
53
+ ans = input(aki.question + "\n\t")
54
+ if ans == "b":
55
+ try:
56
+ aki.back()
57
+ except akipy.CantGoBackAnyFurther:
58
+ pass
59
+ else:
60
+ aki.answer(ans)
61
+
62
+ print(aki.name_proposition)
63
+ print(aki.description_proposition)
64
+ print(aki.pseudo)
65
+ print(aki.photo)
66
+ ```
67
+
68
+
69
+
70
+
71
+
72
+
@@ -0,0 +1,9 @@
1
+ """
2
+ akipy - A Python wrapper library for Akinator
3
+
4
+ :copyright: (c) 2024, advnpzn
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ from .akinator import Akinator
9
+ from .exceptions import *
@@ -0,0 +1,185 @@
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2024 advnpzn
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+
24
+ """
25
+ import json
26
+ import re
27
+
28
+ try:
29
+ import httpx
30
+ except ImportError:
31
+ raise ImportError('httpx is not installed')
32
+
33
+ from .dicts import HEADERS, THEME_ID, THEMES, LANG_MAP
34
+ from .exceptions import InvalidLanguageError, CantGoBackAnyFurther
35
+ from .utils import get_answer_id, request_handler
36
+
37
+
38
+ class Akinator:
39
+ """
40
+ The ``Akinator`` Class represents the Akinator Game.
41
+ You need to create an Instance of this Class to get started.
42
+ """
43
+
44
+ def __init__(self):
45
+ self.photo = None
46
+ self.pseudo = None
47
+ self.uri = None
48
+ self.theme = None
49
+ self.session = None
50
+ self.signature = None
51
+ self.child_mode: bool = False
52
+ self.lang = None
53
+ self.available_themes = None
54
+ self.theme = None
55
+
56
+ self.question = None
57
+ self.progression = None
58
+ self.step = None
59
+ self.akitude = None
60
+ self.step_last_proposition = ""
61
+
62
+ self.win = False
63
+ self.name_proposition = None
64
+ self.description_proposition = None
65
+ self.completion = None
66
+
67
+ def start_game(self, language: str | None = "en", child_mode: bool = False):
68
+ """
69
+ This method is responsible for actually starting the game scene.
70
+ You can pass the following parameters to set your language preference and as well as the Child Mode.
71
+ If language is not set, English is used by default. Child Mode is set to ``False`` by default.
72
+ :param language: "en"
73
+ :param child_mode: False
74
+ :return: None
75
+ """
76
+
77
+ self.__get_region(lang=language)
78
+ self.__initialise()
79
+
80
+ def answer(self, option):
81
+ url = f"{self.uri}/answer"
82
+ data = {
83
+ "step": self.step,
84
+ "progression": self.progression,
85
+ "sid": self.theme,
86
+ "cm": str(self.child_mode).lower(),
87
+ "answer": get_answer_id(option),
88
+ "step_last_proposition": self.step_last_proposition,
89
+ "session": self.session,
90
+ "signature": self.signature,
91
+ }
92
+ print(data)
93
+ try:
94
+ req = request_handler(url=url, method='POST', data=data)
95
+ resp = json.loads(req.text)
96
+
97
+ if re.findall(r"id_proposition", str(resp)):
98
+ self.__update(action="win", resp=resp)
99
+ else:
100
+ self.__update(action="answer", resp=resp)
101
+ self.completion = resp['completion']
102
+ except Exception as e:
103
+ raise e
104
+
105
+ def back(self):
106
+ if self.step == 1:
107
+ raise CantGoBackAnyFurther
108
+ else:
109
+ url = f"{self.uri}/cancel_answer"
110
+ data = {
111
+ "step": self.step,
112
+ "progression": self.progression,
113
+ "sid": self.theme,
114
+ "cm": str(self.child_mode).lower(),
115
+ "session": self.session,
116
+ "signature": self.signature,
117
+ }
118
+
119
+ try:
120
+ req = request_handler(url=url, method='POST', data=data)
121
+ resp = json.loads(req.text)
122
+ self.__update(action="back", resp=resp)
123
+ except Exception as e:
124
+ raise e
125
+
126
+ def __update(self, action: str, resp):
127
+ if action == "answer":
128
+ self.akitude = resp['akitude']
129
+ self.step = resp['step']
130
+ self.progression = resp['progression']
131
+ self.question = resp['question']
132
+ elif action == "back":
133
+ self.akitude = resp['akitude']
134
+ self.step = resp['step']
135
+ self.progression = resp['progression']
136
+ self.question = resp['question']
137
+ elif action == "win":
138
+ self.win = True
139
+ self.name_proposition = resp['name_proposition']
140
+ self.description_proposition = resp['description_proposition']
141
+ self.pseudo = resp['pseudo']
142
+ self.photo = resp['photo']
143
+
144
+ def __get_region(self, lang):
145
+ try:
146
+ if len(lang) > 2:
147
+ lang = LANG_MAP[lang]
148
+ else:
149
+ assert (lang in LANG_MAP.values())
150
+ except Exception:
151
+ raise InvalidLanguageError(lang)
152
+ url = f"https://{lang}.akinator.com"
153
+ try:
154
+ req = request_handler(url=url, method='GET')
155
+ if req.status_code != 200:
156
+ raise httpx.HTTPStatusError
157
+ else:
158
+ self.uri = url
159
+ self.lang = lang
160
+
161
+ self.available_themes = THEMES[lang]
162
+ self.theme = THEME_ID[self.available_themes[0]]
163
+ except Exception as e:
164
+ raise e
165
+
166
+ def __initialise(self):
167
+ url = f"{self.uri}/game"
168
+ data = {
169
+ "sid": self.theme,
170
+ "cm": str(self.child_mode).lower()
171
+ }
172
+ try:
173
+ req = request_handler(url=url, method='POST', data=data).text
174
+ match = re.findall(r"[a-zA-Z0-9+/]+==", req)[-2:]
175
+
176
+ self.session = match[0]
177
+ self.signature = match[1]
178
+
179
+ match = re.search(r'<div class="bubble-body"><p class="question-text" id="question-label">(.*?)</p></div>',
180
+ req)
181
+ self.question = match.group(1)
182
+ self.progression = "0.00000"
183
+ self.step = 0
184
+ except Exception:
185
+ raise httpx.HTTPStatusError
@@ -0,0 +1,8 @@
1
+ """
2
+ akipy - A Python wrapper library for Akinator
3
+
4
+ :copyright: (c) 2024, advnpzn
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ from .async_akinator import Akinator
@@ -0,0 +1,187 @@
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2024 advnpzn
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+
24
+ """
25
+ import json
26
+ import re
27
+ import asyncio
28
+
29
+ try:
30
+ import httpx
31
+ except ImportError:
32
+ raise ImportError('httpx is not installed')
33
+
34
+ from ..dicts import HEADERS, THEME_ID, THEMES, LANG_MAP
35
+ from ..exceptions import InvalidLanguageError, CantGoBackAnyFurther
36
+ from ..utils import get_answer_id, async_request_handler
37
+
38
+
39
+ class Akinator:
40
+ """
41
+ The ``Akinator`` Class represents the Akinator Game.
42
+ You need to create an Instance of this Class to get started.
43
+ """
44
+
45
+ def __init__(self):
46
+ self.photo = None
47
+ self.pseudo = None
48
+ self.uri = None
49
+ self.theme = None
50
+ self.session = None
51
+ self.signature = None
52
+ self.child_mode: bool = False
53
+ self.lang = None
54
+ self.available_themes = None
55
+ self.theme = None
56
+
57
+ self.question = None
58
+ self.progression = None
59
+ self.step = None
60
+ self.akitude = None
61
+ self.step_last_proposition = ""
62
+
63
+ self.win = False
64
+ self.name_proposition = None
65
+ self.description_proposition = None
66
+ self.completion = None
67
+
68
+ async def __update(self, action: str, resp):
69
+ if action == "answer":
70
+ self.akitude = resp['akitude']
71
+ self.step = resp['step']
72
+ self.progression = resp['progression']
73
+ self.question = resp['question']
74
+ elif action == "back":
75
+ self.akitude = resp['akitude']
76
+ self.step = resp['step']
77
+ self.progression = resp['progression']
78
+ self.question = resp['question']
79
+ elif action == "win":
80
+ self.win = True
81
+ self.name_proposition = resp['name_proposition']
82
+ self.description_proposition = resp['description_proposition']
83
+ self.pseudo = resp['pseudo']
84
+ self.photo = resp['photo']
85
+
86
+ async def __get_region(self, lang):
87
+ try:
88
+ if len(lang) > 2:
89
+ lang = LANG_MAP[lang]
90
+ else:
91
+ assert (lang in LANG_MAP.values())
92
+ except Exception:
93
+ raise InvalidLanguageError(lang)
94
+ url = f"https://{lang}.akinator.com"
95
+ try:
96
+ req = await async_request_handler(url=url, method='GET')
97
+ if req.status_code != 200:
98
+ raise httpx.HTTPStatusError
99
+ else:
100
+ self.uri = url
101
+ self.lang = lang
102
+
103
+ self.available_themes = THEMES[lang]
104
+ self.theme = THEME_ID[self.available_themes[0]]
105
+ except Exception as e:
106
+ raise e
107
+
108
+ async def __initialise(self):
109
+ url = f"{self.uri}/game"
110
+ data = {
111
+ "sid": self.theme,
112
+ "cm": str(self.child_mode).lower()
113
+ }
114
+ try:
115
+ req = await async_request_handler(url=url, method='POST', data=data)
116
+ match = re.findall(r"[a-zA-Z0-9+/]+==", req.text)[-2:]
117
+
118
+ self.session = match[0]
119
+ self.signature = match[1]
120
+
121
+ match = re.search(r'<div class="bubble-body"><p class="question-text" id="question-label">(.*?)</p></div>',
122
+ req.text)
123
+ self.question = match.group(1)
124
+ self.progression = "0.00000"
125
+ self.step = 0
126
+ except Exception:
127
+ raise httpx.HTTPStatusError
128
+
129
+ async def start_game(self, language: str | None = "en", child_mode: bool = False):
130
+ """
131
+ This method is responsible for actually starting the game scene.
132
+ You can pass the following parameters to set your language preference and as well as the Child Mode.
133
+ If language is not set, English is used by default. Child Mode is set to ``False`` by default.
134
+ :param language: "en"
135
+ :param child_mode: False
136
+ :return: None
137
+ """
138
+
139
+ await self.__get_region(lang=language)
140
+
141
+ await self.__initialise()
142
+
143
+ async def answer(self, option):
144
+ url = f"{self.uri}/answer"
145
+ data = {
146
+ "step": self.step,
147
+ "progression": self.progression,
148
+ "sid": self.theme,
149
+ "cm": str(self.child_mode).lower(),
150
+ "answer": get_answer_id(option),
151
+ "step_last_proposition": self.step_last_proposition,
152
+ "session": self.session,
153
+ "signature": self.signature,
154
+ }
155
+
156
+ try:
157
+ req = await async_request_handler(url=url, method='POST', data=data)
158
+ resp = json.loads(req.text)
159
+
160
+ if re.findall(r"id_proposition", str(resp)):
161
+ await self.__update(action="win", resp=resp)
162
+ else:
163
+ await self.__update(action="answer", resp=resp)
164
+ self.completion = resp['completion']
165
+ except Exception as e:
166
+ raise e
167
+
168
+ async def back(self):
169
+ if self.step == 1:
170
+ raise CantGoBackAnyFurther
171
+ else:
172
+ url = f"{self.uri}/cancel_answer"
173
+ data = {
174
+ "step": self.step,
175
+ "progression": self.progression,
176
+ "sid": self.theme,
177
+ "cm": str(self.child_mode).lower(),
178
+ "session": self.session,
179
+ "signature": self.signature,
180
+ }
181
+
182
+ try:
183
+ req = await async_request_handler(url=url, method='POST', data=data)
184
+ resp = json.loads(req.text)
185
+ await self.__update(action="back", resp=resp)
186
+ except Exception as e:
187
+ raise e
@@ -0,0 +1,67 @@
1
+ HEADERS = {
2
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
3
+ "Accept-Encoding": "gzip, deflate",
4
+ "Accept-Language": "en-US,en;q=0.9",
5
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) snap Chromium/81.0.4044.92 "
6
+ "Chrome/81.0.4044.92 Safari/537.36",
7
+ "x-requested-with": "XMLHttpRequest",
8
+ }
9
+
10
+ LANG_MAP = {
11
+ "english": "en",
12
+ "arabic": "ar",
13
+ "chinese": "cn",
14
+ "german": "de",
15
+ "spanish": "es",
16
+ "french": "fr",
17
+ "hebrew": "il",
18
+ "italian": "it",
19
+ "japanese": "jp",
20
+ "korean": "kr",
21
+ "dutch": "nl",
22
+ "polish": "pl",
23
+ "portuguese": "pt",
24
+ "russian": "ru",
25
+ "turkish": "tr",
26
+ "indonesian": "id"
27
+ }
28
+
29
+ THEME_ID = {
30
+ "c": 1,
31
+ "a": 14,
32
+ "o": 2
33
+ }
34
+
35
+ """
36
+ c - characters
37
+ a - animals
38
+ o - objects
39
+ """
40
+
41
+ THEMES = {
42
+ "en": ["c", "a", "o"],
43
+ "ar": ["c"],
44
+ "cn": ["c"],
45
+ "de": ["c", "a"],
46
+ "es": ["c", "a"],
47
+ "fr": ["c", "a", "o"],
48
+ "il": ["c"],
49
+ "it": ["c", "a"],
50
+ "jp": ["c", "a"],
51
+ "kr": ["c"],
52
+ "nl": ["c"],
53
+ "pl": ["c"],
54
+ "pt": ["c"],
55
+ "ru": ["c"],
56
+ "tr": ["c"],
57
+ "id": ["c"],
58
+ }
59
+
60
+ ANSWERS = {
61
+ 0: ["yes", "y", '0'],
62
+ 1: ["no", "n", '1'],
63
+ 2: ["i", "idk", "i dont know", "i don't know", '2'],
64
+ 3: ["p", "probably", '3'],
65
+ 4: ["pn", "probably not", '4'],
66
+ }
67
+
@@ -0,0 +1,8 @@
1
+ class InvalidLanguageError(ValueError):
2
+ """Raise when the user input language is invalid or not supported by Akinator"""
3
+ pass
4
+
5
+
6
+ class CantGoBackAnyFurther(Exception):
7
+ """Raises when the user is in the first question and tries to go back further"""
8
+ pass
@@ -0,0 +1,27 @@
1
+ import httpx
2
+
3
+ from .dicts import ANSWERS, HEADERS
4
+
5
+
6
+ def request_handler(url: str, method: str, data: dict | None = None) -> httpx.Response:
7
+ if method == 'GET':
8
+ return httpx.get(url, headers=HEADERS, timeout=30.0)
9
+ elif method == 'POST':
10
+ return httpx.post(url, headers=HEADERS, data=data, timeout=30.0)
11
+
12
+
13
+ async def async_request_handler(url: str, method: str, data: dict | None = None) -> httpx.Response:
14
+ if method == 'GET':
15
+ async with httpx.AsyncClient() as client:
16
+ return await client.get(url, headers=HEADERS, timeout=30.0)
17
+ elif method == 'POST':
18
+ async with httpx.AsyncClient() as client:
19
+ return await client.post(url, headers=HEADERS, data=data, timeout=30.0)
20
+
21
+
22
+ def get_answer_id(ans: str | int):
23
+ for key, values in ANSWERS.items():
24
+ if ans in values:
25
+ return key
26
+ else:
27
+ continue
@@ -0,0 +1,15 @@
1
+ [tool.poetry]
2
+ name = "akipy"
3
+ version = "0.1.0"
4
+ description = "A Python library wrapper for Akinator"
5
+ authors = ["advnpzn <adenosinetp10@protonmail.com>"]
6
+ readme = "README.md"
7
+
8
+ [tool.poetry.dependencies]
9
+ python = "^3.12"
10
+ httpx = "^0.27.0"
11
+
12
+
13
+ [build-system]
14
+ requires = ["poetry-core"]
15
+ build-backend = "poetry.core.masonry.api"