mirror of
https://github.com/logos-messaging/nim-chat-poc.git
synced 2026-01-04 07:03:13 +00:00
157 lines
4.3 KiB
Nim
157 lines
4.3 KiB
Nim
## Client API - FFI bindings for Client lifecycle and operations
|
|
## Uses the {.ffi.} pragma for async request handling
|
|
|
|
import std/json
|
|
import chronicles
|
|
import chronos
|
|
import ffi
|
|
|
|
import ../../src/chat
|
|
import ../../src/chat/proto_types
|
|
import ../../src/chat/delivery/waku_client
|
|
import ../../src/chat/identity
|
|
import ../utils
|
|
|
|
logScope:
|
|
topics = "chat ffi client"
|
|
|
|
#################################################
|
|
# Client Creation Request (for chat_new)
|
|
#################################################
|
|
|
|
type ChatCallbacks* = object
|
|
onNewMessage*: MessageCallback
|
|
onNewConversation*: NewConvoCallback
|
|
onDeliveryAck*: DeliveryAckCallback
|
|
|
|
proc createChatClient(
|
|
configJson: cstring, chatCallbacks: ChatCallbacks
|
|
): Future[Result[Client, string]] {.async.} =
|
|
try:
|
|
let config = parseJson($configJson)
|
|
|
|
# Parse identity name
|
|
let name = config.getOrDefault("name").getStr("anonymous")
|
|
|
|
# Parse Waku configuration or use defaults
|
|
var wakuCfg = DefaultConfig()
|
|
|
|
if config.hasKey("port"):
|
|
wakuCfg.port = config["port"].getInt().uint16
|
|
|
|
if config.hasKey("clusterId"):
|
|
wakuCfg.clusterId = config["clusterId"].getInt().uint16
|
|
|
|
if config.hasKey("shardId"):
|
|
wakuCfg.shardId = @[config["shardId"].getInt().uint16]
|
|
|
|
if config.hasKey("staticPeers"):
|
|
wakuCfg.staticPeers = @[]
|
|
for peer in config["staticPeers"]:
|
|
wakuCfg.staticPeers.add(peer.getStr())
|
|
|
|
# Create identity
|
|
let identity = createIdentity(name)
|
|
|
|
# Create Waku client
|
|
let wakuClient = initWakuClient(wakuCfg)
|
|
|
|
# Create Chat client
|
|
let client = newClient(wakuClient, identity)
|
|
|
|
# Register event handlers
|
|
client.onNewMessage(chatCallbacks.onNewMessage)
|
|
client.onNewConversation(chatCallbacks.onNewConversation)
|
|
client.onDeliveryAck(chatCallbacks.onDeliveryAck)
|
|
|
|
notice "Chat client created", name = name
|
|
return ok(client)
|
|
except CatchableError as e:
|
|
return err("failed to create client: " & e.msg)
|
|
|
|
registerReqFFI(CreateClientRequest, ctx: ptr FFIContext[Client]):
|
|
proc(
|
|
configJson: cstring, chatCallbacks: ChatCallbacks
|
|
): Future[Result[string, string]] {.async.} =
|
|
ctx[].myLib[] = (await createChatClient(configJson, chatCallbacks)).valueOr:
|
|
error "CreateClientRequest failed", error = error
|
|
return err($error)
|
|
return ok("")
|
|
|
|
#################################################
|
|
# Client Lifecycle Operations
|
|
#################################################
|
|
|
|
proc chat_start(
|
|
ctx: ptr FFIContext[Client],
|
|
callback: FFICallBack,
|
|
userData: pointer
|
|
) {.ffi.} =
|
|
try:
|
|
await ctx[].myLib[].start()
|
|
return ok("")
|
|
except CatchableError as e:
|
|
error "chat_start failed", error = e.msg
|
|
return err("failed to start client: " & e.msg)
|
|
|
|
proc chat_stop(
|
|
ctx: ptr FFIContext[Client],
|
|
callback: FFICallBack,
|
|
userData: pointer
|
|
) {.ffi.} =
|
|
try:
|
|
await ctx[].myLib[].stop()
|
|
return ok("")
|
|
except CatchableError as e:
|
|
error "chat_stop failed", error = e.msg
|
|
return err("failed to stop client: " & e.msg)
|
|
|
|
#################################################
|
|
# Client Info Operations
|
|
#################################################
|
|
|
|
proc chat_get_id(
|
|
ctx: ptr FFIContext[Client],
|
|
callback: FFICallBack,
|
|
userData: pointer
|
|
) {.ffi.} =
|
|
## Get the client's identifier
|
|
let clientId = ctx[].myLib[].getId()
|
|
return ok(clientId)
|
|
|
|
proc chat_get_default_inbox_id(
|
|
ctx: ptr FFIContext[Client],
|
|
callback: FFICallBack,
|
|
userData: pointer
|
|
) {.ffi.} =
|
|
## Get the default inbox conversation ID
|
|
let inboxId = ctx[].myLib[].defaultInboxConversationId()
|
|
return ok(inboxId)
|
|
|
|
#################################################
|
|
# Conversation List Operations
|
|
#################################################
|
|
|
|
proc chat_list_conversations(
|
|
ctx: ptr FFIContext[Client],
|
|
callback: FFICallBack,
|
|
userData: pointer
|
|
) {.ffi.} =
|
|
## List all conversations as JSON array
|
|
let convos = ctx[].myLib[].listConversations()
|
|
var convoList = newJArray()
|
|
for convo in convos:
|
|
convoList.add(%*{"id": convo.id()})
|
|
return ok($convoList)
|
|
|
|
proc chat_get_conversation(
|
|
ctx: ptr FFIContext[Client],
|
|
callback: FFICallBack,
|
|
userData: pointer,
|
|
convoId: cstring
|
|
) {.ffi.} =
|
|
## Get a specific conversation by ID
|
|
let convo = ctx[].myLib[].getConversation($convoId)
|
|
return ok($(%*{"id": convo.id()}))
|
|
|