-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommunication_backend.py
More file actions
347 lines (263 loc) · 12.8 KB
/
communication_backend.py
File metadata and controls
347 lines (263 loc) · 12.8 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
from steembase.account import PrivateKey
from websocket import create_connection
from steem import Steem
import steem
import time
import random
import math
import socket
from memo_saving import interpret
from memo_saving import main
import json
import steem
import requests
import json
import time
import datetime
from websocket import create_connection
from steem import Steem
import json
import os
from smtplib import SMTP as SMTP
import random
from multiprocessing import Process
import threading
from steembase.account import PrivateKey
# Will spawn threads for I/O with user
# Will use processes for blockchain related tasks
# The main class is the basis for the communication within the different areas of the backend.
# Multiple mains can run in different processes. Users can only see ongoing systems within their own main
# When a new system is requested by a user the main will hold it, when something is joined the session can be moved if needed
class Main():
def __init__(self,node,active_key,port):
self.sending_account = "co-in"
self.memo_account = "co-in-memo"
self.user_sessions = {}
self.curation_sessions = {}
self.steem_node = node
self.active_key = active_key
self.info_out = []
self.json_return_list = []
self.locks = {"user-sessions":threading.Lock(),"curation_sessions":threading.Lock(),"input-info":threading.Lock(),"return_list":threading.Lock()}
self.TCP_IP = '127.0.0.1'
self.TCP_PORT = port
print(self.TCP_PORT)
self.BUFFER_SIZE = 1024
# this brings it to about 20 posts per curation system, when it is full
# Force user to spend at least 3-5 min per post to keep votes lower
self.posts_per_user_ratio = 1/5.0
self.users_per_curation_system = 100
thread = threading.Thread(target=self.communication_loop)
thread.daemon = True
thread.start()
# {"Session":{"class":class,"new_input":[[user1/system1,input1],[user2/system2,input2]], "lock":lock}}
def communication_loop(self):
# waits for internal socket connections (from celery in the flask_app sections)
# takes the json sent, and then makes a new thread to process it
# also processes jsons sent to get status data of tasks, which is blocking
TCP_IP = self.TCP_IP
TCP_PORT = 5005
BUFFER_SIZE = self.BUFFER_SIZE
while True:
try:
num = 1
# creates re-usable socket and listens until connection is made.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(TCP_PORT)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 2)
s.bind((TCP_IP, TCP_PORT))
s.listen(0)
while True:
num+= 1
conn, addr = s.accept()
data = ""
if addr[0] == TCP_IP:
try:
# gives id for retrieval of status for tasks
id_num = random.randrange(1000000000000000000000000)
while True:
new_data = conn.recv(BUFFER_SIZE)
if not new_data: break
if not len(new_data) > 0: break
data += new_data.decode()
if not len(new_data) >= BUFFER_SIZE: break
try:
new_list = []
sent = False
if json.loads(data)["action"] == "return_json":
with self.locks["return_list"]:
for i in range(len(self.info_out)):
if self.info_out[i][0]["idnum"] == json.loads(data)["idnum"]:
sent = True
conn.send(json.dumps(self.info_out[i][0]).encode())
elif not time.time()-self.info_out[i][2] > 600:
new_list.append(self.info_out[i])
self.info_out = new_list
if not sent:
conn.send("404".encode())
else:
thread = threading.Thread(target=self.read_json, args=([data, id_num]))
thread.daemon = True
thread.start()
conn.send(json.dumps({"idnum":id_num}).encode())
except Exception as e:
print(e)
conn.send(json.dumps({"success":False, "error":-1}).encode())
except Exception as e:
print(e)
pass
conn.close()
# creates thread to do stuff with inputs
except Exception as e:
print(e)
pass
def read_json(self,json_object,idnum):
print(json_object)
# takes the json and id num and does actions based on what it contains
# then creates a status memo based on the id and how the task went.
json_object = json.loads(json_object)
user_info = {"steem-account":json_object["steem-name"]}
json_object["idnum"] = idnum
if json_object["action"] == "create_session":
if self.verify(json_object["steem-name"],json_object["key"]):
self.create_session(user_info)
self.return_json({"success":True,"action":"session created", "idnum":json_object["idnum"]},user_info)
else:
self.return_json({"success":False,"error":1,"idnum":json_object["idnum"]},user_info) # Session could not be created
elif json_object["action"]["type"] == "account":
with self.locks["user-sessions"]:
# Checks if session exists and key is correct. If not, it returns an error
try:
self.user_sessions[json_object["steem-name"]]
if self.verify_key(json_object["steem-name"],json_object["key"]):
json_object["action"]["idnum"] = json_object["idnum"]
self.user_sessions[json_object["steem-name"]]["inputs"].append(json_object["action"])
print("xxxxxxxxxx",self.user_sessions)
else:
self.return_json({"success": False, "error":3,"idnum":json_object["idnum"]},user_info) # The key is incorrect
except Exception as e:
print(e)
print(100)
self.return_json({"success": False, "error":2,"idnum":json_object["idnum"]},user_info) # Session does not exist
def create_session(self,user_info):
# Creates session once users key has been verified.
# Each session runs on a different thread.
with self.locks["user-sessions"]:
self.user_sessions[user_info["steem-account"]] = \
{"user-info":user_info,"session":Session(user_info, self.locks,self, self.steem_node),"inputs":[]}
print(self.user_sessions)
def verify(self, name, key):
# Checks if the account exists, if the account does not exist in our system it checks if it really does exist
# if the account does not exist on steem, ends, if it does exist it creates an account in our platform
try:
s = Steem()
pubkey = PrivateKey(key).pubkey
account = s.get_account(name)
pubkey2 = account['posting']['key_auths'][0][0]
if str(pubkey) != str(pubkey2):
return False
except Exception as e:
print("99")
print(e)
return False
if not interpret.get_account_info(name, self.active_key, self.sending_account, self.memo_account,
self.steem_node) is None:
# account does exist on our platform. Next checks if the key for the account is correct
if not self.verify_key(name, key):
return False
return True
else:
# checks if account exists on steem
if not self.verify_key(name, key):
return False
interpret.start_account(name, self.active_key, self.memo_account, self.sending_account, self.steem_node)
return True
# verifies key
def verify_key(self, name, key):
s = Steem(keys=key)
try:
pubkey = PrivateKey(key).pubkey
account = s.get_account(name)
pubkey2 = account['posting']['key_auths'][0][0]
if str(pubkey) != str(pubkey2):
return False
return True
except Exception as e:
print(9)
print(e)
return False
def return_json(self,json,user_info):
with self.locks["return_list"]:
self.info_out.append([json, user_info,time.time()])
pass
# Each session runs on their own thread (through main_loop), is able to communicate with everything within the main class
class Session:
def __init__(self, user_info, locks, main,steem_node):
self.main = main
self.user_info = user_info # {"steem-account":str}
self.steem_node = steem_node
self.locks = locks
self.vote_lock = threading.Lock()
self.time_of_last_vote = 0
self.token_prices = {"token-upvote-perm":0.5,"ad-token-perm":0.75}
thread = threading.Thread(target=self.main_loop)
thread.daemon = True
thread.start()
def main_loop(self):
time_since_last_communication = 0
sleep_time = 2
print(8)
while True:
with self.locks["user-sessions"]:
input_thing = self.main.user_sessions[self.user_info["steem-account"]]["inputs"]
while len(input_thing) > 0:
self.read_json(input_thing.pop())
time_since_last_communication = 0
time.sleep(sleep_time)
time_since_last_communication += sleep_time
if time_since_last_communication > 1000:
pass
# END COMMUNICATION, REMOVE CLASS OBJECT
# This is the hub of communication between the client and user, reads jsons as they come in
pass
def read_json(self,info):
# Takes a json and determines if it is valid if it is what to do.
# If it is valid it calls the correct function
print(24)
if info["action_type"] == "make_purchase":
print(25)
try:
print(12)
if info["amount"] > 0:
self.make_purchase(info["token_type"],info["amount"])
self.return_json({"success": True, "action":"purchase_tokens","idnum":info["idnum"]})
print(26)
else:
self.return_json({"success": False, "error": -20,"idnum":info["idnum"]}) # can only buy tokens
except :
self.return_json({"success": False, "error":10,"idnum":info["idnum"]}) # function doesnt work
pass
def return_json(self,json):
# This takes information returned and creates a json to send back out of it.
self.main.return_json(json,self.user_info)
pass
def make_purchase(self,token,amount):
# This takes GP the user has and buys a Token from it.
try:
account = interpret.get_account_info(self.user_info["steem-account"],self.main.active_key,self.main.sending_account, self.main.memo_account,self.steem_node)
print(27)
# Checks if the account has enough GP to buy the tokens, if it does update the account with the new amount
if account[2]["gp"] > self.token_prices[token] * amount:
print(28)
interpret.update_account(self.user_info["steem-account"],self.main.sending_account,self.main.memo_account,
[["gp", account[2]["gp"] - self.token_prices[token] * amount], [token, account[2][token] + amount]],self.main.active_key,self.main.steem_node)
else:
print(29)
#elif account[2]["gp"] + account[2]["steem-owed"] > self.token_prices[token] * amount:
# interpret.update_account(self.user_info["steem-account"])
print(account)
return account
except Exception as e:
print(e)
return False
thing = Main("wss://gtg.steem.house:8090","active_key",5005)