JSON-RPC: replace integer properties with proper enum/boolean types

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-02 17:48:45 +00:00
parent 1108a1365f
commit 9727f23bf9
4 changed files with 136 additions and 42 deletions
+48 -7
View File
@@ -16,6 +16,10 @@ use deltachat::chat::{
};
use deltachat::chatlist::Chatlist;
use deltachat::config::{get_all_ui_config_keys, Config};
use deltachat::constants::{
DC_GCL_ADD_ALLDONE_HINT, DC_GCL_ADD_SELF, DC_GCL_ADDRESS, DC_GCL_ARCHIVED_ONLY,
DC_GCL_FOR_FORWARDING, DC_GCL_NO_SPECIALS,
};
use deltachat::constants::DC_MSG_ID_DAYMARKER;
use deltachat::contact::{may_be_valid_addr, Contact, ContactId, Origin};
use deltachat::context::get_info;
@@ -722,17 +726,39 @@ impl CommandApi {
// chat list
// ---------------------------------------------
/// Returns chat list entry IDs.
///
/// * `archived_only` - Only return archived chats. If not set, only unarchived chats are returned.
/// * `no_specials` - Do not add the archive link entry to the chatlist.
/// * `for_forwarding` - Sort "Saved messages" to the top of the chatlist; typically used when forwarding.
/// * `add_alldone_hint` - Add a hint entry `DC_CHAT_ID_ALLDONE_HINT` to the chatlist if there are only archived chats.
async fn get_chatlist_entries(
&self,
account_id: u32,
list_flags: Option<u32>,
archived_only: Option<bool>,
no_specials: Option<bool>,
for_forwarding: Option<bool>,
add_alldone_hint: Option<bool>,
query_string: Option<String>,
query_contact_id: Option<u32>,
) -> Result<Vec<u32>> {
let ctx = self.get_context(account_id).await?;
let mut list_flags: usize = 0;
if archived_only.unwrap_or_default() {
list_flags |= DC_GCL_ARCHIVED_ONLY;
}
if no_specials.unwrap_or_default() {
list_flags |= DC_GCL_NO_SPECIALS;
}
if for_forwarding.unwrap_or_default() {
list_flags |= DC_GCL_FOR_FORWARDING;
}
if add_alldone_hint.unwrap_or_default() {
list_flags |= DC_GCL_ADD_ALLDONE_HINT;
}
let list = Chatlist::try_load(
&ctx,
list_flags.unwrap_or(0) as usize,
list_flags,
query_string.as_deref(),
query_contact_id.map(ContactId::new),
)
@@ -1664,17 +1690,24 @@ impl CommandApi {
///
/// By default, key-contacts are listed.
///
/// * `list_flags` - A combination of flags:
/// - `DC_GCL_ADD_SELF` - Add SELF unless filtered by other parameters.
/// - `DC_GCL_ADDRESS` - List address-contacts instead of key-contacts.
/// * `add_self` - Add SELF contact to the list unless filtered by other parameters.
/// * `address_book` - List address-contacts instead of key-contacts.
/// * `query` - A string to filter the list.
async fn get_contact_ids(
&self,
account_id: u32,
list_flags: u32,
add_self: Option<bool>,
address_book: Option<bool>,
query: Option<String>,
) -> Result<Vec<u32>> {
let ctx = self.get_context(account_id).await?;
let mut list_flags: u32 = 0;
if add_self.unwrap_or_default() {
list_flags |= DC_GCL_ADD_SELF;
}
if address_book.unwrap_or_default() {
list_flags |= DC_GCL_ADDRESS;
}
let contacts = Contact::get_all(&ctx, list_flags, query.as_deref()).await?;
Ok(contacts.into_iter().map(|c| c.to_u32()).collect())
}
@@ -1686,10 +1719,18 @@ impl CommandApi {
async fn get_contacts(
&self,
account_id: u32,
list_flags: u32,
add_self: Option<bool>,
address_book: Option<bool>,
query: Option<String>,
) -> Result<Vec<ContactObject>> {
let ctx = self.get_context(account_id).await?;
let mut list_flags: u32 = 0;
if add_self.unwrap_or_default() {
list_flags |= DC_GCL_ADD_SELF;
}
if address_book.unwrap_or_default() {
list_flags |= DC_GCL_ADDRESS;
}
let contact_ids = Contact::get_all(&ctx, list_flags, query.as_deref()).await?;
let mut contacts: Vec<ContactObject> = Vec::with_capacity(contact_ids.len());
for id in contact_ids {
+65 -6
View File
@@ -9,10 +9,10 @@ use deltachat::contact::Contact;
use deltachat::context::Context;
use deltachat::download;
use deltachat::message::Message;
use deltachat::message::MessageState;
use deltachat::message::MsgId;
use deltachat::message::Viewtype;
use deltachat::reaction::get_msg_reactions;
use num_traits::cast::ToPrimitive;
use serde::{Deserialize, Serialize};
use typescript_type_def::TypeDef;
@@ -48,7 +48,7 @@ pub struct MessageObject {
has_location: bool,
has_html: bool,
view_type: MessageViewtype,
state: u32,
state: JsonrpcMessageState,
/// An error text, if there is one.
error: Option<String>,
@@ -213,10 +213,7 @@ impl MessageObject {
has_location: message.has_location(),
has_html: message.has_html(),
view_type: message.get_viewtype().into(),
state: message
.get_state()
.to_u32()
.context("state conversion to number failed")?,
state: message.get_state().into(),
error: message.error(),
timestamp: message.get_timestamp(),
@@ -363,6 +360,68 @@ impl From<MessageViewtype> for Viewtype {
}
}
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "MessageState")]
pub enum JsonrpcMessageState {
/// Undefined message state.
Undefined,
/// Incoming *fresh* message. Fresh messages are neither noticed
/// nor seen and are typically shown in notifications.
InFresh,
/// Incoming *noticed* message. E.g. chat opened but message not
/// yet read - noticed messages are not counted as unread but did
/// not marked as read nor resulted in MDNs.
InNoticed,
/// Incoming message, really *seen* by the user. Marked as read on
/// IMAP and MDN may be sent.
InSeen,
/// For files which need time to be prepared before they can be
/// sent, the message enters this state before OutPending.
OutPreparing,
/// Message saved as draft.
OutDraft,
/// The user has pressed the "send" button but the message is not
/// yet sent and is pending in some way. Maybe we're offline (no
/// checkmark).
OutPending,
/// *Unrecoverable* error (*recoverable* errors result in pending
/// messages).
OutFailed,
/// Outgoing message successfully delivered to server (one
/// checkmark). Note, that already delivered messages may get into
/// the OutFailed state if we get such a hint from the server.
OutDelivered,
/// Outgoing message read by the recipient (two checkmarks; this
/// requires goodwill on the receiver's side).
OutMdnRcvd,
}
impl From<MessageState> for JsonrpcMessageState {
fn from(state: MessageState) -> Self {
match state {
MessageState::Undefined => JsonrpcMessageState::Undefined,
MessageState::InFresh => JsonrpcMessageState::InFresh,
MessageState::InNoticed => JsonrpcMessageState::InNoticed,
MessageState::InSeen => JsonrpcMessageState::InSeen,
MessageState::OutPreparing => JsonrpcMessageState::OutPreparing,
MessageState::OutDraft => JsonrpcMessageState::OutDraft,
MessageState::OutPending => JsonrpcMessageState::OutPending,
MessageState::OutFailed => JsonrpcMessageState::OutFailed,
MessageState::OutDelivered => JsonrpcMessageState::OutDelivered,
MessageState::OutMdnRcvd => JsonrpcMessageState::OutMdnRcvd,
}
}
}
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
pub enum DownloadState {
Done,
@@ -9,7 +9,7 @@ from warnings import warn
from ._utils import AttrDict, futuremethod
from .chat import Chat
from .const import ChatlistFlag, ContactFlag, EventType, SpecialContactId
from .const import EventType, SpecialContactId
from .contact import Contact
from .message import Message
@@ -246,14 +246,10 @@ class Account:
:param with_self: if True the self-contact is also included if it matches the query.
:param snapshot: If True return a list of contact snapshots instead of Contact instances.
"""
flags = 0
if with_self:
flags |= ContactFlag.ADD_SELF
if snapshot:
contacts = self._rpc.get_contacts(self.id, flags, query)
contacts = self._rpc.get_contacts(self.id, with_self, None, query)
return [AttrDict(contact=Contact(self, contact["id"]), **contact) for contact in contacts]
contacts = self._rpc.get_contact_ids(self.id, flags, query)
contacts = self._rpc.get_contact_ids(self.id, with_self, None, query)
return [Contact(self, contact_id) for contact_id in contacts]
@property
@@ -288,17 +284,15 @@ class Account:
as needed.
:param snapshot: If True return a list of chat snapshots instead of Chat instances.
"""
flags = 0
if archived_only:
flags |= ChatlistFlag.ARCHIVED_ONLY
if for_forwarding:
flags |= ChatlistFlag.FOR_FORWARDING
if no_specials:
flags |= ChatlistFlag.NO_SPECIALS
if alldone_hint:
flags |= ChatlistFlag.ADD_ALLDONE_HINT
entries = self._rpc.get_chatlist_entries(self.id, flags, query, contact and contact.id)
entries = self._rpc.get_chatlist_entries(
self.id,
archived_only,
no_specials,
for_forwarding,
alldone_hint,
query,
contact and contact.id,
)
if not snapshot:
return [Chat(self, entry) for entry in entries]
@@ -183,19 +183,19 @@ class SystemMessageType(str, Enum):
WEBXDC_INFO_MESSAGE = "WebxdcInfoMessage"
class MessageState(IntEnum):
class MessageState(str, Enum):
"""State of the message."""
UNDEFINED = 0
IN_FRESH = 10
IN_NOTICED = 13
IN_SEEN = 16
OUT_PREPARING = 18
OUT_DRAFT = 19
OUT_PENDING = 20
OUT_FAILED = 24
OUT_DELIVERED = 26
OUT_MDN_RCVD = 28
UNDEFINED = "Undefined"
IN_FRESH = "InFresh"
IN_NOTICED = "InNoticed"
IN_SEEN = "InSeen"
OUT_PREPARING = "OutPreparing"
OUT_DRAFT = "OutDraft"
OUT_PENDING = "OutPending"
OUT_FAILED = "OutFailed"
OUT_DELIVERED = "OutDelivered"
OUT_MDN_RCVD = "OutMdnRcvd"
class MessageId(IntEnum):