skeleton for the rewrite
This commit is contained in:
parent
abe6521fd6
commit
2dddb0dc89
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
BUNDLE_PATH: ".gems"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
include:
|
||||||
|
- "**/*.rb"
|
||||||
|
exclude:
|
||||||
|
- spec/**/*
|
||||||
|
- test/**/*
|
||||||
|
- vendor/**/*
|
||||||
|
- ".bundle/**/*"
|
||||||
|
require: []
|
||||||
|
domains: []
|
||||||
|
reporters:
|
||||||
|
- rubocop
|
||||||
|
- require_not_found
|
||||||
|
- typecheck:typed
|
||||||
|
formatter:
|
||||||
|
rubocop:
|
||||||
|
cops: safe
|
||||||
|
except: []
|
||||||
|
only: []
|
||||||
|
extra_args: []
|
||||||
|
require_paths: []
|
||||||
|
plugins: []
|
||||||
|
max_files: 5000
|
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
gem 'websocket'
|
||||||
|
gem 'landline'
|
||||||
|
gem 'puma'
|
|
@ -0,0 +1,124 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Heimdall
|
||||||
|
# Container for any uniquely identifiable object
|
||||||
|
# @abstract
|
||||||
|
class UUIDObject
|
||||||
|
UUIDSYM = (('0'..'9').to_a + ('a'..'f').to_a).freeze
|
||||||
|
class << self
|
||||||
|
# Add uuids to subclass
|
||||||
|
def inherited(subclass)
|
||||||
|
@uuids ||= {}
|
||||||
|
@foreign_ids ||= {}
|
||||||
|
@last ||= 0
|
||||||
|
super(subclass)
|
||||||
|
subclass.uuids = @uuids
|
||||||
|
subclass.foreign_ids = @foreign_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create a new UUIDObject with unique UUID
|
||||||
|
# @return [self]
|
||||||
|
def new
|
||||||
|
object = super
|
||||||
|
@uuids[object.uuid] = object
|
||||||
|
@last = object.uuid
|
||||||
|
@foreign_ids[object.foreign_id] = object if object.foreign_id
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get object by UUID
|
||||||
|
# @param uuid
|
||||||
|
# @return [self, nil]
|
||||||
|
def get(uuid)
|
||||||
|
@uuids[uuid] if @uuids[uuid].is_a? self
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get object by foreign id
|
||||||
|
# @param foreign_id
|
||||||
|
# @return [self, nil]
|
||||||
|
def get_foreign(foreign_id)
|
||||||
|
@foreign_ids[foreign_id] if @foreign_ids[foreign_id].is_a? self
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :uuids, :foreign_ids, :last
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@uuid = __gen_uuid
|
||||||
|
@foreign_ids = []
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :uuid, :foreign_id
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def __gen_uuid
|
||||||
|
newuuid = (Time.now.to_f * 1000).to_i * 10000
|
||||||
|
if (self.class.last / 1000) == (newuuid / 1000)
|
||||||
|
newuuid += (self.class.last % 1000) + 1
|
||||||
|
end
|
||||||
|
newuuid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PubSub abstract container
|
||||||
|
# @abstract
|
||||||
|
class PubSub
|
||||||
|
def initialize(buffer_size: 1024)
|
||||||
|
@buffer_size = buffer_size
|
||||||
|
@listeners = []
|
||||||
|
@messages = []
|
||||||
|
end
|
||||||
|
|
||||||
|
# Push message to all listeners
|
||||||
|
# @param msg [UUIDObject]
|
||||||
|
# @return [void]
|
||||||
|
def push(msg)
|
||||||
|
@listeners.each { |x| x.call(msg) }
|
||||||
|
@messages.append(msg)
|
||||||
|
@messages.shift if @messages.length > @buffer_size
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add a listener to the PubSub
|
||||||
|
# @param listener [#call]
|
||||||
|
# @return [void]
|
||||||
|
def listen(listener)
|
||||||
|
@listeners.append(listener)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Pull all messages since UUID
|
||||||
|
# @param uuid [String]
|
||||||
|
# @return [Array<UUIDObject>]
|
||||||
|
def pull(uuid)
|
||||||
|
output = []
|
||||||
|
@messages.reverse_each do |x|
|
||||||
|
break if x.uuid < uuid
|
||||||
|
|
||||||
|
output.unshift(x)
|
||||||
|
end
|
||||||
|
output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Message struct
|
||||||
|
class Message < UUIDObject
|
||||||
|
def initialize(datahash, **params)
|
||||||
|
super(**params)
|
||||||
|
|
||||||
|
@from = UUIDObject.get(datahash["from"])
|
||||||
|
@to = UUIDObject.get(datahash["to"])
|
||||||
|
@content = datahash["content"]
|
||||||
|
# @reply_to = datahash["reply_to"] # TODO: make this make sense
|
||||||
|
@attachments = datahash["attachments"]
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :from, :to, :content, :reply_to, :attachments
|
||||||
|
end
|
||||||
|
|
||||||
|
# User struct
|
||||||
|
class User < UUIDObject
|
||||||
|
def initialize(datahash, **params)
|
||||||
|
super(**params)
|
||||||
|
|
||||||
|
@id = datahash["id"]
|
||||||
|
end
|
|
@ -0,0 +1,64 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '.env'
|
||||||
|
require_relative 'proto'
|
||||||
|
require 'landline'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
# Primary server class
|
||||||
|
class HeimdallServer < Landline::App
|
||||||
|
before do
|
||||||
|
# Match data type against a list of datatypes
|
||||||
|
# @param obj [Object]
|
||||||
|
# @param type [Array, Class]
|
||||||
|
def match_type(obj, type)
|
||||||
|
if type.is_a? Array
|
||||||
|
type.any? { |t| obj.is_a? t }
|
||||||
|
else
|
||||||
|
obj.is_a? type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Validate json body for a post request
|
||||||
|
# @param args [Hash] hash of key - type pairs to check JSON data against
|
||||||
|
def validate_json(**args)
|
||||||
|
die(400, backtrace: ['JSON body expected']) unless json?
|
||||||
|
data = begin
|
||||||
|
JSON.parse(request.body)
|
||||||
|
rescue StandardError
|
||||||
|
die(400, backtrace: ['JSON body is invalid'])
|
||||||
|
end
|
||||||
|
args.each do |k, v|
|
||||||
|
unless data.include?(k) and match_type(data[k], v)
|
||||||
|
die(400, backtrace: ["Key #{k} is missing"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
filter do
|
||||||
|
request.cookies["token"] == BOT_TOKEN
|
||||||
|
end
|
||||||
|
|
||||||
|
path "/user" do
|
||||||
|
post "/register" do
|
||||||
|
validate_json("id" => Integer,
|
||||||
|
"username" => String,
|
||||||
|
"nickname" => [String, NilClass])
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
handle do |status, backtrace: nil|
|
||||||
|
page = JSON.dump({
|
||||||
|
"error" => backtrace.join("\n"),
|
||||||
|
"code" => status
|
||||||
|
})
|
||||||
|
[{
|
||||||
|
"content-length": page.bytesize,
|
||||||
|
"content-type": "application/json"
|
||||||
|
}, page]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
run HeimdallServer.new
|
Loading…
Reference in New Issue