#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# EM Intro. - http://keijinsonyaban.blogspot.jp/2010/12/eventmachine.html
# irb to EM - https://keyesberry.hatenadiary.org/entry/20110929/p1
#
# Browser Settings:
# Chrome: https://blog.hello-world.jp.net/node-js/1821/
require 'em-websocket'
require 'sqlite3'
require 'json'
require './userdb.rb'
PORT = 8889
MAILFROM = "admin@e.koeki-u.ac.jp"
clients = Hash.new # 各クライアントの接続関連全情報を格納
# キーにコネクションが入る
print("No clients yet...")
EM::WebSocket.start({:host => "0.0.0.0", :port => PORT}) do |ws_conn|
userdb = UserDB.new
# クライアント接続がある度にその情報が ws_conn に入って来る
ws_conn.onopen do # そのクライアントが接続開始してきたとき
clients[ws_conn] = {} # クライアントを集合に追加
printf("%d guest(s)\n", clients.length)
end
ws_conn.onmessage do |message| # クライアントから文字列が来たとき
# messageは必ずJSONで送ってもらう
p message
given = JSON.parse(message)
param=clients[ws_conn] # クライアントの情報一覧
user = param["user"]||given["user"]
data = {}
# 認証成功は2つの可能性:
# 1つはtmpkeyとパスコードの組み合わせ
# もう1つはブラウザlocalStorageに残っていたセッションキーを送ってくる
if param["authok"]
# 認証完了したクライアントとは自由に通信
p "USER=#{user}"
if given["note"]
data["reply"] = userdb.notAI(given, user)
param["last"] = Time.now
end
elsif given["tmpkey"]
# tmpkeyとパスコードの組み合わせを送ってきたとき
param["skey"] = userdb.authTmpKey(user, given["tmpkey"], given["passcode"])
STDERR.puts "tmpKeyAuth= #{param['skey']}"
if param["skey"]
param["authok"] = true # 認証完了!
data["skey"] = param["skey"]
end
elsif given["skey"]
# skeyを送ってきたとき
param["user"] = given["user"]
param["skey"] = userdb.authSkey(user, given["skey"])
if param["skey"] #
param["authok"] = true # 認証完了!
data["skey"] = param["skey"]
param["last"] = Time.now
end
elsif given["user"]
puts "Got: #{given['user']}"
param["user"] = given["user"]
data["tmpkey"] = userdb.genTmpkey(param["user"])
else # 何も情報がなければlogin
# data["body"] = htmls["login"]
end
resp = JSON.pretty_generate(data)
STDERR.puts "Sent: #{resp}"
ws_conn.send(resp)
end
ws_conn.onclose do # クライアントが切断したとき
clients.delete(ws_conn) # そのクライアントを集合から削除
# p "bye"+ws_conn.inspect
printf("%d GUEST(s)\n", clients.length)
end
EM::defer do # 共通で実行するスレッド
# Thread.new do のほうがいいかも
puts "..captured!"
Thread.new { # 別スレッドを起こして並行動作させる
loop do # 無限ループ(末尾で5秒休憩)
clients.each do |conn, hash| # 全クライアントに対して繰り返す
next unless hash["last"] # 最終操作時刻未設定ならパス
p Time.now - hash["last"]
if Time.now - hash["last"] > 10
# 10秒書き込み操作のないクライアントにメッセージを送る
rep = %w(なんか喋り おーい おるんか? 暇だ ぬ ほぇ? 静寂 遅いわ
どしたん話聞こか 打鍵が遅いのか? 帰ってよいか? つまらぬ).sample
conn.send(JSON.generate({"reply"=>rep}))
hash["last"] = Time.now # 最終操作時刻を上書き
end
end
sleep 5
end
} # 別スレッドここまで
loop do
print("Enter message for all clients: ")
line = gets
puts("Sending")
clients.keys.each{|conn|
conn.send(JSON.generate({"reply"=>line.chomp}))
}
end
end
end