#!/usr/bin/ruby require 'rubygems' require 'stomp' require 'digest/md5' #users = [ "mihawksrv", "qwnu", "qwnuposter", "pauldevqw", "paulkibito" ] # WRITE COMMANDS as ROLE everyone: # PING - reply from central: PONG # WHO - reply from everyone: WHO_RE # C - reply from central: C # PART - reply from central: SYS Goodbye # WRITE COMMANDS as ROLE broadcast: # REQ_BC - reply from central: BC_ID # BC_RE # WRITE COMMANDS as ROLE adminspecbots: # REQ_ASSIGN - reply from specbot: assign_re.. # REQ_UNASSIGN - reply from specbot: unassign_re.. # REQ_PING - reply from specbots: ping_re.. # REQ_ASSIGNMENTS - reply from specbot: assignments_re.. # WRITE COMMANDS as ROLE specbot: # ASSIGN_RE # UNASSIGN_RE # PING_RE # ASSIGNMENTS_RE # USERS: ROLE # paulkibito: broadcast # qwnu: broadcast # mihawk: broadcast specbot # pauldevqw: broadcast specbot # qwsbalance: adminspecbots # # .. allowed commands .. ROLES = CAPABILITIES # normal users have ROLE broadcast. Roles are defined on a per-user basis .. in a config. STDOUT.sync = true raise "ARGV[0] must be a userstring - no numbers!" unless ARGV[0] =~ /^[a-zA-Z]+$/ $user = "%s" % [ARGV[0]] $broadcasts = Hash.new $debug = 0 def put_debug(msg) if $debug == 1 puts msg end end def put_log(msg) puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S %z")}: #{msg}" end # consuming process with a loop def consuming(user) put_log "SYS Starting consuming/reading thread\n" client = Stomp::Connection.new("", "", "localhost", 61613, true) client.subscribe("/topic/messages") client.subscribe("/topic/#{user}-replies") loop do begin msg = client.receive if not msg.body =~ /^[\d]+ #{user}:/ put_debug "DEBUG: #{msg.body}" message = msg.body regex = Regexp.new('^(\d+) ([a-zA-Z]+):[ ,](([a-zA-Z_]+)[ ,](.*))$') msg_array = message.scan(regex) put_debug "msg.headers #{msg.headers["reply-to"]}" put_debug "msg_array #{msg_array}" m_time = msg_array[0][0] m_user = msg_array[0][1] m_msg = msg_array[0][2] m_cmd = msg_array[0][3] m_pload= msg_array[0][4] if m_cmd =~ /^JOIN/ put_log "JOINED User '#{m_user}' just joined the party." elsif m_cmd =~ /^C/ put_log "C #{m_user}: #{m_pload}" elsif m_cmd =~ /^BC_RE/ put_log "BC_RE #{m_pload}" elsif m_cmd =~ /^BC/ # we received a broadcast from #{m_user} with a hash. save it for later. m_pload =~ /^(.+?) / bcid = $1 #put_log "bcid #{bcid}" $broadcasts[bcid] = m_user # give sth to the client to process. put_log "BC #{m_pload}" #sending a fake reply. if $user == "paulfakereply" put_log "debug: sending fake reply to #{m_user}" send("/topic/#{m_user}-replies", "BC_RE #{bcid} Squirrels=2,Nuts=5") end elsif m_cmd =~ /^WHO_RE/ put_log "WHO_RE '#{m_user}' with ROLES: xyz,xyz in the house." elsif m_cmd =~ /^WHO/ reply_to_msg(msg, "WHO_RE #{user} is online.") elsif m_cmd =~ /^PART/ put_log "PARTED User '#{m_user}' just left the party." else put_log "dbg: #{m_cmd}" end else put_debug "RECEIVED from myself. Ignoring." end rescue put_debug "hum?" retry end end end def reply_to_msg(msg, payload) if msg.headers["reply-to"] send(msg.headers["reply-to"], payload) end end def send(path, inputmsg, *header) begin finalmessage = "" Timeout::timeout(2) do stomp = Stomp::Client.new("", "", "localhost", 61613) finalmessage = "%d %s: %s" % [Time.now.utc.to_i, $user, inputmsg] if header != "" stomp.publish(path, finalmessage, *header) else stomp.publish(path, finalmessage) end stomp.close end rescue Timeout::Error put_debug "Failed to send within the 2 second timeout" exit 1 else put_debug "SENT: #{finalmessage}" end end put_log "HELLO Hi user '#{$user}'! How are you?" send("/topic/messages", "JOIN Hi guys, I'm user '#{$user}'.") thread_consuming = Thread.new {consuming $user} #put_log "SYS Going into input loop" inputmessage = "" while inputmessage != "PART" inputmessage = "" inputmessage = STDIN.gets.chomp if inputmessage =~ /^(PING)$/ put_log "PONG" elsif inputmessage =~ /^(REQ_BC)/ inputmessage =~ /^(REQ_BC)[ ,](.+),(.+),(.+),'(.+)','(.+)'$/ # n f s ni txt error = 0 # $& # The string matched by the last successful pattern match in this scope, or nil if the last pattern match failed. (Mnemonic: like & in some editors.) This variable is read-only. if $& == nil put_log "SYS Command format is REQ_BC ,,,'',''" error = 1 else command = "BC" network = $2 freqname = $3 source = $4 nickname = $5 text = $6 if network =~ /^(QWalt)|(QDEV)/ else put_log "SYS Network name #{network} is unknown: QWalt or QDEV allowed." error = 1 end if freqname =~ /^(-qw-)|(-spam-)|(-dev-)/ else put_log "SYS Frequency name is unknown #{freqname}" error = 1 end if source =~ /^(#.+)|(qw:\/\/)|(http:\/\/)/ else put_log "SYS Source string is not in the form ^(#.+)|(qw:\/\/)|(http:\/\/) was: #{source}" error = 1 end if nickname =~ /^.+/ else put_log "SYS Nickname string is not in the form ^.+ #{nickname}" error = 1 end if text =~ /^.+/ else put_log "SYS Message string is not in the form ^.+ #{text}" error = 1 end end if error == 0 finalmessage = "%s network:%s frequency:%s source:%s nickname:%s message:%s" % [command, network, freqname, source, nickname, text] # building hash here (bcid) bcid = Digest::MD5.hexdigest("%d %s %s %s %s %s" % [Time.now.utc.to_i, network, freqname, source, nickname, text]) #bcid = OpenSSL::Digest::MD5.hexdigest("%d %s %s %s %s %s" % [Time.now.utc.to_i, network, freqname, source, nickname, text]) finalmessage = "%s %s %s,%s,%s,'%s','%s'" % [command, bcid, network, freqname, source, nickname, text] #finalmessage = "%s" % [inputmessage] send("/topic/messages", finalmessage) put_log "BC_ID #{bcid} for: #{network},#{freqname},#{source}" end elsif inputmessage =~ /^(BC_RE)/ inputmessage =~ /^(BC_RE) (.+) (.+)=(\d+),(.+)=(\d+)$/ if $& == nil put_log "SYS Format is BC_RE =,=" else command = $1 bcid = $2 user_string = $3 user_count = $4 item_string = $5 item_count = $6 finalmessage = "%s %s %s=%d,%s=%d" % [command, bcid, user_string, user_count, item_string, item_count] # according bcid it is possible to get the originating user.. so send only to his topic! if $broadcasts[bcid] to_user = $broadcasts[bcid] put_log "SYS Broadcast reply bcid: #{bcid} underway. To: '#{to_user}'." send("/topic/#{to_user}-replies", finalmessage) else put_log "SYS Broadcast reply bcid: #{bcid} underway." send("/topic/messages", finalmessage) end end elsif inputmessage =~ /^(C)/ inputmessage =~ /^(C) (.+)$/ error = 0 if $& == nil put_log "SYS Format is C " error = 1 else put_log "C #{$user}: #{$2}" send("/topic/messages", "C #{$2}") end elsif inputmessage =~ /^(PART)$/ put_log "SYS Goodbye '#{$user}'." send("/topic/messages", "PART The party was fun.") elsif inputmessage =~ /^(WHO)/ put_log "SYS Asking who's here." send("/topic/messages", "WHO is here?", "reply-to" => "/topic/#{$user}-replies") else put_log "SYS Not a known command, #{inputmessage}, possible commands are:" put_log "SYS 'C' 'REQ_BC' 'BC_RE' 'WHO' 'PING' or 'PART'" end # puts "%d: " % [Time.now.utc.to_i] #frequency = "-qw-" #inputmessage #channel = "#qwnet" #inputmessage #nickname = user #message = inputmessage #find type of message? #validate message against that type .. #then send in a format. #client sending message and awaiting replies #stomp.subscribe("/temp-queue/random_replies") #stomp.publish("/queue/random_generator", "random", {"reply-to" => "/temp-queue/random_replies"}) #Timeout::timeout(2) do # msg = stomp.receive # puts "Got the response: #{msg.body}" #end # #stomp.publish(msg.headers["reply-to"], number) # # end