Almost functional websocket based server list updater

This commit is contained in:
2021-12-27 18:37:02 -06:00
parent 822a9a8971
commit 92f6a76381
2 changed files with 83 additions and 23 deletions

View File

@@ -1,62 +1,120 @@
class W3DHub
class Api
class ServerListUpdater
class Connection < ::Protocol::WebSocket::Connection
##!!! When this breaks update from: https://github.com/socketry/async-websocket/blob/master/lib/async/websocket/connection.rb
# refinements preserves super... 😢
class PatchedConnection < ::Protocol::WebSocket::Connection
include ::Protocol::WebSocket::Headers
def self.call(framer, protocol = [], **options)
instance = self.new(framer, Array(protocol).first, **options)
return instance unless block_given?
begin
yield instance
ensure
instance.close
end
end
def initialize(framer, protocol = nil, response: nil, **options)
super(framer, **options)
@protocol = protocol
@response = response
end
def close
super
if @response
@response.finish
@response = nil
end
end
attr :protocol
def read
if (buffer = super)
buffer.split("\x1e").map { |json| parse(json) }
end
end
def read1
read1&.first
end
def write(object)
super("#{dump(object)}\x1e")
end
def parse(buffer)
JSON.parse(buffer, symbolize_names: true)
end
def dump(object)
JSON.dump(object)
end
def call
self.close
end
end
@@instance = nil
def self.instance
return @@instance if @@instance
@@instance = ServerListUpdater.new
end
def initialize
run
end
# TODO: Properly start up and monitor for updates to server list
def initialize
def run
Async do |task|
headers = [["User-Agent", "Cyberarm's Websocket Testing"]]
internet = Async::HTTP::Internet.instance
response = internet.post("https://gsh.w3dhub.com/listings/push/v2/negotiate?negotiateVersion=1", headers, [""])
response = internet.post("https://gsh.w3dhub.com/listings/push/v2/negotiate?negotiateVersion=1", Api::DEFAULT_HEADERS, [""])
data = JSON.parse(response.read, symbolize_names: true)
# TODO: Replace with Api.server_list
response = internet.get("https://gsh.w3dhub.com/listings/getAll/v2?statusLevel=2", headers, [""])
servers = JSON.parse(response.read, symbolize_names: true)
id = data[:connectionToken]
endpoint = Async::HTTP::Endpoint.parse("https://gsh.w3dhub.com/listings/push/v2?id=#{id}", alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
Async::WebSocket::Client.connect(endpoint, headers: headers, handler: WSS::Connection) do |connection|
Async::WebSocket::Client.connect(endpoint, headers: Api::DEFAULT_HEADERS, handler: PatchedConnection) do |connection|
connection.write({ protocol: "json", version: 1 })
connection.flush
# Should be an empty hash for protocol agreement
connection.read
# Write keep alive?
pp connection.read
connection.write({ "type": 6 })
# Subscribe to server changes
servers.each_with_index do |server, i|
puts "servers: #{Store.server_list&.count}"
Store.server_list.each_with_index do |server, i|
i += 1
out = { "type": 1, "invocationId": "#{i}", "target": "SubscribeToServerStatusUpdates", "arguments": [server[:id], 2] }
mode = 1 # 2 full details, 1 basic details
out = { "type": 1, "invocationId": "#{i}", "target": "SubscribeToServerStatusUpdates", "arguments": [server.id, 1] }
connection.write(out)
end
while (message = connection.read)
# Keep alive?
connection.write({ type: 6 }) if message.first[:type] == 6
# TODO: process messages (of type 3?)
pp message
if message&.first&.fetch(:type) == 1
message.each do |rpc|
next unless rpc[:target] == "ServerStatusChanged"
id, data = rpc[:arguments]
pp [id, data.length, data]
server = Api::ServerListServer.new(data)
pp [server.player_count, server.max_players]
end
end
end
end
ensure
@@instance = nil
end
end
end

View File

@@ -122,6 +122,8 @@ class W3DHub
Store.server_list_last_fetch = Gosu.milliseconds
Api::ServerListUpdater.instance
@tasks[:server_list][:complete] = true
rescue => e
# Something went wrong!