File size: 5,006 Bytes
d8d884a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import coding
import scratchattach as scratch3
import threading
import time
import random
global conn
global projectid
global endpoint
global users
users = {}
with open("password.txt") as f:
    session = scratch3.login("PolyPenguin", f.read())
class User:
    def __init__(self, name, id):
        self.name = name
        self.id = id
class Responder:
    def __init__(self, projectid, channel, can_respond, can_stream, value):
        self.projectid = projectid
        self.can_respond = can_respond
        self.can_stream = can_stream
        self.channel = channel
        self.cooldown = time.time()
        self.wrote = False
        self.last_value = value
    def poll(self):
        value = scratch3.get_var(self.projectid, "channel "+str(self.channel))
        if value != self.last_value and value != None:
            self.last_value = value
            binary = coding.decimal_to_binary(int(value))
            if binary[1:3]=="01":
                value = str(coding.binary_to_decimal(binary[3:]))
            if binary[1:3]=="10":
                value = str("true" if binary[3:] == 1 else "false")
            if binary[1:3]=="11":
                value = coding.convert_to_text(binary[3:])
            
            return value
    def close(self):
        if self.can_stream or not self.can_respond:
            conn.set_var("channel "+str(self.channel), "0")
        else:
            while str(scratch3.get_var(self.projectid, "channel "+str(self.channel))) !="0":
                pass
    def respond(self, response):
        global conn
        if self.wrote and not self.can_stream:
            raise Exception("Can't stream to this as a response")
        if not (self.can_respond or self.can_stream):
            raise Exception("Can't respond to this")
        while time.time() - self.cooldown < 0.5:
            time.sleep(0.5 - (time.time() - self.cooldown))
        if self.can_respond or self.can_stream:
            payload = "1"
            if type(response) is int:
                payload+="01"+coding.decimal_to_binary(response)
            elif type(response) is bool:
                payload+="10"+"1" if response else "0"
            elif type(response) is str:
                payload+="11"+coding.convert_to_binary(response)
            self.last_value = str(coding.binary_to_decimal(payload))
            conn.set_var("channel "+str(self.channel), str(coding.binary_to_decimal(payload)))
            t= time.time()
            times=0.2
            while scratch3.get_var(self.projectid, "channel "+str(self.channel)) !=str(coding.binary_to_decimal(payload)):
                if time.time()-t>=times:
                    print("Message not sent, retrying")
                    times+=0.1
                    conn.set_var("channel "+str(self.channel), str(coding.binary_to_decimal(payload)))
                    t=time.time()
        self.wrote = True
class ConnectionEndpoint:
    def __init__(self):
        pass
    def receivedMessage(self, message, user, responder):
        global users
        r=random.randrange(1, 2047)
        while r in users:
            r=random.randrange(1, 2047)
        users[r] = User(message, r)
        responder.respond(r)
        responder.close()

def thread(n):
    global users
    global conn
    global projectid
    global endpoint
    conn.set_var("channel "+str(n), "0")
    while True:
        
        value = scratch3.get_var(projectid, "channel "+str(n))
        if str(value) != "0" and value != None:
            binary = coding.decimal_to_binary(int(value))
            reqendpoint = coding.binary_to_decimal(binary[1:6])
            header = coding.binary_to_decimal(binary[6:17])
            staticpayload = binary[17] == '1'
            streamingpayload = binary[18] == '1'
            acceptstaticpayload = binary[19] == '1'
            acceptstreamingpayload = binary[20] == '1'
            payload = None
            if staticpayload and not streamingpayload:
                payloadformat = binary[21:23]
                if payloadformat == "01":
                    payload = str(coding.binary_to_decimal(binary[23:]))
                if payloadformat == "10":
                    payload = "true" if binary[23:]=='1' else "false"
                if payloadformat == "11":
                    payload = coding.convert_to_text(binary[23:])
            respond = Responder(projectid, n, acceptstaticpayload, acceptstreamingpayload, value)
            if header in users:
                user = users[header]
            else:
                user = None
            endpoint[reqendpoint].receivedMessage(payload, user, respond)


def start_server(endpoints, project_id):
    global projectid
    global conn
    global endpoint
    endpoints.insert(0, ConnectionEndpoint())
    endpoint = endpoints
    projectid = project_id
    conn = session.connect_cloud(project_id)
    threads = [threading.Thread(target=thread, args=(i+1,)) for i in range(10)]
    for t in threads:
        t.start()
    return t