heimdall/server.rb

605 lines
15 KiB
Ruby
Raw Normal View History

2023-04-30 07:56:21 +00:00
require_relative "proto"
require_relative "hyde/hyde"
2023-05-11 21:41:59 +00:00
require 'webrick/websocket'
2023-04-30 07:56:21 +00:00
require "json"
Users = Heimdall::UserCache.new
2023-05-12 22:46:42 +00:00
Rooms = Heimdall::RoomCache.new
2023-05-11 21:41:59 +00:00
SocketsMap = {}
NotifyList = {}
2023-04-30 07:56:21 +00:00
2023-04-30 18:52:32 +00:00
def _require_keys(dict,key_dict)
2023-04-30 07:56:21 +00:00
raise KeyError, "not a dict" unless dict.kind_of? Hash
key_dict.each_pair { |k,v|
2023-04-30 18:52:32 +00:00
unless (dict.has_key? k.to_s) and (dict[k.to_s].kind_of? v) then
2023-04-30 07:56:21 +00:00
raise KeyError, "key #{k} of type #{v} required"
end
}
end
2023-04-30 18:52:32 +00:00
def _send_json(res,data,code: 200)
res.body = JSON::fast_generate(data)
res['Content-Type'] = "application/json"
res.status = code
end
def _throw_error(res,error)
_send_json(res,{
error: "#{error}"
},code: 400)
end
def _parse_json(body,key_dict)
data = JSON::Parser.new(body).parse
_require_keys(data,key_dict)
return data
end
2023-04-30 07:56:21 +00:00
server = Hyde::Server.new Port: 8000 do
path "user" do
2023-05-11 09:06:28 +00:00
path "find" do
2023-05-12 22:46:42 +00:00
index ["by-name"]
2023-05-11 09:06:28 +00:00
2023-05-12 22:46:42 +00:00
get "by-name" do |ctx|
2023-05-11 09:06:28 +00:00
req,res = ctx.request,ctx.response
begin
_require_keys(req.query, {
username: String
})
_send_json(res, {
2023-05-12 22:46:42 +00:00
"results": Users.search_by_name(req.query['username']).map { |x| x[1].to_card }
2023-05-11 09:06:28 +00:00
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
end
end
get "by-protoid" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query, {
protocol_id: String
})
_send_json(res, {
2023-05-12 22:46:42 +00:00
"results": Users.search_by_protoid(req.query['protocol_id']).map { |x| x[1].to_card; x }
2023-05-11 09:06:28 +00:00
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
end
end
end
2023-05-12 22:46:42 +00:00
post "sync" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
data: Array
})
Users.sync(data["data"])
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "bulk-delete" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
users: Array
})
Users.bulk_delete(data["users"])
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
2023-04-30 18:52:32 +00:00
get "exists" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query, {
protocol_id: String
})
_send_json(res,{
exists: (Users.get(req.query["protocol_id"]) != nil)
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue Heimdall::ProtocolError => protoerr
_send_json(res, {
exists: false
})
end
end
2023-04-30 07:56:21 +00:00
post "new" do |ctx|
req,res = ctx.request,ctx.response
begin
2023-04-30 18:52:32 +00:00
data = _parse_json(req.body,{
2023-04-30 07:56:21 +00:00
username: String,
protocol_id: String
})
2023-04-30 18:52:32 +00:00
new_user = Heimdall::User.new(data)
Users.add(new_user)
_send_json(res,{
2023-05-11 21:41:59 +00:00
status: true
2023-04-30 18:52:32 +00:00
})
2023-05-11 21:41:59 +00:00
NotifyList[new_user.UID] = []
2023-04-30 07:56:21 +00:00
rescue JSON::ParserError => jsonerror
2023-04-30 18:52:32 +00:00
_throw_error(res,jsonerror)
rescue KeyError => keyerror
_throw_error(res,keyerror)
2023-05-12 22:46:42 +00:00
rescue ProtocolError => protoerr
_throw_error(res,protoerr)
end
end
post "modify" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
data: Hash,
protocol_id: String
})
user = Users.get(data["protocol_id"])
user.modify(data["data"])
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue ProtocolError => protoerr
_throw_error(res,protoerr)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
2023-04-30 18:52:32 +00:00
end
end
post "send" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
content: String,
from: String,
to: String
2023-04-30 07:56:21 +00:00
})
2023-04-30 18:52:32 +00:00
new_message = Heimdall::Message.new(data)
2023-05-11 21:41:59 +00:00
user = Users.get(new_message.to)
if NotifyList[user.UID].length != 0 then
NotifyList[user.UID].each { |sockid|
sock = SocketsMap[sockid]
msg = new_message.to_struct
msg["user"] = Users.get(msg["from"]).to_card
sock.puts(JSON::fast_generate(msg))
}
2023-05-12 22:46:42 +00:00
user.channel.send_silent(new_message)
2023-05-11 21:41:59 +00:00
else
2023-05-12 22:46:42 +00:00
user.channel.send(new_message)
2023-05-11 21:41:59 +00:00
end
2023-04-30 18:52:32 +00:00
_send_json(res,{
2023-05-11 21:41:59 +00:00
status: true
2023-04-30 18:52:32 +00:00
})
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
2023-04-30 07:56:21 +00:00
rescue KeyError => keyerror
2023-04-30 18:52:32 +00:00
_throw_error(res,keyerror)
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
end
end
get "get" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query,{
n: Integer,
protocol_id: String
})
number = req.query[:n]
id = req.query["protocol_id"]
user = Users.get(id)
2023-05-12 22:46:42 +00:00
messages = user.channel.get(number)
2023-04-30 18:52:32 +00:00
_send_json(res, {
messages: messages.map { |x|
x = x.to_struct
2023-05-11 09:06:28 +00:00
x["user"] = Users.get(x["from"]).to_card
2023-04-30 18:52:32 +00:00
x
}
2023-04-30 07:56:21 +00:00
})
2023-04-30 18:52:32 +00:00
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
2023-04-30 07:56:21 +00:00
end
end
2023-04-30 18:52:32 +00:00
get "read" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query,{
protocol_id: String
})
id = req.query["protocol_id"]
user = Users.get(id)
2023-05-12 22:46:42 +00:00
messages = user.channel.read
2023-04-30 18:52:32 +00:00
_send_json(res, {
messages: messages.map { |x|
x = x.to_struct
2023-05-11 09:06:28 +00:00
x["user"] = Users.get(x["from"]).to_card
2023-04-30 18:52:32 +00:00
x
}
})
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
end
end
2023-05-11 21:41:59 +00:00
post "listen" do |ctx|
req,res = ctx.request, ctx.response
begin
data = _parse_json(req.body, {
websocket: String,
protocol_id: String
})
uid = Users.get(data["protocol_id"]).UID
raise KeyError, "websocket does not exist" unless SocketsMap.has_key? data["websocket"]
NotifyList[uid].append data["websocket"]
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
2023-05-12 22:46:42 +00:00
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "unlisten" do |ctx|
req,res = ctx.request, ctx.response
begin
data = _parse_json(req.body, {
websocket: String,
protocol_id: String
})
uid = Users.get(data["protocol_id"]).UID
raise KeyError, "websocket does not exist" unless SocketsMap.has_key? data["websocket"]
NotfiyList[uid].delete data["websocket"]
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
2023-05-11 21:41:59 +00:00
end
end
2023-04-30 18:52:32 +00:00
post "delete" do |ctx|
req,res = ctx.request, ctx.response
begin
data = _parse_json(req.body,{
protocol_id: String
})
id = data["protocol_id"]
_send_json(res, {
2023-05-11 21:41:59 +00:00
status: true
2023-04-30 18:52:32 +00:00
})
2023-05-11 21:41:59 +00:00
user = Users.get(id)
NotifyList.delete(user.UID)
2023-04-30 18:52:32 +00:00
Users.delete(id)
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
2023-05-12 22:46:42 +00:00
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
end
path "room" do
path "find" do
index ["by-name"]
get "by-name" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query, {
username: String
})
_send_json(res, {
"results": Rooms.search_by_name(req.query['username']).map { |x| x[1].to_card }
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
end
end
get "by-protoid" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query, {
protocol_id: String
})
_send_json(res, {
"results": Rooms.search_by_protoid(req.query['protocol_id']).map { |x| x[1].to_card; x }
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
end
end
end
post "new" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
name: String,
protocol_id: String
})
new_room = Heimdall::Room.new(data)
Rooms.add(new_room)
_send_json(res, {
status: true
})
NotifyList[new_room.UID] = []
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "send" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
content: String,
from: String,
to: String
})
new_message = Heimdall::Message.new(data)
room = Rooms.get(new_message.to)
if NotifyList[room.UID].length != 0 then
NotifyList[room.UID].each { |sockid|
sock = SocketsMap[sockid]
msg = new_message.to_struct
msg["user"] = Users.get(msg["from"]).to_card
msg["room"] = room.to_card
sock.puts(JSON::fast_generate(msg))
}
room.channel.send_silent(new_message)
else
room.channel.send(new_message)
end
_send_json(res,{
status: true
})
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
end
end
get "get" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query,{
n: Integer,
protocol_id: String
})
number = req.query[:n]
id = req.query["protocol_id"]
room = Rooms.get(id)
messages = room.channel.get(number)
_send_json(res, {
messages: messages.map { |x|
x = x.to_struct
x["user"] = Users.get(x["from"]).to_card
x["room"] = room.to_card
x
}
})
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
end
end
post "listen" do |ctx|
req,res = ctx.request, ctx.response
begin
data = _parse_json(req.body, {
websocket: String,
protocol_id: String
})
uid = Rooms.get(data["protocol_id"]).UID
raise KeyError, "websocket does not exist" unless SocketsMap.has_key? data["websocket"]
NotifyList[uid].append data["websocket"]
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
2023-04-30 18:52:32 +00:00
end
end
2023-05-12 22:46:42 +00:00
post "unlisten" do |ctx|
req,res = ctx.request, ctx.response
begin
data = _parse_json(req.body, {
websocket: String,
protocol_id: String
})
uid = Rooms.get(data["protocol_id"]).UID
raise KeyError, "websocket does not exist" unless SocketsMap.has_key? data["websocket"]
NotfiyList[uid].delete data["websocket"]
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "modify" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
data: Hash,
protocol_id: String
})
room = Rooms.get(data["protocol_id"])
room.modify(data["data"])
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue ProtocolError => protoerr
_throw_error(res,protoerr)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "delete" do |ctx|
req,res = ctx.request, ctx.response
begin
data = _parse_json(req.body,{
protocol_id: String
})
id = data["protocol_id"]
_send_json(res, {
status: true
})
room = Rooms.get(id)
NotifyList.delete(room.UID)
Rooms.delete(id)
rescue Heimdall::ProtocolError => protoerr
_throw_error(res,protoerr)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "sync" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
data: Array
})
Rooms.sync(data["data"])
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
post "bulk-delete" do |ctx|
req,res = ctx.request,ctx.response
begin
data = _parse_json(req.body, {
users: Array
})
Rooms.bulk_delete(data["users"])
_send_json(res, {
status: true
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue JSON::ParserError => jsonerror
_throw_error(res,jsonerror)
end
end
get "exists" do |ctx|
req,res = ctx.request,ctx.response
begin
_require_keys(req.query, {
protocol_id: String
})
_send_json(res,{
exists: (Rooms.get(req.query["protocol_id"]) != nil)
})
rescue KeyError => keyerror
_throw_error(res,keyerror)
rescue Heimdall::ProtocolError => protoerr
_send_json(res, {
exists: false
})
end
end
2023-04-30 18:52:32 +00:00
end
2023-05-12 22:46:42 +00:00
2023-04-30 18:52:32 +00:00
get "version" do |ctx|
ctx.response.body = "{\"version\":\"#{Heimdall::VERSION}\"}"
ctx.response['Content-Type'] = "application/json"
2023-04-30 07:56:21 +00:00
end
2023-05-12 22:46:42 +00:00
2023-04-30 07:56:21 +00:00
end
2023-05-11 21:41:59 +00:00
at_exit do
server.shutdown
end
class WebsocketUID < Heimdall::UID
def initialize
@UID_prefix = "websocket"
super
end
end
class EventServlet < WEBrick::Websocket::Servlet
def socket_open(sock)
@UID = WebsocketUID.new
@connected_listeners = []
SocketsMap[@UID.UID] = sock
sock.puts(JSON::fast_generate({
websocket: @UID.UID.to_s
}))
end
def socket_close(sock)
SocketsMap.delete @UID.UID
NotifyList.each do |k,v|
if v.include? @UID.UID
v.delete @UID.UID
end
end
end
def socket_text(sock,text)
# do nothing
end
end
Thread.new do
websocket_server = WEBrick::Websocket::HTTPServer.new Port:8001
websocket_server.mount "/", EventServlet
websocket_server.start
at_exit do
websocket_server.shutdown
end
end
2023-04-30 07:56:21 +00:00
server.start