aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--LICENSE22
-rw-r--r--MANIFEST.in3
-rw-r--r--README.md3
-rw-r--r--requirements.txt2
-rwxr-xr-xsetup.py38
-rw-r--r--south_browser/__init__.py2
-rw-r--r--south_browser/__main__.py39
-rw-r--r--south_browser/rpc.py84
-rw-r--r--tox.ini8
10 files changed, 208 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bd4481d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+build
+dist
+*.egg-info
+__pycache__
+*.pyc
+.tox
+env
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..207309d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) Jan Drögehoff
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..bb910eb
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,3 @@
+include README.md
+include LICENSE
+include requirements.txt
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5d05605
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# South Browser
+
+Server Browser for Northstar using [SouthRPC](https://github.com/Jan200101/SouthRPC)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..28d6b26
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+requests
+inquirer
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..46c6a5e
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+import setuptools
+import re
+
+requirements = []
+with open('requirements.txt') as f:
+ requirements = f.read().splitlines()
+
+version = None
+with open('south_browser/__init__.py') as f:
+ version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE).group(1)
+
+if not version:
+ raise RuntimeError('version is not set')
+
+long_description = ""
+with open("README.md", "r") as fh:
+ long_description = fh.read()
+
+
+setuptools.setup(
+ name = "south-browser",
+ version = version,
+ description = "python based",
+ long_description = long_description,
+ long_description_content_type = "text/markdown",
+ packages = [
+ "south_browser",
+ ],
+
+ python_requires = ">=3.6",
+
+ entry_points = {
+ 'console_scripts': [
+ 'south-browser=south_browser.__main__:main',
+ ],
+ },
+)
diff --git a/south_browser/__init__.py b/south_browser/__init__.py
new file mode 100644
index 0000000..9561ba9
--- /dev/null
+++ b/south_browser/__init__.py
@@ -0,0 +1,2 @@
+
+__version__ = "0.0.0"
diff --git a/south_browser/__main__.py b/south_browser/__main__.py
new file mode 100644
index 0000000..f0040b3
--- /dev/null
+++ b/south_browser/__main__.py
@@ -0,0 +1,39 @@
+import inquirer
+
+from requests.exceptions import ConnectionError
+from .rpc import *
+
+def main():
+ try:
+ work()
+ except ConnectionError:
+ print("Failed to connect to RPC")
+
+def work():
+ servers = NSGetGameServers()
+
+ choices = [f"{s[2]} ({s[6]}/{s[7]})" for s in servers]
+ questions = [
+ inquirer.List('server_index',
+ message="What server do you want to join?",
+ choices=choices,
+ ),
+ ]
+
+ answers = inquirer.prompt(questions)
+ i = answers["server_index"]
+ si = choices.index(i)
+
+ NSTryAuthWithServer(si)
+
+ sleep(1)
+
+ if not NSWasAuthSuccessful():
+ print("Failed to auth")
+ return
+
+ NSConnectToAuthedServer()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/south_browser/rpc.py b/south_browser/rpc.py
new file mode 100644
index 0000000..fe76829
--- /dev/null
+++ b/south_browser/rpc.py
@@ -0,0 +1,84 @@
+import json
+
+from requests import post
+from time import time, sleep
+
+_PAYLOAD_ID = 0
+LOCAL_RPC = "http://localhost:26503/rpc"
+
+def cmd(method: str, params = None):
+ global _PAYLOAD_ID
+ _PAYLOAD_ID += 1
+
+ payload = {
+ "jsonrpc": "2.0",
+ "id": int(time()),
+ "method": method
+ }
+
+ if params is not None:
+ payload["params"] = params
+
+ r = post(LOCAL_RPC, data=json.dumps(payload))
+
+ if r.status_code != 200:
+ raise Exception(r.text)
+
+ data = r.json()
+ return data
+
+def NSRequestServerList():
+ return cmd("execute_squirrel", {
+ "code": "return NSRequestServerList()"
+ })["result"]
+
+def NSGetServerCount(repeat: bool = True):
+ data = cmd("execute_squirrel", {
+ "code": "return NSGetServerCount()"
+ })
+
+ c = data["result"]
+
+ if not c and repeat:
+ NSRequestServerList()
+ sleep(1) # give it a second to popualte
+ return NSGetServerCount(False)
+
+ return c
+
+def NSGetGameServers():
+ # work around Squirrel closure bullshit
+ server_count = NSGetServerCount()
+
+ for i in range(server_count):
+
+ primret = []
+
+ for c in range(server_count):
+ primret.append(f"[s[{c}].index, s[{c}].id, s[{c}].name, s[{c}].description, s[{c}].map, s[{c}].playlist, s[{c}].playerCount, s[{c}].maxPlayerCount, s[{c}].requiresPassword, s[{c}].region]")
+
+ ret = "[" + ",".join(primret) + "]"
+
+ return cmd("execute_squirrel", {
+ "code": f"array<ServerInfo> s = NSGetGameServers()\nreturn {ret}"
+ })["result"]
+
+ return []
+
+def NSTryAuthWithServer(index: int, password: str = None):
+ if password is None:
+ password = ""
+
+ return cmd("execute_squirrel", {
+ "code": f"return NSTryAuthWithServer({index}, {json.dumps(password)})"
+ })["result"]
+
+def NSWasAuthSuccessful():
+ return cmd("execute_squirrel", {
+ "code": "return NSWasAuthSuccessful()"
+ })["result"]
+
+def NSConnectToAuthedServer():
+ return cmd("execute_squirrel", {
+ "code": "return NSConnectToAuthedServer()"
+ })["result"]
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..f824619
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,8 @@
+[tox]
+envlist = py38,mypy
+
+[testenv]
+deps = pytest
+commands = pytest
+setenv =
+ TOX = 1 \ No newline at end of file