JSO wrote:
Hm - it seems like I have connected succesfully, although I don't know if anyone is online. Why doesn't it show a short message about other members in the room?
type /list. If that doesn't work, try manually broadcasting "<chat/online", then try again.
Offline
JSO wrote:
Hm - it seems like I have connected succesfully, although I don't know if anyone is online. Why doesn't it show a short message about other members in the room?
What Zippy said, but it's actually broadcasting ">chat/online" and then you look at the sensor-value block for "chat/online" then it should display it.
I'm online now.
Offline
meee
Offline
So you're not impersonating...
Offline
bobbybee wrote:
So you're not impersonating...
It's impossible to impersonate *Magnie. He's a ServerNinja.
Offline
Wow, I really didn't see it coming
Offline
# Scratch Server # Version 1.0.0 # By: Magnie import threading import socket import sys from array import array from time import strftime import time import cPickle import hashlib import math #import urllib.request 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") # All the variables and values are saved to this file, so they still exist even after a Server reset 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: bad_file = open("badwords.txt", "r") # Bad words list. self.badwords = bad_file.read().split("\n") self.badwords.pop() bad_file.close() except IOError: bad_file = open("badwords.txt", "w") bad_file.close() self.badwords = [] try: good_file = open("goodwords.txt", "r") # Good words list. self.goodwords = good_file.read().split("\n") self.goodwords.pop() good_file.close() except IOError: good_file = open("goodwords.txt", "w") good_file.close() self.goodwords = [] try: auth_file = open("accounts.txt", "r") # All the accounts are saved here. 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'] } save() try: log_file = open("log.txt", "r") # This logs all data sent to the server, can be used for debugging purposes. self.log = log_file.read().split("\n") log_file.close() except IOError: log_file = open("log.txt", "w") log_file.close() self.log = [] self.blocked_ips = [] # Blocked IP list. self.mute_list = [] # Muted name list for chat. self.motd = ''' 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. http://scratch.mit.edu/forums/viewtopic.php?pid=1083067 Please support it so you can chat in your browser! ''' # The MOTD. I may add a feature so I can change it without reseting the server. self.join_message = " has joined!" # The messages for joining and leaving. 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() # Open a socket so people can connect. self.setup() # Run the set up 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. print c.address[0] if c.address[0] not in self.blocked_ips: # Checks if the user is not in the IP ban list. 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.space = Space() self.alive = 1 # If the socket some how disconnects in a way that the thread doesn't die, # this is switched to zero and the thread will be deleted. if self.address in s.blocked_ips: print self.address, 'failed to connect.' else: print self.address, 'has connected.' def run(self): self.running = 1 while self.running: try: data = self.client.recv(self.size) # Wait for data. save() # Save the log if self.address[0] in s.blocked_ips: # If the IP is banned while being connect, data = '' # it sets the data to '' so the is disconnects. except: # If there is an error of any kind, it disconnects the client. data = '' data = parseScratchCommand(data) # Parse the data. #print self.address[0], ":", data if data[0] == '*ping': # If a user wants to test something, they can send a 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('"', "") # Put it into an easy structure. 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 != '#' and self.name not in s.mute_list: self.chat.name = data[2] self.chat.rank = "-" if data[1] == "Space/TurnL": self.space.turn_left() if data[1] == "Space/TurnR": self.space.turn_right() if data[1] == "Space/Forward": self.space.go_forward() if data[1] == "Space/Shot": self.space.fire_shot() 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: # If the variable doesn't exist, create it. s.variables[ data[1][1:] ] = "" if data[1][0] == '>': # The client wants to get the value of a variable 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] == '<': # The client wants to set a variable. 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/addGood': value = self.chat.addGood(value) if vari == 'chat/addBad': value = self.chat.addBad(value) if vari == 'chat/mute': value = self.chat.mute(value) if vari == 'chat/ipban': value = self.chat.ipban(value) if vari == 'chat/ipof': value = self.chat.ipof(value) if vari == 'chat/auth': value = self.chat.auth(value) if vari == 'chat/rank': value = self.chat.ranker(value) if vari == 'chat/temprank': value = self.chat.ranker2(value) if vari == 'chat/create': value = self.chat.create(value) if vari == 'chat/delete': value = self.chat.delete(value) if vari == 'chat/motd': self.chat.new_motd(value) if vari == 'direct': value = self.chat.direct_broadcast(value) # End of Reserved Variables # self.set_var( vari, value ) s.log.append(self.address[0]+"("+self.chat.name+"): "+vari+" = "+value) elif data[1][0] == '^': # The client wants to "follow" a variable for updates. vari = data[1][1:] self.follow_var( vari ) elif data[1] == '*flush': # Clean up all the dead threads. i = 0 deleted = 0 for ip in s.threads: if ip.alive == 0: s.threads.pop(i) deleted += 1 i += 1 self.client.send( sendScratchCommand('sensor-update "*flushed" "'+str(deleted)+'"') ) print "Deleted",deleted,"threads." else: print self.address[0], ":", data s.log.append(self.address[0]+"("+self.chat.name+"): "+str(data)) continue else: # If there isn't anything the data goes with, disconnect. 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_'+vari+'"') ) 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+'"') ) # Send client the value of 'vari' 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.client.send( sendScratchCommand('broadcast "^follow_update"') ) self.client.send( sendScratchCommand('broadcast "^follow_update_chat"') ) time.sleep(0.3) 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: *, ~, +, -, !, # self.warned = 0 self.old_chat = "" def message(self, value): if self.name in s.mute_list and self.rank not in "*~" or self.rank == '#': return False if value == self.old_chat: return False self.old_chat = value skip = censor(value) if skip == 'skip' or self.rank not in '-!#': pass elif skip == 'cuss': if self.warned == 0: value = "["+strftime("%H:%M:%S")+"]ServerNinja: No swearing, "+self.name+", you have been warned." s.mute_list.append(self.name) self.warned = 1 else: value = "["+strftime("%H:%M:%S")+"]ServerNinja: No swearing, "+self.name+", you have been muted. If you were muted because of typing out a word that was not a swear word, please contact Magnie or Ohaider to add the word as an exception and they will unmute you." self.warned = 0 value = value.split(":") value[0] = self.rank+self.name value = ':'.join(value) value = "["+strftime("%H:%M:%S")+"]"+value return value def auth(self, value): value = value.split(" ") if len(value) != 2: return self.name+ ' has failed to login.' 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): if self.name in s.mute_list: return self.name+ " has failed to create "+ name value = value.split(" ") if len(value) != 2: return self.name+ ' has failed to create an account.' 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 delete(self, value): if self.rank != '*': return self.name+" has attempted to delete "+value if value in s.auth: del s.auth[value] return self.name+" has deleted account "+value return self.name+" has attempted to delete the account "+value def mute(self, value): if self.rank not in '*~': return self.name+" tried to mute "+value if value in s.mute_list: s.mute_list.remove(value) else: s.mute_list.append(value) return self.name+" has either muted or unmuted "+value def ipban(self, value): if self.rank != '*': return self.name+" tried to ip ban." if value in s.blocked_ips: s.blocked_ips.remove(value) else: s.blocked_ips.append(value) def ipof(self, value): if self.rank not in '*~': return self.name+" tried to find the IP of "+value for ip in s.threads: if ip.chat.name == value: return ip.address[0] return "No such user." 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 def ranker2(self, value): if self.rank == '*': value = value.split(' ') name = value[0] rank = value[1] for ip in s.threads: if ip.chat.name == name: ip.chat.rank = 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 addGood(self, value): if self.rank not in '*~': return self.name+', please login as a Moderator or Awesome Owner.' if value in s.goodwords: s.goodwords.remove(value) else: s.goodwords.append(value) return "["+strftime("%H:%M:%S")+"] Word Added." def addBad(self, value): if self.rank not in '*~': return self.name+', please login as a Moderator or Awesome Owner.' if value in s.badwords: s.badwords.remove(value) else: s.badwords.append(value) return "["+strftime("%H:%M:%S")+"] Word Added." 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 new_motd(self, value): if self.rank not in '*': return "Fail" s.motd = value def direct_broadcast(self, value): value = value.split(' ') for ip in s.threads: if ip.chat.name == value[0]: while xrange(1, int(value[1])): ip.client.send( sendScratchCommand( 'broadcast "'+' '.join( value[2:] )+'"' ) ) return '0' 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() bad_file = open("badwords.txt", "w") for line in s.badwords: bad_file.write(line+"\n") bad_file.close() good_file = open("goodwords.txt", "w") for line in s.goodwords: good_file.write(line+"\n") good_file.close() log_file = open("log.txt", "w") for log in s.log: log_file.write(log+"\n") log_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) def censor(value): value = value.lower().split() for word in value: cuss = 0 for bad in s.badwords: if bad in word: for good in s.goodwords: if bad in good and word == good: cuss = 0 break else: cuss = 1 if cuss == 0: continue else: break if cuss == 1: return 'cuss' else: return 'skip' 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 if __name__ == "__main__": s = Server() s.run()
Current server source.
Offline
I updated the FireMMO thread, the newest post has a link to the Windows version of FireMMO.
Offline
zippynk wrote:
Wait a second, "Magnie has muted or unmuted bobbybee". Was that a mistake?
I don't think he's muted if that's what you are wondering.
Offline
Well, I can't talk on my normal name.
Offline
Oh, Magnie, can you tell me if you can get the FireMMO binary working. (I updated the link, at least scroll down)
Btw, the port the Windows binary is using it 42002.
Offline
bobbybee wrote:
Well, I can't talk on my normal name.
I noticed that the last mute was that "Magnie has either muted or unmuted bobbybee," but I don't think that happened on purpose. I think you should request for Magnie to un-mute you
Offline
Nah, I can survive using a name like bobbybeeRealAccount...
Offline
J_B_Production wrote:
It doesnt work!
Could you explain what's wrong?
Also bobbybee, next time you are on, can you try your name again? I think I fixed it, though I'm not entirely sure.
Last edited by Magnie (2012-01-23 10:34:06)
Offline
Alright. I'll try in a few hours. (I have very limited time right now)
Offline
New Announcement!
You can skip downloading the project now and go to this link: http://zero-bgn.de/scratchgerman/meshjava/ which uses a Mesh Java Player, allowing you to chat with your browser! All thanks to ZeroLuck!
Offline
Do you know how to set it up with FireMMO? Speaking of FIreMMO, has the new version I released worked?
Offline
@Magnie
I am able to chat with my MeshJavaPlayer with many accounts at once...
( If you want I can send you a screen shot )
But can you look in the "Java console"?
I think there will be the stack trace of the error...
Last edited by ZeroLuck (2012-01-25 13:38:36)
Offline
Stop IP-banning me. It's getting annoying. I didn't break any rules.
Offline
cocolover76 wrote:
Stop IP-banning me. It's getting annoying. I didn't break any rules.
I never IP banned you. In fact, I've never IP banned anyone yet.
Offline