def disconnect(redis, chat, session_id, disconnect_message=None): online_state = get_online_state(redis, chat, session_id) redis.srem('chat.'+chat+'.'+online_state, session_id) redis.zrem('chats-alive', chat+'/'+session_id) redis.srem('sessions-chatting', session_id) if online_state!='offline': send_message(redis, chat, -1, 'user_change', disconnect_message)
def ping(redis, chat, session, chat_type): online_state = get_online_state(redis, chat, session.session_id) if online_state=='offline': # Check IP bans. if redis.zrank('ip-bans', chat+'/'+request.environ['HTTP_X_REAL_IP']) is not None: abort(403) # The user isn't online already. Add them to the chat. # Remove the chat from the delete queue. redis.zrem('delete-queue', chat) # Add to the archive queue, but only if it's saved. if chat_type!='unsaved' and redis.zscore('archive-queue', chat) is None: redis.zadd('archive-queue', chat, get_time(ARCHIVE_PERIOD)) # Log their IP address. redis.hset('session.'+session.session_id+'.meta', 'last_ip', request.environ['HTTP_X_REAL_IP']) # Set user state. redis.sadd('chat.'+chat+'.online', session.session_id) if session.meta['group']=='silent': join_message = None else: join_message = '%s [%s] joined chat.' % (session.character['name'], session.character['acronym']) send_message(redis, chat, -1, 'user_change', join_message) redis.sadd('sessions-chatting', session.session_id) # Add character to chat character list. redis.sadd('chat.'+chat+'.characters', session.character['character']) redis.zadd('chats-alive', chat+'/'+session.session_id, get_time(PING_PERIOD*2)) return True redis.zadd('chats-alive', chat+'/'+session.session_id, get_time(PING_PERIOD*2)) return False
def ping(redis, chat, session, chat_type): online_state = get_online_state(redis, chat, session.session_id) if online_state=='offline': # Check for Redis loading. if session.meta['counter'] == "Redis is loading the dataset in memory": abort(500) # Check IP bans. if redis.zscore('ip-bans', chat+'/'+request.headers['CF-Connecting-IP']) is not None: abort(403) # The user isn't online already. Add them to the chat. # Remove the chat from the delete queue. redis.zrem('delete-queue', chat) # Add to the archive queue, but only if it's saved. if chat_type!='unsaved' and redis.zscore('archive-queue', chat) is None: redis.zadd('archive-queue', chat, get_time(ARCHIVE_PERIOD)) # Log their IP address. redis.hset('session.'+session.session_id+'.meta', 'last_ip', request.headers['CF-Connecting-IP']) # Set user state. redis.sadd('chat.'+chat+'.online', session.session_id) if session.meta['group']=='silent': join_message = None elif session.meta['group']=='globalmod': join_message = '%s [%s] joined chat. ~~ %s ~~ [u]MSPARP STAFF[/u]' % (session.character['name'], session.character['acronym'], session.meta['counter']) else: join_message = '%s [%s] joined chat. ~~ %s ~~' % (session.character['name'], session.character['acronym'], session.meta['counter']) send_message(redis, chat, -1, 'user_change', join_message) redis.sadd('sessions-chatting', session.session_id) # Add character to chat character list. redis.sadd('chat.'+chat+'.characters', session.character['character']) redis.zadd('chats-alive', chat+'/'+session.session_id, get_time(PING_PERIOD*2)) return True redis.zadd('chats-alive', chat+'/'+session.session_id, get_time(PING_PERIOD*2)) return False
def disconnect(redis, chat, session_id, disconnect_message=None): online_state = get_online_state(redis, chat, session_id) redis.srem('chat.' + chat + '.' + online_state, session_id) redis.zrem('chats-alive', chat + '/' + session_id) redis.srem('sessions-chatting', session_id) if online_state != 'offline': send_message(redis, chat, -1, 'user_change', disconnect_message)
def change_state(redis, chat, session_id, state): current_state = get_online_state(redis, chat, session_id) if state != current_state: redis.smove('chat.' + chat + '.' + current_state, 'chat.' + chat + '.' + state, session_id) # Update userlist. send_message(redis, chat, -1, 'user_change')
def ping(redis, chat, session, chat_type): online_state = get_online_state(redis, chat, session.session_id) if online_state == 'offline': # Don't let the user in if there are more than 30 people online already. # XXX SHOW THEM A PROPER ERROR MESSAGE FOR THIS if redis.sismember( "global-mods", session.session_id) is False and redis.scard('chat.' + chat + '.online') >= 30: abort(403) # Global bans if redis.hexists("global-bans", request.headers['CF-Connecting-IP']): abort(403) # Check for Redis loading. if session.meta['counter'] == "Redis is loading the dataset in memory": abort(500) # Check IP bans. if redis.zscore('ip-bans', chat + '/' + request.headers['CF-Connecting-IP']) is not None: abort(403) # The user isn't online already. Add them to the chat. # Remove the chat from the delete queue. redis.zrem('delete-queue', chat) # Add to the archive queue, but only if it's saved. if chat_type != 'unsaved' and redis.zscore('archive-queue', chat) is None: redis.zadd('archive-queue', chat, get_time(ARCHIVE_PERIOD)) # Log their IP address. redis.hset('session.' + session.session_id + '.meta', 'last_ip', request.headers['CF-Connecting-IP']) # Set user state. redis.sadd('chat.' + chat + '.online', session.session_id) if session.meta['group'] == 'silent': join_message = None elif session.meta['group'] == 'globalmod' and redis.hget( "session." + session.session_id + ".meta", "noglobal") != "1": join_message = '%s [%s] joined chat. ~~ %s ~~ [u]MSPARP STAFF[/u]' % ( session.character['name'], session.character['acronym'], session.meta['counter']) else: join_message = '%s [%s] joined chat. ~~ %s ~~' % ( session.character['name'], session.character['acronym'], session.meta['counter']) send_message(redis, chat, -1, 'user_change', join_message) redis.sadd('sessions-chatting', session.session_id) # Add character to chat character list. redis.sadd('chat.' + chat + '.characters', session.character['character']) redis.zadd('chats-alive', chat + '/' + session.session_id, get_time(PING_PERIOD * 2)) return True redis.zadd('chats-alive', chat + '/' + session.session_id, get_time(PING_PERIOD * 2)) return False
def ping(redis, chat, session, chat_type): online_state = get_online_state(redis, chat, session.session_id) if online_state=='offline': # Don't let the user in if there are more than 30 people online already. # XXX SHOW THEM A PROPER ERROR MESSAGE FOR THIS if redis.scard('chat.'+chat+'.online')>=30: abort(403) # Global bans if redis.hexists("global-bans", request.headers['CF-Connecting-IP']): abort(403) # Check for Redis loading. if session.meta['counter'] == "Redis is loading the dataset in memory": abort(500) # Check IP bans. if redis.zscore('ip-bans', chat+'/'+request.headers['CF-Connecting-IP']) is not None: abort(403) # The user isn't online already. Add them to the chat. # Remove the chat from the delete queue. redis.zrem('delete-queue', chat) # Add to the archive queue, but only if it's saved. if chat_type!='unsaved' and redis.zscore('archive-queue', chat) is None: redis.zadd('archive-queue', chat, get_time(ARCHIVE_PERIOD)) # Log their IP address. redis.hset('session.'+session.session_id+'.meta', 'last_ip', request.headers['CF-Connecting-IP']) # Set user state. redis.sadd('chat.'+chat+'.online', session.session_id) if session.meta['group']=='silent': join_message = None elif session.meta['group']=='globalmod': join_message = '%s [%s] joined chat. ~~ %s ~~ [tshadow= 1px 1px 0px #000000, -1px 1px 0px #000000, 1px -1px 0px #000000, -1px -1px 0px #000000, 1px 0px 0px #000000, -1px 0px 0px #000000, 0px -1px 0px #000000, 0px 1px 0px #000000; color:#FFFFFF; background-image: url(//upload.wikimedia.org/wikipedia/commons/2/22/Animated_fire_by_nevit.gif); padding: 6px; border-radius: 5px; background-position: left bottom; line-height:0px; font-size:12px][u]MSPARP STAFF[/u][/tshadow]' % (session.character['name'], session.character['acronym'], session.meta['counter']) else: join_message = '%s [%s] joined chat. ~~ %s ~~' % (session.character['name'], session.character['acronym'], session.meta['counter']) send_message(redis, chat, -1, 'user_change', join_message) redis.sadd('sessions-chatting', session.session_id) # Add character to chat character list. redis.sadd('chat.'+chat+'.characters', session.character['character']) redis.zadd('chats-alive', chat+'/'+session.session_id, get_time(PING_PERIOD*2)) return True redis.zadd('chats-alive', chat+'/'+session.session_id, get_time(PING_PERIOD*2)) return False
def change_state(redis, chat, session_id, state): current_state = get_online_state(redis, chat, session_id) if state!=current_state: redis.smove('chat.'+chat+'.'+current_state, 'chat.'+chat+'.'+state, session_id) # Update userlist. send_message(redis, chat, -1, 'user_change')
disconnect(redis, chat, session, disconnect_message) print "dead", dead for dead in redis.zrangebyscore("searchers", 0, get_time()): print "reaping searcher", dead redis.zrem("searchers", dead) new_time = datetime.datetime.now() # Every minute if new_time.minute != current_time.minute: mysql = sm() # Send blank messages to avoid socket timeouts. for chat in redis.zrangebyscore("longpoll-timeout", 0, get_time()): send_message(redis, chat, -1, "message") # Expire IP bans. redis.zremrangebyscore("ip-bans", 0, get_time()) # Archive chats. for chat in redis.zrangebyscore("archive-queue", 0, get_time()): archive_chat(redis, mysql, chat, 50) pipe = redis.pipeline() pipe.scard("chat." + chat + ".online") pipe.scard("chat." + chat + ".idle") online, idle = pipe.execute() # Stop archiving if no-one is online any more. if online + idle == 0: redis.zrem("archive-queue", chat) else:
def postMessage(): chat = request.form['chat'] if 'line' in request.form and g.user.meta['group']!='silent': # Remove linebreaks and truncate to 1500 characters. line = request.form['line'].replace('\n', ' ')[:1500] send_message(g.redis, chat, g.user.meta['counter'], 'message', line, g.user.character['color'], g.user.character['acronym']) if 'state' in request.form and request.form['state'] in ['online', 'idle']: change_state(g.redis, chat, g.user.session_id, request.form['state']) # Mod options. if g.user.meta['group'] in MOD_GROUPS: if 'set_group' in request.form and 'counter' in request.form: set_group = request.form['set_group'] set_session_id = g.redis.hget('chat.'+chat+'.counters', request.form['counter']) or abort(400) ss_key = 'session.'+set_session_id+'.chat.'+chat ss_meta_key = 'session.'+set_session_id+'.meta.'+chat current_group = g.redis.hget(ss_meta_key, 'group') # You can't promote people to or demote people from a group higher than your own. if ( GROUP_RANKS[current_group]>GROUP_RANKS[g.user.meta['group']] or GROUP_RANKS[set_group]>GROUP_RANKS[g.user.meta['group']] ): return 'ok' if current_group!=set_group and set_group in GROUP_RANKS.keys(): g.redis.hset(ss_meta_key, 'group', set_group) set_message = None # XXX make a function for fetching name and acronym? # Convert the name and acronym to unicode. ss_character = g.redis.hget(ss_key, 'character') set_session_name = unicode( g.redis.hget(ss_key, 'name') or CHARACTER_DETAILS[ss_character]['name'], encoding='utf8' ) set_session_acronym = unicode( g.redis.hget(ss_key, 'acronym') or CHARACTER_DETAILS[ss_character]['acronym'], encoding='utf8' ) if set_group=='mod': set_message = '%s [%s] set %s [%s] to Professional Wet Blanket. They can now silence, kick and ban other users.' elif set_group=='mod2': set_message = '%s [%s] set %s [%s] to Bum\'s Rusher. They can now silence and kick other users.' elif set_group=='mod3': set_message = '%s [%s] set %s [%s] to Amateur Gavel-Slinger. They can now silence other users.' elif set_group=='user': if current_group in MOD_GROUPS: set_message = '%s [%s] removed moderator status from %s [%s].' else: set_message = '%s [%s] unsilenced %s [%s].' elif set_group=='silent': set_message = '%s [%s] silenced %s [%s].' if set_message is not None: set_message = set_message % ( g.user.character['name'], g.user.character['acronym'], set_session_name, set_session_acronym ) send_message(g.redis, chat, -1, 'user_change', set_message) if 'user_action' in request.form and 'counter' in request.form and request.form['user_action'] in MINIMUM_RANKS: # Check if we're high enough to perform this action. if GROUP_RANKS[g.user.meta['group']]<MINIMUM_RANKS[request.form['user_action']]: return 'ok' their_session_id = g.redis.hget('chat.'+chat+'.counters', request.form['counter']) or abort(400) their_group = g.redis.hget('session.'+their_session_id+'.meta.'+chat, 'group') # Check if we're high enough to affect the other user. if GROUP_RANKS[g.user.meta['group']]<GROUP_RANKS[their_group]: return 'ok' # XXX make a function for fetching name and acronym? # Fetch their name and convert to unicode. their_chat_key = 'session.'+their_session_id+'.chat.'+chat their_character = g.redis.hget(their_chat_key, 'character') their_session_name = unicode( g.redis.hget(their_chat_key, 'name') or CHARACTER_DETAILS[their_character]['name'], encoding='utf8' ) their_session_acronym = unicode( g.redis.hget(their_chat_key, 'acronym') or CHARACTER_DETAILS[their_character]['acronym'], encoding='utf8' ) if request.form['user_action']=='kick': g.redis.publish('channel.'+chat+'.'+their_session_id, '{"exit":"kick"}') disconnect(g.redis, chat, their_session_id, "%s [%s] kicked %s [%s] from the chat." % ( g.user.character['name'], g.user.character['acronym'], their_session_name, their_session_acronym )) # Don't ban people from the oubliette because that'll just put us in an infinite loop. elif request.form['user_action']=='ip_ban' and chat!='theoubliette': their_ip_address = g.redis.hget('session.'+their_session_id+'.meta', 'last_ip') ban_id = chat+'/'+their_ip_address if their_ip_address is not None: g.redis.zadd('ip-bans', ban_id, get_time(IP_BAN_PERIOD)) if 'reason' in request.form: g.redis.hset('ban-reasons', ban_id, request.form['reason']) g.redis.publish('channel.'+chat+'.'+their_session_id, '{"exit":"ban"}') disconnect(g.redis, chat, their_session_id, "%s [%s] IP banned %s [%s]." % ( g.user.character['name'], g.user.character['acronym'], their_session_name, their_session_acronym )) if 'meta_change' in request.form: for flag in CHAT_FLAGS: if flag in request.form: if request.form[flag]=='1': g.redis.hset('chat.'+chat+'.meta', flag, '1') else: g.redis.hdel('chat.'+chat+'.meta', flag) send_message(g.redis, chat, -1, 'meta_change') if 'topic' in request.form: if request.form['topic']!='': truncated_topic = request.form['topic'][:1500] g.redis.hset('chat.'+chat+'.meta', 'topic', truncated_topic) send_message(g.redis, chat, -1, 'meta_change', '%s changed the conversation topic to "%s".' % ( g.user.character['name'], truncated_topic )) else: g.redis.hdel('chat.'+chat+'.meta', 'topic') send_message(g.redis, chat, -1, 'meta_change', '%s removed the conversation topic.' % g.user.character['name']) return 'ok'