Put TDLib messages in a dedicated local dataspace
Communicating with TDLib on a remote dataspace is wasteful. Create and assert a local dataspace so that only messages observed by remote actors are relayed. This also allows the TDLib interface to be isolated from high-level actors.
This commit is contained in:
parent
be910a5ffa
commit
54aefcb22e
18
README.md
18
README.md
|
@ -26,13 +26,19 @@ let ?ds = dataspace
|
||||||
]
|
]
|
||||||
|
|
||||||
$ds [
|
$ds [
|
||||||
|
? ?v [
|
||||||
|
$log ! <log "-" { |+++|: $v }>
|
||||||
|
?- $log ! <log "-" { |---|: $v }>
|
||||||
|
]
|
||||||
|
|
||||||
|
# Raw TDLib interaction.
|
||||||
|
? <tdlib ?messages> $messages [
|
||||||
|
?? <send ?v> [ $log ! <log "-" { |>>>|: $v }> ]
|
||||||
|
?? <recv ?v> [ $log ! <log "-" { |<<<|: $v }> ]
|
||||||
?? <recv {"@type": "error", "code": ?code, "message": ?message}> [
|
?? <recv {"@type": "error", "code": ?code, "message": ?message}> [
|
||||||
$log ! <log "-" { error: {code: $code, message: $message } }>
|
$log ! <log "-" { error: {code: $code, message: $message } }>
|
||||||
]
|
]
|
||||||
?? <send ?v> [ $log ! <log "-" { |>>>|: $v }> ]
|
|
||||||
?? <recv ?v> [ $log ! <log "-" { |<<<|: $v }> ]
|
|
||||||
? ?v [ $log ! <log "-" { assertion: $v }> ]
|
|
||||||
? <telegram-ready> [
|
|
||||||
! <send {"@type": "getOption", "name":"version"}>
|
! <send {"@type": "getOption", "name":"version"}>
|
||||||
|
|
||||||
?? <recv {"@type": "updateAuthorizationState", "authorization_state": {"@type": "authorizationStateWaitTdlibParameters"}}> [
|
?? <recv {"@type": "updateAuthorizationState", "authorization_state": {"@type": "authorizationStateWaitTdlibParameters"}}> [
|
||||||
|
@ -100,9 +106,7 @@ $ds [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}> [
|
}> [
|
||||||
$ds ? <user $user_id ?first_name> [
|
$log ! <log "-" { updateChatLastMessage: { chat_id: $chat_id, date: $date, text: $text, user_id: $user_id } }>
|
||||||
$log ! <log "-" { chat_id: $chat_id, first_name: $first_name, updateChatLastMessage: $text, date: $date, user_id: $user_id }>
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
version 1 .
|
version 1 .
|
||||||
|
|
||||||
|
# Assert to the actor to register a dataspace for interaction.
|
||||||
TelegramArguments = <telegram-client {
|
TelegramArguments = <telegram-client {
|
||||||
dataspace: #:any
|
dataspace: #:any
|
||||||
}>.
|
}>.
|
||||||
|
|
||||||
# Assertion made when the client is ready to process messages.
|
# Assertion made to when the client is ready to process messages.
|
||||||
TelegramReady = <telegram-ready> .
|
TelegramReady = <telegram-ready> .
|
||||||
|
|
||||||
|
# Asserted to telegram-client to expose TDLib messages.
|
||||||
|
# Messages received from and sent to TDLib are in the
|
||||||
|
# form of <recv {…}> and <sent {…}> respectively.
|
||||||
|
TDLibClient = <tdlib @messages #:any>.
|
||||||
|
|
|
@ -25,21 +25,22 @@ let actor = bootActor("main") do (turn: Turn):
|
||||||
state.initialRef = ds
|
state.initialRef = ds
|
||||||
|
|
||||||
during(turn, ds, TelegramArguments.grabTypeFlat) do (ds: Cap):
|
during(turn, ds, TelegramArguments.grabTypeFlat) do (ds: Cap):
|
||||||
|
|
||||||
# Extern actors assert themselves here and a ClientId
|
# Extern actors assert themselves here and a ClientId
|
||||||
# is used to isolate their conversations with tdlib.
|
# is used to isolate their conversations with tdlib.
|
||||||
let client = td_create_client_id()
|
let
|
||||||
state.subscribers[client.int] = ds
|
client = td_create_client_id()
|
||||||
|
tdlib = turn.newDataspace()
|
||||||
|
state.subscribers[client.int] = tdlib
|
||||||
|
|
||||||
onMessage(turn, ds, grabRecord("send", grab())) do (v: Value):
|
onMessage(turn, tdlib, grabRecord("send", grab())) do (v: Value):
|
||||||
state.buffer.setPosition 0
|
state.buffer.setPosition 0
|
||||||
state.buffer.writeText(v, textJson)
|
state.buffer.writeText(v, textJson)
|
||||||
state.buffer.data.setLen state.buffer.getPosition
|
state.buffer.data.setLen state.buffer.getPosition
|
||||||
td_send(client, state.buffer.data)
|
td_send(client, state.buffer.data)
|
||||||
# TODO: enforce that the subscriber has not set "@client_id"?
|
# TODO: enforce that the subscriber has not set "@client_id"?
|
||||||
|
|
||||||
publish(turn, ds, TelegramReady())
|
publish(turn, ds, TDLibClient(messages: tdlib.embed))
|
||||||
# Assert to the subscriber that the messages
|
|
||||||
# it sends will be processed.
|
|
||||||
|
|
||||||
do:
|
do:
|
||||||
state.subscribers.del client.int
|
state.subscribers.del client.int
|
||||||
|
|
|
@ -3,6 +3,9 @@ import
|
||||||
preserves
|
preserves
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TDLibClient* {.preservesRecord: "tdlib".} = object
|
||||||
|
`messages`* {.preservesEmbedded.}: Value
|
||||||
|
|
||||||
TelegramReady* {.preservesRecord: "telegram-ready".} = object
|
TelegramReady* {.preservesRecord: "telegram-ready".} = object
|
||||||
|
|
||||||
TelegramArgumentsField0* {.preservesDictionary.} = object
|
TelegramArgumentsField0* {.preservesDictionary.} = object
|
||||||
|
@ -11,8 +14,8 @@ type
|
||||||
TelegramArguments* {.preservesRecord: "telegram-client".} = object
|
TelegramArguments* {.preservesRecord: "telegram-client".} = object
|
||||||
`field0`*: TelegramArgumentsField0
|
`field0`*: TelegramArgumentsField0
|
||||||
|
|
||||||
proc `$`*(x: TelegramReady | TelegramArguments): string =
|
proc `$`*(x: TDLibClient | TelegramReady | TelegramArguments): string =
|
||||||
`$`(toPreserves(x))
|
`$`(toPreserves(x))
|
||||||
|
|
||||||
proc encode*(x: TelegramReady | TelegramArguments): seq[byte] =
|
proc encode*(x: TDLibClient | TelegramReady | TelegramArguments): seq[byte] =
|
||||||
encode(toPreserves(x))
|
encode(toPreserves(x))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version = "20240521"
|
version = "20240522"
|
||||||
author = "Emery Hemingway"
|
author = "Emery Hemingway"
|
||||||
description = "Telegram client as a Syndicated Actor"
|
description = "Telegram client as a Syndicated Actor"
|
||||||
license = "Unlicense"
|
license = "Unlicense"
|
||||||
|
|
Loading…
Reference in New Issue