From 1f4407eabe5eb6e0d55471526dea127ee3df3d89 Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski <mail@justjanne.de>
Date: Sun, 13 Apr 2025 22:32:01 +0200
Subject: [PATCH] Unify DTO structure for network objects

---
 .../api/client/AliasManagerClientApi.kt       |   6 +-
 .../api/client/BacklogManagerClientApi.kt     |   7 ++
 .../api/client/BufferSyncerClientApi.kt       |   3 +
 .../api/client/BufferViewConfigClientApi.kt   |  33 +++---
 .../api/client/BufferViewManagerClientApi.kt  |   3 +
 .../api/client/CertManagerClientApi.kt        |   8 +-
 .../protocol/api/client/CoreInfoClientApi.kt  |   3 +
 .../client/HighlightRuleManagerClientApi.kt   |   3 +
 .../protocol/api/client/IdentityClientApi.kt  |   3 +
 .../api/client/IgnoreListManagerClientApi.kt  |   3 +
 .../api/client/IrcChannelClientApi.kt         |   3 +
 .../api/client/IrcListHelperClientApi.kt      |   7 ++
 .../protocol/api/client/IrcUserClientApi.kt   |   4 +-
 .../protocol/api/client/NetworkClientApi.kt   |   2 +
 .../api/client/NetworkConfigClientApi.kt      |   3 +
 .../protocol/api/dto/AliasManagerDto.kt       |  47 --------
 .../protocol/api/dto/BufferSyncerDto.kt       | 107 ------------------
 .../api/server/AliasManagerServerApi.kt       |  10 +-
 .../api/server/BacklogManagerServerApi.kt     |   9 +-
 .../api/server/BufferSyncerServerApi.kt       |   5 +-
 .../api/server/BufferViewConfigServerApi.kt   |   4 +-
 .../api/server/BufferViewManagerServerApi.kt  |   8 +-
 .../api/server/CertManagerServerApi.kt        |   4 +-
 .../server/HighlightRuleManagerServerApi.kt   |   9 +-
 .../protocol/api/server/IdentityServerApi.kt  |   5 +-
 .../api/server/IgnoreListManagerServerApi.kt  |   7 ++
 .../api/server/IrcListHelperServerApi.kt      |   9 +-
 .../api/server/NetworkConfigServerApi.kt      |   9 +-
 .../protocol/api/server/NetworkServerApi.kt   |  10 +-
 .../protocol/api/server/RpcServerApi.kt       |   4 +-
 .../backend/AliasManagerPersister.kt          |  13 +--
 .../backend/BacklogManagerPersister.kt        |   2 +
 .../backend/BufferSyncerPersister.kt          |   4 +-
 .../backend/BufferViewConfigPersister.kt      |  31 ++---
 .../backend/IrcListHelperPersister.kt         |   2 +
 .../connection/ClientSessionHandler.kt        |  17 ++-
 .../libquassel/client/QuasselApiTest.kt       |  46 ++++++--
 .../persistence/MessageRepository.kt          |   6 +
 .../protocol/dto/AliasManagerDto.kt           |  66 +++++++++++
 .../protocol/dto/BacklogManagerDto.kt         |  19 ++++
 .../protocol/dto/BufferSyncerDto.kt           |  85 ++++++++++++++
 .../protocol/dto/BufferViewConfigDto.kt       |  33 ++++++
 .../protocol/dto/BufferViewManagerDto.kt      |  39 +++++++
 .../libquassel/protocol/dto/CertManagerDto.kt |  32 ++++++
 .../libquassel/protocol/dto/CoreInfoDto.kt    |  87 ++++++++++++++
 .../protocol/dto/HighlightRuleManagerDto.kt   |  94 +++++++++++++++
 .../libquassel/protocol/dto/IdentityDto.kt    |  87 ++++++++++++++
 .../protocol/dto/IgnoreListManagerDto.kt      |  95 ++++++++++++++++
 .../libquassel/protocol/dto/IrcChannelDto.kt  |  48 ++++++++
 .../protocol/dto/IrcListHelperDto.kt          |  20 ++++
 .../libquassel/protocol/dto/IrcUserDto.kt     |  81 +++++++++++++
 .../protocol/dto/NetworkConfigDto.kt          |  63 +++++++++++
 .../libquassel/protocol/dto/NetworkDto.kt     |  32 ++++++
 .../libquassel/protocol/dto/NetworkInfoDto.kt | 107 ++++++++++++++++++
 .../protocol/dto/SyncableSerializer.kt        |  17 +++
 .../protocol/models/HandshakeMessage.kt       |   2 +-
 .../protocol/models/SignalProxyMessage.kt     |   2 +-
 .../protocol/models/network/IrcChannelDto.kt  |  43 -------
 .../protocol/models/network/IrcUserDto.kt     |  32 ------
 .../protocol/models/network/NetworkInfoDto.kt |  41 -------
 .../models/rules/HighlightNickType.kt         |   3 +-
 .../protocol/models/rules/IgnoreType.kt       |   3 +-
 .../protocol/models/rules/ScopeType.kt        |   3 +-
 .../protocol/models/rules/StrictnessType.kt   |   3 +-
 .../handshake/SessionInitSerializer.kt        |   2 +-
 .../serializers/quassel/IdentitySerializer.kt |   2 +-
 .../quassel/IrcChannelSerializer.kt           |   2 +-
 .../serializers/quassel/IrcUserSerializer.kt  |   2 +-
 .../quassel/NetworkInfoSerializer.kt          |   2 +-
 .../handshake/SessionInitSerializerTest.kt    |   4 +-
 .../quassel/IrcChannelSerializerTest.kt       |   4 +-
 .../quassel/IrcUserSerializerTest.kt          |   5 +-
 .../quassel/NetworkInfoSerializerTest.kt      |   6 +-
 .../signalproxy/RpcSerializerTest.kt          |   5 -
 .../libquassel/protocol/testutil/Random.kt    |  19 ++--
 75 files changed, 1261 insertions(+), 388 deletions(-)
 delete mode 100644 libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/AliasManagerDto.kt
 delete mode 100644 libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/BufferSyncerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/AliasManagerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BacklogManagerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferSyncerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewConfigDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewManagerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CertManagerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CoreInfoDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/HighlightRuleManagerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IdentityDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IgnoreListManagerDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcChannelDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcListHelperDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcUserDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkConfigDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkInfoDto.kt
 create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/SyncableSerializer.kt
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcChannelDto.kt
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcUserDto.kt
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/NetworkInfoDto.kt

diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/AliasManagerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/AliasManagerClientApi.kt
index af85247..2545bf9 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/AliasManagerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/AliasManagerClientApi.kt
@@ -11,9 +11,9 @@ package de.justjanne.libquassel.protocol.api.client
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
-import de.justjanne.libquassel.protocol.api.dto.AliasManagerDto
+import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.AliasManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("AliasManager", side = ProtocolSide.CORE)
@@ -21,5 +21,5 @@ interface AliasManagerClientApi {
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
 
-  suspend fun update(properties: AliasManagerDto) = update(properties.serialize())
+  suspend fun update(properties: AliasManagerDto) = update(properties.let(AliasManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BacklogManagerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BacklogManagerClientApi.kt
index 3145844..148e65b 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BacklogManagerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BacklogManagerClientApi.kt
@@ -13,9 +13,11 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.BacklogManagerDto
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.MsgId
 import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("BacklogManager", side = ProtocolSide.CORE)
 interface BacklogManagerClientApi {
@@ -91,4 +93,9 @@ interface BacklogManagerClientApi {
     @RpcParam.Int flags: Int = -1,
     @RpcParam.QVariantList messages: QVariantList
   )
+
+  @RpcCall("update")
+  suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: BacklogManagerDto) = update(properties.let(BacklogManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferSyncerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferSyncerClientApi.kt
index c4b103b..dc2fa25 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferSyncerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferSyncerClientApi.kt
@@ -13,6 +13,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.BufferSyncerDto
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.MsgId
 import de.justjanne.libquassel.protocol.variant.QVariantMap
@@ -45,4 +46,6 @@ interface BufferSyncerClientApi {
 
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: BufferSyncerDto) = update(properties.let(BufferSyncerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewConfigClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewConfigClientApi.kt
index 6868a03..aeb5b64 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewConfigClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewConfigClientApi.kt
@@ -14,6 +14,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.api.ObjectName
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
 import de.justjanne.libquassel.protocol.variant.QVariantMap
@@ -21,47 +22,49 @@ import de.justjanne.libquassel.protocol.variant.QVariantMap
 @RpcApi("BufferViewConfig", side = ProtocolSide.CORE)
 interface BufferViewConfigClientApi {
   @RpcCall("addBuffer")
-  suspend fun addBuffer(@RpcParam.UserType.BufferId buffer: BufferId, @RpcParam.Int pos: Int)
+  suspend fun addBuffer(objectName: ObjectName, @RpcParam.UserType.BufferId buffer: BufferId, @RpcParam.Int pos: Int)
 
   @RpcCall("moveBuffer")
-  suspend fun moveBuffer(@RpcParam.UserType.BufferId buffer: BufferId, @RpcParam.Int pos: Int)
+  suspend fun moveBuffer(objectName: ObjectName, @RpcParam.UserType.BufferId buffer: BufferId, @RpcParam.Int pos: Int)
 
   @RpcCall("removeBuffer")
-  suspend fun removeBuffer(@RpcParam.UserType.BufferId buffer: BufferId)
+  suspend fun removeBuffer(objectName: ObjectName, @RpcParam.UserType.BufferId buffer: BufferId)
 
   @RpcCall("removeBufferPermanently")
-  suspend fun removeBufferPermanently(@RpcParam.UserType.BufferId buffer: BufferId)
+  suspend fun removeBufferPermanently(objectName: ObjectName, @RpcParam.UserType.BufferId buffer: BufferId)
 
   @RpcCall("setBufferViewName")
-  suspend fun setBufferViewName(@RpcParam.QString value: String)
+  suspend fun setBufferViewName(objectName: ObjectName, @RpcParam.QString value: String)
 
   @RpcCall("setAddNewBuffersAutomatically")
-  suspend fun setAddNewBuffersAutomatically(@RpcParam.Bool value: Boolean)
+  suspend fun setAddNewBuffersAutomatically(objectName: ObjectName, @RpcParam.Bool value: Boolean)
 
   @RpcCall("setAllowedBufferTypes")
-  suspend fun setAllowedBufferTypes(@RpcParam.Int value: Int)
+  suspend fun setAllowedBufferTypes(objectName: ObjectName, @RpcParam.Int value: Int)
 
   @RpcCall("setDisableDecoration")
-  suspend fun setDisableDecoration(@RpcParam.Bool value: Boolean)
+  suspend fun setDisableDecoration(objectName: ObjectName, @RpcParam.Bool value: Boolean)
 
   @RpcCall("setHideInactiveBuffers")
-  suspend fun setHideInactiveBuffers(@RpcParam.Bool value: Boolean)
+  suspend fun setHideInactiveBuffers(objectName: ObjectName, @RpcParam.Bool value: Boolean)
 
   @RpcCall("setHideInactiveNetworks")
-  suspend fun setHideInactiveNetworks(@RpcParam.Bool value: Boolean)
+  suspend fun setHideInactiveNetworks(objectName: ObjectName, @RpcParam.Bool value: Boolean)
 
   @RpcCall("setMinimumActivity")
-  suspend fun setMinimumActivity(@RpcParam.Int value: Int)
+  suspend fun setMinimumActivity(objectName: ObjectName, @RpcParam.Int value: Int)
 
   @RpcCall("setNetworkId")
-  suspend fun setNetworkId(@RpcParam.UserType.NetworkId value: NetworkId)
+  suspend fun setNetworkId(objectName: ObjectName, @RpcParam.UserType.NetworkId value: NetworkId)
 
   @RpcCall("setShowSearch")
-  suspend fun setShowSearch(@RpcParam.Bool value: Boolean)
+  suspend fun setShowSearch(objectName: ObjectName, @RpcParam.Bool value: Boolean)
 
   @RpcCall("setSortAlphabetically")
-  suspend fun setSortAlphabetically(@RpcParam.Bool value: Boolean)
+  suspend fun setSortAlphabetically(objectName: ObjectName, @RpcParam.Bool value: Boolean)
 
   @RpcCall("update")
-  suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+  suspend fun update(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  //suspend fun update(objectName: ObjectName, properties: BufferViewConfigDto) = update(objectName, properties.let(BufferViewConfigDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewManagerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewManagerClientApi.kt
index 4e49961..c291fb5 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewManagerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/BufferViewManagerClientApi.kt
@@ -13,6 +13,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.BufferViewManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("BufferViewManager", side = ProtocolSide.CORE)
@@ -25,4 +26,6 @@ interface BufferViewManagerClientApi {
 
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: BufferViewManagerDto) = update(properties.let(BufferViewManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CertManagerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CertManagerClientApi.kt
index 483dc46..d990bce 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CertManagerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CertManagerClientApi.kt
@@ -19,12 +19,14 @@ import java.nio.ByteBuffer
 
 @RpcApi("CertManager", side = ProtocolSide.CORE)
 interface CertManagerClientApi {
-      @RpcCall("setSslCert")
+  @RpcCall("setSslCert")
   suspend fun setSslCert(objectName: ObjectName, @RpcParam.QByteArray encoded: ByteBuffer)
 
-      @RpcCall("setSslKey")
+  @RpcCall("setSslKey")
   suspend fun setSslKey(objectName: ObjectName, @RpcParam.QByteArray encoded: ByteBuffer)
 
-      @RpcCall("update")
+  @RpcCall("update")
   suspend fun update(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  //suspend fun update(objectName: ObjectName, properties: CertManagerDto) = update(objectName, properties.let(CertManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CoreInfoClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CoreInfoClientApi.kt
index bc11a73..da4421e 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CoreInfoClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/CoreInfoClientApi.kt
@@ -13,6 +13,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.CoreInfoDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("CoreInfo", side = ProtocolSide.CORE)
@@ -22,4 +23,6 @@ interface CoreInfoClientApi {
 
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: CoreInfoDto) = update(properties.let(CoreInfoDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/HighlightRuleManagerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/HighlightRuleManagerClientApi.kt
index 6161e4a..d872c2b 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/HighlightRuleManagerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/HighlightRuleManagerClientApi.kt
@@ -13,6 +13,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.HighlightRuleManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("HighlightRuleManager", side = ProtocolSide.CORE)
@@ -44,4 +45,6 @@ interface HighlightRuleManagerClientApi {
 
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: HighlightRuleManagerDto) = update(properties.let(HighlightRuleManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IdentityClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IdentityClientApi.kt
index 56de683..56b800c 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IdentityClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IdentityClientApi.kt
@@ -14,6 +14,7 @@ import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
+import de.justjanne.libquassel.protocol.dto.IdentityDto
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
 import de.justjanne.libquassel.protocol.variant.QVariantMap
@@ -98,4 +99,6 @@ interface IdentityClientApi {
 
   @RpcCall("update")
   suspend fun update(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(objectName: ObjectName, properties: IdentityDto) = update(objectName, properties.let(IdentityDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IgnoreListManagerClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IgnoreListManagerClientApi.kt
index b414164..e98f14c 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IgnoreListManagerClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IgnoreListManagerClientApi.kt
@@ -13,6 +13,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.IgnoreListManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("IgnoreListManager", side = ProtocolSide.CORE)
@@ -36,4 +37,6 @@ interface IgnoreListManagerClientApi {
 
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: IgnoreListManagerDto) = update(properties.let(IgnoreListManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcChannelClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcChannelClientApi.kt
index 4b0c8d0..19b0243 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcChannelClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcChannelClientApi.kt
@@ -14,6 +14,7 @@ import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
+import de.justjanne.libquassel.protocol.dto.IrcChannelDto
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
@@ -61,4 +62,6 @@ interface IrcChannelClientApi  {
 
   @RpcCall("update")
   suspend fun update(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(objectName: ObjectName, properties: IrcChannelDto) = update(objectName, properties.let(IrcChannelDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcListHelperClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcListHelperClientApi.kt
index ed9bedb..04a7187 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcListHelperClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcListHelperClientApi.kt
@@ -13,9 +13,11 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.IrcListHelperDto
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
 import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("IrcListHelper", side = ProtocolSide.CORE)
 interface IrcListHelperClientApi  {
@@ -27,4 +29,9 @@ interface IrcListHelperClientApi  {
 
   @RpcCall("reportFinishedList")
   suspend fun reportFinishedList(@RpcParam.UserType.NetworkId netId: NetworkId)
+
+  @RpcCall("update")
+  suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: IrcListHelperDto) = update(properties.let(IrcListHelperDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcUserClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcUserClientApi.kt
index 3af4033..ea363da 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcUserClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/IrcUserClientApi.kt
@@ -14,6 +14,7 @@ import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
+import de.justjanne.libquassel.protocol.dto.IrcUserDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import org.threeten.bp.temporal.Temporal
 
@@ -90,5 +91,6 @@ interface IrcUserClientApi {
 
   @RpcCall("update")
   suspend fun update(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
-}
 
+  suspend fun update(objectName: ObjectName, properties: IrcUserDto) = update(objectName, properties.let(IrcUserDto.Serializer::serialize))
+}
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkClientApi.kt
index 256dc96..dcc2644 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkClientApi.kt
@@ -171,4 +171,6 @@ interface NetworkClientApi {
 
   @RpcCall("update")
   suspend fun update(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  //suspend fun update(objectName: ObjectName, properties: NetworkDto) = update(objectName, properties.let(NetworkDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkConfigClientApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkConfigClientApi.kt
index 979dc07..757737f 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkConfigClientApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/client/NetworkConfigClientApi.kt
@@ -13,6 +13,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.NetworkConfigDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("NetworkConfig", side = ProtocolSide.CORE)
@@ -43,4 +44,6 @@ interface NetworkConfigClientApi {
 
   @RpcCall("update")
   suspend fun update(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun update(properties: NetworkConfigDto) = update(properties.let(NetworkConfigDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/AliasManagerDto.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/AliasManagerDto.kt
deleted file mode 100644
index 1bc2087..0000000
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/AliasManagerDto.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2025 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.api.dto
-
-import de.justjanne.libquassel.protocol.models.QStringList
-import de.justjanne.libquassel.protocol.models.types.QtType
-import de.justjanne.libquassel.protocol.variant.QVariantMap
-import de.justjanne.libquassel.protocol.variant.into
-import de.justjanne.libquassel.protocol.variant.qVariant
-
-data class AliasManagerDto(
-  val aliases: AliasesDto
-) {
-  data class AliasesDto(
-    val names: List<String?>,
-    val expansions: List<String?>
-  ) {
-    fun serialize(): QVariantMap = mapOf(
-      "names" to qVariant(names, QtType.QStringList),
-      "expansions" to qVariant(expansions, QtType.QStringList)
-    )
-
-    companion object {
-      fun deserialize(data: QVariantMap) = AliasesDto(
-        names = data["names"].into<QStringList>().orEmpty(),
-        expansions = data["expansions"].into<QStringList>().orEmpty(),
-      )
-    }
-  }
-
-  fun serialize(): QVariantMap = mapOf(
-    "Aliases" to qVariant(aliases.serialize(), QtType.QVariantMap)
-  )
-
-  companion object {
-    fun deserialize(data: QVariantMap) = AliasManagerDto(
-      aliases = data["Aliases"].into<QVariantMap>().orEmpty().let(AliasesDto::deserialize)
-    )
-  }
-}
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/BufferSyncerDto.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/BufferSyncerDto.kt
deleted file mode 100644
index 2791ced..0000000
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/dto/BufferSyncerDto.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2025 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.api.dto
-
-import de.justjanne.libquassel.protocol.models.ids.BufferId
-import de.justjanne.libquassel.protocol.models.ids.MsgId
-import de.justjanne.libquassel.protocol.models.types.QtType
-import de.justjanne.libquassel.protocol.models.types.QuasselType
-import de.justjanne.libquassel.protocol.util.collections.pairs
-import de.justjanne.libquassel.protocol.variant.QVariantList
-import de.justjanne.libquassel.protocol.variant.QVariantMap
-import de.justjanne.libquassel.protocol.variant.QVariant_
-import de.justjanne.libquassel.protocol.variant.into
-import de.justjanne.libquassel.protocol.variant.qVariant
-
-private typealias BufferMap = Map<BufferId, QVariant_>
-
-private fun BufferMap.toVariantList(): QVariantList = entries.flatMap {
-  listOf(qVariant(it.key, QuasselType.BufferId), it.value)
-}
-
-private fun QVariantList.toBufferMap(): BufferMap = pairs { key, value ->
-  Pair(key.into<BufferId>() ?: return@pairs null, value)
-}.filterNotNull().toMap()
-
-data class BufferSyncerDto(
-  val activities: Map<BufferId, Int>,
-  val highlightCounts: Map<BufferId, Int>,
-  val lastSeenMsg: Map<BufferId, MsgId>,
-  val markerLines: Map<BufferId, MsgId>,
-) {
-
-  fun serialize(): QVariantMap = mapOf(
-    "Activities" to qVariant(
-      activities.flatMap {
-        listOf(
-          qVariant(it.key, QuasselType.BufferId),
-          qVariant(it.value, QtType.Int),
-        )
-      },
-      QtType.QVariantList
-    ),
-    "HighlightCounts" to qVariant(
-      highlightCounts.flatMap {
-        listOf(
-          qVariant(it.key, QuasselType.BufferId),
-          qVariant(it.value, QtType.Int),
-        )
-      },
-      QtType.QVariantList
-    ),
-    "LastSeenMsg" to qVariant(
-      lastSeenMsg.flatMap {
-        listOf(
-          qVariant(it.key, QuasselType.BufferId),
-          qVariant(it.value, QuasselType.MsgId),
-        )
-      },
-      QtType.QVariantList
-    ),
-    "MarkerLines" to qVariant(
-      markerLines.flatMap {
-        listOf(
-          qVariant(it.key, QuasselType.BufferId),
-          qVariant(it.value, QuasselType.MsgId),
-        )
-      },
-      QtType.QVariantList
-    ),
-  )
-
-  companion object {
-    fun deserialize(data: QVariantMap) = BufferSyncerDto(
-      activities = data["Activities"].into<QVariantList>().orEmpty().pairs { key, value ->
-        Pair(
-          key.into<BufferId>() ?: return@pairs null,
-          value.into<Int>() ?: return@pairs null
-        )
-      }.filterNotNull().toMap(),
-      highlightCounts = data["HighlightCounts"].into<QVariantList>().orEmpty().pairs { key, value ->
-        Pair(
-          key.into<BufferId>() ?: return@pairs null,
-          value.into<Int>() ?: return@pairs null
-        )
-      }.filterNotNull().toMap(),
-      lastSeenMsg = data["LastSeenMsg"].into<QVariantList>().orEmpty().pairs { key, value ->
-        Pair(
-          key.into<BufferId>() ?: return@pairs null,
-          value.into<MsgId>() ?: return@pairs null
-        )
-      }.filterNotNull().toMap(),
-      markerLines = data["MarkerLines"].into<QVariantList>().orEmpty().pairs { key, value ->
-        Pair(
-          key.into<BufferId>() ?: return@pairs null,
-          value.into<MsgId>() ?: return@pairs null
-        )
-      }.filterNotNull().toMap(),
-    )
-  }
-}
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/AliasManagerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/AliasManagerServerApi.kt
index 3682c13..121fd61 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/AliasManagerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/AliasManagerServerApi.kt
@@ -11,9 +11,9 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
-import de.justjanne.libquassel.protocol.api.dto.AliasManagerDto
+import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.AliasManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("AliasManager", side = ProtocolSide.CLIENT)
@@ -25,9 +25,7 @@ interface AliasManagerServerApi {
   )
 
   @RpcCall("requestUpdate")
-  suspend fun requestUpdate(
-    @RpcParam.QVariantMap properties: QVariantMap
-  )
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
 
-  suspend fun requestUpdate(properties: AliasManagerDto) = requestUpdate(properties.serialize())
+  suspend fun requestUpdate(properties: AliasManagerDto) = requestUpdate(properties.let(AliasManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BacklogManagerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BacklogManagerServerApi.kt
index 786db45..e0d7d7d 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BacklogManagerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BacklogManagerServerApi.kt
@@ -11,10 +11,12 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
+import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.BacklogManagerDto
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.MsgId
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("BacklogManager", side = ProtocolSide.CLIENT)
 interface BacklogManagerServerApi {
@@ -113,4 +115,9 @@ interface BacklogManagerServerApi {
     @RpcParam.Int type: Int = -1,
     @RpcParam.Int flags: Int = -1
   )
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: BacklogManagerDto) = requestUpdate(properties.let(BacklogManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferSyncerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferSyncerServerApi.kt
index 785f142..77fc792 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferSyncerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferSyncerServerApi.kt
@@ -11,8 +11,9 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
+import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.BufferSyncerDto
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.MsgId
 import de.justjanne.libquassel.protocol.variant.QVariantMap
@@ -54,4 +55,6 @@ interface BufferSyncerServerApi {
 
   @RpcCall("requestUpdate")
   suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: BufferSyncerDto) = requestUpdate(properties.let(BufferSyncerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewConfigServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewConfigServerApi.kt
index b4e1805..c8e4ac3 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewConfigServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewConfigServerApi.kt
@@ -11,8 +11,8 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
+import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.variant.QVariantMap
@@ -36,4 +36,6 @@ interface BufferViewConfigServerApi {
 
   @RpcCall("requestUpdate")
   suspend fun requestUpdate(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  //suspend fun requestUpdate(objectName: ObjectName, properties: BufferViewConfigDto) = requestUpdate(objectName, properties.let(BufferViewConfigDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewManagerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewManagerServerApi.kt
index 6a2e77c..5b0530e 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewManagerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/BufferViewManagerServerApi.kt
@@ -11,8 +11,9 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
+import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.BufferViewManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantList
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
@@ -26,5 +27,10 @@ interface BufferViewManagerServerApi {
 
   @RpcCall("requestDeleteBufferView")
   suspend fun requestDeleteBufferView(@RpcParam.Int bufferViewConfigId: Int)
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: BufferViewManagerDto) = requestUpdate(properties.let(BufferViewManagerDto.Serializer::serialize))
 }
 
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/CertManagerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/CertManagerServerApi.kt
index c8b8693..8ee8f65 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/CertManagerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/CertManagerServerApi.kt
@@ -11,8 +11,8 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
+import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
@@ -20,4 +20,6 @@ import de.justjanne.libquassel.protocol.variant.QVariantMap
 interface CertManagerServerApi {
   @RpcCall("requestUpdate")
   suspend fun requestUpdate(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  //suspend fun requestUpdate(objectName: ObjectName, properties: CertManagerDto) = requestUpdate(objectName, properties.let(CertManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/HighlightRuleManagerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/HighlightRuleManagerServerApi.kt
index 9751f27..04739b3 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/HighlightRuleManagerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/HighlightRuleManagerServerApi.kt
@@ -10,9 +10,11 @@
 package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
-import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcApi
+import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.HighlightRuleManagerDto
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("HighlightRuleManager", side = ProtocolSide.CLIENT)
 interface HighlightRuleManagerServerApi {
@@ -40,4 +42,9 @@ interface HighlightRuleManagerServerApi {
 
   @RpcCall("requestSetNicksCaseSensitive")
   suspend fun requestSetNicksCaseSensitive(@RpcParam.Bool nicksCaseSensitive: Boolean)
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: HighlightRuleManagerDto) = requestUpdate(properties.let(HighlightRuleManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IdentityServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IdentityServerApi.kt
index 05fe4ba..b32fdd1 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IdentityServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IdentityServerApi.kt
@@ -10,14 +10,17 @@
 package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
-import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcApi
+import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
+import de.justjanne.libquassel.protocol.dto.IdentityDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("Identity", side = ProtocolSide.CLIENT)
 interface IdentityServerApi {
   @RpcCall("requestUpdate")
   suspend fun requestUpdate(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(objectName: ObjectName, properties: IdentityDto) = requestUpdate(objectName, properties.let(IdentityDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IgnoreListManagerServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IgnoreListManagerServerApi.kt
index ed57165..0377a43 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IgnoreListManagerServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IgnoreListManagerServerApi.kt
@@ -13,6 +13,8 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.IgnoreListManagerDto
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("IgnoreListManager", side = ProtocolSide.CLIENT)
 interface IgnoreListManagerServerApi {
@@ -32,4 +34,9 @@ interface IgnoreListManagerServerApi {
 
   @RpcCall("requestToggleIgnoreRule")
   suspend fun requestToggleIgnoreRule(@RpcParam.QString ignoreRule: String?)
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: IgnoreListManagerDto) = requestUpdate(properties.let(IgnoreListManagerDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IrcListHelperServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IrcListHelperServerApi.kt
index 2e2eff2..7f3242a 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IrcListHelperServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/IrcListHelperServerApi.kt
@@ -11,13 +11,20 @@ package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
-import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.annotations.RpcCall
+import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.IrcListHelperDto
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("IrcListHelper", side = ProtocolSide.CLIENT)
 interface IrcListHelperServerApi {
   @RpcCall("requestChannelList")
   suspend fun requestChannelList(@RpcParam.UserType.NetworkId netId: NetworkId, @RpcParam.QStringList channelFilters: QStringList)
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: IrcListHelperDto) = requestUpdate(properties.let(IrcListHelperDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkConfigServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkConfigServerApi.kt
index 7e8e6e4..e494311 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkConfigServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkConfigServerApi.kt
@@ -10,9 +10,11 @@
 package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
-import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcApi
+import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.NetworkConfigDto
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("NetworkConfig", side = ProtocolSide.CLIENT)
 interface NetworkConfigServerApi {
@@ -39,4 +41,9 @@ interface NetworkConfigServerApi {
 
   @RpcCall("requestSetStandardCtcp")
   suspend fun requestSetStandardCtcp(@RpcParam.Bool enabled: Boolean)
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(@RpcParam.QVariantMap properties: QVariantMap)
+
+  suspend fun requestUpdate(properties: NetworkConfigDto) = requestUpdate(properties.let(NetworkConfigDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkServerApi.kt
index 14b7328..452d24b 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/NetworkServerApi.kt
@@ -10,11 +10,12 @@
 package de.justjanne.libquassel.protocol.api.server
 
 import de.justjanne.libquassel.annotations.ProtocolSide
-import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcApi
+import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
 import de.justjanne.libquassel.protocol.api.ObjectName
-import de.justjanne.libquassel.protocol.models.network.NetworkInfoDto
+import de.justjanne.libquassel.protocol.dto.NetworkInfoDto
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi("Network", side = ProtocolSide.CLIENT)
 interface NetworkServerApi {
@@ -26,4 +27,9 @@ interface NetworkServerApi {
 
   @RpcCall("requestSetNetworkInfo")
   suspend fun requestSetNetworkInfo(objectName: ObjectName, @RpcParam.UserType.NetworkInfo info: NetworkInfoDto)
+
+  @RpcCall("requestUpdate")
+  suspend fun requestUpdate(objectName: ObjectName, @RpcParam.QVariantMap properties: QVariantMap)
+
+  //suspend fun requestUpdate(properties: NetworkDto) = requestUpdate(properties.let(NetworkDto.Serializer::serialize))
 }
diff --git a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/RpcServerApi.kt b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/RpcServerApi.kt
index 5dfae0d..c852df8 100644
--- a/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/RpcServerApi.kt
+++ b/libquassel-api/src/main/kotlin/de/justjanne/libquassel/protocol/api/server/RpcServerApi.kt
@@ -13,11 +13,11 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.annotations.RpcApi
 import de.justjanne.libquassel.annotations.RpcCall
 import de.justjanne.libquassel.annotations.RpcParam
+import de.justjanne.libquassel.protocol.dto.IdentityDto
+import de.justjanne.libquassel.protocol.dto.NetworkInfoDto
 import de.justjanne.libquassel.protocol.models.BufferInfo
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
-import de.justjanne.libquassel.protocol.models.network.NetworkInfoDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
 @RpcApi(side = ProtocolSide.CLIENT)
diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/AliasManagerPersister.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/AliasManagerPersister.kt
index 56e55a5..6d2dcd0 100644
--- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/AliasManagerPersister.kt
+++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/AliasManagerPersister.kt
@@ -12,7 +12,7 @@ package de.justjanne.libquassel.backend
 import de.justjanne.libquassel.persistence.AliasEntity
 import de.justjanne.libquassel.persistence.AliasRepository
 import de.justjanne.libquassel.protocol.api.client.AliasManagerClientApi
-import de.justjanne.libquassel.protocol.api.dto.AliasManagerDto
+import de.justjanne.libquassel.protocol.dto.AliasManagerDto
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import javax.inject.Inject
 
@@ -20,17 +20,10 @@ class AliasManagerPersister @Inject constructor(
   private val repository: AliasRepository,
 ) : AliasManagerClientApi {
   override suspend fun update(properties: QVariantMap) {
-    val data = AliasManagerDto.deserialize(properties)
-    val names = data.aliases.names.requireNoNulls()
-    val expansions = data.aliases.expansions.requireNoNulls()
-    require(names.size == expansions.size) {
-      "Sizes do not match: names=${names.size}, expansions=${expansions.size}"
-    }
-
-    val aliases = names.zip(expansions).mapIndexed { index, (name, expansion) ->
+    val data = AliasManagerDto.Serializer.deserialize(properties)
+    val aliases = data.aliases.mapIndexed { index, (name, expansion) ->
       AliasEntity(index, name, expansion)
     }
-
     repository.sync(aliases)
   }
 }
diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BacklogManagerPersister.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BacklogManagerPersister.kt
index ce3001a..7345cb9 100644
--- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BacklogManagerPersister.kt
+++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BacklogManagerPersister.kt
@@ -16,6 +16,7 @@ import de.justjanne.libquassel.protocol.models.Message
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.MsgId
 import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.into
 import javax.inject.Inject
 
@@ -29,4 +30,5 @@ class BacklogManagerPersister @Inject constructor(
   override suspend fun receiveBacklogForward(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, type: Int, flags: Int, messages: QVariantList)  = Unit
   override suspend fun receiveBacklogAll(first: MsgId, last: MsgId, limit: Int, additional: Int, messages: QVariantList)  = Unit
   override suspend fun receiveBacklogAllFiltered(first: MsgId, last: MsgId, limit: Int, additional: Int, type: Int, flags: Int, messages: QVariantList)  = Unit
+  override suspend fun update(properties: QVariantMap) = Unit
 }
diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferSyncerPersister.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferSyncerPersister.kt
index 43bf4f4..c95ad80 100644
--- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferSyncerPersister.kt
+++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferSyncerPersister.kt
@@ -11,7 +11,7 @@ package de.justjanne.libquassel.backend
 
 import de.justjanne.libquassel.persistence.BufferRepository
 import de.justjanne.libquassel.protocol.api.client.BufferSyncerClientApi
-import de.justjanne.libquassel.protocol.api.dto.BufferSyncerDto
+import de.justjanne.libquassel.protocol.dto.BufferSyncerDto
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.MsgId
 import de.justjanne.libquassel.protocol.variant.QVariantMap
@@ -21,7 +21,7 @@ class BufferSyncerPersister @Inject constructor(
   private val repository: BufferRepository,
 ) : BufferSyncerClientApi {
   override suspend fun update(properties: QVariantMap) {
-    val data = BufferSyncerDto.deserialize(properties)
+    val data = BufferSyncerDto.Serializer.deserialize(properties)
     repository.syncActivites(data.activities)
     repository.syncHighlightCounts(data.highlightCounts)
     repository.syncLastSeenMsgs(data.lastSeenMsg)
diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferViewConfigPersister.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferViewConfigPersister.kt
index d237e96..a60b2b0 100644
--- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferViewConfigPersister.kt
+++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/BufferViewConfigPersister.kt
@@ -9,6 +9,7 @@
 
 package de.justjanne.libquassel.backend
 
+import de.justjanne.libquassel.protocol.api.ObjectName
 import de.justjanne.libquassel.protocol.api.client.BufferViewConfigClientApi
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
@@ -16,19 +17,19 @@ import de.justjanne.libquassel.protocol.variant.QVariantMap
 import javax.inject.Inject
 
 class BufferViewConfigPersister @Inject constructor(): BufferViewConfigClientApi {
-  override suspend fun addBuffer(buffer: BufferId, pos: Int)  = Unit
-  override suspend fun moveBuffer(buffer: BufferId, pos: Int)  = Unit
-  override suspend fun removeBuffer(buffer: BufferId)  = Unit
-  override suspend fun removeBufferPermanently(buffer: BufferId)  = Unit
-  override suspend fun setBufferViewName(value: String)  = Unit
-  override suspend fun setAddNewBuffersAutomatically(value: Boolean)  = Unit
-  override suspend fun setAllowedBufferTypes(value: Int)  = Unit
-  override suspend fun setDisableDecoration(value: Boolean)  = Unit
-  override suspend fun setHideInactiveBuffers(value: Boolean)  = Unit
-  override suspend fun setHideInactiveNetworks(value: Boolean)  = Unit
-  override suspend fun setMinimumActivity(value: Int)  = Unit
-  override suspend fun setNetworkId(value: NetworkId)  = Unit
-  override suspend fun setShowSearch(value: Boolean)  = Unit
-  override suspend fun setSortAlphabetically(value: Boolean)  = Unit
-  override suspend fun update(properties: QVariantMap)  = Unit
+  override suspend fun addBuffer(objectName: ObjectName, buffer: BufferId, pos: Int)  = Unit
+  override suspend fun moveBuffer(objectName: ObjectName, buffer: BufferId, pos: Int)  = Unit
+  override suspend fun removeBuffer(objectName: ObjectName, buffer: BufferId)  = Unit
+  override suspend fun removeBufferPermanently(objectName: ObjectName, buffer: BufferId)  = Unit
+  override suspend fun setBufferViewName(objectName: ObjectName, value: String)  = Unit
+  override suspend fun setAddNewBuffersAutomatically(objectName: ObjectName, value: Boolean)  = Unit
+  override suspend fun setAllowedBufferTypes(objectName: ObjectName, value: Int)  = Unit
+  override suspend fun setDisableDecoration(objectName: ObjectName, value: Boolean)  = Unit
+  override suspend fun setHideInactiveBuffers(objectName: ObjectName, value: Boolean)  = Unit
+  override suspend fun setHideInactiveNetworks(objectName: ObjectName, value: Boolean)  = Unit
+  override suspend fun setMinimumActivity(objectName: ObjectName, value: Int)  = Unit
+  override suspend fun setNetworkId(objectName: ObjectName, value: NetworkId)  = Unit
+  override suspend fun setShowSearch(objectName: ObjectName, value: Boolean)  = Unit
+  override suspend fun setSortAlphabetically(objectName: ObjectName, value: Boolean)  = Unit
+  override suspend fun update(objectName: ObjectName, properties: QVariantMap)  = Unit
 }
diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/IrcListHelperPersister.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/IrcListHelperPersister.kt
index 0484ff3..5428185 100644
--- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/IrcListHelperPersister.kt
+++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/backend/IrcListHelperPersister.kt
@@ -13,10 +13,12 @@ import de.justjanne.libquassel.protocol.api.client.IrcListHelperClientApi
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
 import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
 import javax.inject.Inject
 
 class IrcListHelperPersister @Inject constructor(): IrcListHelperClientApi {
   override suspend fun receiveChannelList(netId: NetworkId, channelFilters: QStringList, channels: QVariantList)  = Unit 
   override suspend fun reportError(error: String?)  = Unit 
   override suspend fun reportFinishedList(netId: NetworkId)  = Unit
+  override suspend fun update(properties: QVariantMap) = Unit
 }
diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/connection/ClientSessionHandler.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/connection/ClientSessionHandler.kt
index c470ea8..09fe4ff 100644
--- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/connection/ClientSessionHandler.kt
+++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/connection/ClientSessionHandler.kt
@@ -36,8 +36,20 @@ class ClientSessionHandler(
 
     val initRequests = listOf(
       Pair("AliasManager", ""),
-      Pair("BufferSyncer", "")
+      Pair("BufferSyncer", ""),
+      Pair("BufferViewManager", ""),
+      Pair("CoreInfo", ""),
+      Pair("IgnoreListManager", ""),
+      Pair("HighlightRuleManager", ""),
+      Pair("IrcListHelper", ""),
+      Pair("NetworkConfig", "GlobalNetworkConfig"),
+      Pair("BacklogManager", ""),
     )
+      /*
+      .plus(handshake.sessionInit.networkIds.map { Pair("Network", "${it.id}") })
+      .plus(handshake.sessionInit.identities.map { Pair("Identity", "${it.identityId.id}") })
+      .plus(handshake.sessionInit.identities.map { Pair("CertManager", "${it.identityId.id}") })
+       */
 
     bufferRepository.sync(handshake.sessionInit.bufferInfos)
 
@@ -47,8 +59,10 @@ class ClientSessionHandler(
     }
 
     while (true) {
+      println("Reading:")
       val message = connection.read { SignalProxyMessageSerializer.deserialize(it, handshake.clientInitAck.featureSet) }
       println("Receive: $message")
+      println("Waiting: ${toInit.value}")
       when (message) {
         is SignalProxyMessage.HeartBeat -> connection.send(SignalProxyMessage.HeartBeatReply(message.timestamp))
         is SignalProxyMessage.HeartBeatReply -> Unit
@@ -60,6 +74,7 @@ class ClientSessionHandler(
         is SignalProxyMessage.Rpc -> rpc.invoke(message.slotName, message.params)
         is SignalProxyMessage.Sync -> sync.invoke(message.className, ObjectName(message.objectName), message.slotName, message.params)
       }
+      println("Finished")
     }
   }
 }
diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt
index bacd285..f8650bb 100644
--- a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt
+++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/QuasselApiTest.kt
@@ -82,7 +82,6 @@ import de.justjanne.libquassel.protocol.connection.ProtocolVersion
 import de.justjanne.libquassel.protocol.exceptions.RpcInvocationFailedException
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.CoroutineChannel
-import de.justjanne.libquassel.protocol.models.BufferInfo
 import de.justjanne.libquassel.protocol.models.HandshakeMessage
 import de.justjanne.libquassel.protocol.models.SignalProxyMessage
 import de.justjanne.libquassel.protocol.models.ids.BufferId
@@ -94,7 +93,6 @@ import de.justjanne.libquassel.protocol.variant.QVariant_
 import de.justjanne.libquassel.protocol.variant.qVariant
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.TimeoutCancellationException
 import kotlinx.coroutines.cancelAndJoin
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.collectLatest
@@ -103,9 +101,7 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withTimeout
 import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
 import java.net.InetSocketAddress
-import java.nio.channels.ClosedByInterruptException
 import javax.inject.Inject
 import javax.inject.Singleton
 import kotlin.test.assertFails
@@ -137,6 +133,19 @@ class ProxyImpl @Inject constructor(
   }
 }
 
+@Singleton
+class OfflineProxyImpl @Inject constructor() : Proxy {
+  override suspend fun sync(className: String, objectName: ObjectName, function: String, params: QVariantList) {
+    val message = SignalProxyMessage.Sync(className, objectName.objectName, function, params)
+    println("Send: $message")
+  }
+
+  override suspend fun rpc(function: String, params: QVariantList) {
+    val message = SignalProxyMessage.Rpc(function, params)
+    println("Send: $message")
+  }
+}
+
 @Module
 interface ClientModule {
   @Binds fun bindAliasManagerPersister(impl: AliasManagerPersister): AliasManagerClientApi
@@ -155,9 +164,18 @@ interface ClientModule {
   @Binds fun bindNetworkConfigPersister(impl: NetworkConfigPersister): NetworkConfigClientApi
   @Binds fun bindNetworkPersister(impl: NetworkPersister): NetworkClientApi
   @Binds fun bindRpcPersister(impl: RpcPersister): RpcClientApi
+}
+
+@Module
+interface OnlineClientModule {
   @Binds fun bindProxy(impl: ProxyImpl): Proxy
 }
 
+@Module
+interface OfflineClientModule {
+  @Binds fun bindProxy(impl: OfflineProxyImpl): Proxy
+}
+
 @Module
 class DatabaseModule {
   @Singleton
@@ -194,7 +212,7 @@ class QuasselApiClient @Inject constructor(
 )
 
 @Singleton
-@Component(modules = [ClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class])
+@Component(modules = [ClientModule::class, OnlineClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class])
 interface ClientComponent {
   fun db(): AppDatabase
   fun sync(): SyncHandler
@@ -209,10 +227,19 @@ interface ClientComponent {
   }
 }
 
+@Singleton
+@Component(modules = [ClientModule::class, OfflineClientModule::class, DatabaseModule::class, ClientDispatcherModule::class, ClientProxyModule::class])
+interface OfflineClientComponent {
+  fun db(): AppDatabase
+  fun sync(): SyncHandler
+  fun rpc(): RpcDispatcher
+  fun api(): QuasselApiClient
+}
+
 class QuasselApiTest {
   @Test
   fun test() = runBlocking {
-    val client = DaggerClientComponent.builder().build()
+    val client = DaggerOfflineClientComponent.builder().build()
     client.sync().invoke(
       "AliasManager",
       ObjectName(""),
@@ -300,15 +327,16 @@ class QuasselApiTest {
     launch {
       sessionHandler.handle(connection)
     }
-    withTimeout(2.seconds) {
+    withTimeout(20.seconds) {
       sessionHandler.toInit.first { it != null && it.isEmpty() }
     }
     val bufferInfo = handshake.sessionInit.bufferInfos.first { it.bufferName == "#quassel-test" }
-    di.api().rpc.sendInput(bufferInfo, "/SAY Test from libquassel?")
-    delay(15.seconds)
+    di.api().rpc.sendInput(bufferInfo, "/PRINT Test from libquassel?")
+    delay(1.seconds)
     channel.close()
     println(di.db().alias().getAll())
     println(di.db().buffer().getAll())
+    println(di.db().message().getAll())
     Unit
   }
 }
diff --git a/libquassel-persistence/src/main/kotlin/de/justjanne/libquassel/persistence/MessageRepository.kt b/libquassel-persistence/src/main/kotlin/de/justjanne/libquassel/persistence/MessageRepository.kt
index 7cb353a..3187814 100644
--- a/libquassel-persistence/src/main/kotlin/de/justjanne/libquassel/persistence/MessageRepository.kt
+++ b/libquassel-persistence/src/main/kotlin/de/justjanne/libquassel/persistence/MessageRepository.kt
@@ -19,6 +19,12 @@ import kotlinx.coroutines.flow.Flow
 
 @Dao
 interface MessageRepository {
+  @Query("SELECT * FROM MessageEntity ORDER BY messageId ASC")
+  suspend fun getAll(): List<MessageEntity>
+
+  @Query("SELECT * FROM MessageEntity ORDER BY messageId ASC")
+  fun collectAll(): Flow<List<MessageEntity>>
+
   @Query("SELECT * FROM MessageEntity WHERE buffer = :buffer ORDER BY messageId ASC")
   suspend fun getAll(buffer: BufferId): List<MessageEntity>
 
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/AliasManagerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/AliasManagerDto.kt
new file mode 100644
index 0000000..de3036b
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/AliasManagerDto.kt
@@ -0,0 +1,66 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.QStringList
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+
+data class AliasManagerDto(
+  val aliases: List<AliasDto>
+) {
+  data class AliasDto(
+    val name: String,
+    val expansion: String,
+  )
+
+  object Serializer : SyncableSerializer<AliasManagerDto> {
+    override fun serialize(data: AliasManagerDto): QVariantMap = mapOf(
+      "Aliases" to qVariant(mapOf(
+        "names" to qVariant(data.aliases.map { it.name }, QtType.QStringList),
+        "expansions" to qVariant(data.aliases.map { it.expansion }, QtType.QStringList),
+      ), QtType.QVariantMap),
+    )
+
+    override fun deserialize(data: QVariantMap): AliasManagerDto = AliasManagerDto(
+      aliases = data["Aliases"].into<QVariantMap>()?.let { aliases ->
+        val names = aliases["names"].into<QStringList>().orEmpty().map { it ?: "" }
+        val expansions = aliases["expansions"].into<QStringList>().orEmpty().map { it ?: "" }
+        if (names.size != expansions.size) return@let null
+        names.indices.map { index ->
+          AliasDto(
+            name = names[index],
+            expansion = expansions[index],
+          )
+        }
+        names.zip(expansions, ::AliasDto)
+      }.orEmpty()
+    )
+  }
+
+  companion object {
+    val Defaults = AliasManagerDto(
+      aliases = listOf(
+        AliasDto("j", "/join $0"),
+        AliasDto("ns", "/quote nickserv $0"),
+        AliasDto("nickserv", "/quote nickserv $0"),
+        AliasDto("cs", "/quote chanserv $0"),
+        AliasDto("chanserv", "/quote chanserv $0"),
+        AliasDto("hs", "/quote hostserv $0"),
+        AliasDto("hostserv", "/quote hostserv $0"),
+        AliasDto("wii", "/whois $0 $0"),
+        AliasDto("back", "/quote away"),
+        AliasDto("raw", "/quote $0"),
+      )
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BacklogManagerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BacklogManagerDto.kt
new file mode 100644
index 0000000..bc134ff
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BacklogManagerDto.kt
@@ -0,0 +1,19 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data object BacklogManagerDto {
+  object Serializer : SyncableSerializer<BacklogManagerDto> {
+    override fun serialize(data: BacklogManagerDto): QVariantMap = emptyMap()
+    override fun deserialize(data: QVariantMap) = BacklogManagerDto
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferSyncerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferSyncerDto.kt
new file mode 100644
index 0000000..d8321d3
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferSyncerDto.kt
@@ -0,0 +1,85 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.ids.BufferId
+import de.justjanne.libquassel.protocol.models.ids.MsgId
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.models.types.QuasselType
+import de.justjanne.libquassel.protocol.util.collections.pairs
+import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+
+data class BufferSyncerDto(
+  val activities: Map<BufferId, Int>,
+  val highlightCounts: Map<BufferId, Int>,
+  val lastSeenMsg: Map<BufferId, MsgId>,
+  val markerLines: Map<BufferId, MsgId>,
+) {
+  object Serializer : SyncableSerializer<BufferSyncerDto> {
+    private inline fun <reified T> QVariantList.deserialize(): Map<BufferId, T> = pairs { key, value ->
+      Pair(
+        key.into<BufferId>() ?: return@pairs null,
+        value.into<T>() ?: return@pairs null
+      )
+    }.filterNotNull().toMap()
+
+    private inline fun <reified T> Map<BufferId, T>.serialize(type: QuasselType): QVariantList = flatMap {
+      listOf(
+        qVariant(it.key, QuasselType.BufferId),
+        qVariant(it.value, type),
+      )
+    }
+
+    private inline fun <reified T> Map<BufferId, T>.serialize(type: QtType): QVariantList = flatMap {
+      listOf(
+        qVariant(it.key, QuasselType.BufferId),
+        qVariant(it.value, type),
+      )
+    }
+
+    override fun serialize(data: BufferSyncerDto): QVariantMap = mapOf(
+      "Activities" to qVariant(
+        data.activities.serialize(QtType.Int),
+        QtType.QVariantList
+      ),
+      "HighlightCounts" to qVariant(
+        data.highlightCounts.serialize(QtType.Int),
+        QtType.QVariantList
+      ),
+      "LastSeenMsg" to qVariant(
+        data.lastSeenMsg.serialize(QuasselType.MsgId),
+        QtType.QVariantList
+      ),
+      "MarkerLines" to qVariant(
+        data.markerLines.serialize(QuasselType.MsgId),
+        QtType.QVariantList
+      ),
+    )
+
+    override fun deserialize(data: QVariantMap) = BufferSyncerDto(
+      activities = data["Activities"].into<QVariantList>()?.deserialize() ?: Defaults.activities,
+      highlightCounts = data["HighlightCounts"].into<QVariantList>()?.deserialize() ?: Defaults.highlightCounts,
+      lastSeenMsg = data["LastSeenMsg"].into<QVariantList>()?.deserialize() ?: Defaults.lastSeenMsg,
+      markerLines = data["MarkerLines"].into<QVariantList>()?.deserialize() ?: Defaults.markerLines,
+    )
+  }
+
+  companion object {
+    val Defaults = BufferSyncerDto(
+      activities = emptyMap(),
+      highlightCounts = emptyMap(),
+      lastSeenMsg = emptyMap(),
+      markerLines = emptyMap(),
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewConfigDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewConfigDto.kt
new file mode 100644
index 0000000..f508158
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewConfigDto.kt
@@ -0,0 +1,33 @@
+
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data class BufferViewConfigDto(
+  val `null`: Nothing,
+) {
+  object Serializer : SyncableSerializer<BufferViewConfigDto> {
+    override fun serialize(data: BufferViewConfigDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = BufferViewConfigDto(
+      TODO()
+    )
+  }
+
+  companion object {
+    val Defaults = BufferViewConfigDto(
+      TODO()
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewManagerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewManagerDto.kt
new file mode 100644
index 0000000..f43afda
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/BufferViewManagerDto.kt
@@ -0,0 +1,39 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+
+data class BufferViewManagerDto(
+  val ids: List<Int> ,
+) {
+  object Serializer : SyncableSerializer<BufferViewManagerDto> {
+    override fun serialize(data: BufferViewManagerDto): QVariantMap = mapOf(
+      "BufferViewIds" to qVariant(
+        data.ids.map { qVariant(it, QtType.Int) },
+        QtType.QVariantList,
+      )
+    )
+
+    override fun deserialize(data: QVariantMap) = BufferViewManagerDto(
+      data["BufferViewIds"].into<QVariantList>()?.mapNotNull { it.into<Int>() } ?: Defaults.ids
+    )
+  }
+
+  companion object {
+    val Defaults = BufferViewManagerDto(
+      ids = emptyList(),
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CertManagerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CertManagerDto.kt
new file mode 100644
index 0000000..29edd07
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CertManagerDto.kt
@@ -0,0 +1,32 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data class CertManagerDto(
+  val `null`: Nothing,
+) {
+  object Serializer : SyncableSerializer<CertManagerDto> {
+    override fun serialize(data: CertManagerDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = CertManagerDto(
+      TODO()
+    )
+  }
+
+  companion object {
+    val Defaults = CertManagerDto(
+      TODO()
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CoreInfoDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CoreInfoDto.kt
new file mode 100644
index 0000000..d5a7fa7
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/CoreInfoDto.kt
@@ -0,0 +1,87 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.QStringList
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+import org.threeten.bp.Instant
+
+data class CoreInfoDto(
+  val quasselVersion: String?,
+  val quasselBuildDate: String?,
+  val startTime: Instant?,
+  val sessionConnectedClients: Int?,
+  val sessionConnectedClientData: List<ClientDto>,
+) {
+  data class ClientDto(
+    val secure: Boolean?,
+    val remoteAddress: String?,
+    val id: Int?,
+    val features: UInt?,
+    val featureList: List<String>,
+    val connectedSince: Instant?,
+    val clientVersionDate: String?,
+    val clientVersion: String?,
+  ) {
+    object Serializer : SyncableSerializer<ClientDto> {
+      override fun serialize(data: ClientDto): QVariantMap = mapOf(
+        "secure" to qVariant(data.secure, QtType.Bool),
+        "remoteAddress" to qVariant(data.remoteAddress, QtType.QString),
+        "id" to qVariant(data.id, QtType.Int),
+        "features" to qVariant(data.features, QtType.UInt),
+        "featureList" to qVariant(data.featureList, QtType.QStringList),
+        "connectedSince" to qVariant(data.connectedSince, QtType.QDateTime),
+        "clientVersionDate" to qVariant(data.clientVersionDate, QtType.QString),
+        "clientVersion" to qVariant(data.clientVersion, QtType.QString),
+      )
+
+      override fun deserialize(data: QVariantMap) = ClientDto(
+        secure = data["secure"].into<Boolean>(),
+        remoteAddress = data["remoteAddress"].into<String>(),
+        id = data["id"].into<Int>(),
+        features = data["features"].into<UInt>(),
+        featureList = data["featureList"].into<QStringList>().orEmpty().filterNotNull(),
+        connectedSince = data["connectedSince"].into<Instant>(),
+        clientVersionDate = data["clientVersionDate"].into<String>(),
+        clientVersion = data["clientVersion"].into<String>(),
+      )
+    }
+  }
+
+  object Serializer : SyncableSerializer<CoreInfoDto> {
+    override fun serialize(data: CoreInfoDto): QVariantMap = mapOf(
+      "coreData" to qVariant(
+        mapOf(
+          "quasselVersion" to qVariant(data.quasselVersion, QtType.QString),
+          "quasselBuildDate" to qVariant(data.quasselBuildDate, QtType.QString),
+          "startTime" to qVariant(data.startTime, QtType.QDateTime),
+          "sessionConnectedClients" to qVariant(data.sessionConnectedClients, QtType.Int),
+          "sessionConnectedClientData" to qVariant(data.sessionConnectedClientData, QtType.QVariantList),
+        ),
+        QtType.QVariantMap,
+      )
+    )
+
+    override fun deserialize(data: QVariantMap) = data["coreData"].into<QVariantMap>().orEmpty().let { properties ->
+      CoreInfoDto(
+        quasselVersion = properties["quasselVersion"].into<String>(),
+        quasselBuildDate = properties["quasselBuildDate"].into<String>(),
+        startTime = properties["startTime"].into<Instant>(),
+        sessionConnectedClients = properties["sessionConnectedClients"].into<Int>(),
+        sessionConnectedClientData = properties["sessionConnectedClientData"].into<QVariantList>()
+          ?.mapNotNull { it.into<QVariantMap>()?.let(ClientDto.Serializer::deserialize) }.orEmpty(),
+      )
+    }
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/HighlightRuleManagerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/HighlightRuleManagerDto.kt
new file mode 100644
index 0000000..ad030c1
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/HighlightRuleManagerDto.kt
@@ -0,0 +1,94 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.QStringList
+import de.justjanne.libquassel.protocol.models.rules.HighlightNickType
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+
+data class HighlightRuleManagerDto(
+  val rules: List<HighlightRuleDto>,
+  val highlightNick: HighlightNickType,
+  val nicksCaseSensitive: Boolean,
+) {
+  data class HighlightRuleDto(
+    val id: Int,
+    val name: String,
+    val isRegEx: Boolean,
+    val isCaseSensitive: Boolean,
+    val isEnabled: Boolean,
+    val isInverse: Boolean,
+    val sender: String,
+    val channel: String,
+  )
+
+  object Serializer : SyncableSerializer<HighlightRuleManagerDto> {
+    override fun serialize(data: HighlightRuleManagerDto): QVariantMap = mapOf(
+      "highlightNick" to qVariant(data.highlightNick.value, QtType.Int),
+      "nicksCaseSensitive" to qVariant(data.nicksCaseSensitive, QtType.Bool),
+      "HighlightRuleList" to qVariant(mapOf(
+        "id" to qVariant(data.rules.map { qVariant(it.id, QtType.Int) }, QtType.QVariantList),
+        "name" to qVariant(data.rules.map { it.name }, QtType.QStringList),
+        "isRegEx" to qVariant(data.rules.map { qVariant(it.isRegEx, QtType.Bool) }, QtType.QVariantList),
+        "isCaseSensitive" to qVariant(data.rules.map { qVariant(it.isCaseSensitive, QtType.Bool) }, QtType.QVariantList),
+        "isEnabled" to qVariant(data.rules.map { qVariant(it.isEnabled, QtType.Bool) }, QtType.QVariantList),
+        "isInverse" to qVariant(data.rules.map { qVariant(it.isInverse, QtType.Bool) }, QtType.QVariantList),
+        "sender" to qVariant(data.rules.map { it.sender }, QtType.QStringList),
+        "channel" to qVariant(data.rules.map { it.channel }, QtType.QStringList),
+      ), QtType.QVariantMap),
+    )
+
+    override fun deserialize(data: QVariantMap) = HighlightRuleManagerDto(
+      highlightNick = data["highlightNick"].into<Int>()?.let(HighlightNickType::of) ?: Defaults.highlightNick,
+      nicksCaseSensitive = data["nicksCaseSensitive"].into<Boolean>(Defaults.nicksCaseSensitive),
+      rules = data["HighlightRuleList"].into<QVariantMap>()?.let { rules ->
+        val id = rules["id"].into<QVariantList>().orEmpty().map { it.into<Int>(0) }
+        val name = rules["name"].into<QStringList>().orEmpty().map { it ?: "" }
+        val isRegEx = rules["isRegEx"].into<QVariantList>().orEmpty().map { it.into<Boolean>(false) }
+        val isCaseSensitive = rules["isCaseSensitive"].into<QVariantList>().orEmpty().map { it.into<Boolean>(false) }
+        val isEnabled = rules["isEnabled"].into<QVariantList>().orEmpty().map { it.into<Boolean>(false) }
+        val isInverse = rules["isInverse"].into<QVariantList>().orEmpty().map { it.into<Boolean>(false) }
+        val sender = rules["sender"].into<QStringList>().orEmpty().map { it ?: "" }
+        val channel = rules["channel"].into<QStringList>().orEmpty().map { it ?: "" }
+        if (id.size != name.size) return@let null
+        if (id.size != isRegEx.size) return@let null
+        if (id.size != isCaseSensitive.size) return@let null
+        if (id.size != isEnabled.size) return@let null
+        if (id.size != isInverse.size) return@let null
+        if (id.size != sender.size) return@let null
+        if (id.size != channel.size) return@let null
+        id.indices.map { index ->
+          HighlightRuleDto(
+            id = id[index],
+            name = name[index],
+            isRegEx = isRegEx[index],
+            isCaseSensitive = isCaseSensitive[index],
+            isEnabled = isEnabled[index],
+            isInverse = isInverse[index],
+            sender = sender[index],
+            channel = channel[index],
+          )
+        }
+      }.orEmpty()
+    )
+  }
+
+  companion object {
+    val Defaults = HighlightRuleManagerDto(
+      highlightNick = HighlightNickType.CurrentNick,
+      nicksCaseSensitive = false,
+      rules = emptyList(),
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IdentityDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IdentityDto.kt
new file mode 100644
index 0000000..bf950d6
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IdentityDto.kt
@@ -0,0 +1,87 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.ids.IdentityId
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data class IdentityDto(
+  val identityId: IdentityId,
+  val identityName: String,
+  val realName: String,
+  val nicks: List<String>,
+  val awayNick: String,
+  val awayNickEnabled: Boolean,
+  val awayReason: String,
+  val awayReasonEnabled: Boolean,
+  val autoAwayEnabled: Boolean,
+  val autoAwayTime: Int,
+  val autoAwayReason: String,
+  val autoAwayReasonEnabled: Boolean,
+  val detachAwayEnabled: Boolean,
+  val detachAwayReason: String,
+  val detachAwayReasonEnabled: Boolean,
+  val ident: String,
+  val kickReason: String,
+  val partReason: String,
+  val quitReason: String,
+) {
+  object Serializer : SyncableSerializer<IdentityDto> {
+    override fun serialize(data: IdentityDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = IdentityDto(
+      identityId = TODO(),
+      identityName = TODO(),
+      realName = TODO(),
+      nicks = TODO(),
+      awayNick = TODO(),
+      awayNickEnabled = TODO(),
+      awayReason = TODO(),
+      awayReasonEnabled = TODO(),
+      autoAwayEnabled = TODO(),
+      autoAwayTime = TODO(),
+      autoAwayReason = TODO(),
+      autoAwayReasonEnabled = TODO(),
+      detachAwayEnabled = TODO(),
+      detachAwayReason = TODO(),
+      detachAwayReasonEnabled = TODO(),
+      ident = TODO(),
+      kickReason = TODO(),
+      partReason = TODO(),
+      quitReason = TODO(),
+    )
+  }
+
+  companion object {
+    val Defaults = IdentityDto(
+      identityId = IdentityId(-1),
+      identityName = "<empty>",
+      realName = "",
+      nicks = listOf("quassel"),
+      awayNick = "",
+      awayNickEnabled = false,
+      awayReason = "Gone fishing.",
+      awayReasonEnabled = true,
+      autoAwayEnabled = false,
+      autoAwayTime = 10,
+      autoAwayReason = "Not here. No really. not here!",
+      autoAwayReasonEnabled = false,
+      detachAwayEnabled = false,
+      detachAwayReason = "All Quassel clients vanished from the face of the earth...",
+      detachAwayReasonEnabled = false,
+      ident = "quassel",
+      kickReason = "Kindergarten is elsewhere!",
+      partReason = "http://quassel-irc.org - Chat comfortably. Anywhere.",
+      quitReason = "http://quassel-irc.org - Chat comfortably. Anywhere.",
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IgnoreListManagerDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IgnoreListManagerDto.kt
new file mode 100644
index 0000000..52d7262
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IgnoreListManagerDto.kt
@@ -0,0 +1,95 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.QStringList
+import de.justjanne.libquassel.protocol.models.rules.IgnoreType
+import de.justjanne.libquassel.protocol.models.rules.ScopeType
+import de.justjanne.libquassel.protocol.models.rules.StrictnessType
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.variant.QVariantList
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+
+data class IgnoreListManagerDto(
+  val rules: List<IgnoreRuleDto>,
+) {
+  data class IgnoreRuleDto(
+    val ignoreType: IgnoreType,
+    val ignoreRule: String,
+    val isRegEx: Boolean,
+    val strictness: StrictnessType,
+    val scope: ScopeType,
+    val scopeRule: String,
+    val isActive: Boolean,
+  ) {
+    companion object {
+      val Defaults = IgnoreRuleDto(
+        ignoreType = IgnoreType.SenderIgnore,
+        ignoreRule = "",
+        isRegEx = false,
+        strictness = StrictnessType.UnmatchedStrictness,
+        scope = ScopeType.GlobalScope,
+        scopeRule = "",
+        isActive = false,
+      )
+    }
+  }
+
+  object Serializer : SyncableSerializer<IgnoreListManagerDto> {
+    override fun serialize(data: IgnoreListManagerDto): QVariantMap = mapOf(
+      "IgnoreList" to qVariant(mapOf(
+        "ignoreType" to qVariant(data.rules.map { qVariant(it.ignoreType.value, QtType.Int) }, QtType.QVariantList),
+        "ignoreRule" to qVariant(data.rules.map { it.ignoreRule }, QtType.QStringList),
+        "isRegEx" to qVariant(data.rules.map { qVariant(it.isRegEx, QtType.Bool) }, QtType.QVariantList),
+        "strictness" to qVariant(data.rules.map { qVariant(it.strictness.value, QtType.Int) }, QtType.QVariantList),
+        "scope" to qVariant(data.rules.map { qVariant(it.scope.value, QtType.Int) }, QtType.QVariantList),
+        "scopeRule" to qVariant(data.rules.map { it.scopeRule }, QtType.QStringList),
+        "isActive" to qVariant(data.rules.map { qVariant(it.isActive, QtType.Bool) }, QtType.QVariantList),
+      ), QtType.QVariantMap),
+    )
+
+    override fun deserialize(data: QVariantMap) = IgnoreListManagerDto(
+      rules = data["IgnoreList"].into<QVariantMap>()?.let { rules ->
+        val ignoreType = rules["ignoreType"].into<QVariantList>().orEmpty().map { it.into<Int>() }
+        val ignoreRule = rules["ignoreRule"].into<QStringList>().orEmpty().map { it ?: "" }
+        val isRegEx = rules["isRegEx"].into<QVariantList>().orEmpty().map { it.into<Boolean>(IgnoreRuleDto.Defaults.isRegEx) }
+        val strictness = rules["strictness"].into<QVariantList>().orEmpty().map { it.into<Int>() }
+        val scope = rules["scope"].into<QVariantList>().orEmpty().map { it.into<Int>() }
+        val scopeRule = rules["scopeRule"].into<QStringList>().orEmpty().map { it ?: "" }
+        val isActive = rules["isActive"].into<QVariantList>().orEmpty().map { it.into<Boolean>(IgnoreRuleDto.Defaults.isActive) }
+        if (ignoreRule.size != ignoreType.size) return@let null
+        if (ignoreRule.size != isRegEx.size) return@let null
+        if (ignoreRule.size != strictness.size) return@let null
+        if (ignoreRule.size != scope.size) return@let null
+        if (ignoreRule.size != scopeRule.size) return@let null
+        if (ignoreRule.size != isActive.size) return@let null
+        ignoreRule.indices.map { index ->
+          IgnoreRuleDto(
+            ignoreType = ignoreType[index]?.let(IgnoreType::of) ?: IgnoreRuleDto.Defaults.ignoreType,
+            ignoreRule = ignoreRule[index],
+            isRegEx = isRegEx[index],
+            strictness = strictness[index]?.let(StrictnessType::of) ?: IgnoreRuleDto.Defaults.strictness,
+            scope = scope[index]?.let(ScopeType::of) ?: IgnoreRuleDto.Defaults.scope,
+            scopeRule = scopeRule[index],
+            isActive = isActive[index],
+          )
+        }
+      }.orEmpty()
+    )
+  }
+
+  companion object {
+    val Defaults = IgnoreListManagerDto(
+      rules = emptyList(),
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcChannelDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcChannelDto.kt
new file mode 100644
index 0000000..5bc18f9
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcChannelDto.kt
@@ -0,0 +1,48 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.network.ChannelModes
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data class IrcChannelDto(
+  val name: String,
+  val topic: String,
+  val password: String,
+  val encrypted: Boolean,
+  val channelModes: ChannelModes,
+  val userModes: Map<String, Set<Char>>,
+) {
+  object Serializer : SyncableSerializer<IrcChannelDto> {
+    override fun serialize(data: IrcChannelDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = IrcChannelDto(
+      name = TODO(),
+      topic = TODO(),
+      password = TODO(),
+      encrypted = TODO(),
+      channelModes = TODO(),
+      userModes = TODO()
+    )
+  }
+
+  companion object {
+    val Defaults = IrcChannelDto(
+      name = "",
+      topic = "",
+      password = "",
+      encrypted = false,
+      channelModes = ChannelModes(),
+      userModes = emptyMap(),
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcListHelperDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcListHelperDto.kt
new file mode 100644
index 0000000..bcf0a1e
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcListHelperDto.kt
@@ -0,0 +1,20 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data object IrcListHelperDto {
+  object Serializer : SyncableSerializer<IrcListHelperDto> {
+    override fun serialize(data: IrcListHelperDto): QVariantMap = emptyMap()
+    override fun deserialize(data: QVariantMap) = IrcListHelperDto
+  }
+}
+
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcUserDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcUserDto.kt
new file mode 100644
index 0000000..6aaf8ad
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/IrcUserDto.kt
@@ -0,0 +1,81 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import org.threeten.bp.Instant
+
+data class IrcUserDto(
+  val nick: String,
+  val user: String,
+  val host: String,
+  val realName: String,
+  val account: String,
+  val away: Boolean,
+  val awayMessage: String,
+  val idleTime: Instant,
+  val loginTime: Instant,
+  val server: String,
+  val ircOperator: String,
+  val lastAwayMessageTime: Instant,
+  val whoisServiceReply: String,
+  val suserHost: String,
+  val encrypted: Boolean,
+  val channels: Set<String>,
+  val userModes: Set<Char>,
+) {
+  object Serializer : SyncableSerializer<IrcUserDto> {
+    override fun serialize(data: IrcUserDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = IrcUserDto(
+      nick = TODO(),
+      user = TODO(),
+      host = TODO(),
+      realName = TODO(),
+      account = TODO(),
+      away = TODO(),
+      awayMessage = TODO(),
+      idleTime = TODO(),
+      loginTime = TODO(),
+      server = TODO(),
+      ircOperator = TODO(),
+      lastAwayMessageTime = TODO(),
+      whoisServiceReply = TODO(),
+      suserHost = TODO(),
+      encrypted = TODO(),
+      channels = TODO(),
+      userModes = TODO()
+    )
+  }
+
+  companion object {
+    val Defaults = IrcUserDto(
+      nick = "",
+      user = "",
+      host = "",
+      realName = "",
+      account = "",
+      away = false,
+      awayMessage = "",
+      idleTime = Instant.EPOCH,
+      loginTime = Instant.EPOCH,
+      server = "",
+      ircOperator = "",
+      lastAwayMessageTime = Instant.EPOCH,
+      whoisServiceReply = "",
+      suserHost = "",
+      encrypted = false,
+      channels = emptySet(),
+      userModes = emptySet(),
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkConfigDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkConfigDto.kt
new file mode 100644
index 0000000..461484c
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkConfigDto.kt
@@ -0,0 +1,63 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.types.QtType
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+import de.justjanne.libquassel.protocol.variant.into
+import de.justjanne.libquassel.protocol.variant.qVariant
+
+data class NetworkConfigDto(
+  val pingTimeoutEnabled: Boolean,
+  val pingInterval: Int,
+  val maxPingCount: Int,
+  val autoWhoEnabled: Boolean,
+  val autoWhoInterval: Int,
+  val autoWhoNickLimit: Int,
+  val autoWhoDelay: Int,
+  val standardCtcp: Boolean,
+) {
+  object Serializer : SyncableSerializer<NetworkConfigDto> {
+    override fun serialize(data: NetworkConfigDto): QVariantMap = mapOf(
+      "pingTimeoutEnabled" to qVariant(data.pingTimeoutEnabled, QtType.Bool),
+      "pingInterval" to qVariant(data.pingInterval, QtType.Int),
+      "maxPingCount" to qVariant(data.maxPingCount, QtType.Int),
+      "autoWhoEnabled" to qVariant(data.autoWhoEnabled, QtType.Bool),
+      "autoWhoInterval" to qVariant(data.autoWhoInterval, QtType.Int),
+      "autoWhoNickLimit" to qVariant(data.autoWhoNickLimit, QtType.Int),
+      "autoWhoDelay" to qVariant(data.autoWhoDelay, QtType.Int),
+      "standardCtcp" to qVariant(data.standardCtcp, QtType.Bool),
+    )
+
+    override fun deserialize(data: QVariantMap) = NetworkConfigDto(
+      pingTimeoutEnabled = data["pingTimeoutEnabled"].into<Boolean>(Defaults.pingTimeoutEnabled),
+      pingInterval = data["pingInterval"].into<Int>(Defaults.pingInterval),
+      maxPingCount = data["maxPingCount"].into<Int>(Defaults.maxPingCount),
+      autoWhoEnabled = data["autoWhoEnabled"].into<Boolean>(Defaults.autoWhoEnabled),
+      autoWhoInterval = data["autoWhoInterval"].into<Int>(Defaults.autoWhoInterval),
+      autoWhoNickLimit = data["autoWhoNickLimit"].into<Int>(Defaults.autoWhoNickLimit),
+      autoWhoDelay = data["autoWhoDelay"].into<Int>(Defaults.autoWhoDelay),
+      standardCtcp = data["standardCtcp"].into<Boolean>(Defaults.standardCtcp),
+    )
+  }
+
+  companion object {
+    val Defaults = NetworkConfigDto(
+      pingTimeoutEnabled = true,
+      pingInterval = 30,
+      maxPingCount = 6,
+      autoWhoEnabled = true,
+      autoWhoInterval = 90,
+      autoWhoNickLimit = 200,
+      autoWhoDelay = 5,
+      standardCtcp = false
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkDto.kt
new file mode 100644
index 0000000..d78cafa
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkDto.kt
@@ -0,0 +1,32 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data class NetworkDto(
+  val `null`: Nothing,
+) {
+  object Serializer : SyncableSerializer<NetworkDto> {
+    override fun serialize(data: NetworkDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = NetworkDto(
+      TODO()
+    )
+  }
+
+  companion object {
+    val Defaults = NetworkDto(
+      TODO()
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkInfoDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkInfoDto.kt
new file mode 100644
index 0000000..11c4376
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/NetworkInfoDto.kt
@@ -0,0 +1,107 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.models.ids.IdentityId
+import de.justjanne.libquassel.protocol.models.ids.NetworkId
+import de.justjanne.libquassel.protocol.models.network.NetworkServer
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+data class NetworkInfoDto(
+  val networkId: NetworkId,
+  val networkName: String,
+  val identity: IdentityId,
+  val useCustomEncodings: Boolean,
+  val codecForServer: String,
+  val codecForEncoding: String,
+  val codecForDecoding: String,
+  val serverList: List<NetworkServer>,
+  val useRandomServer: Boolean,
+  val perform: List<String>,
+  val useAutoIdentify: Boolean,
+  val autoIdentifyService: String,
+  val autoIdentifyPassword: String,
+  val useSasl: Boolean,
+  val saslAccount: String,
+  val saslPassword: String,
+  val useAutoReconnect: Boolean,
+  val autoReconnectInterval: UInt,
+  val autoReconnectRetries: UShort,
+  val unlimitedReconnectRetries: Boolean,
+  val rejoinChannels: Boolean,
+  val useCustomMessageRate: Boolean,
+  val messageRateBurstSize: UInt,
+  val messageRateDelay: UInt,
+  val unlimitedMessageRate: Boolean,
+) {
+  object Serializer : SyncableSerializer<NetworkInfoDto> {
+    override fun serialize(data: NetworkInfoDto): QVariantMap = mapOf(
+      TODO()
+    )
+
+    override fun deserialize(data: QVariantMap) = NetworkInfoDto(
+      networkId = TODO(),
+      networkName = TODO(),
+      identity = TODO(),
+      useCustomEncodings = TODO(),
+      codecForServer = TODO(),
+      codecForEncoding = TODO(),
+      codecForDecoding = TODO(),
+      serverList = TODO(),
+      useRandomServer = TODO(),
+      perform = TODO(),
+      useAutoIdentify = TODO(),
+      autoIdentifyService = TODO(),
+      autoIdentifyPassword = TODO(),
+      useSasl = TODO(),
+      saslAccount = TODO(),
+      saslPassword = TODO(),
+      useAutoReconnect = TODO(),
+      autoReconnectInterval = TODO(),
+      autoReconnectRetries = TODO(),
+      unlimitedReconnectRetries = TODO(),
+      rejoinChannels = TODO(),
+      useCustomMessageRate = TODO(),
+      messageRateBurstSize = TODO(),
+      messageRateDelay = TODO(),
+      unlimitedMessageRate = TODO()
+    )
+  }
+
+  companion object {
+    val Defaults = NetworkInfoDto(
+      networkId = NetworkId(-1),
+      networkName = "",
+      identity = IdentityId(-1),
+      useCustomEncodings = false,
+      codecForServer = "UTF_8",
+      codecForEncoding = "UTF_8",
+      codecForDecoding = "UTF_8",
+      serverList = emptyList(),
+      useRandomServer = false,
+      perform = emptyList(),
+      useAutoIdentify = false,
+      autoIdentifyService = "",
+      autoIdentifyPassword = "",
+      useSasl = false,
+      saslAccount = "",
+      saslPassword = "",
+      useAutoReconnect = true,
+      autoReconnectInterval = 0u,
+      autoReconnectRetries = 0u,
+      unlimitedReconnectRetries = true,
+      rejoinChannels = true,
+      useCustomMessageRate = false,
+      messageRateBurstSize = 0u,
+      messageRateDelay = 0u,
+      unlimitedMessageRate = false,
+    )
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/SyncableSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/SyncableSerializer.kt
new file mode 100644
index 0000000..201fcd6
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/dto/SyncableSerializer.kt
@@ -0,0 +1,17 @@
+/*
+ * libquassel
+ * Copyright (c) 2025 Janne Mareike Koschinski
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package de.justjanne.libquassel.protocol.dto
+
+import de.justjanne.libquassel.protocol.variant.QVariantMap
+
+interface SyncableSerializer<T> {
+  fun serialize(data: T): QVariantMap
+  fun deserialize(data: QVariantMap): T
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/HandshakeMessage.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/HandshakeMessage.kt
index 1a5db8b..16f93d1 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/HandshakeMessage.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/HandshakeMessage.kt
@@ -9,9 +9,9 @@
 
 package de.justjanne.libquassel.protocol.models
 
+import de.justjanne.libquassel.protocol.dto.IdentityDto
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
 import de.justjanne.libquassel.protocol.models.setup.BackendInfo
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/SignalProxyMessage.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/SignalProxyMessage.kt
index 6280cb1..97bc598 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/SignalProxyMessage.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/SignalProxyMessage.kt
@@ -99,7 +99,7 @@ sealed class SignalProxyMessage {
     val initData: QVariantMap,
   ) : SignalProxyMessage() {
     override fun toString(): String {
-      return "InitData::$className($objectName)"
+      return "InitData::$className/$objectName(${initData.toString()})"
     }
   }
 
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcChannelDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcChannelDto.kt
deleted file mode 100644
index c344858..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcChannelDto.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2024 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.models.network
-
-import de.justjanne.libquassel.protocol.models.ids.IdentityId
-
-data class IrcChannelDto(
-  val name: String,
-  val topic: String = "",
-  val password: String = "",
-  val encrypted: Boolean = false,
-  val channelModes: ChannelModes = ChannelModes(),
-  val userModes: Map<String, Set<Char>> = emptyMap(),
-)
-
-data class IdentityDto(
-  val identityId: IdentityId = IdentityId(-1),
-  val identityName: String = "<empty>",
-  val realName: String = "",
-  val nicks: List<String> = listOf("quassel"),
-  val awayNick: String = "",
-  val awayNickEnabled: Boolean = false,
-  val awayReason: String = "Gone fishing.",
-  val awayReasonEnabled: Boolean = true,
-  val autoAwayEnabled: Boolean = false,
-  val autoAwayTime: Int = 10,
-  val autoAwayReason: String = "Not here. No really. not here!",
-  val autoAwayReasonEnabled: Boolean = false,
-  val detachAwayEnabled: Boolean = false,
-  val detachAwayReason: String = "All Quassel clients vanished from the face of the earth...",
-  val detachAwayReasonEnabled: Boolean = false,
-  val ident: String = "quassel",
-  val kickReason: String = "Kindergarten is elsewhere!",
-  val partReason: String = "http://quassel-irc.org - Chat comfortably. Anywhere.",
-  val quitReason: String = "http://quassel-irc.org - Chat comfortably. Anywhere.",
-)
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcUserDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcUserDto.kt
deleted file mode 100644
index fdf1641..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/IrcUserDto.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2024 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.models.network
-
-import org.threeten.bp.Instant
-
-data class IrcUserDto(
-  val nick: String,
-  val user: String,
-  val host: String,
-  val realName: String = "",
-  val account: String = "",
-  val away: Boolean = false,
-  val awayMessage: String = "",
-  val idleTime: Instant = Instant.EPOCH,
-  val loginTime: Instant = Instant.EPOCH,
-  val server: String = "",
-  val ircOperator: String = "",
-  val lastAwayMessageTime: Instant = Instant.EPOCH,
-  val whoisServiceReply: String = "",
-  val suserHost: String = "",
-  val encrypted: Boolean = false,
-  val channels: Set<String> = emptySet(),
-  val userModes: Set<Char> = emptySet(),
-)
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/NetworkInfoDto.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/NetworkInfoDto.kt
deleted file mode 100644
index a649435..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/network/NetworkInfoDto.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2024 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.models.network
-
-import de.justjanne.libquassel.protocol.models.ids.IdentityId
-import de.justjanne.libquassel.protocol.models.ids.NetworkId
-
-data class NetworkInfoDto(
-  val networkId: NetworkId = NetworkId(-1),
-  val networkName: String = "",
-  val identity: IdentityId = IdentityId(-1),
-  val useCustomEncodings: Boolean = false,
-  val codecForServer: String = "UTF_8",
-  val codecForEncoding: String = "UTF_8",
-  val codecForDecoding: String = "UTF_8",
-  val serverList: List<NetworkServer> = emptyList(),
-  val useRandomServer: Boolean = false,
-  val perform: List<String> = emptyList(),
-  val useAutoIdentify: Boolean = false,
-  val autoIdentifyService: String = "",
-  val autoIdentifyPassword: String = "",
-  val useSasl: Boolean = false,
-  val saslAccount: String = "",
-  val saslPassword: String = "",
-  val useAutoReconnect: Boolean = true,
-  val autoReconnectInterval: UInt = 0u,
-  val autoReconnectRetries: UShort = 0u,
-  val unlimitedReconnectRetries: Boolean = true,
-  val rejoinChannels: Boolean = true,
-  val useCustomMessageRate: Boolean = false,
-  val messageRateBurstSize: UInt = 0u,
-  val messageRateDelay: UInt = 0u,
-  val unlimitedMessageRate: Boolean = false,
-)
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/HighlightNickType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/HighlightNickType.kt
index 883d078..256b8a0 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/HighlightNickType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/HighlightNickType.kt
@@ -14,8 +14,7 @@ enum class HighlightNickType(
 ) {
   NoNick(0),
   CurrentNick(1),
-  AllNicks(2),
-  ;
+  AllNicks(2);
 
   companion object {
     private val values =
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/IgnoreType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/IgnoreType.kt
index e786518..549d646 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/IgnoreType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/IgnoreType.kt
@@ -14,8 +14,7 @@ enum class IgnoreType(
 ) {
   SenderIgnore(0),
   MessageIgnore(1),
-  CtcpIgnore(2),
-  ;
+  CtcpIgnore(2);
 
   companion object {
     private val values =
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/ScopeType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/ScopeType.kt
index 87ddcbd..c08d8e2 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/ScopeType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/ScopeType.kt
@@ -14,8 +14,7 @@ enum class ScopeType(
 ) {
   GlobalScope(0),
   NetworkScope(1),
-  ChannelScope(2),
-  ;
+  ChannelScope(2);
 
   companion object {
     private val values =
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/StrictnessType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/StrictnessType.kt
index 7bc8f00..00b33bb 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/StrictnessType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/rules/StrictnessType.kt
@@ -14,8 +14,7 @@ enum class StrictnessType(
 ) {
   UnmatchedStrictness(0),
   SoftStrictness(1),
-  HardStrictness(2),
-  ;
+  HardStrictness(2);
 
   companion object {
     private val values =
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt
index ea8c624..d088b46 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt
@@ -9,10 +9,10 @@
 
 package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.dto.IdentityDto
 import de.justjanne.libquassel.protocol.models.BufferInfo
 import de.justjanne.libquassel.protocol.models.HandshakeMessage
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
 import de.justjanne.libquassel.protocol.models.types.QtType
 import de.justjanne.libquassel.protocol.models.types.QuasselType
 import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt
index 53e44b5..a1539d4 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt
@@ -9,10 +9,10 @@
 
 package de.justjanne.libquassel.protocol.serializers.quassel
 
+import de.justjanne.libquassel.protocol.dto.IdentityDto
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
 import de.justjanne.libquassel.protocol.models.types.QtType
 import de.justjanne.libquassel.protocol.models.types.QuasselType
 import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt
index 0e474f6..d98d941 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt
@@ -9,10 +9,10 @@
 
 package de.justjanne.libquassel.protocol.serializers.quassel
 
+import de.justjanne.libquassel.protocol.dto.IrcChannelDto
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
 import de.justjanne.libquassel.protocol.models.network.ChannelModes
-import de.justjanne.libquassel.protocol.models.network.IrcChannelDto
 import de.justjanne.libquassel.protocol.models.types.QtType
 import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.QVariantMapSerializer
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt
index e4fea90..e5b1a69 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt
@@ -9,9 +9,9 @@
 
 package de.justjanne.libquassel.protocol.serializers.quassel
 
+import de.justjanne.libquassel.protocol.dto.IrcUserDto
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
-import de.justjanne.libquassel.protocol.models.network.IrcUserDto
 import de.justjanne.libquassel.protocol.models.types.QtType
 import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.QVariantMapSerializer
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializer.kt
index 441043c..7f23115 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializer.kt
@@ -9,12 +9,12 @@
 
 package de.justjanne.libquassel.protocol.serializers.quassel
 
+import de.justjanne.libquassel.protocol.dto.NetworkInfoDto
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.NetworkInfoDto
 import de.justjanne.libquassel.protocol.models.network.NetworkServer
 import de.justjanne.libquassel.protocol.models.types.QtType
 import de.justjanne.libquassel.protocol.models.types.QuasselType
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializerTest.kt
index 185724d..8640520 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializerTest.kt
@@ -9,13 +9,13 @@
 package de.justjanne.libquassel.protocol.serializers.handshake
 
 import de.justjanne.bitflags.of
+import de.justjanne.libquassel.protocol.dto.IdentityDto
 import de.justjanne.libquassel.protocol.models.BufferInfo
 import de.justjanne.libquassel.protocol.models.HandshakeMessage
 import de.justjanne.libquassel.protocol.models.flags.BufferType
 import de.justjanne.libquassel.protocol.models.ids.BufferId
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
 import de.justjanne.libquassel.protocol.testutil.byteBufferOf
 import de.justjanne.libquassel.protocol.testutil.handshakeSerializerTest
 import org.junit.jupiter.api.Tag
@@ -83,7 +83,7 @@ class SessionInitSerializerTest {
       HandshakeMessage.SessionInit(
         identities =
           listOf(
-            IdentityDto(
+            IdentityDto.Defaults.copy(
                 identityId = IdentityId(1),
             ),
           ),
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializerTest.kt
index c857f28..91a0418 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializerTest.kt
@@ -8,7 +8,7 @@
  */
 package de.justjanne.libquassel.protocol.serializers.quassel
 
-import de.justjanne.libquassel.protocol.models.network.IrcChannelDto
+import de.justjanne.libquassel.protocol.dto.IrcChannelDto
 import de.justjanne.libquassel.protocol.models.types.QuasselType
 import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer
 import de.justjanne.libquassel.protocol.testutil.byteBufferOf
@@ -30,7 +30,7 @@ class IrcChannelSerializerTest {
   @Test
   fun testNormal() = primitiveSerializerTest(
       IrcChannelSerializer as PrimitiveSerializer<IrcChannelDto>,
-      IrcChannelDto(
+      IrcChannelDto.Defaults.copy(
             name = "#quassel",
       ),
       encoded = byteBufferOf(
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializerTest.kt
index 9d198f0..7726d9b 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializerTest.kt
@@ -8,11 +8,10 @@
  */
 package de.justjanne.libquassel.protocol.serializers.quassel
 
-import de.justjanne.libquassel.protocol.models.network.IrcUserDto
+import de.justjanne.libquassel.protocol.dto.IrcUserDto
 import de.justjanne.libquassel.protocol.models.types.QuasselType
 import de.justjanne.libquassel.protocol.testutil.byteBufferOf
 import de.justjanne.libquassel.protocol.testutil.primitiveSerializerTest
-import de.justjanne.libquassel.protocol.variant.QVariantMap
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Tag
 import org.junit.jupiter.api.Test
@@ -31,7 +30,7 @@ class IrcUserSerializerTest {
   fun testNormal() =
     primitiveSerializerTest(
       IrcUserSerializer,
-      IrcUserDto(
+      IrcUserDto.Defaults.copy(
         nick = "AzureDiamond",
         user = "~azure",
         host = "127.0.0.1",
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializerTest.kt
index 78d3fcc..5c6caec 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkInfoSerializerTest.kt
@@ -8,8 +8,8 @@
  */
 package de.justjanne.libquassel.protocol.serializers.quassel
 
+import de.justjanne.libquassel.protocol.dto.NetworkInfoDto
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.NetworkInfoDto
 import de.justjanne.libquassel.protocol.models.types.QuasselType
 import de.justjanne.libquassel.protocol.testutil.byteBufferOf
 import de.justjanne.libquassel.protocol.testutil.primitiveSerializerTest
@@ -31,7 +31,7 @@ class NetworkInfoSerializerTest {
   fun testEmptyMap() =
     primitiveSerializerTest(
       NetworkInfoSerializer,
-      NetworkInfoDto(),
+      NetworkInfoDto.Defaults,
       byteBufferOf(
         // no elements
         0x00u,
@@ -47,7 +47,7 @@ class NetworkInfoSerializerTest {
   fun testNormal() =
     primitiveSerializerTest(
       NetworkInfoSerializer,
-      NetworkInfoDto(
+      NetworkInfoDto.Defaults.copy(
         networkId = NetworkId(4),
       ),
       byteBufferOf(
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/signalproxy/RpcSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/signalproxy/RpcSerializerTest.kt
index 82ddb60..54c55da 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/signalproxy/RpcSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/signalproxy/RpcSerializerTest.kt
@@ -9,13 +9,8 @@
 package de.justjanne.libquassel.protocol.serializers.signalproxy
 
 import de.justjanne.libquassel.protocol.models.SignalProxyMessage
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
-import de.justjanne.libquassel.protocol.models.types.QtType
-import de.justjanne.libquassel.protocol.models.types.QuasselType
 import de.justjanne.libquassel.protocol.testutil.byteBufferOf
 import de.justjanne.libquassel.protocol.testutil.signalProxySerializerTest
-import de.justjanne.libquassel.protocol.variant.QVariant_
-import de.justjanne.libquassel.protocol.variant.qVariant
 import org.junit.jupiter.api.Tag
 import org.junit.jupiter.api.Test
 
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt
index 6705c44..3f587cd 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt
@@ -9,16 +9,15 @@
 
 package de.justjanne.libquassel.protocol.testutil
 
+import de.justjanne.libquassel.protocol.dto.IdentityDto
+import de.justjanne.libquassel.protocol.dto.IrcChannelDto
+import de.justjanne.libquassel.protocol.dto.IrcUserDto
+import de.justjanne.libquassel.protocol.dto.NetworkInfoDto
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
 import de.justjanne.libquassel.protocol.models.ids.NetworkId
-import de.justjanne.libquassel.protocol.models.network.IdentityDto
-import de.justjanne.libquassel.protocol.models.network.IrcChannelDto
-import de.justjanne.libquassel.protocol.models.network.IrcUserDto
-import de.justjanne.libquassel.protocol.models.network.NetworkInfoDto
 import de.justjanne.libquassel.protocol.models.network.NetworkServer
 import org.threeten.bp.Instant
-import java.util.UUID
-import java.util.EnumSet
+import java.util.*
 import kotlin.random.Random
 import kotlin.random.nextUInt
 
@@ -42,7 +41,7 @@ inline fun <reified T : Enum<T>> Random.nextEnum(): T {
 fun Random.nextInstant(): Instant = Instant.ofEpochMilli(nextLong())
 
 fun Random.nextNetworkInfo(networkId: NetworkId = NetworkId(nextInt())) =
-  NetworkInfoDto(
+  NetworkInfoDto.Defaults.copy(
     networkId = networkId,
     identity = IdentityId(nextInt()),
     networkName = nextString(),
@@ -91,7 +90,7 @@ fun Random.nextNetworkServer() =
   )
 
 fun Random.nextIrcUser() =
-  IrcUserDto(
+  IrcUserDto.Defaults.copy(
     nick = nextString(),
     user = nextString(),
     host = nextString(),
@@ -110,7 +109,7 @@ fun Random.nextIrcUser() =
   )
 
 fun Random.nextIrcChannel() =
-  IrcChannelDto(
+  IrcChannelDto.Defaults.copy(
     name = nextString(),
     topic = nextString(),
     password = nextString(),
@@ -118,7 +117,7 @@ fun Random.nextIrcChannel() =
   )
 
 fun Random.nextIdentity(identityId: IdentityId = IdentityId(nextInt())) =
-  IdentityDto(
+  IdentityDto.Defaults.copy(
     identityId = identityId,
     identityName = nextString(),
     realName = nextString(),
-- 
GitLab