-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
131 lines (113 loc) · 3.67 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
"""
Client which receives the requests
Args:
type (1-10)
API Token
Kind Code (abcd, efgh, etc.)
API Base (https://...)
"""
from flask import Flask, request
import logging
import argparse
import requests
import boto3
#logging.basicConfig(level=logging.INFO)
# parsing arguments
PARSER = argparse.ArgumentParser(description='Client message processor')
PARSER.add_argument('type', help="the type of the code release")
PARSER.add_argument('API_token', help="the individual API token given to your team")
PARSER.add_argument('kind_code', help="the kind code for the messages")
PARSER.add_argument('API_base', help="the base URL for the game API")
ARGS = PARSER.parse_args()
# defining global vars
KIND_CODE = ARGS.kind_code # The codes for different kinds of messages
MESSAGES = {} # A dictionary that contains message parts
API_BASE = ARGS.API_base
DYNAMODB = boto3.resource('dynamodb')
STATE_TABLE = DYNAMODB.Table('gameday-messages-state')
APP = Flask(__name__)
# creating flask route for type argument
@APP.route('/'+ARGS.type, methods=['GET', 'POST'])
def main_handler():
"""
main routing for requests
"""
if request.method == 'POST':
return process_message(request.get_json())
else:
return get_message_stats()
def store_message(input_id, part_num, data):
"""
stores the message locally on a file on disk for persistence
"""
STATE_TABLE.update_item(
Key={
'Id': input_id
},
UpdateExpression="set #key=:val",
ExpressionAttributeValues={
":val":data
},
ExpressionAttributeNames={
"#key":str(part_num)
}
)
def check_messages(input_id):
"""
checking to see in dynamo if we have the part already
"""
# do a get item from dynamo to see if item exists
response = STATE_TABLE.get_item(
Key={
'Id': input_id
},
ConsistentRead=True
)
item = response['Item']
# check if both parts exist
if "0" in item and "1" in item:
print "we have both!"
# we have all the parts
build_final(item, input_id)
else:
# we have some parts but not all
return
def build_final(parts, msg_id):
"""
building the response to return to the server
"""
# We can build the final message.
result = parts['0'] + parts['1'] + KIND_CODE
# sending the response to the score calculator
# format:
# url -> api_base/jFgwN4GvTB1D2QiQsQ8GHwQUbbIJBS6r7ko9RVthXCJqAiobMsLRmsuwZRQTlOEW
# headers -> x-gameday-token = API_token
# data -> EaXA2G8cVTj1LGuRgv8ZhaGMLpJN2IKBwC5eYzAPNlJwkN4Qu1DIaI3H1zyUdf1H5NITR
APP.logger.debug("ID: %s" % msg_id)
APP.logger.debug("RESULT: %s" % result)
url = API_BASE + '/' + msg_id
requests.post(url, data=result, headers={'x-gameday-token':ARGS.API_token})
def get_message_stats():
"""
provides a status that players can check
"""
msg_count = len(MESSAGES.keys())
return "There are %d messages in the MESSAGES dictionary" % msg_count
def process_message(msg):
"""
processes the messages by combining and appending the kind code
"""
msg_id = msg['Id'] # The unique ID for this message
part_number = msg['PartNumber'] # Which part of the message it is
data = msg['Data'] # The data of the message
# put the part received into dynamo
store_message(msg_id, part_number, data)
# Try to get the parts of the message from the Dynamo.
check_messages(msg_id)
return 'OK'
if __name__ == "__main__":
PORT = ARGS.type
# want the port range to be 8080, 8081...
PORT = '80'+str(80+int(PORT))
APP.run(host="0.0.0.0", port=PORT)