stomp-allinone-central.rb 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #!/usr/bin/ruby
  2. require 'rubygems'
  3. require 'stomp'
  4. require 'digest/md5'
  5. #users = [ "mihawksrv", "qwnu", "qwnuposter", "pauldevqw", "paulkibito" ]
  6. # WRITE COMMANDS as ROLE everyone:
  7. # PING - reply from central: PONG
  8. # WHO - reply from everyone: WHO_RE
  9. # C - reply from central: C
  10. # PART - reply from central: SYS Goodbye
  11. # WRITE COMMANDS as ROLE broadcast:
  12. # REQ_BC - reply from central: BC_ID
  13. # BC_RE
  14. # WRITE COMMANDS as ROLE adminspecbots:
  15. # REQ_ASSIGN - reply from specbot: assign_re..
  16. # REQ_UNASSIGN - reply from specbot: unassign_re..
  17. # REQ_PING - reply from specbots: ping_re..
  18. # REQ_ASSIGNMENTS - reply from specbot: assignments_re..
  19. # WRITE COMMANDS as ROLE specbot:
  20. # ASSIGN_RE
  21. # UNASSIGN_RE
  22. # PING_RE
  23. # ASSIGNMENTS_RE
  24. # USERS: ROLE
  25. # paulkibito: broadcast
  26. # qwnu: broadcast
  27. # mihawk: broadcast specbot
  28. # pauldevqw: broadcast specbot
  29. # qwsbalance: adminspecbots
  30. #
  31. # .. allowed commands .. ROLES = CAPABILITIES
  32. # normal users have ROLE broadcast. Roles are defined on a per-user basis .. in a config.
  33. STDOUT.sync = true
  34. raise "ARGV[0] must be a userstring - no numbers!" unless ARGV[0] =~ /^[a-zA-Z\._]+$/
  35. $user = "%s" % [ARGV[0]]
  36. $broadcasts = Hash.new
  37. $debug = 0
  38. def put_debug(msg)
  39. if $debug == 1
  40. puts msg
  41. end
  42. end
  43. def put_log(msg)
  44. puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S %z")}: #{msg}"
  45. end
  46. # consuming process with a loop
  47. def consuming(user)
  48. put_log "SYS Starting consuming/reading thread\n"
  49. client = Stomp::Connection.new("", "", "localhost", 61613, true)
  50. client.subscribe("/topic/messages")
  51. client.subscribe("/topic/#{user}-replies")
  52. loop do
  53. begin
  54. msg = client.receive
  55. if not msg.body =~ /^[\d]+ #{user}:/
  56. put_debug "DEBUG: #{msg.body}"
  57. message = msg.body
  58. regex = Regexp.new('^(\d+) ([a-zA-Z_\.]+):[ ,](([a-zA-Z_]+)[ ,](.*))$')
  59. msg_array = message.scan(regex)
  60. put_debug "msg.headers #{msg.headers["reply-to"]}"
  61. put_debug "msg_array #{msg_array}"
  62. m_time = msg_array[0][0]
  63. m_user = msg_array[0][1]
  64. m_msg = msg_array[0][2]
  65. m_cmd = msg_array[0][3]
  66. m_pload= msg_array[0][4]
  67. if m_cmd =~ /^JOIN/
  68. put_log "JOINED User '#{m_user}' just joined the party."
  69. elsif m_cmd =~ /^C/
  70. put_log "C #{m_user}: #{m_pload}"
  71. elsif m_cmd =~ /^BC_RE/
  72. put_log "BC_RE #{m_pload}"
  73. elsif m_cmd =~ /^BC/
  74. # we received a broadcast from #{m_user} with a hash. save it for later.
  75. m_pload =~ /^(.+?) /
  76. bcid = $1
  77. #put_log "bcid #{bcid}"
  78. $broadcasts[bcid] = m_user
  79. # give sth to the client to process.
  80. put_log "BC #{m_pload}"
  81. #sending a fake reply.
  82. if $user == "paulfakereply"
  83. put_log "debug: sending fake reply to #{m_user}"
  84. send("/topic/#{m_user}-replies", "BC_RE #{bcid} Squirrels=2,Nuts=5")
  85. end
  86. elsif m_cmd =~ /^WHO_RE/
  87. put_log "WHO_RE '#{m_user}' with ROLES: xyz,xyz in the house."
  88. elsif m_cmd =~ /^WHO/
  89. reply_to_msg(msg, "WHO_RE #{user} is online.")
  90. elsif m_cmd =~ /^PART/
  91. put_log "PARTED User '#{m_user}' just left the party."
  92. else
  93. put_log "dbg: #{m_cmd}"
  94. end
  95. else
  96. put_debug "RECEIVED from myself. Ignoring."
  97. end
  98. rescue
  99. put_debug "hum?"
  100. retry
  101. end
  102. end
  103. end
  104. def reply_to_msg(msg, payload)
  105. if msg.headers["reply-to"]
  106. send(msg.headers["reply-to"], payload)
  107. end
  108. end
  109. def send(path, inputmsg, *header)
  110. begin
  111. finalmessage = ""
  112. Timeout::timeout(2) do
  113. stomp = Stomp::Client.new("", "", "localhost", 61613)
  114. finalmessage = "%d %s: %s" % [Time.now.utc.to_i, $user, inputmsg]
  115. if header != ""
  116. stomp.publish(path, finalmessage, *header)
  117. else
  118. stomp.publish(path, finalmessage)
  119. end
  120. stomp.close
  121. end
  122. rescue Timeout::Error
  123. put_debug "Failed to send within the 2 second timeout"
  124. exit 1
  125. else
  126. put_debug "SENT: #{finalmessage}"
  127. end
  128. end
  129. put_log "HELLO Hi user '#{$user}'! How are you?"
  130. send("/topic/messages", "JOIN Hi guys, I'm user '#{$user}'.")
  131. thread_consuming = Thread.new {consuming $user}
  132. #put_log "SYS Going into input loop"
  133. inputmessage = ""
  134. while inputmessage != "PART"
  135. inputmessage = ""
  136. inputmessage = STDIN.gets.chomp
  137. if inputmessage =~ /^(PING)$/
  138. put_log "PONG"
  139. elsif inputmessage =~ /^(REQ_BC)/
  140. inputmessage =~ /^(REQ_BC)[ ,](.+),(.+),(.+),'(.+)','(.+)'$/
  141. # n f s ni txt
  142. error = 0
  143. # $&
  144. # 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.
  145. if $& == nil
  146. put_log "SYS Command format is REQ_BC <network>,<frequency>,<source/channel>,'<nickname>','<message>'"
  147. error = 1
  148. else
  149. command = "BC"
  150. network = $2
  151. freqname = $3
  152. source = $4
  153. nickname = $5
  154. text = $6
  155. if network =~ /^(QWalt)|(QDEV)/
  156. else
  157. put_log "SYS Network name #{network} is unknown: QWalt or QDEV allowed."
  158. error = 1
  159. end
  160. if freqname =~ /^(-qw-)|(-spam-)|(-dev-)/
  161. else
  162. put_log "SYS Frequency name is unknown #{freqname}"
  163. error = 1
  164. end
  165. if source =~ /^(#.+)|(qw:\/\/)|(http:\/\/)/
  166. else
  167. put_log "SYS Source string is not in the form ^(#.+)|(qw:\/\/)|(http:\/\/) was: #{source}"
  168. error = 1
  169. end
  170. if nickname =~ /^.+/
  171. else
  172. put_log "SYS Nickname string is not in the form ^.+ #{nickname}"
  173. error = 1
  174. end
  175. if text =~ /^.+/
  176. else
  177. put_log "SYS Message string is not in the form ^.+ #{text}"
  178. error = 1
  179. end
  180. end
  181. if error == 0
  182. finalmessage = "%s network:%s frequency:%s source:%s nickname:%s message:%s" % [command, network, freqname, source, nickname, text]
  183. # building hash here (bcid)
  184. bcid = Digest::MD5.hexdigest("%d %s %s %s %s %s" % [Time.now.utc.to_i, network, freqname, source, nickname, text])
  185. #bcid = OpenSSL::Digest::MD5.hexdigest("%d %s %s %s %s %s" % [Time.now.utc.to_i, network, freqname, source, nickname, text])
  186. finalmessage = "%s %s %s,%s,%s,'%s','%s'" % [command, bcid, network, freqname, source, nickname, text]
  187. #finalmessage = "%s" % [inputmessage]
  188. send("/topic/messages", finalmessage)
  189. put_log "BC_ID #{bcid} for: #{network},#{freqname},#{source}"
  190. end
  191. elsif inputmessage =~ /^(BC_RE)/
  192. inputmessage =~ /^(BC_RE) (.+) (.+)=(\d+),(.+)=(\d+)$/
  193. if $& == nil
  194. put_log "SYS Format is BC_RE <bcid> <userstring>=<usercount>,<itemstring>=<itemcount>"
  195. else
  196. command = $1
  197. bcid = $2
  198. user_string = $3
  199. user_count = $4
  200. item_string = $5
  201. item_count = $6
  202. finalmessage = "%s %s %s=%d,%s=%d" % [command, bcid, user_string, user_count, item_string, item_count]
  203. # according bcid it is possible to get the originating user.. so send only to his topic!
  204. if $broadcasts[bcid]
  205. to_user = $broadcasts[bcid]
  206. put_log "SYS Broadcast reply bcid: #{bcid} underway. To: '#{to_user}'."
  207. send("/topic/#{to_user}-replies", finalmessage)
  208. else
  209. put_log "SYS Broadcast reply bcid: #{bcid} underway."
  210. send("/topic/messages", finalmessage)
  211. end
  212. end
  213. elsif inputmessage =~ /^(C)/
  214. inputmessage =~ /^(C) (.+)$/
  215. error = 0
  216. if $& == nil
  217. put_log "SYS Format is C <chattext>"
  218. error = 1
  219. else
  220. put_log "C #{$user}: #{$2}"
  221. send("/topic/messages", "C #{$2}")
  222. end
  223. elsif inputmessage =~ /^(PART)$/
  224. put_log "SYS Goodbye '#{$user}'."
  225. send("/topic/messages", "PART The party was fun.")
  226. elsif inputmessage =~ /^(WHO)/
  227. put_log "SYS Asking who's here."
  228. send("/topic/messages", "WHO is here?", "reply-to" => "/topic/#{$user}-replies")
  229. else
  230. put_log "SYS Not a known command, #{inputmessage}, possible commands are:"
  231. put_log "SYS 'C' 'REQ_BC' 'BC_RE' 'WHO' 'PING' or 'PART'"
  232. end
  233. # puts "%d: " % [Time.now.utc.to_i]
  234. #frequency = "-qw-" #inputmessage
  235. #channel = "#qwnet" #inputmessage
  236. #nickname = user
  237. #message = inputmessage
  238. #find type of message?
  239. #validate message against that type ..
  240. #then send in a format.
  241. #client sending message and awaiting replies
  242. #stomp.subscribe("/temp-queue/random_replies")
  243. #stomp.publish("/queue/random_generator", "random", {"reply-to" => "/temp-queue/random_replies"})
  244. #Timeout::timeout(2) do
  245. # msg = stomp.receive
  246. # puts "Got the response: #{msg.body}"
  247. #end
  248. #
  249. #stomp.publish(msg.headers["reply-to"], number)
  250. #
  251. #
  252. end