Magnie wrote:
Yes, I'm always online.
Magnie is always watching. o.O
Creeeepppy XD
Offline
DUz it wurk on mac?
Offline
Laternenpfahl wrote:
DUz it wurk on mac?
Works on any computer as long as you have Java and Scratch installed.
Offline
The chat seems to be down... I get the thing that says
Welcome to the Server!
If you are seeing this, you have successfully connected!
Please read the rules on the forum thread before chatting with anyone.
but then nothing else, no "zippynk has joined!", not even things I type. Anyone know what's going on?
Offline
zippynk wrote:
The chat seems to be down... I get the thing that says
Welcome to the Server!
If you are seeing this, you have successfully connected!
Please read the rules on the forum thread before chatting with anyone.
but then nothing else, no "zippynk has joined!", not even things I type. Anyone know what's going on?
Same with me
Magnie? Whats going on?
Offline
ohaiderstudios wrote:
zippynk wrote:
The chat seems to be down... I get the thing that says
Welcome to the Server!
If you are seeing this, you have successfully connected!
Please read the rules on the forum thread before chatting with anyone.
but then nothing else, no "zippynk has joined!", not even things I type. Anyone know what's going on?Same with me
Magnie? Whats going on?
Well, it's good to know I'm not the only one this is happening to.
For a while I thought I was muted.
Edit: The last successful login I know of was that puppymk logged in sometime between 2:00 and 3:00 PM MST. And that's not nessesarily where I live, I'm just using the same time zone as the "silent hours" are advertised in.
Last edited by zippynk (2012-01-01 20:23:53)
Offline
I've reset the server and it's fixed now. I think I've found out a theory of why this happens. I believe that an error occurs from one of the clients ( either from disconnecting or from sending an odd message ) and the error somehow affects all the other clients. Though I'm not sure what the error is.
Offline
JoLLDS wrote:
is odd, is the first time I enter this site, I registered, send comments and does not send. in fact, knew the game: saving the dragons and humans part2'm putting online chats with the block "host mesh"?
anyone care to translate this?
Offline
midnightleopard wrote:
JoLLDS wrote:
is odd, is the first time I enter this site, I registered, send comments and does not send. in fact, knew the game: saving the dragons and humans part2'm putting online chats with the block "host mesh"?
anyone care to translate this?
The first time he came on Chat he registered and sent some messages and they didn't display. He is making a game and he is putting online chat in it with Mesh.
Offline
Magnie wrote:
1. The chat has the same rules as the Scratch website
2. Follow Rule #1, it's the Golden Rule
3. No swearing, cussing, foul talk, or inappropriate language.
4. No linking to bad sites. ( Inappropriate, lots of swearing )
5. No asking about private information. ( their location, phone number, age, gender )
6. Behave. No flaming, being rude, talking rudely of others, and in general, be nice.
7. No spoofing. No impersonating other users or pretending to be them.
8. No spamming. No sending useless, annoying, non-related text to chat.
Any violation of the following rules will result in a warning, mute, or IP ban from the server.An example of what you can do with the Scratch Live Clone I made:
1. Download: http://scratch.mit.edu/projects/Magnie/2234885
2. Open the project up.
3. Enable Remote Connections ( Go to Sensors > Right-Click the Sensor Value block and select "enable remote connections" )
4. Open: http://jsscratch.co.cc/MirrorApplet.html and allow it to run. Thanks MathWizz for creating it. ( http://mirror.playfultest.tk is a mirror of the mirror. )
5. Click the green flag.
Skins are here: http://scratch.mit.edu/forums/viewtopic … 0#p1054090
New Update [12/26/2011~2:50AM MST]
Announcement [12/24/2011~09:10AM MST]
Please note, that there are people usually on around 10AM through 10PM MST. So if you don't see anyone on, then it's probably during one of the "silent" times.
-------------------------------------------------------------------------------------------
You can make your own projects/chat projects with the broadcast block. For example, you can broadcast "<chat Magnie is awesome!" and it will set the variable 'chat' on the server to "Magnie is awesome" and anyone who decides to broadcast ">chat" and then look at the Sensor Value of 'chat' they will see it says "Magnie is awesome".
Broadcasts you can send:
http://tiny.cc/4sylu sets a variable 'var' to 'value'.
[url]http://block.site90.net/[broadcast%20(>var)][/url] retrieves the variable 'var', you can use the Sensor Value block to see the value.
[url]http://block.site90.net/[broadcast%20(^var)][/url] follows a variable 'var' so whenever there is an update, it sends you the update.
By using the "When I Receive" hat-block you can receive "^follow_update" which is triggered when someone sends an update to a variable you are following, like 'var'.
With the Chat project posted above, you can see the scripts use [url]http://block.site90.net/[broadcast%20(^chat)][/url] to follow the variable 'chat'. It uses http://tiny.cc/rg1t2 to set the variable 'chat'. When the server receives the update, it tells everyone that is follow the variable the update and also sends the broadcast "^follow_update" which the chat project takes advantage of this and checks the Sensor Value for the value of 'chat' then adds it to the list.
So many of the scripts in the project at the moment are lots of extra additions to make the project a little more fun. And that is what you can do with Scratch Live Clone!
-------------------------------------------------------------------------------------------
Mirror Source:Code:
# Scratch Mirror # Version 1.5.0 # By: Magnie import socket # Network base import time # For delaying purposes mostly. import threading # So it can send and receive at the same time anytime. # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # CHOST is the IP Scratch is running on, if you are running it # # on this computer, then the IP is 127.0.0.1 # # Theoretically you could run this Mirror on another computer. # # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # CPOST is the port Scratch is listening on, the default is # # 42001. Usually this is only change by a Scratcher who knows a # # about Squeak and networking with sockets. # # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # CHOST = '127.0.0.1' CPORT = 42001 # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # SHOST is the IP the server is running on. # # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # SPORT is the port that the server is using. 42002 is the # # unofficial port for Scratch Servers. The host will need to make # # sure to port-forward the port so people can connect from the # # internet. # # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # SHOST = raw_input("Server IP: ") SPORT = int( raw_input("Server Port: ") ) # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # Some extra settings that are more for advanced users are below. # # ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # # Time between checking the threads for broken ones. THREADCHECK = 5 class Client(threading.Thread): # This class listens for messages sent from Scratch and sends it to the Server. def __init__(self, CHOST, CPORT): threading.Thread.__init__(self) # Initialize it, basically just separate it from the main thread. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Defines the type of connection ( UPD, TCP on IPv4 or IPv6 ) print("Connecting to Scratch...") self.sock.connect((CHOST, CPORT)) # Connect to Scratch print("Connected to Scratch!") self.alive = 1 def run(self): global running print "Listening for Scratch messages." while running: try: data = self.sock.recv(1024) # Listens for messages sent from Scratch. self.send(data) except: self.alive = 0 def send(self, message): server.sock.send(message) # Send the data to the server. def disconnect(self): self.sock.close() class Server(threading.Thread): # This class listens for messages from the Server and sends it to Scratch. def __init__(self, SHOST, SPORT): threading.Thread.__init__(self) # Initialize it, basically just separate it from the main thread. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Defines the type of connection ( UPD, TCP on IPv4 or IPv6 ) print("Connecting to Scratch Server...") self.sock.connect((SHOST, SPORT)) # Connect to the Server. print("Connected to Server!") self.alive = 1 def run(self): global running print "Listening for Server messages." while running: try: data = self.sock.recv(1024) # Listens for messages sent from the Server. self.send(data) except: self.alive = 0 def send(self, message): scratch.sock.send(message) # Sends messages to Scratch. def disconnect(self): self.sock.close() running = 1 server = Server(SHOST, SPORT) # Start up the class for Server server.start() # This starts the 'run' function on the class as well. scratch = Client(CHOST, CPORT) # Start up the class for Scratch scratch.start() # This starts the 'run' function. while running: time.sleep(THREADCHECK) # The longer the wait time, the less CPU is used I think. if scratch.alive != 1: running = 0 if server.alive != 1: running = 0 if running == 0: running = 0 server.disconnect() # Tell the server thread to disconnect scratch.disconnect() # Tell the scratch thread to disconnect server.join() # End the server thread. scratch.join() # End the scratch thread. print 'Error Check: Yes.' else: pass #print 'Error Check: No errors.' print "Finished running."Server Source:
Code:
# Scratch Server # Version 1.0.0 # By: Magnie import threading import socket import sys from array import array from time import strftime import cPickle import hashlib class Server: def __init__(self): # Server Information self.host = '' # Game host self.port = int( raw_input("Host Port: ") ) # Game port self.backlog = 5 # Maximum clients? self.size = 1024 # Maximum receive size self.server = None self.threads = [] # Client threads ( just a record ) def setup(self): try: vari_file = open("variables.txt", "r") self.variables = cPickle.load(vari_file) vari_file.close() except IOError: vari_file = open("variables.txt", "w") cPickle.dump({}, vari_file) vari_file.close() self.variables = {} # { 'variable' : 'value' } try: auth_file = open("accounts.txt", "r") self.auth = cPickle.load(auth_file) auth_file.close() except IOError: auth_file = open("accounts.txt", "w") cPickle.dump({}, auth_file) auth_file.close() self.auth = {} # { user : ['word', 'rank'] } self.auth["admin"] = [hashlib.sha512( "password" ).digest(), "*"] save() self.blocked_ips = {} # IP : IP or False self.motd = """ Welcome to the Server! If you are seeing this, you have successfully connected! """ self.join_message = " has joined!" self.left_message = " has left!" def open_socket(self): try: # Try settings up the connection self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Define socket type self.server.bind((self.host,self.port)) # Bind server to port self.server.listen( self.backlog ) # Wait for clients to connect except socket.error, (value,message): # If it can't connect Then print out the error and shut down the server. if self.server: self.server.close() print "Could not open socket: " + message sys.exit(1) def run(self): self.open_socket() self.setup() running = 1 id = 0 # To define each client. while running: id += 1 # Increase so no client has the same ID. c = Client(self.server.accept()) # Waits for a client then accepts it. not_blocked = 1 print c.address[0] for ip in self.blocked_ips: print ip if ip == c.address[0]: not_blocked = 0 else: not_blocked = 1 print not_blocked if not_blocked: c.start() # Starts it. self.threads.append(c) # Adds it to a list so the variable c and be used for the next client. # Disconnect all clients. self.server.close() # Disconnect socket. for c in self.threads: # For each thread c.join() # End that thread. class Client(threading.Thread): def __init__(self,(client,address)): threading.Thread.__init__(self) self.client = client self.address = address self.size = 1024 self.follow = [] self.chat = Chat("") self.alive = 1 print self.address, 'has connected.' def run(self): self.running = 1 while self.running: try: data = self.client.recv(self.size) # Wait for data. if self.address[0] in s.blocked_ips: data = '' except: data = '' data = parseScratchCommand(data) # Parse the data. #print self.address[0], ":", data if data[0] == '*ping': self.client.send("Pong") print self.address[0], 'sent a ping.' elif data[0] == 'sensor-update': # If a variable is updated print self.address[0], ":", data data[1] = data[1].replace('"', "") data[2] = data[2].replace('"', "") data[-1] = data[-1].replace('"', "") args = data[2:-1] if data[1] == "Name": if self.chat.name == "": self.chat.name = data[2] self.chat.rank = '-' else: if self.chat.rank != '#': self.chat.name = data[2] self.chat.rank = "-" continue elif data[0] == 'broadcast': # If a broadcast is sent data[1] = data[1][1:] data[-1] = data[-1][:-1] if data[1] == '': continue if data[1][0] == '<' or data[1][0] == '>': if data[1][1:] not in s.variables: s.variables[ data[1][1:] ] = "" if data[1][0] == '>': vari = data[1][1:] value = s.variables[ vari ] # Start of Reserved Variables # if vari == 'time': value = strftime("%H:%M:%S") if vari == 'chat/online': value = self.chat.online() # End of Reserved Variables # self.get_var(vari, value) elif data[1][0] == '<': vari = data[1][1:] value = ' '.join( data[2:] ) # Start of Reserved Variables # if vari == 'chat': value = self.chat.message(value) if value == False: continue if vari == 'chat/mute': value = self.chat.mute(value) if vari == 'chat/auth': value = self.chat.auth(value) if vari == 'chat/rank': value = self.chat.ranker(value) if vari == 'chat/create': value = self.chat.create(value) # End of Reserved Variables # self.set_var( vari, value ) elif data[1][0] == '^': vari = data[1][1:] self.follow_var( vari ) elif data[1] == '*flush': i = 0 deleted = 0 for ip in s.threads: if ip.alive == 0: s.threads.pop(i) deleted += 1 i += 1 print "Deleted",deleted,"threads." else: print self.address[0], ":", data continue else: print self.address[0], ":", data self.client.close() # Close the connection. print self.address, 'has closed the connection.' # Debugging purposes and just informative if you are watching it. self.running = 0 self.alive = 0 if "chat" in self.follow: self.set_var( "chat", self.chat.left() ) def follow_update(self, vari): if vari in self.follow and self.alive == 1: value = s.variables[ vari ] try: self.client.send( sendScratchCommand('sensor-update "'+vari+'" "'+value+'"') ) self.client.send( sendScratchCommand('broadcast "^follow_update"') ) except: print '--Dead Thread--' self.running = 0 self.alive = 0 self.join() def set_var(self, vari, value): s.variables[ vari ] = value #if self.alive == 1: # self.client.send( sendScratchCommand('sensor-update "'+vari+'" "'+value+'"') ) for follow in s.threads: follow.follow_update(vari) print self.address[0],":",vari,"=",value save() s.variables[ "last_save" ] = "["+strftime("%H:%M:%S")+"]" def get_var(self, vari, value): if self.alive == 1: self.client.send( sendScratchCommand('sensor-update "'+vari+'" "'+value+'"') ) print self.address[0], "retrevied variable ", vari,"." def follow_var(self, vari): self.follow.append( vari ) if vari == 'chat' and self.alive == 1: motd = self.chat.motd() self.client.send( sendScratchCommand('sensor-update "chat" "'+motd+'"') ) self.set_var("chat", self.chat.name+" has joined!") print self.address, "has followed", vari,"." class Chat: def __init__(self, name): self.name = name self.rank = "-" # Ranks from Highest to Lowest: *, ~, +, -, !, # def message(self, value): if self.rank == '#': return False value = value.split(":") value[0] = self.rank+self.name value = ':'.join(value) return "["+strftime("%H:%M:%S")+"]"+value def auth(self, value): value = value.split(" ") name = value[0] word = hashlib.sha512( value[1] ).digest() if name not in s.auth: return self.name+ ' has failed to login as '+ name if s.auth[name][0] == word: if s.auth[name][1] != "*" and s.auth[name][1] != "~" and self.rank == '#': return self.name+ ' has failed to login as '+ name self.rank = s.auth[name][1] self.name = name return name+' has logged in as '+self.name+'.' else: self.rank = "!" return self.name+ ' has failed to login as '+ name def create(self, value): value = value.split(" ") name = value[0] word = hashlib.sha512( value[1] ).digest() if name in s.auth: return name+ " is already taken." else: s.auth[name] = [word, '+'] return self.name+ " has created "+ name save() def mute(self, name): if self.rank == '*' or self.rank == '~': pass else: return self.name+ ' has attempted to mute, '+ name+', and failed.' for ip in s.threads: if ip.chat.name == name: if ip.chat.rank == '#': ip.chat.rank = '-' return name+ ' has been unmuted by '+ self.name else: ip.chat.rank = '#' return name+ ' has been muted by '+ self.name def ranker(self, value): if self.rank == '*': value = value.split(' ') name = value[0] rank = value[1] if name in s.auth: s.auth[name] = [s.auth[name][0], rank] return self.name+ " has set "+ name+ " to "+rank else: return self.name+ " has failed to set "+ name+ " to "+rank return False def motd(self): return s.motd def join(self): return self.name+s.join_message def left(self): return self.name+s.left_message def online(self): online = "" for user in s.threads: if "chat" in user.follow and user.alive == 1: online += user.chat.name+", " online = online[0:-2]+"." return online def save(): try: vari_file = open("variables.txt", "w") cPickle.dump(s.variables, vari_file) # variable : value vari_file.close() auth_file = open("accounts.txt", "w") cPickle.dump(s.auth, auth_file) # user : ['word', 'rank'] auth_file.close() except IOError ,e: print e def parseScratchCommand(cmd): cmd = cmd[4:] # Remove the first four letters ( it's annoying to deal with ) cmd = cmd.split(' ') # Split the string where there is a space. It helps to find out broadcasts. return cmd # Return the list. ['broadcast/sensor-update', 'valueWord1', 'valueWord2'] def sendScratchCommand(cmd): # I was never sure what this did, but it's required. n = len(cmd) a = array('c') a.append(chr((n >> 24) & 0xFF)) a.append(chr((n >> 16) & 0xFF)) a.append(chr((n >> 8) & 0xFF)) a.append(chr(n & 0xFF)) return (a.tostring() + cmd) if __name__ == "__main__": s = Server() s.run()Any thoughts?
Why can't we ask about age and gender? Those seem like perfectly ok things to ask.
Offline
ElectricSparx wrote:
Magnie wrote:
5. No asking about private information. ( their location, phone number, age, gender )
Why can't we ask about age and gender? Those seem like perfectly ok things to ask.
This rule was made because we got reports from people who did not feel comfortable giving that information to total strangers, that said strangers were soliciting said information from them on said chat.
Offline
Connecting to client...
java.net.ConnectException: Connection refused
Are remote sensor connections enabled?
Offline
Laternenpfahl wrote:
Connecting to client...
java.net.ConnectException: Connection refused
Are remote sensor connections enabled?
you need to open the proejct in scratch, right click on the sensor blocks (The very bottom blocks under the 'sensing' category and select 'enable remote sensor connections.)
Offline
I said something along the lines of "Ooo... I got in!" and it warned me, so I said "Hi!" and it muted me?
Offline
Cassiedragon wrote:
I said something along the lines of "Ooo... I got in!" and it warned me, so I said "Hi!" and it muted me?
Yeah, sorry. It's probably because of "Cassie" (if you can see the swear word in it). I've added an exception and you shouldn't have any problems now. Sorry again.
Offline
I figured out how to authenticate real scratch accounts using python. It only works in 3.2.2. Updating mine right now...
It uses urllib2
Offline
midnightleopard wrote:
I figured out how to authenticate real scratch accounts using python. It only works in 3.2.2. Updating mine right now...
It uses urllib2
Cool! Could you post the code? I may be able to convert it to 2.X
Offline
Magnie wrote:
Cassiedragon wrote:
I said something along the lines of "Ooo... I got in!" and it warned me, so I said "Hi!" and it muted me?
Yeah, sorry. It's probably because of "Cassie" (if you can see the swear word in it). I've added an exception and you shouldn't have any problems now. Sorry again.
Thanks!
Now I can't chat... it said I'd successfully joined and "Cassiedragon has joined!" but none of my messages show up. (/list worked though.)
Offline
Cassiedragon wrote:
Magnie wrote:
Cassiedragon wrote:
I said something along the lines of "Ooo... I got in!" and it warned me, so I said "Hi!" and it muted me?
Yeah, sorry. It's probably because of "Cassie" (if you can see the swear word in it). I've added an exception and you shouldn't have any problems now. Sorry again.
Thanks!
Now I can't chat... it said I'd successfully joined and "Cassiedragon has joined!" but none of my messages show up. (/list worked though.)
Do you think you could join with a different name? I'm going to have to recode the server so it will ignore usernames (currently the server puts the entire message together (time, rank, name: message ) since it is checking the time with the name and message, which makes it nearly impossible to fix the problem without recoding.
Offline
Hey Magnie, I have something for you. How would you like REAL scratch account authentication?
Check this out:
import urllib.request def authenticateUser(username, password): string = "http://scratch.mit.edu/api/authenticateuser?username=", username, "&password=" , password string = "".join(string) fp = urllib.request.urlopen(string) result = fp.read() fp.close() result = result.decode("utf8") if result == ' \r\nfalse': return False else: return True
It doesn't work if you have symbols in your password, but I am working on that.
If someone has symbols in their password, a work around would be entering the RFC 3986 code (like %26 for a & sign).
For example, you could enter cookies%26cream instead of the password cookies&cream
Or just change the password to something with just letters and numbers.
Last edited by midnightleopard (2012-01-06 15:51:41)
Offline
midnightleopard wrote:
Hey Magnie, I have something for you. How would you like REAL scratch account authentication?
Check this out:Code:
import urllib.request def authenticateUser(username, password): string = "http://scratch.mit.edu/api/authenticateuser?username=", username, "&password=" , password string = "".join(string) fp = urllib.request.urlopen(string) result = fp.read() fp.close() result = result.decode("utf8") if result == ' \r\nfalse': return False else: return TrueIt doesn't work if you have symbols in your password, but I am working on that.
If someone has symbols in their password, a work around would be entering the RFC 3986 code (like %26 for a & sign).
For example, you could enter cookies%26cream instead of the password cookies&cream
Or just change the password to something with just letters and numbers.
Thanks for posting it. The only problem is that the passwords are sent insecurely, and I don't want people worrying about me finding out their passwords. Which is why I tell people not to put their real password in, so they don't have to worry about me finding out their real password and I don't have to worry about them or the Scratch Team getting after me.
I would have been able to make the script myself (just some quick learning on urllib), but I didn't know the api url for it (http://scratch.mit.edu/api/authenticateuser).
Thanks again for posting it.
Offline
Magnie wrote:
I would have been able to make the script myself (just some quick learning on urllib), but I didn't know the api url for it (http://scratch.mit.edu/api/authenticateuser).
Thanks again for posting it.
You could encode it using an md5 module.
Offline