Reduce for a redo, use entities core at each friend
This commit is contained in:
parent
7afc67e912
commit
389fd04c4a
43
protocol.prs
43
protocol.prs
|
@ -1,36 +1,15 @@
|
||||||
version 1 .
|
version 1 .
|
||||||
|
|
||||||
ListenOn = <listen-on @dataspace #!any> .
|
ToxDataspace = <tox @publicKey bytes @entity #!any> .
|
||||||
|
|
||||||
|
FriendDataspace = <friend @publicKey bytes @entity #!any> .
|
||||||
|
|
||||||
|
CoreVersion = <core @major int @minor int @patch int> .
|
||||||
|
|
||||||
|
Address = <address @text string> .
|
||||||
|
|
||||||
|
Name = <name @name string> .
|
||||||
|
|
||||||
|
StatusMessage = <status-message @msg string> .
|
||||||
|
|
||||||
BootstrapNode = <bootstrap @publicKey string @host string @port int> .
|
BootstrapNode = <bootstrap @publicKey string @host string @port int> .
|
||||||
|
|
||||||
ToxCoreVersion = <ToxCoreVersion @major int @minor int @patch int> .
|
|
||||||
|
|
||||||
ToxSelfAddress = <ToxSelfAddress @address bytes> .
|
|
||||||
|
|
||||||
ToxSelfConnectionStatus = <ToxSelfConnectionStatus @status symbol> .
|
|
||||||
|
|
||||||
ToxSelfName = <ToxSelfName @name string> .
|
|
||||||
|
|
||||||
Status = =online / =away / =busy .
|
|
||||||
ToxSelfStatus = <ToxSelfStatus @status Status> .
|
|
||||||
|
|
||||||
ToxSelfStatusMessage = <ToxSelfStatusMessage @message string> .
|
|
||||||
|
|
||||||
ToxFriendRequest = <ToxFriendRequest @key bytes @message string> .
|
|
||||||
|
|
||||||
ToxFriendKey = <ToxFriendkey @num int @key bytes> .
|
|
||||||
|
|
||||||
ToxFriendLastOnline = <ToxFriendLastNnline @num int @unixEpoch double> .
|
|
||||||
|
|
||||||
ToxFriendName = <ToxFriendName @num int @name string> .
|
|
||||||
|
|
||||||
ToxFriendStatusMessage = <ToxFriendStatusMessage @num int @message string> .
|
|
||||||
|
|
||||||
ToxFriendTyping = <ToxFriendTyping @num int> .
|
|
||||||
|
|
||||||
ToxFriendAdd = <ToxFriendAdd @address bytes @message string> .
|
|
||||||
|
|
||||||
ToxFriendSend = <ToxFriendSend @num int @message string> .
|
|
||||||
|
|
||||||
ToxFriendBacklog = <ToxFriendBacklog @num int @start double @stop double> .
|
|
||||||
|
|
106
src/protocol.nim
106
src/protocol.nim
|
@ -3,106 +3,42 @@ import
|
||||||
std/typetraits, preserves
|
std/typetraits, preserves
|
||||||
|
|
||||||
type
|
type
|
||||||
ToxFriendSend* {.preservesRecord: "ToxFriendSend".} = object
|
Name* {.preservesRecord: "name".} = object
|
||||||
`num`*: int
|
`name`*: string
|
||||||
`message`*: string
|
|
||||||
|
|
||||||
ToxCoreVersion* {.preservesRecord: "ToxCoreVersion".} = object
|
FriendDataspace*[E] {.preservesRecord: "friend".} = ref object
|
||||||
`major`*: int
|
`publicKey`*: seq[byte]
|
||||||
`minor`*: int
|
`entity`*: Preserve[E]
|
||||||
`patch`*: int
|
|
||||||
|
|
||||||
ToxFriendLastOnline* {.preservesRecord: "ToxFriendLastNnline".} = object
|
Address* {.preservesRecord: "address".} = object
|
||||||
`num`*: int
|
`text`*: string
|
||||||
`unixEpoch`*: float64
|
|
||||||
|
|
||||||
ToxSelfConnectionStatus* {.preservesRecord: "ToxSelfConnectionStatus".} = object
|
ToxDataspace*[E] {.preservesRecord: "tox".} = ref object
|
||||||
`status`*: Symbol
|
`publicKey`*: seq[byte]
|
||||||
|
`entity`*: Preserve[E]
|
||||||
ToxSelfStatus* {.preservesRecord: "ToxSelfStatus".} = object
|
|
||||||
`status`*: Status
|
|
||||||
|
|
||||||
ToxFriendBacklog* {.preservesRecord: "ToxFriendBacklog".} = object
|
|
||||||
`num`*: int
|
|
||||||
`start`*: float64
|
|
||||||
`stop`*: float64
|
|
||||||
|
|
||||||
BootstrapNode* {.preservesRecord: "bootstrap".} = object
|
BootstrapNode* {.preservesRecord: "bootstrap".} = object
|
||||||
`publicKey`*: string
|
`publicKey`*: string
|
||||||
`host`*: string
|
`host`*: string
|
||||||
`port`*: int
|
`port`*: int
|
||||||
|
|
||||||
ToxSelfStatusMessage* {.preservesRecord: "ToxSelfStatusMessage".} = object
|
StatusMessage* {.preservesRecord: "status-message".} = object
|
||||||
`message`*: string
|
`msg`*: string
|
||||||
|
|
||||||
`Status`* {.preservesOr, pure.} = enum
|
CoreVersion* {.preservesRecord: "core".} = object
|
||||||
`online`, `away`, `busy`
|
`major`*: int
|
||||||
ToxSelfName* {.preservesRecord: "ToxSelfName".} = object
|
`minor`*: int
|
||||||
`name`*: string
|
`patch`*: int
|
||||||
|
|
||||||
ToxFriendKey* {.preservesRecord: "ToxFriendkey".} = object
|
proc `$`*[E](x: FriendDataspace[E] | ToxDataspace[E]): string =
|
||||||
`num`*: int
|
|
||||||
`key`*: seq[byte]
|
|
||||||
|
|
||||||
ListenOn*[E] {.preservesRecord: "listen-on".} = ref object
|
|
||||||
`dataspace`*: Preserve[E]
|
|
||||||
|
|
||||||
ToxSelfAddress* {.preservesRecord: "ToxSelfAddress".} = object
|
|
||||||
`address`*: seq[byte]
|
|
||||||
|
|
||||||
ToxFriendAdd* {.preservesRecord: "ToxFriendAdd".} = object
|
|
||||||
`address`*: seq[byte]
|
|
||||||
`message`*: string
|
|
||||||
|
|
||||||
ToxFriendStatusMessage* {.preservesRecord: "ToxFriendStatusMessage".} = object
|
|
||||||
`num`*: int
|
|
||||||
`message`*: string
|
|
||||||
|
|
||||||
ToxFriendRequest* {.preservesRecord: "ToxFriendRequest".} = object
|
|
||||||
`key`*: seq[byte]
|
|
||||||
`message`*: string
|
|
||||||
|
|
||||||
ToxFriendName* {.preservesRecord: "ToxFriendName".} = object
|
|
||||||
`num`*: int
|
|
||||||
`name`*: string
|
|
||||||
|
|
||||||
ToxFriendTyping* {.preservesRecord: "ToxFriendTyping".} = object
|
|
||||||
`num`*: int
|
|
||||||
|
|
||||||
proc `$`*[E](x: ListenOn[E]): string =
|
|
||||||
`$`(toPreserve(x, E))
|
`$`(toPreserve(x, E))
|
||||||
|
|
||||||
proc encode*[E](x: ListenOn[E]): seq[byte] =
|
proc encode*[E](x: FriendDataspace[E] | ToxDataspace[E]): seq[byte] =
|
||||||
encode(toPreserve(x, E))
|
encode(toPreserve(x, E))
|
||||||
|
|
||||||
proc `$`*(x: ToxFriendSend | ToxCoreVersion | ToxFriendLastOnline |
|
proc `$`*(x: Name | Address | BootstrapNode | StatusMessage | CoreVersion): string =
|
||||||
ToxSelfConnectionStatus |
|
|
||||||
ToxSelfStatus |
|
|
||||||
ToxFriendBacklog |
|
|
||||||
BootstrapNode |
|
|
||||||
ToxSelfStatusMessage |
|
|
||||||
ToxSelfName |
|
|
||||||
ToxFriendKey |
|
|
||||||
ToxSelfAddress |
|
|
||||||
ToxFriendAdd |
|
|
||||||
ToxFriendStatusMessage |
|
|
||||||
ToxFriendRequest |
|
|
||||||
ToxFriendName |
|
|
||||||
ToxFriendTyping): string =
|
|
||||||
`$`(toPreserve(x))
|
`$`(toPreserve(x))
|
||||||
|
|
||||||
proc encode*(x: ToxFriendSend | ToxCoreVersion | ToxFriendLastOnline |
|
proc encode*(x: Name | Address | BootstrapNode | StatusMessage | CoreVersion): seq[
|
||||||
ToxSelfConnectionStatus |
|
byte] =
|
||||||
ToxSelfStatus |
|
|
||||||
ToxFriendBacklog |
|
|
||||||
BootstrapNode |
|
|
||||||
ToxSelfStatusMessage |
|
|
||||||
ToxSelfName |
|
|
||||||
ToxFriendKey |
|
|
||||||
ToxSelfAddress |
|
|
||||||
ToxFriendAdd |
|
|
||||||
ToxFriendStatusMessage |
|
|
||||||
ToxFriendRequest |
|
|
||||||
ToxFriendName |
|
|
||||||
ToxFriendTyping): seq[byte] =
|
|
||||||
encode(toPreserve(x))
|
encode(toPreserve(x))
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway
|
# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway
|
||||||
# SPDX-License-Identifier: Unlicense
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
import std/[asyncdispatch, logging, parseopt, streams, strutils, tables]
|
import std/[asyncdispatch, logging, parseopt, strutils, tables]
|
||||||
from std/os import getEnv, fileExists, moveFile
|
|
||||||
from std/sequtils import toSeq
|
from std/sequtils import toSeq
|
||||||
from std/times import inMilliseconds
|
from std/times import inMilliseconds
|
||||||
|
|
||||||
import syndicate, syndicate/actors
|
import preserves, syndicate, syndicate/actors
|
||||||
|
|
||||||
import cbor, toxcore
|
import toxcore
|
||||||
import ./protocol
|
import ./protocol
|
||||||
# import ./logging
|
# import ./logging
|
||||||
|
|
||||||
addHandler(newConsoleLogger(useStderr = true))
|
addHandler(newConsoleLogger(useStderr = true))
|
||||||
# register global logger to stderr
|
# register global logger to stderr
|
||||||
|
|
||||||
var alive: bool
|
|
||||||
setControlCHook do:
|
|
||||||
if not alive:
|
|
||||||
# hard stop
|
|
||||||
quit "exited without saving Tox data"
|
|
||||||
alive = false
|
|
||||||
|
|
||||||
proc logging_callback(
|
proc logging_callback(
|
||||||
core: Core; level: Log_Level;
|
core: Core; level: Log_Level;
|
||||||
file: cstring; line: uint32;
|
file: cstring; line: uint32;
|
||||||
|
@ -36,43 +28,36 @@ proc logging_callback(
|
||||||
if lvl != lvlNone:
|
if lvl != lvlNone:
|
||||||
log(lvl, `func`, ": ", message)
|
log(lvl, `func`, ": ", message)
|
||||||
|
|
||||||
proc saveFilePath(): string =
|
type
|
||||||
for kind, key, val in getopt():
|
Entity = ref object of RootObj
|
||||||
if kind == cmdLongOption and key == "save-file" and val != "":
|
facet: Facet
|
||||||
result = val
|
ds: Ref
|
||||||
|
|
||||||
type GlobalState = ref object
|
FriendHandles = object
|
||||||
|
name, statusMessage, lastOnline, typing: Handle
|
||||||
|
|
||||||
|
FriendEntity {.final.} = ref object of Entity
|
||||||
|
handles: FriendHandles
|
||||||
|
|
||||||
|
CoreHandles = object
|
||||||
|
address, name, statusMessage, connectionStatus: Handle
|
||||||
|
CoreEntity {.final.} = ref object of Entity
|
||||||
core: Tox
|
core: Tox
|
||||||
statusCounts: array[3, int]
|
statusCounts: array[3, int]
|
||||||
|
handles: CoreHandles
|
||||||
|
friendRequests: Table[toxcore.PublicKey, Handle]
|
||||||
|
friendEntities: seq[FriendEntity]
|
||||||
|
|
||||||
proc writeSaveData(state: GlobalState) =
|
proc init(e: Entity; turn: var Turn; parent: Ref): Handle =
|
||||||
let path = saveFilePath()
|
assert e.facet.isNil
|
||||||
if path != "":
|
e.facet = turn.facet
|
||||||
let tmpPath = path & ".tmp"
|
e.ds = newRef(turn, parent.target)
|
||||||
debug("Dumping save data to ", tmpPath)
|
|
||||||
var stream = newFileStream(tmpPath, fmWrite)
|
|
||||||
stream.writeCbor(state.core.saveData)
|
|
||||||
close(stream)
|
|
||||||
moveFile(tmpPath, path)
|
|
||||||
debug("Data saved to ", path)
|
|
||||||
|
|
||||||
proc newGlobalState(): GlobalState =
|
proc initCore(entity: CoreEntity; turn: var Turn; parentRef: Ref) =
|
||||||
new result
|
assert entity.core.isNil
|
||||||
let saveFile = saveFilePath()
|
block: # Tox initialization
|
||||||
var saveData: seq[byte]
|
var proxy_host: cstring
|
||||||
if fileExists saveFile:
|
entity.core = newTox do (opts: toxcore.Options):
|
||||||
block:
|
|
||||||
var
|
|
||||||
stream = newFileStream(saveFile, fmRead)
|
|
||||||
parser: CborParser
|
|
||||||
dbPath: string
|
|
||||||
open(parser, stream)
|
|
||||||
parser.next()
|
|
||||||
if not saveData.fromCbor(parser.nextNode()):
|
|
||||||
raise newException(ValueError, "failed to parse Tox save data")
|
|
||||||
close(stream)
|
|
||||||
var proxy_host: string
|
|
||||||
result.core = newTox do (opts: toxcore.Options):
|
|
||||||
opts.log_callback = logging_callback
|
opts.log_callback = logging_callback
|
||||||
debug "parsing command-line options…"
|
debug "parsing command-line options…"
|
||||||
proc parseBoolParam(key, val: string): bool =
|
proc parseBoolParam(key, val: string): bool =
|
||||||
|
@ -121,214 +106,55 @@ proc newGlobalState(): GlobalState =
|
||||||
of cmdShortOption, cmdArgument:
|
of cmdShortOption, cmdArgument:
|
||||||
quit("unhandled command-line parameter: " & key)
|
quit("unhandled command-line parameter: " & key)
|
||||||
of cmdEnd: discard
|
of cmdEnd: discard
|
||||||
if saveData.len > 0:
|
block: # Syndicate entity initialization
|
||||||
opts.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE
|
discard init(entity, turn, parentRef)
|
||||||
opts.savedata = saveData
|
discard publish(turn, parentRef, ToxDataspace[Ref](
|
||||||
let
|
publicKey: entity.core.publicKey.bytes.toSeq,
|
||||||
ms = result.core.iterationInterval.inMilliseconds.int
|
entity: entity.ds.embed))
|
||||||
oneshot = false
|
discard publish(turn, entity.ds,
|
||||||
global = result
|
CoreVersion(
|
||||||
addTimer(ms, oneshot) do (fd: AsyncFD) -> bool:
|
|
||||||
if not alive:
|
|
||||||
writeSaveData(global)
|
|
||||||
quit()
|
|
||||||
iterate global.core
|
|
||||||
writeSaveData(global)
|
|
||||||
info "Tox ready"
|
|
||||||
info result.core.dhtId, "@:", result.core.udpPort
|
|
||||||
|
|
||||||
type
|
|
||||||
SelfHandles = object
|
|
||||||
connectionStatus, name, status, statusMessage: Handle
|
|
||||||
FriendHandles = object
|
|
||||||
`ref`: Ref
|
|
||||||
key, lastOnline, name, statusMessage, typing: Handle
|
|
||||||
|
|
||||||
ToxRelay = ref object
|
|
||||||
global: GlobalState
|
|
||||||
facet: Facet
|
|
||||||
`ref`: Ref
|
|
||||||
self: SelfHandles
|
|
||||||
friendRequests: Table[PublicKey, Handle]
|
|
||||||
friends: Table[Friend, FriendHandles]
|
|
||||||
|
|
||||||
proc publish[T](relay: ToxRelay; assertion: T): Handle =
|
|
||||||
info "publish ", assertion
|
|
||||||
var h: Handle
|
|
||||||
relay.facet.run do (turn: var Turn):
|
|
||||||
h = publish(turn, relay.`ref`, assertion)
|
|
||||||
h
|
|
||||||
|
|
||||||
proc retract(relay: ToxRelay; h: Handle) =
|
|
||||||
relay.facet.run do (turn: var Turn): retract(turn, h)
|
|
||||||
|
|
||||||
template replace[T](relay: ToxRelay; h: var Handle; assertion: T) =
|
|
||||||
relay.facet.run do (turn: var Turn):
|
|
||||||
replace(turn, relay.`ref`, h, assertion)
|
|
||||||
|
|
||||||
proc installCallbacks(relay: ToxRelay; turn: var Turn) =
|
|
||||||
relay.global.core.status = TOX_USER_STATUS_AWAY
|
|
||||||
|
|
||||||
discard publish(turn, relay.`ref`,
|
|
||||||
ToxCoreVersion(
|
|
||||||
major: int version_major(),
|
major: int version_major(),
|
||||||
minor: int version_minor(),
|
minor: int version_minor(),
|
||||||
patch: int version_patch()))
|
patch: int version_patch()))
|
||||||
discard publish(turn, relay.`ref`,
|
entity.handles.address = publish(turn, entity.ds,
|
||||||
ToxSelfAddress(address: relay.global.core.address.bytes.toSeq))
|
protocol.Address(text: $entity.core.address))
|
||||||
|
entity.handles.name = publish(turn, entity.ds,
|
||||||
|
Name(name: entity.core.name))
|
||||||
|
entity.handles.statusMessage = publish(turn, entity.ds,
|
||||||
|
StatusMessage(msg: entity.core.statusMessage))
|
||||||
|
block: # Friends initialization
|
||||||
|
var friendNums = entity.core.friends
|
||||||
|
entity.friendEntities.setLen(friendNums.len)
|
||||||
|
for fn in friendNums:
|
||||||
|
var fe = new FriendEntity
|
||||||
|
discard init(fe, turn, entity.ds)
|
||||||
|
discard publish(turn, entity.ds, FriendDataspace[Ref](
|
||||||
|
publicKey: entity.core.publicKey(fn).bytes.toSeq,
|
||||||
|
entity: fe.ds.embed))
|
||||||
|
if fn.int > entity.friendEntities.len:
|
||||||
|
entity.friendEntities.setLen(fn.int.succ)
|
||||||
|
entity.friendEntities[int fn] = fe
|
||||||
|
|
||||||
if relay.global.core.name != "":
|
var alive: bool
|
||||||
relay.self.name =
|
setControlCHook do:
|
||||||
publish(turn, relay.`ref`,
|
if not alive: quit()
|
||||||
ToxSelfName(name: relay.global.core.name))
|
alive = false
|
||||||
|
|
||||||
if relay.global.core.statusMessage != "":
|
proc run(entity: CoreEntity) =
|
||||||
relay.self.statusMessage =
|
|
||||||
publish(turn, relay.`ref`,
|
|
||||||
ToxSelfStatusMessage(message: relay.global.core.statusMessage))
|
|
||||||
|
|
||||||
relay.global.core.onSelfConnectionStatus do (status: Connection):
|
|
||||||
let sym =
|
|
||||||
case status
|
|
||||||
of TOX_CONNECTION_NONE: Symbol"none"
|
|
||||||
of TOX_CONNECTION_TCP: Symbol"tcp"
|
|
||||||
of TOX_CONNECTION_UDP: Symbol"udp"
|
|
||||||
relay.replace(relay.self.connectionStatus,
|
|
||||||
ToxSelfConnectionStatus(status: sym))
|
|
||||||
|
|
||||||
for num in relay.global.core.friends:
|
|
||||||
var handles = FriendHandles(`ref`: newRef(turn, relay.`ref`.target))
|
|
||||||
handles.key = publish(turn, relay.`ref`,
|
|
||||||
ToxFriendKey(num: int num, key: relay.global.core.publicKey(num).bytes.toSeq))
|
|
||||||
|
|
||||||
let lastOnline = relay.global.core.lastOnline(num)
|
|
||||||
if lastOnline > 0:
|
|
||||||
handles.lastOnline = publish(turn, relay.`ref`,
|
|
||||||
ToxFriendLastOnline(num: int num, unixEpoch: float64 lastOnline))
|
|
||||||
|
|
||||||
handles.name = publish(turn, relay.`ref`,
|
|
||||||
ToxFriendName(num: int num, name: relay.global.core.name(num)))
|
|
||||||
|
|
||||||
handles.statusMessage = publish(turn, relay.`ref`,
|
|
||||||
ToxFriendStatusMessage(num: int num, message: relay.global.core.statusMessage(num)))
|
|
||||||
relay.friends[num] = handles
|
|
||||||
|
|
||||||
relay.global.core.onFriendName do (num: Friend; name: string):
|
|
||||||
relay.replace(relay.friends[num].name, ToxFriendName(num: int num, name: name))
|
|
||||||
|
|
||||||
relay.global.core.onFriendStatusMessage do (num: Friend; msg: string):
|
|
||||||
relay.replace(
|
|
||||||
relay.friends[num].statusMessage,
|
|
||||||
ToxFriendStatusMessage(num: int num, message: msg))
|
|
||||||
|
|
||||||
relay.global.core.onFriendTyping do (num: Friend; typing: bool):
|
|
||||||
if typing:
|
|
||||||
relay.friends[num].typing =
|
|
||||||
relay.publish(
|
|
||||||
ToxFriendTyping(num: int num))
|
|
||||||
else:
|
|
||||||
relay.retract(relay.friends[num].typing)
|
|
||||||
relay.friends[num].typing = 0
|
|
||||||
|
|
||||||
relay.global.core.onFriendRequest do (key: PublicKey; msg: string):
|
|
||||||
var a = ToxFriendRequest(key: key.bytes.toSeq, message: msg)
|
|
||||||
if relay.friendRequests.hasKey key:
|
|
||||||
relay.replace(relay.friendRequests[key], a)
|
|
||||||
else:
|
|
||||||
relay.friendRequests[key] = relay.publish(a)
|
|
||||||
|
|
||||||
proc newToxRelay(global: GlobalState; `ref`: Ref; turn: var Turn): ToxRelay =
|
|
||||||
result = ToxRelay(
|
|
||||||
global: global,
|
|
||||||
facet: turn.facet,
|
|
||||||
`ref`: `ref`)
|
|
||||||
installCallbacks(result, turn)
|
|
||||||
|
|
||||||
bootDataspace("main") do (root: Ref; turn: var Turn):
|
|
||||||
alive = true
|
alive = true
|
||||||
var global = newGlobalState()
|
bootDataspace("main") do (ds: Ref; turn: var Turn):
|
||||||
|
connectStdio(ds, turn)
|
||||||
|
initCore(entity, turn, ds)
|
||||||
|
|
||||||
connectStdio(root, turn)
|
onPublish(turn, ds, ?BootstrapNode) do (key: string; host: string; port: int):
|
||||||
|
|
||||||
onPublish(turn, root, ?BootstrapNode) do (key: string; host: string; port: int):
|
|
||||||
info "Bootstrapping from ", key, "@", host, ":", port
|
info "Bootstrapping from ", key, "@", host, ":", port
|
||||||
try: global.core.bootstrap(host, key.toPublicKey, uint16 port)
|
try: entity.core.bootstrap(host, key.toPublicKey, uint16 port)
|
||||||
except ToxError as e:
|
except ToxError as e:
|
||||||
error "failed to bootstrap: ", e.msg
|
error "failed to bootstrap: ", e.msg
|
||||||
|
|
||||||
during(turn, root, ?ListenOn[Ref]) do (a: Assertion):
|
poll()
|
||||||
let
|
while alive:
|
||||||
ds = unembed a
|
iterate entity.core
|
||||||
relay = newToxRelay(global, ds, turn)
|
poll(entity.core.iterationInterval.inMilliseconds.int)
|
||||||
|
|
||||||
during(turn, ds, ?ToxSelfStatus) do (status: Status):
|
run(new CoreEntity)
|
||||||
let e = case status
|
|
||||||
of Status.online: TOX_USER_STATUS_NONE
|
|
||||||
of Status.away: TOX_USER_STATUS_AWAY
|
|
||||||
of Status.busy: TOX_USER_STATUS_BUSY
|
|
||||||
inc relay.global.statusCounts[int e]
|
|
||||||
let most = max(relay.global.statusCounts)
|
|
||||||
if relay.global.statusCounts[int e] == most:
|
|
||||||
relay.global.core.status = e
|
|
||||||
do:
|
|
||||||
relay.global.statusCounts[int e] = max(0, pred relay.global.statusCounts[int e])
|
|
||||||
let most = max(relay.global.statusCounts)
|
|
||||||
for e in [
|
|
||||||
TOX_USER_STATUS_BUSY,
|
|
||||||
TOX_USER_STATUS_NONE,
|
|
||||||
TOX_USER_STATUS_AWAY]:
|
|
||||||
if relay.global.statusCounts[int e] == most:
|
|
||||||
relay.global.core.status = e
|
|
||||||
break
|
|
||||||
|
|
||||||
onPublish(turn, ds, ?ToxSelfName) do (name: string):
|
|
||||||
debug "ToxSelfName ", rawValues
|
|
||||||
relay.global.core.name = name
|
|
||||||
replace(turn, ds, relay.self.name, ToxSelfName(name: relay.global.core.name))
|
|
||||||
writeSaveData(relay.global)
|
|
||||||
|
|
||||||
onPublish(turn, ds, ?ToxSelfStatusMessage) do (msg: string):
|
|
||||||
debug "ToxSelfStatusMessage ", rawValues
|
|
||||||
relay.global.core.statusMessage = msg
|
|
||||||
replace(turn, ds, relay.self.statusMessage,
|
|
||||||
ToxSelfStatusMessage(message: relay.global.core.statusMessage))
|
|
||||||
relay.global.writeSaveData()
|
|
||||||
|
|
||||||
onMessage(turn, ds, ?ToxFriendRequest) do (bytes: seq[byte]; msg: string):
|
|
||||||
info "got a ToxFriendRequest with a ", bytes.len, " byte key"
|
|
||||||
if bytes.len == TOX_PUBLIC_KEY_SIZE:
|
|
||||||
var key: PublicKey
|
|
||||||
copyMem(addr key.bytes[0], addr bytes[0], key.bytes.len)
|
|
||||||
var h: Handle
|
|
||||||
if relay.friendRequests.pop(key, h):
|
|
||||||
relay.retract(h)
|
|
||||||
try:
|
|
||||||
debug "addFriendNoRequest ", key
|
|
||||||
let friend = relay.global.core.addFriendNoRequest(key)
|
|
||||||
relay.friends[friend] = FriendHandles()
|
|
||||||
relay.global.writeSaveData()
|
|
||||||
except ToxError as e:
|
|
||||||
error "failed to add friend: ", e.msg
|
|
||||||
|
|
||||||
onMessage(turn, ds, ?ToxFriendAdd) do (toxid: seq[byte]; msg: string):
|
|
||||||
var address: Address
|
|
||||||
if toxid.len != address.bytes.len:
|
|
||||||
error "invalid Tox address: ", toxid
|
|
||||||
else:
|
|
||||||
copyMem(addr address.bytes[0], addr toxid[0], address.bytes.len)
|
|
||||||
try:
|
|
||||||
let friend = relay.global.core.addFriend(address, msg)
|
|
||||||
relay.friends[friend] = FriendHandles()
|
|
||||||
relay.global.writeSaveData()
|
|
||||||
# TODO: assert a pending friend?
|
|
||||||
except ToxError as e:
|
|
||||||
error "failed to add friend: ", e.msg
|
|
||||||
|
|
||||||
onMessage(turn, ds, ?ToxFriendSend) do (friend: Friend; msg: string):
|
|
||||||
discard relay.global.core.send(friend, msg)
|
|
||||||
# TODO: assert pending messages?
|
|
||||||
|
|
||||||
do:
|
|
||||||
info "facet stopped within ListenOn body"
|
|
||||||
|
|
||||||
runForever()
|
|
||||||
|
|
Loading…
Reference in New Issue