Initial commit
This commit is contained in:
commit
1f9f3fb03a
|
@ -0,0 +1,3 @@
|
||||||
|
include ../syndicate-nim/depends.tup
|
||||||
|
NIM_FLAGS += --path:$(TUP_CWD)/../syndicate-nim/src
|
||||||
|
NIM_FLAGS += --path:$(TUP_CWD)/../nimble/ws/src
|
|
@ -0,0 +1,33 @@
|
||||||
|
version 1 .
|
||||||
|
|
||||||
|
Attributes = {string: any ...:...} .
|
||||||
|
|
||||||
|
Resp = <resp @time RespItem> .
|
||||||
|
|
||||||
|
RespItem = NewChatItem / Attributes .
|
||||||
|
|
||||||
|
NewChatItem = <newChatItem {"chatItem": ChatItem0 }> .
|
||||||
|
|
||||||
|
ChatItem0 = {
|
||||||
|
"chatInfo": ChatInfo
|
||||||
|
"user": User
|
||||||
|
} .
|
||||||
|
|
||||||
|
ChatInfo = {
|
||||||
|
"chatInfo": ChatInfo
|
||||||
|
"chatItem": ChatItem1
|
||||||
|
} .
|
||||||
|
|
||||||
|
ChatItem1 = {
|
||||||
|
"content": Content
|
||||||
|
} .
|
||||||
|
|
||||||
|
Content = Attributes .
|
||||||
|
|
||||||
|
User = {
|
||||||
|
"activeUser": bool
|
||||||
|
"agentUserId": string
|
||||||
|
"localDisplayName": string
|
||||||
|
"userContactId": int
|
||||||
|
"userId": int
|
||||||
|
} .
|
|
@ -0,0 +1,5 @@
|
||||||
|
let
|
||||||
|
syndicate = builtins.getFlake "syndicate";
|
||||||
|
pkgs =
|
||||||
|
import <nixpkgs> { overlays = builtins.attrValues syndicate.overlays; };
|
||||||
|
in pkgs.nimPackages.syndicate_utils
|
|
@ -0,0 +1,6 @@
|
||||||
|
bin = @["simplex_bot_actor"]
|
||||||
|
license = "Unlicense"
|
||||||
|
srcDir = "src"
|
||||||
|
version = "20230723"
|
||||||
|
|
||||||
|
requires: "nim", "syndicate", ws
|
|
@ -0,0 +1,4 @@
|
||||||
|
include_rules
|
||||||
|
: foreach ../*.prs |> !preserves_schema_nim |> {schema}
|
||||||
|
: simplex_bot_actor.nim | $(SYNDICATE_PROTOCOL) {schema} |> !nim_bin |> {bin}
|
||||||
|
: {bin} |> !assert_built |>
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
import
|
||||||
|
preserves, std/tables
|
||||||
|
|
||||||
|
type
|
||||||
|
Resp* {.preservesRecord: "resp".} = ref object
|
||||||
|
`time`*: RespItem
|
||||||
|
|
||||||
|
RespItemKind* {.pure.} = enum
|
||||||
|
`NewChatItem`, `Attributes`
|
||||||
|
`RespItem`* {.preservesOr.} = ref object
|
||||||
|
case orKind*: RespItemKind
|
||||||
|
of RespItemKind.`NewChatItem`:
|
||||||
|
`newchatitem`*: NewChatItem
|
||||||
|
|
||||||
|
of RespItemKind.`Attributes`:
|
||||||
|
`attributes`*: Attributes
|
||||||
|
|
||||||
|
|
||||||
|
Attributes* = Table[string, Preserve[void]]
|
||||||
|
NewChatItemField0* {.preservesDictionary.} = ref object
|
||||||
|
`"chatItem"`*: ChatItem0
|
||||||
|
|
||||||
|
NewChatItem* {.preservesRecord: "newChatItem".} = ref object
|
||||||
|
`field0`*: NewChatItemField0
|
||||||
|
|
||||||
|
ChatInfo* {.preservesDictionary.} = ref object
|
||||||
|
`"chatInfo"`*: ChatInfo
|
||||||
|
`"chatItem"`*: ChatItem1
|
||||||
|
|
||||||
|
Content* = Attributes
|
||||||
|
ChatItem0* {.preservesDictionary.} = ref object
|
||||||
|
`"chatInfo"`*: ChatInfo
|
||||||
|
`"user"`*: User
|
||||||
|
|
||||||
|
User* {.preservesDictionary.} = object
|
||||||
|
`"activeUser"`*: bool
|
||||||
|
`"agentUserId"`*: string
|
||||||
|
`"localDisplayName"`*: string
|
||||||
|
`"userContactId"`*: BiggestInt
|
||||||
|
`"userId"`*: BiggestInt
|
||||||
|
|
||||||
|
ChatItem1* {.preservesDictionary.} = object
|
||||||
|
`"content"`*: Content
|
||||||
|
|
||||||
|
proc `$`*(x: Resp | RespItem | Attributes | NewChatItem | ChatInfo | Content |
|
||||||
|
ChatItem0 |
|
||||||
|
User |
|
||||||
|
ChatItem1): string =
|
||||||
|
`$`(toPreserve(x))
|
||||||
|
|
||||||
|
proc encode*(x: Resp | RespItem | Attributes | NewChatItem | ChatInfo | Content |
|
||||||
|
ChatItem0 |
|
||||||
|
User |
|
||||||
|
ChatItem1): seq[byte] =
|
||||||
|
encode(toPreserve(x))
|
|
@ -0,0 +1,58 @@
|
||||||
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||||
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
|
import std/[base64, json, parseutils, tables]
|
||||||
|
import preserves
|
||||||
|
|
||||||
|
proc toPreserveHook*(js: JsonNode; E: typedesc): Preserve[E] {.gcsafe.} =
|
||||||
|
case js.kind
|
||||||
|
of JString:
|
||||||
|
var off = js.str.skip("data:")
|
||||||
|
if off == 0:
|
||||||
|
result = Preserve[E](kind: pkString, string: js.str)
|
||||||
|
else:
|
||||||
|
var mime: string
|
||||||
|
off.inc js.str.parseUntil(mime, ';', off)
|
||||||
|
var dataOff = off + js.str.skip(";base64,", off)
|
||||||
|
if dataOff != off:
|
||||||
|
var data = cast[seq[byte]](substr(js.str, dataOff).decode)
|
||||||
|
result = initRecord("mime", mime.toSymbol(E), data.toPreserve(E))
|
||||||
|
else:
|
||||||
|
result = Preserve[E](kind: pkString, string: js.str)
|
||||||
|
of JInt:
|
||||||
|
result = Preserve[E](kind: pkSignedInteger, int: js.num)
|
||||||
|
of JFloat:
|
||||||
|
result = Preserve[E](kind: pkDouble, double: js.fnum)
|
||||||
|
of JBool:
|
||||||
|
result = case js.bval
|
||||||
|
of false: toSymbol("false", E)
|
||||||
|
of true: toSymbol("true", E)
|
||||||
|
of JNull:
|
||||||
|
result = toSymbol("null", E)
|
||||||
|
of JArray:
|
||||||
|
result = Preserve[E](kind: pkSequence,
|
||||||
|
sequence: newSeq[Preserve[E]](js.elems.len))
|
||||||
|
for i, e in js.elems:
|
||||||
|
result.sequence[i] = toPreserveHook(e, E)
|
||||||
|
of JObject:
|
||||||
|
if js.hasKey("type"):
|
||||||
|
var label = js.getOrDefault("type").getStr.toSymbol(E)
|
||||||
|
if js.len == 1:
|
||||||
|
result = initRecord(label)
|
||||||
|
elif js.len == 2:
|
||||||
|
for key, val in js.fields.pairs:
|
||||||
|
if key != "type":
|
||||||
|
result = initRecord(label, val.toPreserve(E))
|
||||||
|
else:
|
||||||
|
var dict = Preserve[E](kind: pkDictionary)
|
||||||
|
for key, val in js.fields.pairs:
|
||||||
|
if key != "type":
|
||||||
|
dict[Preserve[E](kind: pkString, string: key)] = toPreserveHook(val, E)
|
||||||
|
result = initRecord(label, dict)
|
||||||
|
elif js.len == 1:
|
||||||
|
for key, val in js.fields.pairs:
|
||||||
|
result = initRecord(key, val.toPreserve(E))
|
||||||
|
else:
|
||||||
|
result = Preserve[E](kind: pkDictionary)
|
||||||
|
for key, val in js.fields.pairs:
|
||||||
|
result[Preserve[E](kind: pkString, string: key)] = toPreserveHook(val, E)
|
|
@ -0,0 +1,52 @@
|
||||||
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||||
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
|
import std/[asyncdispatch, json, sequtils, streams, tables, uri]
|
||||||
|
import preserves, syndicate
|
||||||
|
import ws
|
||||||
|
|
||||||
|
import private/jsonhooks
|
||||||
|
|
||||||
|
type
|
||||||
|
Args {.preservesDictionary.} = object
|
||||||
|
dataspace: Ref
|
||||||
|
url: string
|
||||||
|
|
||||||
|
Internal* {.preservesRecord: "internal".} = object
|
||||||
|
dataspace: Ref
|
||||||
|
|
||||||
|
proc recvMessages(facet: Facet; ds: Ref; ws: WebSocket) =
|
||||||
|
var fut: Future[string]
|
||||||
|
proc recvMessage() {.gcsafe.} =
|
||||||
|
fut = receiveStrPacket ws
|
||||||
|
addCallback(fut, facet) do (turn: var Turn):
|
||||||
|
message(turn, ds, fut.read.parseJson)
|
||||||
|
recvMessage()
|
||||||
|
recvMessage()
|
||||||
|
|
||||||
|
proc bootClient(turn: var Turn; ds: Ref; ws: WebSocket) =
|
||||||
|
let dumpStream = openFileStream("/tmp/simplex_bot_actor.log", fmWrite)
|
||||||
|
let intern = newDataspace(turn)
|
||||||
|
discard publish(turn, ds, Internal(dataspace: intern))
|
||||||
|
recvMessages(turn.facet, intern, ws)
|
||||||
|
onMessage(turn, intern, grab()) do (msg: Assertion):
|
||||||
|
writeText(dumpStream, msg)
|
||||||
|
write(dumpStream, '\n')
|
||||||
|
flush(dumpStream)
|
||||||
|
|
||||||
|
proc boot*(root: Ref; turn: var Turn) =
|
||||||
|
during(turn, root, ?Args) do (dataspace: Ref, url: string):
|
||||||
|
debugEcho "got dataspace ", dataspace, " and URL ", url
|
||||||
|
var ws: WebSocket
|
||||||
|
newWebSocket(url).addCallback(turn) do (turn: var Turn; s: WebSocket):
|
||||||
|
ws = s
|
||||||
|
debugecho "connected to ", url
|
||||||
|
bootClient(turn, dataspace, ws)
|
||||||
|
do:
|
||||||
|
close ws
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
runActor("eris_actor") do (root: Ref; turn: var Turn):
|
||||||
|
# connectStdio(root, turn)
|
||||||
|
boot(root, turn)
|
||||||
|
discard publish(turn, root, Args(dataspace: root, url: "ws://127.0.0.1:5225/"))
|
Loading…
Reference in New Issue