Skip to content

Commit f02b4c2

Browse files
Support Epic Online Services (EOS) Protocol
1 parent 90fceb9 commit f02b4c2

File tree

8 files changed

+184
-1
lines changed

8 files changed

+184
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ from applications written in the Python language.
1313
from opengsq.protocols.ase import ASE
1414
from opengsq.protocols.battlefield import Battlefield
1515
from opengsq.protocols.doom3 import Doom3
16+
from opengsq.protocols.eos import EOS
1617
from opengsq.protocols.gamespy1 import GameSpy1
1718
from opengsq.protocols.gamespy2 import GameSpy2
1819
from opengsq.protocols.gamespy3 import GameSpy3

opengsq/protocols/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from opengsq.protocols.ase import ASE
22
from opengsq.protocols.battlefield import Battlefield
33
from opengsq.protocols.doom3 import Doom3
4+
from opengsq.protocols.eos import EOS
45
from opengsq.protocols.gamespy1 import GameSpy1
56
from opengsq.protocols.gamespy2 import GameSpy2
67
from opengsq.protocols.gamespy3 import GameSpy3

opengsq/protocols/eos.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import aiohttp
2+
import base64
3+
import json
4+
5+
from opengsq.exceptions import ServerNotFoundException
6+
from opengsq.protocol_base import ProtocolBase
7+
8+
9+
class EOS(ProtocolBase):
10+
"""Epic Online Services (EOS) Protocol"""
11+
full_name = 'Epic Online Services (EOS) Protocol'
12+
13+
_api_url = 'https://api.epicgames.dev'
14+
15+
def __init__(self, host: str, port: int, timeout: float = 5, client_id: str = None, client_secret: str = None, deployment_id: str = None):
16+
super().__init__(host, port, timeout)
17+
18+
if client_id is None or client_secret is None or deployment_id is None:
19+
raise ValueError(
20+
"client_id, client_secret, and deployment_id must not be None")
21+
22+
self.client_id = client_id
23+
self.client_secret = client_secret
24+
self.deployment_id = deployment_id
25+
self.access_token = None
26+
27+
async def _get_access_token(self) -> str:
28+
url = f'{self._api_url}/auth/v1/oauth/token'
29+
body = f"grant_type=client_credentials&deployment_id={self.deployment_id}"
30+
headers = {
31+
"Authorization": f"Basic {base64.b64encode(f'{self.client_id}:{self.client_secret}'.encode('utf-8')).decode('utf-8')}",
32+
"Content-Type": "application/x-www-form-urlencoded"
33+
}
34+
35+
async with aiohttp.ClientSession() as session:
36+
async with session.post(url, data=body, headers=headers) as response:
37+
response.raise_for_status()
38+
data = await response.json()
39+
40+
return data["access_token"]
41+
42+
async def _get_matchmaking(self, data: dict):
43+
if self.access_token is None:
44+
self.access_token = await self._get_access_token()
45+
assert self.access_token is not None, "Failed to get access token"
46+
47+
url = f"{self._api_url}/matchmaking/v1/{self.deployment_id}/filter"
48+
headers = {
49+
"Content-Type": "application/json",
50+
"Accept": "application/json",
51+
"Authorization": f"Bearer {self.access_token}"
52+
}
53+
54+
async with aiohttp.ClientSession() as session:
55+
async with session.post(url, data=json.dumps(data), headers=headers) as response:
56+
response.raise_for_status()
57+
data = await response.json()
58+
59+
return data
60+
61+
async def get_info(self) -> dict:
62+
data = await self._get_matchmaking({
63+
"criteria": [
64+
{
65+
"key": "attributes.ADDRESS_s",
66+
"op": "EQUAL",
67+
"value": self._host
68+
},
69+
{
70+
"key": "attributes.ADDRESSBOUND_s",
71+
"op": "CONTAINS",
72+
"value": self._port
73+
},
74+
]
75+
})
76+
77+
if data["count"] <= 0:
78+
raise ServerNotFoundException()
79+
80+
return data['sessions'][0]
81+
82+
83+
if __name__ == '__main__':
84+
import asyncio
85+
86+
async def main_async():
87+
client_id = 'xyza7891muomRmynIIHaJB9COBKkwj6n'
88+
client_secret = 'PP5UGxysEieNfSrEicaD1N2Bb3TdXuD7xHYcsdUHZ7s'
89+
deployment_id = 'ad9a8feffb3b4b2ca315546f038c3ae2'
90+
91+
eos = EOS(host='150.138.77.118', port=10019, timeout=5.0, client_id=client_id,
92+
client_secret=client_secret, deployment_id=deployment_id)
93+
data = await eos.get_info()
94+
print(json.dumps(data, indent=None) + '\n')
95+
96+
asyncio.run(main_async())

