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