kotlin-signald (deprecated)
signald is now deprecated, so this project is no longer active. See https://gitlab.com/signald/signald/-/blob/main/README.md

A Kotlin Multiplatform library for communicating with signald. For more information about signald, visit
https://signald.org.
This library provides a type-safe way to communicate with a signald UNIX socket, handling (de)serialization of responses
and requests. The client protocol classes are generated from the signald protocol document
(https://signald.org/articles/protocol-documentation/).
Documentation for the library is available at https://inthewaves.github.io/kotlin-signald/
This main motivation for this library was to have a type-safe method to communicate with signald and to also experiment
with KotlinPoet to generate Kotlin code from a protocol document.
Supported platforms
This library is experimental, with the API subject to breaking changes.
Note that since signald currently works by communicating with UNIX sockets, these platforms are effectively limited to
UNIX environments supported by signald.
clientprotocol module
This module contains the model classes for signald, as well as support for serializing them into JSON strings.
The following platforms are supported:
- JVM (JDK 1.8 or higher)
- Linux x86-64
- macOS x86-64
- JavaScript (Node.js)
client module
This module contains a simple client API for communicating with signald, including implementations of the
SocketCommunicator interfaces. It depends on the clientprotocol model and makes it easier to use the
clientprotocol classes (e.g., it will automatically add the account ID to each request that needs it).
The following platforms are supported:
- JVM (JDK 1.8 or higher)
- Linux x86-64
- JavaScript (Node.js; requires coroutines)
client-coroutines module
This module adds coroutine extensions for receiving messages, where incoming messages can be communicated through a
Channel or a SharedFlow.
The following platforms are supported:
- JVM (JDK 1.8 or higher)
- JavaScript (Node.js)
Linux x64 support is incomplete.
Usage
This library is compatible with the signald version in the protocol.json file, which
is used to generate the data classes for requests and responses. Also, to make it more obvious what version of signald
is used to generate the classes in a particular kotlin-signald release, the signald version will be added as the build
metadata in the semantic version strings of the releases.
This project comes with a client library for signald (the client module). There are also coroutine-based message
subscription handlers, which is provided as optional module (client-coroutines) to accommodate cases where a custom
implementation of a message subscription handler is desired.
It's recommended to ensure that a message receiver is active at all times, because signald will not process incoming
messages without any client subscriptions.
Incoming messages are not limited to text messages sent by a user. They can also include
- updates to groups (e.g., when someone joins a group, a message indicating new group info is sent to the group members.
If there are no message receivers active, any group messages sent by signald after someone new joins will not be sent
to that new user),
- read and typing receipts;
- expiration timer changes;
- encryption information (the Signal Protocol expects incoming
messages, e.g., see the Double Ratchet);
- and other implicit message types.
signald will handle these incoming messages, as long as there is a message subscription.
Client protocol
The clientprotocol model contains the generated model classes from signald with support for (de)serializing responses
and requests. However, this module does not contain any implementations of the SocketCommunciator and
SuspendSocketCommunicator interfaces. It's recommended to use the client module instead.
Mirroring the example on the signald site, these
raw classes can be used in the following manner:
import org.inthewaves.kotlinsignald.clientprotocol.SignaldException
org.inthewaves.kotlinsignald.clientprotocol.SocketCommunicator
org.inthewaves.kotlinsignald.clientprotocol.v1.structures.JsonAddress
org.inthewaves.kotlinsignald.clientprotocol.v1.structures.SendRequest
org.inthewaves.kotlinsignald.clientprotocol.v1.structures.SendResponse
socketCommunicator: SocketCommunicator =
request = SendRequest(
username = ,
messageBody = ,
recipientAddress = JsonAddress(number = ),
)
response: SendResponse = {
request.submit(socketWrapper)
} (e: SignaldException) {
}
Gradle
First add mavenCentral() to the dependencies block if you haven't already done so. All of the <current version>
placeholders can be replaced by one of the versions from the
releases.
-
In Kotlin Multiplatform projects, add a dependency to the commonMain source set dependencies
kotlin {
sourceSets {
commonMain {
dependencies {
implementation("org.inthewaves.kotlin-signald:clientprotocol:<current version>")
}
}
}
}
-
For single-platform projects such as JVM, add a dependency to the dependencies block.
Client
The client module has support for connecting to the UNIX socket, as well as providing a simplified client API (the
Signal class implementing the SignaldClient interface).
Ensure that signald is running and that the socket is available. The default socket paths of
$XDG_RUNTIME_DIR/signald/signald.sock and /var/run/signald/signald.sock will be tested if an explicit socket path is
not provided.
This snippet provides an overview of the Signal class (API inspired by pysignald).
Examples of echo bots can be found in the example-bot-jvm,
example-bot-linuxX64, and example-bot-js modules.
Gradle
First add mavenCentral() to the dependencies block if you haven't already done so. All of the <current version>
placeholders can be replaced by one of the versions from the
releases.
-
In Kotlin Multiplatform projects, add a dependency to the commonMain source set dependencies
kotlin {
sourceSets {
commonMain {
dependencies {
implementation("org.inthewaves.kotlin-signald:client:<current version>")
}
}
}
}
-
For single-platform projects such as JVM, add a dependency to the dependencies block.
dependencies {
implementation("org.inthewaves.kotlin-signald:client:<current version>")
}
Coroutine-based message receiver (JVM and JS only)
The client-coroutines module adds coroutine-based message subscription handlers via the signalMessagesChannel and
signalMessagesSharedFlow functions. Each function is an extension function of CoroutineScope that creates a
persistent socket connection to receive messages, launching a coroutine in the inherited scope in order to receive
messages asynchronously. When the inherited CoroutineScope is cancelled, an unsubscribe request is sent and the
socket is closed.
signalMessagesChannel has incoming messages sent through a
Channel.
This is best for when only one subscriber for incoming messages is needed.
signalMessagesSharedFlow has incoming messages emitted through a
.
s support multiple subscribers, so this approach is good for broadcasting incoming messages using one shared
socket connection.
See example-bot-jvm and
example-bot-js for
a full examples of bots that use these coroutine functions.
Gradle
Add mavenCentral() to the dependencies block if you haven't already done so. Then, add:
dependencies {
implementation("org.inthewaves.kotlin-signald:client-coroutines:<current version>")
}
Note that you can replace dependencies on org.inthewaves.kotlin-signald:client with
org.inthewaves.kotlin-signald:client-coroutines, as the client-coroutines module has an API dependency scope on the
client module, which means the client module will be added to the compile classpath by transitivity.
i.e., instead of doing
dependencies {
implementation("org.inthewaves.kotlin-signald:client:<current version>")
implementation("org.inthewaves.kotlin-signald:client-coroutines:<current version>")
}
you can do this:
dependencies {
implementation("org.inthewaves.kotlin-signald:client-coroutines:<current version>")
}
Development
Generating classes
The signald classes are generated from the signald protocol JSON file, located in
client/protocol.json. Generation is handled by the
protocolgen-plugin.
To regenerate the classes,
- Replace
protocol.json with a newer version
- Run
./gradlew generateSignaldClasses
Compiling a dynamic library (experimental)
Kotlin/Native supports compiling the code into a dynamic library which can then be used in native C / C++ programs. More
information on this topic can be found at https://kotlinlang.org/docs/native-dynamic-libraries.html. This library in its
current state is not fit for this purpose, and this feature is not mature, but we document this here for posterity.
Ensure you have these dependencies. For Debian,
sudo apt install libncurses5
Then, run ./gradlew :client:linkReleaseSharedLinuxX64. This will generate libktsignald_api.h and
libktsignald.so inside of client/build/bin/linuxX64/releaseShared.
As noted on the Kotlin site, the way
that Kotlin/Native exports symbols in the header file is subject to change without notice.