Update commander.py, Dockerfile and twenty-five other files
This commit is contained in:
parent
042b931133
commit
1c46d25081
@ -8,5 +8,5 @@ RUN pip3 install -r requirements.txt
|
|||||||
ADD --chown=user . /app
|
ADD --chown=user . /app
|
||||||
RUN chmod +x /app/commander.py
|
RUN chmod +x /app/commander.py
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
ENTRYPOINT [ "/app/commander.py"]
|
ENTRYPOINT [ "/app/main.py"]
|
||||||
CMD ["-s", "/data/store.db"]
|
CMD ["-s", "/data/"]
|
||||||
|
50
commander.py
50
commander.py
@ -1,50 +0,0 @@
|
|||||||
from store import Store
|
|
||||||
from command_line import CommandLine
|
|
||||||
import argparse
|
|
||||||
from models.agent import Agent
|
|
||||||
from api import Api
|
|
||||||
from util import *
|
|
||||||
|
|
||||||
|
|
||||||
class Commander(CommandLine):
|
|
||||||
def __init__(self, store_dir='data', agent=None):
|
|
||||||
self.store_dir = store_dir
|
|
||||||
self.store = Store(store_dir)
|
|
||||||
self.agent = self.select_agent(agent)
|
|
||||||
self.api = Api(self.store, self.agent)
|
|
||||||
self.store.flush()
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
def select_agent(self, agent_str):
|
|
||||||
if agent_str is not None:
|
|
||||||
return self.store.get(Agent, agent_str)
|
|
||||||
else:
|
|
||||||
agents = self.store.all('', Agent)
|
|
||||||
agent = next(agents, None)
|
|
||||||
if agent is None:
|
|
||||||
symbol = input('agent name: ')
|
|
||||||
agent = self.store.get(Agent, symbol)
|
|
||||||
return agent
|
|
||||||
|
|
||||||
def after_cmd(self):
|
|
||||||
self.store.flush()
|
|
||||||
|
|
||||||
def do_info(self):
|
|
||||||
pprint(self.api.info(), 100)
|
|
||||||
|
|
||||||
def do_register(self, faction):
|
|
||||||
self.api.register(faction.upper())
|
|
||||||
|
|
||||||
def do_systems(self, page=1):
|
|
||||||
self.api.list_systems(int(page))
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
c = Commander(args.store_dir, args.agent)
|
|
||||||
c.run()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('-s', '--store-dir', default='data')
|
|
||||||
parser.add_argument('-a', '--agent', default=None)
|
|
||||||
args = parser.parse_args()
|
|
||||||
main(args)
|
|
15
main.py
Normal file
15
main.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import argparse
|
||||||
|
from nullptr.commander import Commander
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
c = Commander(args.store_dir, args.agent)
|
||||||
|
c.run()
|
||||||
|
|
||||||
|
# X1-AG74-41076A
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-s', '--store-dir', default='data')
|
||||||
|
parser.add_argument('-a', '--agent', default=None)
|
||||||
|
args = parser.parse_args()
|
||||||
|
main(args)
|
@ -1,7 +0,0 @@
|
|||||||
from .base import Base
|
|
||||||
|
|
||||||
|
|
||||||
class Waypoint(Base):
|
|
||||||
@classmethod
|
|
||||||
def ext(self):
|
|
||||||
return 'way'
|
|
@ -1,6 +1,8 @@
|
|||||||
import requests
|
import requests
|
||||||
from models.system import System
|
from nullptr.models.system import System
|
||||||
from util import *
|
from nullptr.models.waypoint import Waypoint
|
||||||
|
from nullptr.models.marketplace import Marketplace
|
||||||
|
from .util import *
|
||||||
|
|
||||||
class ApiError(Exception):
|
class ApiError(Exception):
|
||||||
def __init__(self, msg, code):
|
def __init__(self, msg, code):
|
||||||
@ -11,6 +13,7 @@ class Api:
|
|||||||
def __init__(self, store, agent):
|
def __init__(self, store, agent):
|
||||||
self.agent = agent
|
self.agent = agent
|
||||||
self.store = store
|
self.store = store
|
||||||
|
self.meta = None
|
||||||
self.root = 'https://api.spacetraders.io/v2/'
|
self.root = 'https://api.spacetraders.io/v2/'
|
||||||
|
|
||||||
def token(self):
|
def token(self):
|
||||||
@ -30,7 +33,9 @@ class Api:
|
|||||||
self.last_result = result
|
self.last_result = result
|
||||||
if result is None:
|
if result is None:
|
||||||
raise ApiError('http call failed', r.status_code)
|
raise ApiError('http call failed', r.status_code)
|
||||||
elif 'data' not in result:
|
if 'meta' in result:
|
||||||
|
self.last_meta = result['meta']
|
||||||
|
if 'data' not in result:
|
||||||
error_code = sg(result, 'error.code', -1)
|
error_code = sg(result, 'error.code', -1)
|
||||||
self.last_error = error_code
|
self.last_error = error_code
|
||||||
error_message = sg(result, 'error.message')
|
error_message = sg(result, 'error.message')
|
||||||
@ -56,6 +61,16 @@ class Api:
|
|||||||
|
|
||||||
def list_systems(self, page=1):
|
def list_systems(self, page=1):
|
||||||
data = self.request('get', 'systems', params={'page': page})
|
data = self.request('get', 'systems', params={'page': page})
|
||||||
|
#pprint(self.last_meta)
|
||||||
return self.store.update_list(System, data)
|
return self.store.update_list(System, data)
|
||||||
|
|
||||||
|
def list_waypoints(self, system):
|
||||||
|
data = self.request('get', f'systems/{system}/waypoints/')
|
||||||
|
# pprintz(self.last_meta)
|
||||||
|
return self.store.update_list(Waypoint, data)
|
||||||
|
|
||||||
|
def marketplace(self, waypoint):
|
||||||
|
system = waypoint.system()
|
||||||
|
symbol = f'{waypoint}-market'
|
||||||
|
data = self.request('get', f'systems/{system}/waypoints/{waypoint}/market')
|
||||||
|
return self.store.update(Marketplace, symbol, data)
|
@ -35,7 +35,7 @@ class CommandLine:
|
|||||||
print(f'command not found; {c}')
|
print(f'command not found; {c}')
|
||||||
|
|
||||||
def handle_error(self, cmd, args, e):
|
def handle_error(self, cmd, args, e):
|
||||||
logging.error(e, exc_info=str(type(e))=='ApiError')
|
logging.error(e, exc_info=str(type(e))=='ApiErrorp')
|
||||||
|
|
||||||
def handle_empty(self):
|
def handle_empty(self):
|
||||||
pass
|
pass
|
98
nullptr/commander.py
Normal file
98
nullptr/commander.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
from nullptr.command_line import CommandLine
|
||||||
|
from nullptr.store import Store
|
||||||
|
import argparse
|
||||||
|
from nullptr.models.agent import Agent
|
||||||
|
from nullptr.models.system import System
|
||||||
|
from nullptr.models.waypoint import Waypoint
|
||||||
|
from nullptr.api import Api
|
||||||
|
from .util import *
|
||||||
|
from time import sleep
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
class Commander(CommandLine):
|
||||||
|
def __init__(self, store_dir='data', agent=None):
|
||||||
|
self.store_dir = store_dir
|
||||||
|
self.store = Store(store_dir)
|
||||||
|
self.agent = self.select_agent(agent)
|
||||||
|
self.api = Api(self.store, self.agent)
|
||||||
|
self.store.flush()
|
||||||
|
self.stop_auto= False
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def select_agent(self, agent_str):
|
||||||
|
if agent_str is not None:
|
||||||
|
return self.store.get(Agent, agent_str)
|
||||||
|
else:
|
||||||
|
agents = self.store.all('', Agent)
|
||||||
|
agent = next(agents, None)
|
||||||
|
if agent is None:
|
||||||
|
symbol = input('agent name: ')
|
||||||
|
agent = self.store.get(Agent, symbol)
|
||||||
|
return agent
|
||||||
|
|
||||||
|
def after_cmd(self):
|
||||||
|
self.store.flush()
|
||||||
|
|
||||||
|
def do_info(self):
|
||||||
|
pprint(self.api.info(), 100)
|
||||||
|
|
||||||
|
def do_register(self, faction):
|
||||||
|
self.api.register(faction.upper())
|
||||||
|
|
||||||
|
def wait_for_stop(self):
|
||||||
|
input()
|
||||||
|
self.stop_auto = True
|
||||||
|
print('stopping...')
|
||||||
|
|
||||||
|
def do_universe(self):
|
||||||
|
print('universe mode. hit enter to stop')
|
||||||
|
t = Thread(target=self.wait_for_stop)
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
self.all_systems()
|
||||||
|
print('manual mode')
|
||||||
|
|
||||||
|
def all_specials(self, waypoints):
|
||||||
|
for w in waypoints:
|
||||||
|
if 'MARKETPLACE' in w.traits:
|
||||||
|
self.api.marketplace(w)
|
||||||
|
sleep(0.5)
|
||||||
|
|
||||||
|
def all_waypoints(self, systems):
|
||||||
|
for s in systems:
|
||||||
|
if self.stop_auto:
|
||||||
|
break
|
||||||
|
r = self.api.list_waypoints(s)
|
||||||
|
print(f'system {s}: {len(r)} waypoints')
|
||||||
|
sleep(0.5)
|
||||||
|
|
||||||
|
def all_systems(self):
|
||||||
|
self.stop_auto = False
|
||||||
|
data = self.api.list_systems(1)
|
||||||
|
pages = total_pages(self.api.last_meta)
|
||||||
|
print(f'page {1}: {len(data)} results')
|
||||||
|
self.all_waypoints(data)
|
||||||
|
|
||||||
|
print(f'{pages} more pages of systems')
|
||||||
|
for p in range(2, pages):
|
||||||
|
if self.stop_auto:
|
||||||
|
break
|
||||||
|
data = self.api.list_systems(p)
|
||||||
|
print(f'page {p}: {len(data)} systems')
|
||||||
|
self.all_waypoints(data)
|
||||||
|
sleep(0.5)
|
||||||
|
self.store.flush()
|
||||||
|
|
||||||
|
def do_systems(self, page=1):
|
||||||
|
r = self.api.list_systems(int(page))
|
||||||
|
pprint(self.api.last_meta)
|
||||||
|
|
||||||
|
def do_waypoints(self, system_str):
|
||||||
|
system = self.store.get(System, system_str.upper())
|
||||||
|
r = self.api.list_waypoints(system)
|
||||||
|
pprint(r)
|
||||||
|
|
||||||
|
def do_marketplace(self, waypoint_str):
|
||||||
|
waypoint = self.store.get(Waypoint, waypoint_str.upper())
|
||||||
|
r = self.api.marketplace(waypoint)
|
||||||
|
|
0
nullptr/models/__init__.py
Normal file
0
nullptr/models/__init__.py
Normal file
@ -1,6 +1,6 @@
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from util import sg
|
from nullptr.util import sg
|
||||||
@dataclass
|
@dataclass
|
||||||
class Base:
|
class Base:
|
||||||
symbol: str
|
symbol: str
|
||||||
@ -18,6 +18,12 @@ class Base:
|
|||||||
if val is not None:
|
if val is not None:
|
||||||
setattr(self, attr, val)
|
setattr(self, attr, val)
|
||||||
|
|
||||||
|
def setlst(self, attr, d, name, member):
|
||||||
|
val = sg(d, name)
|
||||||
|
if val is not None:
|
||||||
|
lst = [sg(x, member) for x in val]
|
||||||
|
setattr(self, attr, lst)
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name != 'dirty':
|
if name != 'dirty':
|
||||||
self.dirty = True
|
self.dirty = True
|
21
nullptr/models/marketplace.py
Normal file
21
nullptr/models/marketplace.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
from .base import Base
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
class Marketplace(Base):
|
||||||
|
imports:List[str] = []
|
||||||
|
exports:List[str] = []
|
||||||
|
exchange:List[str] = []
|
||||||
|
|
||||||
|
def update(self, d):
|
||||||
|
self.setlst('imports', d, 'imports', 'symbol')
|
||||||
|
self.setlst('exports', d, 'exports', 'symbol')
|
||||||
|
self.setlst('exchange', d, 'exchange', 'symbol')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def ext(self):
|
||||||
|
return 'mkt'
|
||||||
|
|
||||||
|
def path(self):
|
||||||
|
sector, system, symbol, _ = self.symbol.split('-')
|
||||||
|
return f'atlas/{sector}/{system[0:1]}/{system}/{symbol}.{self.ext()}'
|
@ -18,4 +18,4 @@ class System(Base):
|
|||||||
|
|
||||||
def path(self):
|
def path(self):
|
||||||
sector, symbol = self.symbol.split('-')
|
sector, symbol = self.symbol.split('-')
|
||||||
return f'atlas/{sector}/{symbol}.{self.ext()}'
|
return f'atlas/{sector}/{symbol[0:1]}/{symbol}.{self.ext()}'
|
30
nullptr/models/waypoint.py
Normal file
30
nullptr/models/waypoint.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from .base import Base
|
||||||
|
from nullptr.util import *
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
class Waypoint(Base):
|
||||||
|
x:int = 0
|
||||||
|
y:int = 0
|
||||||
|
type:str = 'unknown'
|
||||||
|
traits:List[str]=[]
|
||||||
|
faction:str = ''
|
||||||
|
|
||||||
|
def update(self, d):
|
||||||
|
self.seta('x', d)
|
||||||
|
self.seta('y', d)
|
||||||
|
self.seta('type', d)
|
||||||
|
self.seta('faction', d, 'faction.symbol')
|
||||||
|
if 'traits' in d:
|
||||||
|
self.traits = [mg(t, 'symbol') for t in d['traits'] ]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def ext(self):
|
||||||
|
return 'way'
|
||||||
|
|
||||||
|
def path(self):
|
||||||
|
sector, system, symbol = self.symbol.split('-')
|
||||||
|
return f'atlas/{sector}/{system[0:1]}/{system}/{symbol}.{self.ext()}'
|
||||||
|
|
||||||
|
def system(self):
|
||||||
|
p = self.symbol.split('-')
|
||||||
|
return f'{p[0]}-{p[1]}'
|
@ -1,12 +1,12 @@
|
|||||||
from models.base import Base
|
from nullptr.models.base import Base
|
||||||
from models.waypoint import Waypoint
|
from nullptr.models.waypoint import Waypoint
|
||||||
from models.sector import Sector
|
from nullptr.models.sector import Sector
|
||||||
from models.system import System
|
from nullptr.models.system import System
|
||||||
from models.agent import Agent
|
from nullptr.models.agent import Agent
|
||||||
from os.path import isfile, dirname, isdir
|
from os.path import isfile, dirname, isdir
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
from util import *
|
from .util import *
|
||||||
|
|
||||||
class Store:
|
class Store:
|
||||||
def __init__(self, data_dir):
|
def __init__(self, data_dir):
|
@ -1,4 +1,5 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
def must_get(d, k):
|
def must_get(d, k):
|
||||||
if type(k) == str:
|
if type(k) == str:
|
||||||
@ -57,6 +58,12 @@ def trim(s, l):
|
|||||||
s += ' ' * (l-len(s))
|
s += ' ' * (l-len(s))
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def total_pages(meta):
|
||||||
|
total = mg(meta, 'total')
|
||||||
|
limit = mg(meta, 'limit')
|
||||||
|
pages = ceil(total / limit)
|
||||||
|
return pages
|
||||||
|
|
||||||
# >>> parse_timestamp('2023-06-02T20:34:48.293Z')
|
# >>> parse_timestamp('2023-06-02T20:34:48.293Z')
|
||||||
# 1685738088
|
# 1685738088
|
||||||
def parse_timestamp(ts):
|
def parse_timestamp(ts):
|
@ -1,2 +1 @@
|
|||||||
requests
|
requests
|
||||||
sqlalchemy
|
|
Loading…
Reference in New Issue
Block a user