mirror of
https://github.com/chatmail/core.git
synced 2026-05-03 05:16:28 +03:00
Add documentation
This commit is contained in:
24
src/chat.rs
24
src/chat.rs
@@ -46,7 +46,9 @@ use crate::{location, sql};
|
|||||||
/// An chat item, such as a message or a marker.
|
/// An chat item, such as a message or a marker.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ChatItem {
|
pub enum ChatItem {
|
||||||
|
/// Chat message stored in the database.
|
||||||
Message {
|
Message {
|
||||||
|
/// Database ID of the messsage.
|
||||||
msg_id: MsgId,
|
msg_id: MsgId,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1124,10 +1126,15 @@ impl rusqlite::types::FromSql for ChatId {
|
|||||||
/// if you want an update, you have to recreate the object.
|
/// if you want an update, you have to recreate the object.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct Chat {
|
pub struct Chat {
|
||||||
|
/// Database ID.
|
||||||
pub id: ChatId,
|
pub id: ChatId,
|
||||||
|
|
||||||
|
/// Chat type, e.g. 1:1 chat, group chat, mailing list.
|
||||||
pub typ: Chattype,
|
pub typ: Chattype,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub visibility: ChatVisibility,
|
pub visibility: ChatVisibility,
|
||||||
|
|
||||||
|
/// Group ID.
|
||||||
pub grpid: String,
|
pub grpid: String,
|
||||||
pub(crate) blocked: Blocked,
|
pub(crate) blocked: Blocked,
|
||||||
pub param: Params,
|
pub param: Params,
|
||||||
@@ -1207,6 +1214,7 @@ impl Chat {
|
|||||||
self.param.exists(Param::Devicetalk)
|
self.param.exists(Param::Devicetalk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if chat is a mailing list.
|
||||||
pub fn is_mailing_list(&self) -> bool {
|
pub fn is_mailing_list(&self) -> bool {
|
||||||
self.typ == Chattype::Mailinglist
|
self.typ == Chattype::Mailinglist
|
||||||
}
|
}
|
||||||
@@ -1636,10 +1644,16 @@ impl Chat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the chat is pinned or archived.
|
||||||
#[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub enum ChatVisibility {
|
pub enum ChatVisibility {
|
||||||
|
/// Chat is neither archived nor pinned.
|
||||||
Normal,
|
Normal,
|
||||||
|
|
||||||
|
/// Chat is archived.
|
||||||
Archived,
|
Archived,
|
||||||
|
|
||||||
|
/// Chat is pinned to the top of the chatlist.
|
||||||
Pinned,
|
Pinned,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2334,6 +2348,7 @@ pub async fn send_text_msg(
|
|||||||
send_msg(context, chat_id, &mut msg).await
|
send_msg(context, chat_id, &mut msg).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sends invitation to a videochat.
|
||||||
pub async fn send_videochat_invitation(context: &Context, chat_id: ChatId) -> Result<MsgId> {
|
pub async fn send_videochat_invitation(context: &Context, chat_id: ChatId) -> Result<MsgId> {
|
||||||
ensure!(
|
ensure!(
|
||||||
!chat_id.is_special(),
|
!chat_id.is_special(),
|
||||||
@@ -2992,10 +3007,16 @@ pub(crate) async fn shall_attach_selfavatar(context: &Context, chat_id: ChatId)
|
|||||||
Ok(needs_attach)
|
Ok(needs_attach)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Chat mute duration.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum MuteDuration {
|
pub enum MuteDuration {
|
||||||
|
/// Chat is not muted.
|
||||||
NotMuted,
|
NotMuted,
|
||||||
|
|
||||||
|
/// Chat is muted until the user unmutes the chat.
|
||||||
Forever,
|
Forever,
|
||||||
|
|
||||||
|
/// Chat is muted for a limited period of time.
|
||||||
Until(SystemTime),
|
Until(SystemTime),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3034,6 +3055,7 @@ impl rusqlite::types::FromSql for MuteDuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mutes the chat for a given duration or unmutes it.
|
||||||
pub async fn set_muted(context: &Context, chat_id: ChatId, duration: MuteDuration) -> Result<()> {
|
pub async fn set_muted(context: &Context, chat_id: ChatId, duration: MuteDuration) -> Result<()> {
|
||||||
ensure!(!chat_id.is_special(), "Invalid chat ID");
|
ensure!(!chat_id.is_special(), "Invalid chat ID");
|
||||||
context
|
context
|
||||||
@@ -3048,6 +3070,7 @@ pub async fn set_muted(context: &Context, chat_id: ChatId, duration: MuteDuratio
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes contact from the chat.
|
||||||
pub async fn remove_contact_from_chat(
|
pub async fn remove_contact_from_chat(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
chat_id: ChatId,
|
chat_id: ChatId,
|
||||||
@@ -3251,6 +3274,7 @@ pub async fn set_chat_profile_image(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Forwards multiple messages to a chat.
|
||||||
pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId) -> Result<()> {
|
pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId) -> Result<()> {
|
||||||
ensure!(!msg_ids.is_empty(), "empty msgs_ids: nothing to forward");
|
ensure!(!msg_ids.is_empty(), "empty msgs_ids: nothing to forward");
|
||||||
ensure!(!chat_id.is_special(), "can not forward to special chat");
|
ensure!(!chat_id.is_special(), "can not forward to special chat");
|
||||||
|
|||||||
@@ -32,29 +32,75 @@ use crate::tools::{get_abs_path, improve_single_line_input, EmailAddress};
|
|||||||
)]
|
)]
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
pub enum Config {
|
pub enum Config {
|
||||||
|
/// Email address, used in the `From:` field.
|
||||||
Addr,
|
Addr,
|
||||||
|
|
||||||
|
/// IMAP server hostname.
|
||||||
MailServer,
|
MailServer,
|
||||||
|
|
||||||
|
/// IMAP server username.
|
||||||
MailUser,
|
MailUser,
|
||||||
|
|
||||||
|
/// IMAP server password.
|
||||||
MailPw,
|
MailPw,
|
||||||
|
|
||||||
|
/// IMAP server port.
|
||||||
MailPort,
|
MailPort,
|
||||||
|
|
||||||
|
/// IMAP server security (e.g. TLS, STARTTLS).
|
||||||
MailSecurity,
|
MailSecurity,
|
||||||
|
|
||||||
|
/// How to check IMAP server TLS certificates.
|
||||||
ImapCertificateChecks,
|
ImapCertificateChecks,
|
||||||
|
|
||||||
|
/// SMTP server hostname.
|
||||||
SendServer,
|
SendServer,
|
||||||
|
|
||||||
|
/// SMTP server username.
|
||||||
SendUser,
|
SendUser,
|
||||||
|
|
||||||
|
/// SMTP server password.
|
||||||
SendPw,
|
SendPw,
|
||||||
|
|
||||||
|
/// SMTP server port.
|
||||||
SendPort,
|
SendPort,
|
||||||
|
|
||||||
|
/// SMTP server security (e.g. TLS, STARTTLS).
|
||||||
SendSecurity,
|
SendSecurity,
|
||||||
|
|
||||||
|
/// How to check SMTP server TLS certificates.
|
||||||
SmtpCertificateChecks,
|
SmtpCertificateChecks,
|
||||||
|
|
||||||
|
/// Whether to use OAuth 2.
|
||||||
|
///
|
||||||
|
/// Historically contained other bitflags, which are now deprecated.
|
||||||
|
/// Should not be extended in the future, create new config keys instead.
|
||||||
ServerFlags,
|
ServerFlags,
|
||||||
|
|
||||||
|
/// True if SOCKS5 is enabled.
|
||||||
|
///
|
||||||
|
/// Can be used to disable SOCKS5 without erasing SOCKS5 configuration.
|
||||||
Socks5Enabled,
|
Socks5Enabled,
|
||||||
|
|
||||||
|
/// SOCKS5 proxy server hostname or address.
|
||||||
Socks5Host,
|
Socks5Host,
|
||||||
|
|
||||||
|
/// SOCKS5 proxy server port.
|
||||||
Socks5Port,
|
Socks5Port,
|
||||||
|
|
||||||
|
/// SOCKS5 proxy server username.
|
||||||
Socks5User,
|
Socks5User,
|
||||||
|
|
||||||
|
/// SOCKS5 proxy server password.
|
||||||
Socks5Password,
|
Socks5Password,
|
||||||
|
|
||||||
|
/// Own name to use in the `From:` field when sending messages.
|
||||||
Displayname,
|
Displayname,
|
||||||
|
|
||||||
|
/// Own status to display, sent in message footer.
|
||||||
Selfstatus,
|
Selfstatus,
|
||||||
|
|
||||||
|
/// Own avatar filename.
|
||||||
Selfavatar,
|
Selfavatar,
|
||||||
|
|
||||||
#[strum(props(default = "1"))]
|
#[strum(props(default = "1"))]
|
||||||
@@ -121,15 +167,33 @@ pub enum Config {
|
|||||||
SaveMimeHeaders,
|
SaveMimeHeaders,
|
||||||
/// The primary email address. Also see `SecondaryAddrs`.
|
/// The primary email address. Also see `SecondaryAddrs`.
|
||||||
ConfiguredAddr,
|
ConfiguredAddr,
|
||||||
|
|
||||||
|
/// Configured IMAP server hostname.
|
||||||
ConfiguredMailServer,
|
ConfiguredMailServer,
|
||||||
|
|
||||||
|
/// Configured IMAP server username.
|
||||||
ConfiguredMailUser,
|
ConfiguredMailUser,
|
||||||
|
|
||||||
|
/// Configured IMAP server password.
|
||||||
ConfiguredMailPw,
|
ConfiguredMailPw,
|
||||||
|
|
||||||
|
/// Configured IMAP server port.
|
||||||
ConfiguredMailPort,
|
ConfiguredMailPort,
|
||||||
|
|
||||||
|
/// Configured IMAP server security (e.g. TLS, STARTTLS).
|
||||||
ConfiguredMailSecurity,
|
ConfiguredMailSecurity,
|
||||||
ConfiguredImapCertificateChecks,
|
ConfiguredImapCertificateChecks,
|
||||||
|
|
||||||
|
/// Configured SMTP server hostname.
|
||||||
ConfiguredSendServer,
|
ConfiguredSendServer,
|
||||||
|
|
||||||
|
/// Configured SMTP server username.
|
||||||
ConfiguredSendUser,
|
ConfiguredSendUser,
|
||||||
|
|
||||||
|
/// Configured SMTP server password.
|
||||||
ConfiguredSendPw,
|
ConfiguredSendPw,
|
||||||
|
|
||||||
|
/// Configured SMTP server port.
|
||||||
ConfiguredSendPort,
|
ConfiguredSendPort,
|
||||||
ConfiguredSmtpCertificateChecks,
|
ConfiguredSmtpCertificateChecks,
|
||||||
ConfiguredServerFlags,
|
ConfiguredServerFlags,
|
||||||
@@ -200,6 +264,7 @@ pub enum Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
|
/// Returns true if configuration value is set for the given key.
|
||||||
pub async fn config_exists(&self, key: Config) -> Result<bool> {
|
pub async fn config_exists(&self, key: Config) -> Result<bool> {
|
||||||
Ok(self.sql.get_raw_config(key.as_ref()).await?.is_some())
|
Ok(self.sql.get_raw_config(key.as_ref()).await?.is_some())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ impl Deref for Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Actual context, expensive to clone.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InnerContext {
|
pub struct InnerContext {
|
||||||
/// Blob directory path
|
/// Blob directory path
|
||||||
@@ -570,6 +571,7 @@ impl Context {
|
|||||||
* UI chat/message related API
|
* UI chat/message related API
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
/// Returns information about the context as key-value pairs.
|
||||||
pub async fn get_info(&self) -> Result<BTreeMap<&'static str, String>> {
|
pub async fn get_info(&self) -> Result<BTreeMap<&'static str, String>> {
|
||||||
let unset = "0";
|
let unset = "0";
|
||||||
let l = LoginParam::load_candidate_params_unchecked(self).await?;
|
let l = LoginParam::load_candidate_params_unchecked(self).await?;
|
||||||
@@ -878,16 +880,19 @@ impl Context {
|
|||||||
Ok(list)
|
Ok(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if given folder name is the name of the inbox.
|
||||||
pub async fn is_inbox(&self, folder_name: &str) -> Result<bool> {
|
pub async fn is_inbox(&self, folder_name: &str) -> Result<bool> {
|
||||||
let inbox = self.get_config(Config::ConfiguredInboxFolder).await?;
|
let inbox = self.get_config(Config::ConfiguredInboxFolder).await?;
|
||||||
Ok(inbox.as_deref() == Some(folder_name))
|
Ok(inbox.as_deref() == Some(folder_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if given folder name is the name of the "sent" folder.
|
||||||
pub async fn is_sentbox(&self, folder_name: &str) -> Result<bool> {
|
pub async fn is_sentbox(&self, folder_name: &str) -> Result<bool> {
|
||||||
let sentbox = self.get_config(Config::ConfiguredSentboxFolder).await?;
|
let sentbox = self.get_config(Config::ConfiguredSentboxFolder).await?;
|
||||||
Ok(sentbox.as_deref() == Some(folder_name))
|
Ok(sentbox.as_deref() == Some(folder_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if given folder name is the name of the "Delta Chat" folder.
|
||||||
pub async fn is_mvbox(&self, folder_name: &str) -> Result<bool> {
|
pub async fn is_mvbox(&self, folder_name: &str) -> Result<bool> {
|
||||||
let mvbox = self.get_config(Config::ConfiguredMvboxFolder).await?;
|
let mvbox = self.get_config(Config::ConfiguredMvboxFolder).await?;
|
||||||
Ok(mvbox.as_deref() == Some(folder_name))
|
Ok(mvbox.as_deref() == Some(folder_name))
|
||||||
@@ -908,6 +913,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns core version as a string.
|
||||||
pub fn get_version_str() -> &'static str {
|
pub fn get_version_str() -> &'static str {
|
||||||
&DC_VERSION_STR
|
&DC_VERSION_STR
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ impl Default for Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Events {
|
impl Events {
|
||||||
|
/// Creates a new event channel.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (sender, receiver) = channel::bounded(1_000);
|
let (sender, receiver) = channel::bounded(1_000);
|
||||||
|
|
||||||
Self { receiver, sender }
|
Self { receiver, sender }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits an event.
|
||||||
pub fn emit(&self, event: Event) {
|
pub fn emit(&self, event: Event) {
|
||||||
match self.sender.try_send(event) {
|
match self.sender.try_send(event) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
//! Cryptographic key module.
|
//! Cryptographic key module.
|
||||||
|
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
@@ -332,6 +330,7 @@ pub async fn store_self_keypair(
|
|||||||
pub struct Fingerprint(Vec<u8>);
|
pub struct Fingerprint(Vec<u8>);
|
||||||
|
|
||||||
impl Fingerprint {
|
impl Fingerprint {
|
||||||
|
/// Creates new 160-bit (20 bytes) fingerprint.
|
||||||
pub fn new(v: Vec<u8>) -> Fingerprint {
|
pub fn new(v: Vec<u8>) -> Fingerprint {
|
||||||
debug_assert_eq!(v.len(), 20);
|
debug_assert_eq!(v.len(), 20);
|
||||||
Fingerprint(v)
|
Fingerprint(v)
|
||||||
|
|||||||
@@ -119,8 +119,13 @@ pub fn split_armored_data(buf: &[u8]) -> Result<(BlockType, BTreeMap<String, Str
|
|||||||
/// keys together as they are one unit.
|
/// keys together as they are one unit.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
|
/// Email address.
|
||||||
pub addr: EmailAddress,
|
pub addr: EmailAddress,
|
||||||
|
|
||||||
|
/// Public key.
|
||||||
pub public: SignedPublicKey,
|
pub public: SignedPublicKey,
|
||||||
|
|
||||||
|
/// Secret key.
|
||||||
pub secret: SignedSecretKey,
|
pub secret: SignedSecretKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ pub enum Qr {
|
|||||||
invitenumber: String,
|
invitenumber: String,
|
||||||
authcode: String,
|
authcode: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// `dclogin:` scheme parameters.
|
||||||
Login {
|
Login {
|
||||||
address: String,
|
address: String,
|
||||||
options: LoginOptions,
|
options: LoginOptions,
|
||||||
|
|||||||
11
src/quota.rs
11
src/quota.rs
@@ -1,7 +1,5 @@
|
|||||||
//! # Support for IMAP QUOTA extension.
|
//! # Support for IMAP QUOTA extension.
|
||||||
|
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
@@ -23,8 +21,8 @@ use crate::{job, stock_str, EventType};
|
|||||||
/// quota icon is "yellow".
|
/// quota icon is "yellow".
|
||||||
pub const QUOTA_WARN_THRESHOLD_PERCENTAGE: u64 = 80;
|
pub const QUOTA_WARN_THRESHOLD_PERCENTAGE: u64 = 80;
|
||||||
|
|
||||||
// warning again after this usage percentage is reached,
|
/// warning again after this usage percentage is reached,
|
||||||
// quota icon is "red".
|
/// quota icon is "red".
|
||||||
pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 95;
|
pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 95;
|
||||||
|
|
||||||
/// if quota is below this value (again),
|
/// if quota is below this value (again),
|
||||||
@@ -36,10 +34,11 @@ pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 95;
|
|||||||
/// providers report bad values and we would then spam the user.
|
/// providers report bad values and we would then spam the user.
|
||||||
pub const QUOTA_ALLCLEAR_PERCENTAGE: u64 = 75;
|
pub const QUOTA_ALLCLEAR_PERCENTAGE: u64 = 75;
|
||||||
|
|
||||||
// if recent quota is older,
|
/// if recent quota is older,
|
||||||
// it is re-fetched on dc_get_connectivity_html()
|
/// it is re-fetched on dc_get_connectivity_html()
|
||||||
pub const QUOTA_MAX_AGE_SECONDS: i64 = 60;
|
pub const QUOTA_MAX_AGE_SECONDS: i64 = 60;
|
||||||
|
|
||||||
|
/// Server quota information with an update timestamp.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QuotaInfo {
|
pub struct QuotaInfo {
|
||||||
/// Recently loaded quota information.
|
/// Recently loaded quota information.
|
||||||
|
|||||||
@@ -511,6 +511,7 @@ pub fn open_file_std<P: AsRef<std::path::Path>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads directory and returns a vector of directory entries.
|
||||||
pub async fn read_dir(path: &Path) -> Result<Vec<fs::DirEntry>> {
|
pub async fn read_dir(path: &Path) -> Result<Vec<fs::DirEntry>> {
|
||||||
let res = tokio_stream::wrappers::ReadDirStream::new(fs::read_dir(path).await?)
|
let res = tokio_stream::wrappers::ReadDirStream::new(fs::read_dir(path).await?)
|
||||||
.try_collect()
|
.try_collect()
|
||||||
|
|||||||
Reference in New Issue
Block a user