amongapi 1.0.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.
- amongapi-1.0.0/PKG-INFO +23 -0
- amongapi-1.0.0/README.md +1 -0
- amongapi-1.0.0/amongapi/__init__.py +21 -0
- amongapi-1.0.0/amongapi/exceptions.py +18 -0
- amongapi-1.0.0/amongapi/game.py +87 -0
- amongapi-1.0.0/amongapi/lobby.py +51 -0
- amongapi-1.0.0/amongapi/token.py +108 -0
- amongapi-1.0.0/amongapi/utils.py +5 -0
- amongapi-1.0.0/amongapi.egg-info/PKG-INFO +23 -0
- amongapi-1.0.0/amongapi.egg-info/SOURCES.txt +13 -0
- amongapi-1.0.0/amongapi.egg-info/dependency_links.txt +1 -0
- amongapi-1.0.0/amongapi.egg-info/requires.txt +2 -0
- amongapi-1.0.0/amongapi.egg-info/top_level.txt +1 -0
- amongapi-1.0.0/setup.cfg +4 -0
- amongapi-1.0.0/setup.py +26 -0
amongapi-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: amongapi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Unofficial Among us API for AmongBot
|
|
5
|
+
Home-page: https://github.com/RawanF4X/AmongAPI
|
|
6
|
+
Author: RawanF4X
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: requests>=2.28.0
|
|
13
|
+
Requires-Dist: amongus>=1.0.0
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-dist
|
|
20
|
+
Dynamic: requires-python
|
|
21
|
+
Dynamic: summary
|
|
22
|
+
|
|
23
|
+
just test bruh for amongbot this api for amongbot im just fighting vscode and the terminal to build the library 2026-04-22 13:09
|
amongapi-1.0.0/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
just test bruh for amongbot this api for amongbot im just fighting vscode and the terminal to build the library 2026-04-22 13:09
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .token import verify_token, send_friend_request, get_public_profile
|
|
2
|
+
from .lobby import lobbyValidator, generate_lobby_code
|
|
3
|
+
from .game import gameTracker, gamePhase
|
|
4
|
+
from .exceptions import *
|
|
5
|
+
|
|
6
|
+
__version__ = "1.0.0"
|
|
7
|
+
__all__ = [
|
|
8
|
+
'verify_token',
|
|
9
|
+
'send_friend_request'
|
|
10
|
+
'get_public_profile',
|
|
11
|
+
'lobbyValidator',
|
|
12
|
+
'generate_lobby_code',
|
|
13
|
+
'AmongUsAPIError',
|
|
14
|
+
'InvaildTokenError',
|
|
15
|
+
'AccountBannedError',
|
|
16
|
+
'RateLimitedError',
|
|
17
|
+
'LobbyJoinError',
|
|
18
|
+
'ChatMessageNotFound',
|
|
19
|
+
'gameTracker',
|
|
20
|
+
'gamePhase',
|
|
21
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class AmongAPIError(Exception):
|
|
2
|
+
"""Base exception for Among Us API errors..."""
|
|
3
|
+
pass
|
|
4
|
+
|
|
5
|
+
class InvaildTokenError(AmongAPIError):
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
class AccountBannedError(AmongAPIError):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
class RateLimitedError(AmongAPIError):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
class LobbyJoinError(AmongAPIError):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
class ChatMessageNotFound(AmongAPIError):
|
|
18
|
+
pass
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import Optional, Dict, List, Callable, Awaitable
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from amongus.client import Client
|
|
6
|
+
from amongus.events import on_game_state, on_player_info, on_meeting
|
|
7
|
+
from amongus.enums import GameState as AuGameState
|
|
8
|
+
|
|
9
|
+
class gamePhase(Enum):
|
|
10
|
+
lobby = 'lobby'
|
|
11
|
+
tasks = 'tasks'
|
|
12
|
+
discussion = 'discussion'
|
|
13
|
+
voting = 'voting'
|
|
14
|
+
|
|
15
|
+
class gameTracker:
|
|
16
|
+
def __init__(self, region: str = 'North America', bot_name: str = 'AmongMute'):
|
|
17
|
+
self.region = region
|
|
18
|
+
self.bot_name = bot_name
|
|
19
|
+
self.client: Optional[Client] = None
|
|
20
|
+
self.phase: gamePhase = gamePhase.lobby
|
|
21
|
+
self.players: Dict[str, Dict] = {}
|
|
22
|
+
self._phase_callbacks: List[Callable[[gamePhase], Awaitable]] = []
|
|
23
|
+
self._player_callbacks: List[Callable[[str, bool], Awaitable]] = []
|
|
24
|
+
|
|
25
|
+
def on_phase_change(self, callback: Callable[[gamePhase], Awaitable]):
|
|
26
|
+
self._phase_callbacks.append(callback)
|
|
27
|
+
|
|
28
|
+
def on_player_state_change(self, callback: Callable[[str, bool], Awaitable]):
|
|
29
|
+
self._player_callbacks_append(callback)
|
|
30
|
+
|
|
31
|
+
async def handle_game_state(self, state: AuGameState):
|
|
32
|
+
if state == AuGameState.lobby:
|
|
33
|
+
new_phase = gamePhase.lobby
|
|
34
|
+
elif state == AuGameState.tasks:
|
|
35
|
+
new_phase = gamePhase.tasks
|
|
36
|
+
elif state == AuGameState.discussion:
|
|
37
|
+
new_phase = gamePhase.discussion
|
|
38
|
+
elif state == AuGameState.voting:
|
|
39
|
+
new_phase = gamePhase.voting
|
|
40
|
+
else:
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
if new_phase != self.phase:
|
|
44
|
+
self.phase = new_phase
|
|
45
|
+
for cb in self._phase_callbacks:
|
|
46
|
+
await cb(self.phase)
|
|
47
|
+
|
|
48
|
+
async def handle_player_info(self, players: List):
|
|
49
|
+
for p in players:
|
|
50
|
+
name = p.name
|
|
51
|
+
is_alive = not p.is_dead
|
|
52
|
+
prev = self.players.get(name, {})
|
|
53
|
+
prev_alive = prev.get('is_alive', True)
|
|
54
|
+
self.players[name] = {
|
|
55
|
+
'is_alive': is_alive,
|
|
56
|
+
'is_impostor': p.is_impostor,
|
|
57
|
+
'color': p.color.name if p.color else None
|
|
58
|
+
}
|
|
59
|
+
if is_alive != prev_alive:
|
|
60
|
+
for cb in self._player_callbacks:
|
|
61
|
+
await cb(name, is_alive)
|
|
62
|
+
|
|
63
|
+
async def connect(self):
|
|
64
|
+
self.client = Client(name=self.bot_name)
|
|
65
|
+
self.client.on(on_game_state, self.handle_game_state)
|
|
66
|
+
self.client.on(on_player_info, self.handle_player_info)
|
|
67
|
+
await self.client.start(region=self.region)
|
|
68
|
+
|
|
69
|
+
async def join_lobby(self, code: str) -> bool:
|
|
70
|
+
if not self.client:
|
|
71
|
+
return False
|
|
72
|
+
try:
|
|
73
|
+
return await self.client.join_lobby(code.upper())
|
|
74
|
+
except:
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
async def close(self):
|
|
78
|
+
if self.client:
|
|
79
|
+
await self.client.stop()
|
|
80
|
+
|
|
81
|
+
def get_players_snapshot(self) -> List[Dict]:
|
|
82
|
+
return [
|
|
83
|
+
{'name': name, 'is_alive': data['is_alive']}
|
|
84
|
+
for name, data in self.players.items()
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import Optional, List
|
|
3
|
+
from .exceptions import LobbyJoinError, ChatMessageNotFound
|
|
4
|
+
from .utils import generate_lobby_code
|
|
5
|
+
|
|
6
|
+
# because we cant reverse enginner among us, we will use amongus library
|
|
7
|
+
import amongus
|
|
8
|
+
from amongus.client import Client
|
|
9
|
+
from amongus.events import on_chat
|
|
10
|
+
|
|
11
|
+
class lobbyValidator:
|
|
12
|
+
def __init__(self, region: str = 'North America', bot_name: str = 'AmongBot Verifier'):
|
|
13
|
+
self.region = region
|
|
14
|
+
self.bot_name = bot_name
|
|
15
|
+
self.client = Optional[Client] = None
|
|
16
|
+
self.chat_messages: List[str] = []
|
|
17
|
+
self._chat_event = asyncio.Event()
|
|
18
|
+
self._target_username: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
async def _on_chat(self, player_name: str, message: str):
|
|
21
|
+
self.chat_messages.append(f'{player_name}: {message}')
|
|
22
|
+
if self._target_username and self._target_username.lower() in message.lower():
|
|
23
|
+
self._chat_event.set()
|
|
24
|
+
|
|
25
|
+
async def connect(self):
|
|
26
|
+
self.client = Client(name=self.bot_name)
|
|
27
|
+
self.client.on(on_chat, self._on_chat)
|
|
28
|
+
await self.client.start(region=self.region)
|
|
29
|
+
|
|
30
|
+
async def join_lobby(self, code: str) -> bool:
|
|
31
|
+
if not self.client:
|
|
32
|
+
raise LobbyJoinError('Client not connected...')
|
|
33
|
+
try:
|
|
34
|
+
result = await self.client.join_lobby(code.upper())
|
|
35
|
+
return result
|
|
36
|
+
except Exception as e:
|
|
37
|
+
raise LobbyJoinError(f'Failed to join lobby: {e}')
|
|
38
|
+
|
|
39
|
+
async def wait_for_chat_message(self, expected_text: str, timeout: float = 30.0) -> bool:
|
|
40
|
+
self._target_username = expected_text
|
|
41
|
+
try:
|
|
42
|
+
await asyncio.wait_for(self._chat_event.wait(), timeout=timeout)
|
|
43
|
+
return True
|
|
44
|
+
except asyncio.TimeoutError:
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
async def close(self):
|
|
48
|
+
if self.client:
|
|
49
|
+
await self.client.stop()
|
|
50
|
+
|
|
51
|
+
generate_lobby_code = generate_lobby_code
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import time
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional, Dict, Any
|
|
5
|
+
from .exceptions import *
|
|
6
|
+
|
|
7
|
+
api_base = 'https://api.innersloth.com'
|
|
8
|
+
user_agent = 'AmongUs/2024.11.26 (Windows; Steam)'
|
|
9
|
+
|
|
10
|
+
last_request_time = 0
|
|
11
|
+
min_interval = 1.0
|
|
12
|
+
|
|
13
|
+
def rate_limit():
|
|
14
|
+
global last_request_time
|
|
15
|
+
elapsed = time.time() - last_request_time
|
|
16
|
+
if elapsed < min_interval:
|
|
17
|
+
time.sleep(min_interval - elapsed)
|
|
18
|
+
last_request_time = time.time()
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class tokenVerificationResult:
|
|
22
|
+
valid: bool
|
|
23
|
+
puid: Optional[str] = None
|
|
24
|
+
name: Optional[str] = None
|
|
25
|
+
level: Optional[int] = None
|
|
26
|
+
friend_code: Optional[str] = None
|
|
27
|
+
platform: Optional[str] = None
|
|
28
|
+
cosmetics: Optional[list] = None
|
|
29
|
+
raw_data: Optional[Dict] = None
|
|
30
|
+
error: Optional[str] = None
|
|
31
|
+
|
|
32
|
+
def verify_token(token: str, timeout: int = 15, proxies: Optional[Dict] = None) -> tokenVerificationResult:
|
|
33
|
+
rate_limit()
|
|
34
|
+
session = requests.Session()
|
|
35
|
+
session.headers.update({
|
|
36
|
+
'User-Agent': user_agent,
|
|
37
|
+
'Accept': 'application/json',
|
|
38
|
+
})
|
|
39
|
+
if proxies:
|
|
40
|
+
session.proxies.update(proxies)
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
resp = session.get(
|
|
44
|
+
f'{api_base}/api/v1/user',
|
|
45
|
+
headers={'Authorization': f'Bearer {token}'},
|
|
46
|
+
timeout=timeout
|
|
47
|
+
)
|
|
48
|
+
if resp.status_code == 200:
|
|
49
|
+
data = resp.json()
|
|
50
|
+
return tokenVerificationResult(
|
|
51
|
+
valid = True,
|
|
52
|
+
puid=data.get('puid'),
|
|
53
|
+
name=data.get('name'),
|
|
54
|
+
level=data.get('level'),
|
|
55
|
+
friend_code=data.get('friendCode'),
|
|
56
|
+
platform=data.get('lastPlatform'),
|
|
57
|
+
cosmetics=data.get('cosmetics', []),
|
|
58
|
+
raw_data=data,
|
|
59
|
+
)
|
|
60
|
+
elif resp.status_code == 401:
|
|
61
|
+
raise InvalidTokenError('Token invalid or expired')
|
|
62
|
+
elif resp.status_code == 403:
|
|
63
|
+
raise AccountBannedError('Account banned or cloudflare block')
|
|
64
|
+
elif resp.status_code == 429:
|
|
65
|
+
raise RateLimitedError('Rate limit exceeded')
|
|
66
|
+
else:
|
|
67
|
+
raise AmongAPIError(f'HTTP {resp.status_code}')
|
|
68
|
+
except requests.exceptions.Timeout:
|
|
69
|
+
return tokenVerificationResult(valid=False, error='Connection timeout')
|
|
70
|
+
except requests.exceptions.ConnectionError:
|
|
71
|
+
return tokenVerificationResult(valid=False, error='Network error')
|
|
72
|
+
except AmongAPIError as e:
|
|
73
|
+
return tokenVerificationResult(valid=False, error=str(e))
|
|
74
|
+
except Exception as e:
|
|
75
|
+
return tokenVerificationResult(valid=False, error=f'Unexpected: {e}')
|
|
76
|
+
|
|
77
|
+
def get_public_profile(puid: str, proxies: Optional[Dict] = None) -> Optional[Dict]:
|
|
78
|
+
rate_limit()
|
|
79
|
+
headers = {'User-Agent': user_agent}
|
|
80
|
+
try:
|
|
81
|
+
resp = requests.get(
|
|
82
|
+
f'{api_base}/api/v1/player/public/{puid}',
|
|
83
|
+
headers=headers,
|
|
84
|
+
proxies=proxies,
|
|
85
|
+
timeout=10
|
|
86
|
+
)
|
|
87
|
+
return resp.json() if resp.status_code == 200 else None
|
|
88
|
+
except:
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
def send_friend_request(token: str, target_puid: str, timeout: int = 10) -> bool:
|
|
92
|
+
rate_limit()
|
|
93
|
+
headers = {
|
|
94
|
+
'Authorization': f'Bearer {token}',
|
|
95
|
+
'User-Agent': user_agent,
|
|
96
|
+
'Content-Type': 'application/json'
|
|
97
|
+
}
|
|
98
|
+
payload = {'puid': target_puid}
|
|
99
|
+
try:
|
|
100
|
+
resp = requests.post(
|
|
101
|
+
f'{api_base}/api/v1/friendlist',
|
|
102
|
+
headers=headers,
|
|
103
|
+
json=payload,
|
|
104
|
+
timeout=timeout
|
|
105
|
+
)
|
|
106
|
+
return resp.status_code == 200
|
|
107
|
+
except:
|
|
108
|
+
return False
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: amongapi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Unofficial Among us API for AmongBot
|
|
5
|
+
Home-page: https://github.com/RawanF4X/AmongAPI
|
|
6
|
+
Author: RawanF4X
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: requests>=2.28.0
|
|
13
|
+
Requires-Dist: amongus>=1.0.0
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-dist
|
|
20
|
+
Dynamic: requires-python
|
|
21
|
+
Dynamic: summary
|
|
22
|
+
|
|
23
|
+
just test bruh for amongbot this api for amongbot im just fighting vscode and the terminal to build the library 2026-04-22 13:09
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
amongapi/__init__.py
|
|
4
|
+
amongapi/exceptions.py
|
|
5
|
+
amongapi/game.py
|
|
6
|
+
amongapi/lobby.py
|
|
7
|
+
amongapi/token.py
|
|
8
|
+
amongapi/utils.py
|
|
9
|
+
amongapi.egg-info/PKG-INFO
|
|
10
|
+
amongapi.egg-info/SOURCES.txt
|
|
11
|
+
amongapi.egg-info/dependency_links.txt
|
|
12
|
+
amongapi.egg-info/requires.txt
|
|
13
|
+
amongapi.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
amongapi
|
amongapi-1.0.0/setup.cfg
ADDED
amongapi-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
with open('README.md', 'r') as fh:
|
|
4
|
+
long_description = fh.read()
|
|
5
|
+
|
|
6
|
+
setup(
|
|
7
|
+
name='amongapi',
|
|
8
|
+
version='1.0.0',
|
|
9
|
+
author='RawanF4X',
|
|
10
|
+
description='Unofficial Among us API for AmongBot',
|
|
11
|
+
long_description=long_description,
|
|
12
|
+
long_description_content_type='text/markdown',
|
|
13
|
+
url='https://github.com/RawanF4X/AmongAPI',
|
|
14
|
+
packages=find_packages(),
|
|
15
|
+
include_package_data=True,
|
|
16
|
+
install_requires=[
|
|
17
|
+
'requests>=2.28.0',
|
|
18
|
+
'amongus>=1.0.0',
|
|
19
|
+
],
|
|
20
|
+
classifiers=[
|
|
21
|
+
'Programming Language :: Python :: 3',
|
|
22
|
+
'License :: OSI Approved :: MIT License',
|
|
23
|
+
'Operating System :: OS Independent',
|
|
24
|
+
],
|
|
25
|
+
python_requires='>=3.8',
|
|
26
|
+
)
|