opengsq/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '2.1.2'
1+
__version__ = '2.2.0'

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
aiohttp==3.8.6

setup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
with open('README.md', 'r', encoding='utf-8') as f:
1010
long_description = f.read()
1111

12+
with open('requirements.txt', 'r', encoding='utf-8') as f:
13+
install_requires = f.read().splitlines()
14+
1215
setup(
1316
name='opengsq',
1417
version=version_contents['__version__'],
1518
description='🐍 OpenGSQ - Python library for querying game servers',
1619
long_description=long_description,
1720
long_description_content_type='text/markdown',
21+
install_requires=install_requires,
1822
entry_points={'console_scripts': ['opengsq=opengsq.cli:main']},
1923
packages=find_packages(exclude=['tests', 'tests.*']),
2024
python_requires='>=3.6',

tests/protocols/test_eos.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import os
2+
3+
import pytest
4+
from opengsq.protocols.eos import EOS
5+
6+
from .result_handler import ResultHandler
7+
8+
handler = ResultHandler(os.path.basename(__file__)[:-3])
9+
# handler.enable_save = True
10+
11+
# ARK: Survival Ascended
12+
client_id = 'xyza7891muomRmynIIHaJB9COBKkwj6n'
13+
client_secret = 'PP5UGxysEieNfSrEicaD1N2Bb3TdXuD7xHYcsdUHZ7s'
14+
deployment_id = 'ad9a8feffb3b4b2ca315546f038c3ae2'
15+
16+
eos = EOS(host='150.138.77.118', port=10019, client_id=client_id,
17+
client_secret=client_secret, deployment_id=deployment_id)
18+
19+
20+
@pytest.mark.asyncio
21+
async def test_get_info():
22+
result = await eos.get_info()
23+
await handler.save_result('test_get_info', result)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"deployment": "ad9a8feffb3b4b2ca315546f038c3ae2",
3+
"id": "d0ce97bf965043b4a39d72c41d6aa10a",
4+
"bucket": "TestGameMode_C:<None>:TheIsland_WP",
5+
"settings": {
6+
"maxPublicPlayers": 127,
7+
"allowInvites": true,
8+
"shouldAdvertise": true,
9+
"allowReadById": true,
10+
"allowJoinViaPresence": true,
11+
"allowJoinInProgress": true,
12+
"allowConferenceRoom": false,
13+
"checkSanctions": false,
14+
"allowMigration": false,
15+
"rejoinAfterKick": "",
16+
"platforms": null
17+
},
18+
"totalPlayers": 113,
19+
"openPublicPlayers": 14,
20+
"publicPlayers": [],
21+
"started": false,
22+
"lastUpdated": null,
23+
"attributes": {
24+
"MINORBUILDID_s": "11",
25+
"MODID_l": 0,
26+
"CUSTOMSERVERNAME_s": "服主云服务器出租QQ1165782150 低延迟-带假人++",
27+
"ADDRESSDEV_s": "150.138.77.118,127.0.0.1",
28+
"ISPRIVATE_l": 0,
29+
"SERVERPASSWORD_b": false,
30+
"MATCHTIMEOUT_d": 120.0,
31+
"ENABLEDMODSFILEIDS_s": "4850852,4854705,4846256",
32+
"DAYTIME_s": "126",
33+
"SOTFMATCHSTARTED_b": false,
34+
"STEELSHIELDENABLED_l": 0,
35+
"SERVERUSESBATTLEYE_b": false,
36+
"EOSSERVERPING_l": 252,
37+
"ALLOWDOWNLOADCHARS_l": 1,
38+
"OFFICIALSERVER_s": "0",
39+
"GAMEMODE_s": "TestGameMode_C",
40+
"ADDRESS_s": "150.138.77.118",
41+
"SEARCHKEYWORDS_s": "Custom",
42+
"__EOS_BLISTENING_b": true,
43+
"ALLOWDOWNLOADITEMS_l": 1,
44+
"LEGACY_l": 0,
45+
"ADDRESSBOUND_s": "0.0.0.0:10019",
46+
"SESSIONISPVE_l": 0,
47+
"__EOS_BUSESPRESENCE_b": true,
48+
"ENABLEDMODS_s": "931443,928793,900062",
49+
"SESSIONNAMEUPPER_s": "服主云服务器出租QQ1165782150 低延迟-带假人++ - (V26.11)",
50+
"SERVERPLATFORMTYPE_s": "All",
51+
"MAPNAME_s": "TheIsland_WP",
52+
"BUILDID_s": "26",
53+
"SESSIONNAME_s": "服主云服务器出租QQ1165782150 低延迟-带假人++ - (v26.11)"
54+
},
55+
"owner": "Client_xyza7891muomRmynIIHaJB9COBKkwj6n",
56+
"ownerPlatformId": null
57+
}

0 commit comments

Comments
 (0)