diff --git a/Cargo.lock b/Cargo.lock index c6967a71c..7f283b599 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -716,12 +716,13 @@ dependencies = [ [[package]] name = "deltachat-provider-database" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -738,11 +739,12 @@ name = "deltachat_ffi" version = "1.0.0-beta.20" dependencies = [ "deltachat 1.0.0-beta.20", - "deltachat-provider-database 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "deltachat-provider-database 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3533,7 +3535,7 @@ dependencies = [ "checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" "checksum debug_stub_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "496b7f8a2f853313c3ca370641d7ff3e42c32974fdccda8f0684599ed0a3ff6b" "checksum deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)" = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" -"checksum deltachat-provider-database 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "814dba060d9fdc7a989fccdc4810ada9d1c7a1f09131c78e42412bc6c634b93b" +"checksum deltachat-provider-database 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc18fb898a7bc90565c801d7bd17a4b61478f0da0ea06ecf7f0428bd20242c52" "checksum derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" "checksum derive_builder_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" "checksum des 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74ba5f1b5aee9772379c2670ba81306e65a93c0ee3caade7a1d22b188d88a3af" diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index c386c62a8..5ab325799 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -16,11 +16,12 @@ crate-type = ["cdylib", "staticlib"] [dependencies] deltachat = { path = "../", default-features = false } -deltachat-provider-database = "0.2.1" +deltachat-provider-database = "0.3.0" libc = "0.2" human-panic = "1.0.1" num-traits = "0.2.6" failure = "0.1.6" +serde_json = "1.0" [features] default = ["vendored", "nightly", "ringbuf"] diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index ce09beff8..8e785dfdd 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -18,7 +18,6 @@ typedef struct _dc_chat dc_chat_t; typedef struct _dc_msg dc_msg_t; typedef struct _dc_contact dc_contact_t; typedef struct _dc_lot dc_lot_t; -typedef struct _dc_provider dc_provider_t; /** @@ -3660,106 +3659,28 @@ int dc_contact_is_verified (dc_contact_t* contact); /** * @class dc_provider_t - * - * Opaque object containing information about one single email provider. */ - /** - * Create a provider struct for the given domain. + * Get the provider json object for the given domain. * * @memberof dc_provider_t * @param domain The domain to get provider info for. - * @return a dc_provider_t struct which can be used with the dc_provider_get_* - * accessor functions. If no provider info is found, NULL will be - * returned. + * @return a provider json object as string. If no provider info is found, an empty string will be returned. */ -dc_provider_t* dc_provider_new_from_domain (const char* domain); +char* dc_provider_json_from_domain (const char* domain); /** - * Create a provider struct for the given email address. + * Get the provider json object for the given email address. * * The provider is extracted from the email address and it's information is returned. * * @memberof dc_provider_t * @param email The user's email address to extract the provider info form. - * @return a dc_provider_t struct which can be used with the dc_provider_get_* - * accessor functions. If no provider info is found, NULL will be - * returned. + * @return a provider json object as string. If no provider info is found, an empty string will be returned. */ -dc_provider_t* dc_provider_new_from_email (const char* email); - - -/** - * URL of the overview page. - * - * This URL allows linking to the providers page on providers.delta.chat. - * - * @memberof dc_provider_t - * @param provider The dc_provider_t struct. - * @return A string which must be released using dc_str_unref(). - */ -char* dc_provider_get_overview_page (const dc_provider_t* provider); - - -/** - * The provider's name. - * - * The name of the provider, e.g. "POSTEO". - * - * @memberof dc_provider_t - * @param provider The dc_provider_t struct. - * @return A string which must be released using dc_str_unref(). - */ -char* dc_provider_get_name (const dc_provider_t* provider); - - -/** - * The markdown content of the providers page. - * - * This contains the preparation steps or additional information if the status - * is @ref DC_PROVIDER_STATUS_BROKEN. - * - * @memberof dc_provider_t - * @param provider The dc_provider_t struct. - * @return A string which must be released using dc_str_unref(). - */ -char* dc_provider_get_markdown (const dc_provider_t* provider); - - -/** - * Date of when the state was last checked/updated. - * - * This is returned as a string. - * - * @memberof dc_provider_t - * @param provider The dc_provider_t struct. - * @return A string which must be released using dc_str_unref(). - */ -char* dc_provider_get_status_date (const dc_provider_t* provider); - - -/** - * Whether DC works with this provider. - * - * Can be one of @ref DC_PROVIDER_STATUS_OK, @ref - * DC_PROVIDER_STATUS_PREPARATION and @ref DC_PROVIDER_STATUS_BROKEN. - * - * @memberof dc_provider_t - * @param provider The dc_provider_t struct. - * @return The status as a constant number. - */ -int dc_provider_get_status (const dc_provider_t* provider); - - -/** - * Free the provider info struct. - * - * @memberof dc_provider_t - * @param provider The dc_provider_t struct. - */ -void dc_provider_unref (const dc_provider_t* provider); +char* dc_provider_json_from_email (const char* email); /** @@ -4475,41 +4396,6 @@ void dc_array_add_id (dc_array_t*, uint32_t); // depreca #define DC_SHOW_EMAILS_ALL 2 -/** - * @defgroup DC_PROVIDER_STATUS DC_PROVIDER_STATUS - * - * These constants are used as return values for dc_provider_get_status(). - * - * @addtogroup DC_PROVIDER_STATUS - * @{ - */ - -/** - * Provider status returned by dc_provider_get_status(). - * - * Works right out of the box without any preperation steps needed - */ -#define DC_PROVIDER_STATUS_OK 1 - -/** - * Provider status returned by dc_provider_get_status(). - * - * Works, but preparation steps are needed - */ -#define DC_PROVIDER_STATUS_PREPARATION 2 - -/** - * Provider status returned by dc_provider_get_status(). - * - * Doesn't work (too unstable to use falls also in this category) - */ -#define DC_PROVIDER_STATUS_BROKEN 3 - -/** - * @} - */ - - /* * TODO: Strings need some doumentation about used placeholders. * diff --git a/deltachat-ffi/src/providers.rs b/deltachat-ffi/src/providers.rs index 42c169c77..807407eac 100644 --- a/deltachat-ffi/src/providers.rs +++ b/deltachat-ffi/src/providers.rs @@ -1,93 +1,31 @@ extern crate deltachat_provider_database; -use std::ptr; - use crate::string::{to_string_lossy, StrExt}; -use deltachat_provider_database::StatusState; #[no_mangle] pub type dc_provider_t = deltachat_provider_database::Provider; #[no_mangle] -pub unsafe extern "C" fn dc_provider_new_from_domain( +pub unsafe extern "C" fn dc_provider_json_from_domain( domain: *const libc::c_char, -) -> *const dc_provider_t { - match deltachat_provider_database::get_provider_info(&to_string_lossy(domain)) { - Some(provider) => provider, - None => ptr::null(), +) -> *mut libc::c_char { + let domain = to_string_lossy(domain); + match deltachat_provider_database::get_provider_info(&domain) { + Some(provider) => serde_json::to_string(provider).unwrap().strdup(), + None => "".strdup(), } } #[no_mangle] -pub unsafe extern "C" fn dc_provider_new_from_email( +pub unsafe extern "C" fn dc_provider_json_from_email( email: *const libc::c_char, -) -> *const dc_provider_t { +) -> *mut libc::c_char { let email = to_string_lossy(email); let domain = deltachat_provider_database::get_domain_from_email(&email); match deltachat_provider_database::get_provider_info(domain) { - Some(provider) => provider, - None => ptr::null(), + Some(provider) => serde_json::to_string(provider).unwrap().strdup(), + None => "".strdup(), } } -macro_rules! null_guard { - ($context:tt) => { - if $context.is_null() { - return ptr::null_mut() as *mut libc::c_char; - } - }; -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_overview_page( - provider: *const dc_provider_t, -) -> *mut libc::c_char { - null_guard!(provider); - format!( - "{}/{}", - deltachat_provider_database::PROVIDER_OVERVIEW_URL, - (*provider).overview_page - ) - .strdup() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_name(provider: *const dc_provider_t) -> *mut libc::c_char { - null_guard!(provider); - (*provider).name.strdup() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_markdown( - provider: *const dc_provider_t, -) -> *mut libc::c_char { - null_guard!(provider); - (*provider).markdown.strdup() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_status_date( - provider: *const dc_provider_t, -) -> *mut libc::c_char { - null_guard!(provider); - (*provider).status.date.strdup() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_status(provider: *const dc_provider_t) -> u32 { - if provider.is_null() { - return 0; - } - match (*provider).status.state { - StatusState::OK => 1, - StatusState::PREPARATION => 2, - StatusState::BROKEN => 3, - } -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_unref(_provider: *const dc_provider_t) { - () -} - // TODO expose general provider overview url? diff --git a/python/src/deltachat/provider.py b/python/src/deltachat/provider.py index ad98daf96..cb066fde8 100644 --- a/python/src/deltachat/provider.py +++ b/python/src/deltachat/provider.py @@ -2,7 +2,7 @@ from .capi import ffi, lib from .cutil import as_dc_charpointer, from_dc_charpointer - +import json class ProviderNotFoundError(Exception): """The provider information was not found.""" @@ -16,13 +16,12 @@ class Provider(object): """ def __init__(self, domain): - provider = ffi.gc( - lib.dc_provider_new_from_domain(as_dc_charpointer(domain)), - lib.dc_provider_unref, + provider = from_dc_charpointer( + lib.dc_provider_json_from_domain(as_dc_charpointer(domain)) ) - if provider == ffi.NULL: + if provider == "": raise ProviderNotFoundError("Provider not found") - self._provider = provider + self._provider = json.loads(provider) @classmethod def from_email(cls, email): @@ -35,33 +34,30 @@ class Provider(object): @property def overview_page(self): """URL to the overview page of the provider on providers.delta.chat.""" - return from_dc_charpointer( - lib.dc_provider_get_overview_page(self._provider)) + return "https://providers.delta.chat/" + self._provider['overview_page'] @property def name(self): """The name of the provider.""" - return from_dc_charpointer(lib.dc_provider_get_name(self._provider)) + return self._provider['name'] @property def markdown(self): """Content of the information page, formatted as markdown.""" - return from_dc_charpointer( - lib.dc_provider_get_markdown(self._provider)) + return self._provider['markdown'] @property def status_date(self): """The date the provider info was last updated, as a string.""" - return from_dc_charpointer( - lib.dc_provider_get_status_date(self._provider)) + return self._provider['status']['date'] @property def status(self): """The status of the provider information. - This is one of the - :attr:`deltachat.const.DC_PROVIDER_STATUS_OK`, - :attr:`deltachat.const.DC_PROVIDER_STATUS_PREPARATION` or - :attr:`deltachat.const.DC_PROVIDER_STATUS_BROKEN` constants. + This is + :attr:`"OK"`, + :attr:`"PREPARATION"` or + :attr:`"BROKEN"`. """ - return lib.dc_provider_get_status(self._provider) + return self._provider['status']['state'] diff --git a/python/tests/test_lowlevel.py b/python/tests/test_lowlevel.py index 915631895..85f0948e0 100644 --- a/python/tests/test_lowlevel.py +++ b/python/tests/test_lowlevel.py @@ -3,6 +3,7 @@ from deltachat import capi, cutil, const, set_context_callback, clear_context_ca from deltachat.capi import ffi from deltachat.capi import lib from deltachat.account import EventLogger +import json def test_empty_context(): @@ -103,19 +104,23 @@ def test_get_special_message_id_returns_empty_message(acfactory): def test_provider_info(): - provider = lib.dc_provider_new_from_email(cutil.as_dc_charpointer("ex@example.com")) - assert cutil.from_dc_charpointer( - lib.dc_provider_get_overview_page(provider) - ) == "https://providers.delta.chat/example.com" - assert cutil.from_dc_charpointer(lib.dc_provider_get_name(provider)) == "Example" - assert cutil.from_dc_charpointer(lib.dc_provider_get_markdown(provider)) == "\n..." - assert cutil.from_dc_charpointer(lib.dc_provider_get_status_date(provider)) == "2018-09" - assert lib.dc_provider_get_status(provider) == const.DC_PROVIDER_STATUS_PREPARATION + provider_json = cutil.from_dc_charpointer( + lib.dc_provider_json_from_email(cutil.as_dc_charpointer("ex@example.com")) + ) + provider = json.loads(provider_json) + + assert provider['overview_page'] == "example.com" + assert provider['name'] == "Example" + assert provider['markdown'] == "\n..." + assert provider['status']['date'] == "2018-09" + assert provider['status']['state'] == "PREPARATION" def test_provider_info_none(): - assert lib.dc_provider_new_from_email(cutil.as_dc_charpointer("email@unexistent.no")) == ffi.NULL - + provider_json = cutil.from_dc_charpointer( + lib.dc_provider_json_from_email(cutil.as_dc_charpointer("email@unexistent.no")) + ) + assert provider_json == "" def test_get_info_closed(): ctx = ffi.gc( diff --git a/python/tests/test_provider_info.py b/python/tests/test_provider_info.py index 10c9fb27d..138b950ff 100644 --- a/python/tests/test_provider_info.py +++ b/python/tests/test_provider_info.py @@ -10,7 +10,7 @@ def test_provider_info_from_email(): assert example.name == "Example" assert example.markdown == "\n..." assert example.status_date == "2018-09" - assert example.status == const.DC_PROVIDER_STATUS_PREPARATION + assert example.status == "PREPARATION" def test_provider_info_from_domain(): @@ -19,7 +19,7 @@ def test_provider_info_from_domain(): assert example.name == "Example" assert example.markdown == "\n..." assert example.status_date == "2018-09" - assert example.status == const.DC_PROVIDER_STATUS_PREPARATION + assert example.status == "PREPARATION" def test_provider_info_none():