cleanup, re-add arg parsing
This commit is contained in:
parent
044801328d
commit
26fa771878
6 changed files with 258 additions and 148 deletions
2
Pipfile
2
Pipfile
|
@ -8,8 +8,8 @@ flask = "*"
|
|||
flask-jsonpify = "*"
|
||||
flask-sqlalchemy = "*"
|
||||
flask-restful = "*"
|
||||
psycopg2 = "*"
|
||||
python-etcd = "*"
|
||||
etcd3 = "*"
|
||||
|
||||
|
||||
[dev-packages]
|
||||
|
|
116
Pipfile.lock
generated
116
Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "3a4b0e16a97795721cc169fa6f26982a8bd080805660c08c26052712cd8814e4"
|
||||
"sha256": "c3b848f915e1b6150fc00881b6eb5a6ea53674b251cb31c9b758fd4077cd5347"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -18,10 +18,10 @@
|
|||
"default": {
|
||||
"aniso8601": {
|
||||
"hashes": [
|
||||
"sha256:b8a6a9b24611fc50cf2d9b45d371bfdc4fd0581d1cc52254f5502130a776d4af",
|
||||
"sha256:bb167645c79f7a438f9dfab6161af9bed75508c645b1f07d1158240841d22673"
|
||||
"sha256:513d2b6637b7853806ae79ffaca6f3e8754bdd547048f5ccc1420aec4b714f1e",
|
||||
"sha256:d10a4bf949f619f719b227ef5386e31f49a2b6d453004b21f02661ccc8670c7b"
|
||||
],
|
||||
"version": "==6.0.0"
|
||||
"version": "==7.0.0"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
|
@ -37,13 +37,20 @@
|
|||
],
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"flask": {
|
||||
"etcd3": {
|
||||
"hashes": [
|
||||
"sha256:ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3",
|
||||
"sha256:e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61"
|
||||
"sha256:25a524b9f032c6631ff0097532907dea81243eaa63c3744510fd1598cc4e0e87"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.0.3"
|
||||
"version": "==0.10.0"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
|
||||
"sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"flask-jsonpify": {
|
||||
"hashes": [
|
||||
|
@ -68,6 +75,43 @@
|
|||
"index": "pypi",
|
||||
"version": "==2.4.0"
|
||||
},
|
||||
"grpcio": {
|
||||
"hashes": [
|
||||
"sha256:1303578092f1f6e4bfbc354c04ac422856c393723d3ffa032fff0f7cb5cfd693",
|
||||
"sha256:229c6b313cd82bec8f979b059d87f03cc1a48939b543fe170b5a9c5cf6a6bc69",
|
||||
"sha256:3cd3d99a8b5568d0d186f9520c16121a0f2a4bcad8e2b9884b76fb88a85a7774",
|
||||
"sha256:41cfb222db358227521f9638a6fbc397f310042a4db5539a19dea01547c621cd",
|
||||
"sha256:43330501660f636fd6547d1e196e395cd1e2c2ae57d62219d6184a668ffebda0",
|
||||
"sha256:45d7a2bd8b4f25a013296683f4140d636cdbb507d94a382ea5029a21e76b1648",
|
||||
"sha256:47dc935658a13b25108823dabd010194ddea9610357c5c1ef1ad7b3f5157ebee",
|
||||
"sha256:480aa7e2b56238badce0b9413a96d5b4c90c3bfbd79eba5a0501e92328d9669e",
|
||||
"sha256:4a0934c8b0f97e1d8c18e76c45afc0d02d33ab03125258179f2ac6c7a13f3626",
|
||||
"sha256:5624dab19e950f99e560400c59d87b685809e4cfcb2c724103f1ab14c06071f7",
|
||||
"sha256:60515b1405bb3dadc55e6ca99429072dad3e736afcf5048db5452df5572231ff",
|
||||
"sha256:610f97ebae742a57d336a69b09a9c7d7de1f62aa54aaa8adc635b38f55ba4382",
|
||||
"sha256:64ea189b2b0859d1f7b411a09185028744d494ef09029630200cc892e366f169",
|
||||
"sha256:686090c6c1e09e4f49585b8508d0a31d58bc3895e4049ea55b197d1381e9f70f",
|
||||
"sha256:7745c365195bb0605e3d47b480a2a4d1baa8a41a5fd0a20de5fa48900e2c886a",
|
||||
"sha256:79491e0d2b77a1c438116bf9e5f9e2e04e78b78524615e2ce453eff62db59a09",
|
||||
"sha256:825177dd4c601c487836b7d6b4ba268db59787157911c623ba59a7c03c8d3adc",
|
||||
"sha256:8a060e1f72fb94eee8a035ed29f1201ce903ad14cbe27bda56b4a22a8abda045",
|
||||
"sha256:90168cc6353e2766e47b650c963f21cfff294654b10b3a14c67e26a4e3683634",
|
||||
"sha256:94b7742734bceeff6d8db5edb31ac844cb68fc7f13617eca859ff1b78bb20ba1",
|
||||
"sha256:962aebf2dd01bbb2cdb64580e61760f1afc470781f9ecd5fe8f3d8dcd8cf4556",
|
||||
"sha256:9c8d9eacdce840b72eee7924c752c31b675f8aec74790e08cff184a4ea8aa9c1",
|
||||
"sha256:af5b929debc336f6bab9b0da6915f9ee5e41444012aed6a79a3c7e80d7662fdf",
|
||||
"sha256:b9cdb87fc77e9a3eabdc42a512368538d648fa0760ad30cf97788076985c790a",
|
||||
"sha256:c5e6380b90b389454669dc67d0a39fb4dc166416e01308fcddd694236b8329ef",
|
||||
"sha256:d60c90fe2bfbee735397bf75a2f2c4e70c5deab51cd40c6e4fa98fae018c8db6",
|
||||
"sha256:d8582c8b1b1063249da1588854251d8a91df1e210a328aeb0ece39da2b2b763b",
|
||||
"sha256:ddbf86ba3aa0ad8fed2867910d2913ee237d55920b55f1d619049b3399f04efc",
|
||||
"sha256:e46bc0664c5c8a0545857aa7a096289f8db148e7f9cca2d0b760113e8994bddc",
|
||||
"sha256:f6437f70ec7fed0ca3a0eef1146591bb754b418bb6c6b21db74f0333d624e135",
|
||||
"sha256:f71693c3396530c6b00773b029ea85e59272557e9bd6077195a6593e4229892a",
|
||||
"sha256:f79f7455f8fbd43e8e9d61914ecf7f48ba1c8e271801996fef8d6a8f3cc9f39f"
|
||||
],
|
||||
"version": "==1.23.0"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
|
||||
|
@ -115,22 +159,27 @@
|
|||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"psycopg2": {
|
||||
"protobuf": {
|
||||
"hashes": [
|
||||
"sha256:00cfecb3f3db6eb76dcc763e71777da56d12b6d61db6a2c6ccbbb0bff5421f8f",
|
||||
"sha256:076501fc24ae13b2609ba2303d88d4db79072562f0b8cc87ec1667dedff99dc1",
|
||||
"sha256:4e2b34e4c0ddfeddf770d7df93e269700b080a4d2ec514fec668d71895f56782",
|
||||
"sha256:5cacf21b6f813c239f100ef78a4132056f93a5940219ec25d2ef833cbeb05588",
|
||||
"sha256:61f58e9ecb9e4dc7e30be56b562f8fc10ae3addcfcef51b588eed10a5a66100d",
|
||||
"sha256:8954ff6e47247bdd134db602fcadfc21662835bd92ce0760f3842eacfeb6e0f3",
|
||||
"sha256:b6e8c854cdc623028e558a409b06ea2f16d13438335941c7765d0a42b5bedd33",
|
||||
"sha256:baca21c0f7344576346e260454d0007313ccca8c170684707a63946b27a56c8f",
|
||||
"sha256:bb1735378770fb95dbe392d29e71405d45c8bdcfa064f916504833a92ab03c55",
|
||||
"sha256:de3d3c46c1ee18f996db42d1eb44cf1565cc9e38fb1dbd9b773ff6b3fa8035d7",
|
||||
"sha256:dee885602bb200bdcb1d30f6da6c7bb207360bc786d0a364fe1540dd14af0bab"
|
||||
"sha256:00a1b0b352dc7c809749526d1688a64b62ea400c5b05416f93cfb1b11a036295",
|
||||
"sha256:01acbca2d2c8c3f7f235f1842440adbe01bbc379fa1cbdd80753801432b3fae9",
|
||||
"sha256:0a795bca65987b62d6b8a2d934aa317fd1a4d06a6dd4df36312f5b0ade44a8d9",
|
||||
"sha256:0ec035114213b6d6e7713987a759d762dd94e9f82284515b3b7331f34bfaec7f",
|
||||
"sha256:31b18e1434b4907cb0113e7a372cd4d92c047ce7ba0fa7ea66a404d6388ed2c1",
|
||||
"sha256:32a3abf79b0bef073c70656e86d5bd68a28a1fbb138429912c4fc07b9d426b07",
|
||||
"sha256:55f85b7808766e5e3f526818f5e2aeb5ba2edcc45bcccede46a3ccc19b569cb0",
|
||||
"sha256:64ab9bc971989cbdd648c102a96253fdf0202b0c38f15bd34759a8707bdd5f64",
|
||||
"sha256:64cf847e843a465b6c1ba90fb6c7f7844d54dbe9eb731e86a60981d03f5b2e6e",
|
||||
"sha256:917c8662b585470e8fd42f052661fc66d59fccaae450a60044307dcbf82a3335",
|
||||
"sha256:afed9003d7f2be2c3df20f64220c30faec441073731511728a2cb4cab4cd46a6",
|
||||
"sha256:b883d7eb129b1b57c5128146bc7c2d1f15de457e96a549827fbee6f26eeedc46",
|
||||
"sha256:bf8e05d638b585d1752c5a84247134a0350d3a8b73d3632489a014a9f6f1e758",
|
||||
"sha256:d831b047bd69becaf64019a47179eb22118a50dd008340655266a906c69c6417",
|
||||
"sha256:de2760583ed28749ff885789c1cbc6c9c06d6de92fc825740ab99deb2f25ea4d",
|
||||
"sha256:eabc4cf1bc19689af8022ba52fd668564a8d96e0d08f3b4732d26a64255216a4",
|
||||
"sha256:fcff6086c86fb1628d94ea455c7b9de898afc50378042927a59df8065a79a549"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.8.2"
|
||||
"version": "==3.9.1"
|
||||
},
|
||||
"python-etcd": {
|
||||
"hashes": [
|
||||
|
@ -141,10 +190,10 @@
|
|||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
|
||||
"sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
|
||||
"sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32",
|
||||
"sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7"
|
||||
],
|
||||
"version": "==2019.1"
|
||||
"version": "==2019.2"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
@ -155,9 +204,16 @@
|
|||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:91c54ca8345008fceaec987e10924bf07dcab36c442925357e5a467b36a38319"
|
||||
"sha256:0459bf0ea6478f3e904de074d65769a11d74cdc34438ab3159250c96d089aef0"
|
||||
],
|
||||
"version": "==1.3.3"
|
||||
"version": "==1.3.7"
|
||||
},
|
||||
"tenacity": {
|
||||
"hashes": [
|
||||
"sha256:6a7511a59145c2e319b7d04ddd93c12d48cc3d3c8fa42c2846d33a620ee91f57",
|
||||
"sha256:a4eb168dbf55ed2cae27e7c6b2bd48ab54dabaf294177d998330cf59f294c112"
|
||||
],
|
||||
"version": "==5.1.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
|
@ -168,10 +224,10 @@
|
|||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
|
||||
"sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
|
||||
"sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4",
|
||||
"sha256:a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6"
|
||||
],
|
||||
"version": "==0.15.4"
|
||||
"version": "==0.15.5"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
|
|
23
challenge.py
23
challenge.py
|
@ -1,7 +1,10 @@
|
|||
from flask import request, Response, abort
|
||||
from flask_restful import reqparse
|
||||
|
||||
def require_args(*args):
|
||||
parser = reqparse.RequestParser()
|
||||
for arg in args:
|
||||
parser.add_argument(arg, required=True)
|
||||
parser.add_argument(arg, required=True, help="{} required".format(arg))
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
|
@ -20,10 +23,13 @@ class Challenge(object):
|
|||
def game(self):
|
||||
if request.method == 'GET':
|
||||
return self.describe()
|
||||
if request.method == 'HEAD':
|
||||
return self.describe()
|
||||
if request.method == 'POST':
|
||||
return self.solve()
|
||||
|
||||
def describe(self):
|
||||
""" Describe what to do to solve this challenge"""
|
||||
return self.description
|
||||
|
||||
def save_points(self, user):
|
||||
|
@ -35,3 +41,18 @@ class Challenge(object):
|
|||
def solve(self):
|
||||
""" Needs to be implemented per challenge """
|
||||
pass
|
||||
|
||||
|
||||
def error(self, msg=""):
|
||||
""" Abort with an error """
|
||||
return Response(status=400, response=msg)
|
||||
|
||||
def get_args(self, *args):
|
||||
res = {}
|
||||
f = request.form
|
||||
for arg in args:
|
||||
if arg not in f:
|
||||
abort(Response("Missing argument: {}\n".format(arg)))
|
||||
|
||||
res[arg] = f[arg]
|
||||
return res
|
||||
|
|
83
challenges.py
Normal file
83
challenges.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
import challenge
|
||||
import ipaddress
|
||||
|
||||
from flask import request
|
||||
|
||||
class RegisterNet(challenge.Challenge):
|
||||
points = 10
|
||||
provides = [ "network" ]
|
||||
|
||||
description = """
|
||||
Register a /64 IPv6 network that you fully control.
|
||||
Many other challenges depend on this. You will need to
|
||||
be able to configure IPv6 addresses in this networks
|
||||
and to setup services listening on these IPv6 addresses.
|
||||
|
||||
Submit your network with the "network" parameter.
|
||||
"""
|
||||
def solve(self):
|
||||
args = self.get_args("user", "network")
|
||||
|
||||
network = args['network']
|
||||
user = args['user']
|
||||
|
||||
try:
|
||||
net = ipaddress.IPv6Network(network)
|
||||
except Exception as e:
|
||||
return self.error("Cannot register network {}: {}".format(network, e))
|
||||
|
||||
if not net.prefixlen == 64:
|
||||
return self.error("{} mask is not /64 - please use a /64 network".format(net))
|
||||
|
||||
# Save network
|
||||
self.db.set_user_key(user, "network", network)
|
||||
self.save_points(user)
|
||||
|
||||
return "Network {} registered, that's a good start!\n".format(network)
|
||||
|
||||
class IPv6Address(challenge.Challenge):
|
||||
points = 20
|
||||
requires = [ "network" ]
|
||||
|
||||
description = """
|
||||
You have setup your network, great!
|
||||
Now it is time to show that you are really controlling your network!
|
||||
|
||||
Setup the IPv6 address
|
||||
|
||||
{}
|
||||
|
||||
and POST to this address, when it should be reachable by ping6.
|
||||
"""
|
||||
|
||||
def describe(self):
|
||||
args = self.require_args("user")
|
||||
user = args['user']
|
||||
key = "network"
|
||||
|
||||
network = self.db.get_user_key_or_none(user, key)
|
||||
if not network:
|
||||
return Response(status=400, response="""
|
||||
Register a network before trying to be reachable. Possible challenges that
|
||||
provide the network are:
|
||||
|
||||
{}
|
||||
""".format("\n".join(self.dependencies_provided_by['network'])))
|
||||
|
||||
|
||||
key = "address"
|
||||
address = self.db.get_user_key_or_none(user, key)
|
||||
if not address:
|
||||
address = get_random_ip(network.value)
|
||||
self.db.set_user_key(user, key, address)
|
||||
else:
|
||||
address = address.value
|
||||
|
||||
return self.description.format(address)
|
||||
|
||||
def solve(self):
|
||||
args = require_args("user")
|
||||
user = args['user']
|
||||
|
||||
return Response(status=400, response="""
|
||||
Not yet implemented""")
|
|
@ -1,7 +1,8 @@
|
|||
import etcd
|
||||
import etcd3
|
||||
from flask import abort
|
||||
|
||||
class etcdWrapper(object):
|
||||
class DB(object):
|
||||
""" Generalises some etcd actions """
|
||||
|
||||
def __init__(self, client, base):
|
||||
|
@ -25,3 +26,7 @@ class etcdWrapper(object):
|
|||
def set_user_key(self, user, key, value):
|
||||
path = "{}/user/{}/{}".format(self.base, user, key)
|
||||
self.client.write(path, value)
|
||||
|
||||
|
||||
def get_users(self):
|
||||
pass
|
175
server.py
175
server.py
|
@ -1,103 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# The server part: briding http to logic
|
||||
|
||||
import sys
|
||||
import etcd
|
||||
import json
|
||||
import datetime
|
||||
import inspect
|
||||
|
||||
from ungleich_game_db import *
|
||||
from challenge import Challenge
|
||||
|
||||
from flask import Flask, abort, request, Response
|
||||
from flask_restful import reqparse
|
||||
|
||||
from db import DB
|
||||
from challenge import Challenge
|
||||
import challenges
|
||||
|
||||
class RegisterNet(Challenge):
|
||||
points = 10
|
||||
provides = [ "network" ]
|
||||
|
||||
description = """
|
||||
Register a /64 IPv6 network that you fully control.
|
||||
Many other challenges depend on this. You will need to
|
||||
be able to configure IPv6 addresses in this networks
|
||||
and to setup services listening on these IPv6 addresses.
|
||||
INDEX_MESSAGE = """
|
||||
Welcome to the ungleich game server!
|
||||
|
||||
Submit your network with the "network" parameter.
|
||||
This server is still in development and is running on Nico's
|
||||
notebook. In case it is off-line, ping @nico on
|
||||
https://chat.ungleich.ch.
|
||||
|
||||
To play:
|
||||
|
||||
curl http://{hostname}/challenge
|
||||
|
||||
To see the high score:
|
||||
|
||||
curl http://{hostname}/points
|
||||
|
||||
The code for this game can be found on https://code.ungleich.ch/nico/ungleich-game
|
||||
"""
|
||||
def solve(self):
|
||||
args = require_args("user", "network")
|
||||
network = args['network']
|
||||
user = args['user']
|
||||
|
||||
try:
|
||||
net = ipaddress.IPv6Network(network)
|
||||
except Exception as e:
|
||||
return Response(status=400, response="Cannot register network {}: {}".format(network, e))
|
||||
POINT_MESSAGE = """
|
||||
Point list (aka high score)
|
||||
---------------------------
|
||||
{}
|
||||
|
||||
if not net.prefixlen == 64:
|
||||
return Response(status=400, response="{} mask is not /64 - please use a /64 network".format(net))
|
||||
"""
|
||||
|
||||
# Save network
|
||||
self.db.set_user_key(user, "network", network)
|
||||
self.save_points(user)
|
||||
|
||||
return "Network {} registered, have fun with the next challenge!\n".format(network)
|
||||
|
||||
class IPv6Address(Challenge):
|
||||
points = 20
|
||||
requires = [ "network" ]
|
||||
|
||||
description = """
|
||||
You have setup your network, great!
|
||||
Now it is time to show that you are really controlling your network!
|
||||
|
||||
Setup the IPv6 address
|
||||
CHALLENGE_MESSAGE = """
|
||||
The following challenges are available on this server:
|
||||
|
||||
{}
|
||||
|
||||
and POST to this address, when it should be reachable by ping6.
|
||||
To play, first just curl the URL and if you want to submit solutions,
|
||||
post them like this:
|
||||
|
||||
curl -d user=nico -d network=2a0a:e5c1:101::/64 http://.../challenge/...
|
||||
"""
|
||||
|
||||
def describe(self):
|
||||
args = require_args("user")
|
||||
user = args['user']
|
||||
key = "network"
|
||||
|
||||
network = self.db.get_user_key_or_none(user, key)
|
||||
if not network:
|
||||
return Response(status=400, response="""
|
||||
Register a network before trying to be reachable. Possible challenges that
|
||||
provide the network are:
|
||||
|
||||
{}
|
||||
""".format("\n".join(self.dependencies_provided_by['network'])))
|
||||
|
||||
|
||||
key = "address"
|
||||
address = self.db.get_user_key_or_none(user, key)
|
||||
if not address:
|
||||
address = get_random_ip(network.value)
|
||||
self.db.set_user_key(user, key, address)
|
||||
else:
|
||||
address = address.value
|
||||
|
||||
return self.description.format(address)
|
||||
|
||||
def solve(self):
|
||||
args = require_args("user")
|
||||
user = args['user']
|
||||
|
||||
return Response(status=400, response="""
|
||||
Not yet implemented""")
|
||||
|
||||
|
||||
class Game(object):
|
||||
def __init__(self, name, etcdclient, etcbase="/ungleichgame/v1"):
|
||||
self.client = etcdclient
|
||||
self.etcbase = etcbase
|
||||
|
||||
self.wrapper = etcdWrapper(etcdclient, self.etcbase)
|
||||
self.wrapper = DB(etcdclient, self.etcbase)
|
||||
|
||||
self.app = Flask(name)
|
||||
|
||||
|
@ -110,51 +71,50 @@ class Game(object):
|
|||
|
||||
self.userbase = "{}/user".format(self.etcbase)
|
||||
|
||||
# Automate this
|
||||
challenges = [ RegisterNet, IPv6Address ]
|
||||
challenge_instances = []
|
||||
self.__init_challenges()
|
||||
|
||||
def __init_challenges(self):
|
||||
# Create list of challenges
|
||||
self.app.add_url_rule('/challenge', 'list_of_challenges', self.list_of_challenges)
|
||||
self.app.add_url_rule('/challenge/', 'list_of_challenges', self.list_of_challenges)
|
||||
|
||||
self.providers = {}
|
||||
|
||||
self.list_challenges = []
|
||||
self.challenge_instances = []
|
||||
self.challenge_names = []
|
||||
for challenge in challenges:
|
||||
c = challenge(self.wrapper)
|
||||
challenge_instances.append(c)
|
||||
|
||||
name = type(c).__name__
|
||||
self.challenge_names.append(name)
|
||||
path = "/challenge/{}".format(name)
|
||||
for name, obj in inspect.getmembers(challenges):
|
||||
if inspect.isclass(obj):
|
||||
c = obj(self.wrapper)
|
||||
|
||||
self.app.add_url_rule(path, name, c.game, methods=['GET', 'POST'])
|
||||
self.challenge_instances.append(c)
|
||||
self.list_challenges.append(obj)
|
||||
|
||||
for provider in challenge.provides:
|
||||
if not provider in self.providers:
|
||||
self.providers[provider] = []
|
||||
self.challenge_names.append(name)
|
||||
path = "/challenge/{}".format(name)
|
||||
|
||||
self.providers[provider].append(name)
|
||||
self.app.add_url_rule(path, name, c.game, methods=['GET', 'POST'])
|
||||
|
||||
for provider in c.provides:
|
||||
if not provider in self.providers:
|
||||
self.providers[provider] = []
|
||||
|
||||
self.providers[provider].append(name)
|
||||
|
||||
# Update challenges with provider information
|
||||
for challenge in challenge_instances:
|
||||
for challenge in self.challenge_instances:
|
||||
for requirement in challenge.requires:
|
||||
if not requirement in self.providers:
|
||||
raise Exception("Unplayable server/game: {}".format(type(challenge).__name__))
|
||||
raise Exception("Unplayable challenge: {}".format(type(challenge).__name__))
|
||||
|
||||
challenge.dependencies_provided_by[requirement] = self.providers[requirement]
|
||||
|
||||
|
||||
|
||||
def list_of_challenges(self):
|
||||
base = request.base_url
|
||||
challenges = [ "{} ({})".format(name, "{}/{}".format(base, name)) for name in self.challenge_names ]
|
||||
|
||||
return """The following challenges are available on this server:
|
||||
|
||||
{}
|
||||
|
||||
""".format("\n".join(challenges))
|
||||
|
||||
c = [ "{} ({})".format(name, "{}/{}".format(base, name)) for name in self.challenge_names ]
|
||||
return CHALLENGE_MESSAGE.format("\n".join(c))
|
||||
|
||||
|
||||
def get_points(self):
|
||||
|
@ -182,18 +142,7 @@ class Game(object):
|
|||
return user_points
|
||||
|
||||
def index(self):
|
||||
points = self.points()
|
||||
|
||||
return """Welcome to the game server!
|
||||
|
||||
Current point list is:
|
||||
|
||||
{}
|
||||
|
||||
For more information visit
|
||||
|
||||
https://code.ungleich.ch/nico/ungleich-game
|
||||
""".format(points)
|
||||
return INDEX_MESSAGE.format(hostname=request.headers['Host'])
|
||||
|
||||
def points(self, username=None):
|
||||
point_list = self.get_points()
|
||||
|
@ -212,11 +161,7 @@ https://code.ungleich.ch/nico/ungleich-game
|
|||
for k, v in point_list.items():
|
||||
res.append("{} has {} points".format(k, v))
|
||||
|
||||
return """
|
||||
Point list (aka high score)
|
||||
---------------------------
|
||||
{}
|
||||
""".format("\n".join(res))
|
||||
return POINT_MESSAGE.format("\n".join(res))
|
||||
|
||||
def register(self):
|
||||
args = require_args("user")
|
||||
|
@ -234,5 +179,5 @@ Point list (aka high score)
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = Game(__name__, etcd.Client(port=2379))
|
||||
g.app.run(host="::", port='5002')
|
||||
g = Game(__name__, etcd.Client(port=2379, host='[::1]'))
|
||||
g.app.run(host="::", port='5002', debug=False)
|
||||
|
|
Loading…
Reference in a new issue