Commit da60b49e authored by Alejandro Domínguez's avatar Alejandro Domínguez

Return errors without conversion

parent 0f151216
Pipeline #196132 passed with stages
in 51 minutes and 2 seconds
......@@ -3,7 +3,6 @@ use gtk::prelude::*;
use crate::backend::{user, HandleError};
use glib::clone;
use std::path::PathBuf;
use std::thread;
use crate::app::App;
......@@ -32,8 +31,8 @@ impl AppOp {
}));
thread::spawn(clone!(@strong login_data => move || {
match user::get_avatar(login_data.server_url, login_data.uid) {
Ok(path) => {
match user::get_user_avatar(login_data.server_url, &login_data.uid) {
Ok((_, path)) => {
APPOP!(set_avatar, (path));
}
Err(err) => {
......@@ -146,10 +145,10 @@ impl AppOp {
});
}
pub fn set_avatar(&mut self, path: PathBuf) {
pub fn set_avatar(&mut self, path: String) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
self.set_login_data(LoginData {
avatar: Some(path),
avatar: Some(path.into()),
..login_data
});
}
......
use fractal_api::url::{Host, Url};
use fractal_api::reqwest::Error as ReqwestError;
use fractal_api::url::{Host, ParseError as UrlError, Url};
use crate::globals;
use crate::error::Error;
use crate::backend::HTTP_CLIENT;
use crate::util::cache_dir_path;
......@@ -28,8 +27,8 @@ use crate::APPOP;
#[derive(Debug)]
pub struct DirectoryProtocolsError;
impl<T: Into<Error>> From<T> for DirectoryProtocolsError {
fn from(_: T) -> Self {
impl From<ReqwestError> for DirectoryProtocolsError {
fn from(_: ReqwestError) -> Self {
Self
}
}
......@@ -57,11 +56,14 @@ pub fn protocols(
}
#[derive(Debug)]
pub struct DirectorySearchError;
pub enum DirectorySearchError {
InvalidHomeserverUrl(UrlError),
Reqwest(ReqwestError),
}
impl<T: Into<Error>> From<T> for DirectorySearchError {
fn from(_: T) -> Self {
Self
impl From<ReqwestError> for DirectorySearchError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
......@@ -97,7 +99,8 @@ pub fn room_search(
.unwrap_or_else(|| Host::parse(&hs))
.map(Some)
})
.unwrap_or(Ok(None))?;
.unwrap_or(Ok(None))
.map_err(DirectorySearchError::InvalidHomeserverUrl)?;
let params = PublicRoomsParameters {
access_token,
......
use super::MediaError;
use crate::error::Error;
use crate::globals;
use fractal_api::identifiers::{EventId, RoomId};
use fractal_api::identifiers::{Error as IdError, EventId, RoomId};
use fractal_api::reqwest::Error as ReqwestError;
use fractal_api::url::Url;
use std::sync::mpsc::Sender;
......@@ -72,13 +72,24 @@ pub fn get_media_list_async(
});
}
enum GetRoomMediaListError {
Reqwest(ReqwestError),
EventsDeserialization(IdError),
}
impl From<ReqwestError> for GetRoomMediaListError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
fn get_room_media_list(
baseu: Url,
access_token: AccessToken,
room_id: &RoomId,
limit: u64,
prev_batch: String,
) -> Result<MediaList, Error> {
) -> Result<MediaList, GetRoomMediaListError> {
let params = GetMessagesEventsParams {
access_token,
from: prev_batch,
......@@ -97,7 +108,8 @@ fn get_room_media_list(
let prev_batch = response.end.unwrap_or_default();
let evs = response.chunk.iter().rev();
let media_list = Message::from_json_events_iter(room_id, evs)?;
let media_list = Message::from_json_events_iter(room_id, evs)
.map_err(GetRoomMediaListError::EventsDeserialization)?;
Ok((media_list, prev_batch))
}
use fractal_api::identifiers::{EventId, RoomId};
use fractal_api::url::Url;
use fractal_api::reqwest::Error as ReqwestError;
use fractal_api::url::{ParseError as UrlError, Url};
use lazy_static::lazy_static;
use log::error;
use regex::Regex;
use std::fmt::Debug;
use std::fs::write;
use std::io::Read;
use std::io::{Error as IoError, Read};
use std::path::Path;
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
use std::time::SystemTimeError;
use crate::client::Client;
use crate::error::Error;
......@@ -100,7 +102,7 @@ pub fn get_prev_batch_from(
access_token: AccessToken,
room_id: &RoomId,
event_id: &EventId,
) -> Result<String, Error> {
) -> Result<String, ReqwestError> {
let params = GetContextParameters {
access_token,
limit: 0,
......@@ -115,11 +117,29 @@ pub fn get_prev_batch_from(
}
#[derive(Debug)]
pub struct MediaError(pub(self) Error);
pub enum MediaError {
InvalidMxcUrl(Option<UrlError>),
InvalidDownloadPath(Error),
Reqwest(ReqwestError),
Io(IoError),
SystemTime(SystemTimeError),
}
impl<T: Into<Error>> From<T> for MediaError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for MediaError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
impl From<IoError> for MediaError {
fn from(err: IoError) -> Self {
Self::Io(err)
}
}
impl From<SystemTimeError> for MediaError {
fn from(err: SystemTimeError) -> Self {
Self::SystemTime(err)
}
}
......@@ -131,18 +151,21 @@ pub fn dw_media(
media_type: ContentType,
dest: Option<String>,
) -> Result<String, MediaError> {
let mxc_url = Url::parse(mxc)?;
let mxc_url = Url::parse(mxc).map_err(|url_err| MediaError::InvalidMxcUrl(Some(url_err)))?;
if mxc_url.scheme() != "mxc" {
return Err(MediaError(Error::BackendError));
return Err(MediaError::InvalidMxcUrl(None));
}
let server = mxc_url.host().ok_or(Error::BackendError)?.to_owned();
let server = mxc_url
.host()
.ok_or(MediaError::InvalidMxcUrl(None))?
.to_owned();
let media_id = mxc_url
.path_segments()
.and_then(|mut ps| ps.next())
.filter(|s| !s.is_empty())
.ok_or(Error::BackendError)?;
.ok_or(MediaError::InvalidMxcUrl(None))?;
let request = if let ContentType::Thumbnail(width, height) = media_type {
let params = GetContentThumbnailParameters {
......@@ -158,10 +181,11 @@ pub fn dw_media(
}?;
let fname = match dest {
None if media_type.is_thumbnail() => cache_dir_path(Some("thumbs"), &media_id)?,
None => cache_dir_path(Some("medias"), &media_id)?,
Some(ref d) => d.clone(),
};
None if media_type.is_thumbnail() => cache_dir_path(Some("thumbs"), &media_id),
None => cache_dir_path(Some("medias"), &media_id),
Some(ref d) => Ok(d.clone()),
}
.map_err(MediaError::InvalidDownloadPath)?;
let fpath = Path::new(&fname);
......@@ -175,7 +199,7 @@ pub fn dw_media(
.get_client()
.execute(request)?
.bytes()
.collect::<Result<Vec<u8>, std::io::Error>>()
.collect::<Result<Vec<u8>, IoError>>()
.and_then(|media| write(&fname, media))
.and(Ok(fname))
.map_err(Into::into)
......
use fractal_api::identifiers::{DeviceId, UserId};
use fractal_api::reqwest::Error as ReqwestError;
use fractal_api::url::Url;
use crate::error::Error;
use crate::actions::AppState;
use crate::backend::HTTP_CLIENT;
use crate::globals;
......@@ -27,8 +26,8 @@ use crate::APPOP;
#[derive(Debug)]
pub struct LoginError;
impl<T: Into<Error>> From<T> for LoginError {
fn from(_: T) -> Self {
impl From<ReqwestError> for LoginError {
fn from(_: ReqwestError) -> Self {
Self
}
}
......@@ -78,11 +77,11 @@ pub fn login(
}
#[derive(Debug)]
pub struct LogoutError(Error);
pub struct LogoutError(ReqwestError);
impl<T: Into<Error>> From<T> for LogoutError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for LogoutError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -97,12 +96,8 @@ pub fn logout(server: Url, access_token: AccessToken) -> Result<(), LogoutError>
Ok(())
}
pub fn get_well_known(domain: Url) -> Result<DomainInfoResponse, Error> {
pub fn get_well_known(domain: Url) -> Result<DomainInfoResponse, ReqwestError> {
let request = domain_info(domain)?;
HTTP_CLIENT
.get_client()
.execute(request)?
.json()
.map_err(Into::into)
HTTP_CLIENT.get_client().execute(request)?.json()
}
......@@ -2,14 +2,15 @@ use log::error;
use serde_json::json;
use fractal_api::identifiers::{Error as IdError, EventId, RoomId, UserId};
use fractal_api::reqwest::Error as ReqwestError;
use fractal_api::url::Url;
use std::fs;
use std::io::Error as IoError;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::time::Duration;
use crate::error::Error;
use crate::globals;
use crate::actions::AppState;
......@@ -84,11 +85,14 @@ use crate::i18n::i18n;
use crate::APPOP;
#[derive(Debug)]
pub struct RoomDetailError(Error);
pub enum RoomDetailError {
MalformedKey,
Reqwest(ReqwestError),
}
impl<T: Into<Error>> From<T> for RoomDetailError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for RoomDetailError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
......@@ -98,25 +102,25 @@ pub fn get_room_detail(
base: Url,
access_token: AccessToken,
room_id: RoomId,
keys: String,
key: String,
) -> Result<(RoomId, String, String), RoomDetailError> {
let k = key.split('.').last().ok_or(RoomDetailError::MalformedKey)?;
let params = GetStateEventsForKeyParameters { access_token };
let request = get_state_events_for_key(base, &params, &room_id, &keys)?;
let request = get_state_events_for_key(base, &params, &room_id, &key)?;
let response: JsonValue = HTTP_CLIENT.get_client().execute(request)?.json()?;
let k = keys.split('.').last().ok_or(Error::BackendError)?;
let value = response[&k].as_str().map(Into::into).unwrap_or_default();
Ok((room_id, keys, value))
Ok((room_id, key, value))
}
#[derive(Debug)]
pub struct RoomAvatarError(Error);
pub struct RoomAvatarError(ReqwestError);
impl<T: Into<Error>> From<T> for RoomAvatarError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for RoomAvatarError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -129,40 +133,29 @@ pub fn get_room_avatar(
) -> Result<(RoomId, Option<Url>), RoomAvatarError> {
let params = GetStateEventsForKeyParameters { access_token };
get_state_events_for_key(base.clone(), &params, &room_id, "m.room.avatar")
.map_err(Into::into)
.and_then(|request| {
let response = HTTP_CLIENT
.get_client()
.execute(request)?
.json::<JsonValue>()?;
let avatar = response["url"].as_str().and_then(|s| Url::parse(s).ok());
let dest = cache_dir_path(None, &room_id.to_string()).ok();
if let Some(ref avatar) = avatar {
let _ = dw_media(
base,
avatar.as_str(),
ContentType::default_thumbnail(),
dest,
);
}
let request = get_state_events_for_key(base.clone(), &params, &room_id, "m.room.avatar")?;
let response: JsonValue = HTTP_CLIENT.get_client().execute(request)?.json()?;
Ok((room_id.clone(), avatar))
})
.or_else(|err| match err {
Error::MatrixError(errcode, _) if errcode == "M_NOT_FOUND" => Ok((room_id, None)),
error => Err(error),
})
.map_err(Into::into)
let avatar = response["url"].as_str().and_then(|s| Url::parse(s).ok());
let dest = cache_dir_path(None, &room_id.to_string()).ok();
if let Some(ref avatar) = avatar {
let _ = dw_media(
base,
avatar.as_str(),
ContentType::default_thumbnail(),
dest,
);
}
Ok((room_id.clone(), avatar))
}
#[derive(Debug)]
pub struct RoomMembersError(Error);
pub struct RoomMembersError(ReqwestError);
impl<T: Into<Error>> From<T> for RoomMembersError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for RoomMembersError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -184,11 +177,15 @@ pub fn get_room_members(
}
#[derive(Debug)]
pub struct RoomMessagesToError(Error);
pub enum RoomMessagesToError {
MessageNotSent,
Reqwest(ReqwestError),
EventsDeserialization(IdError),
}
impl<T: Into<Error>> From<T> for RoomMessagesToError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for RoomMessagesToError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
......@@ -220,7 +217,8 @@ pub fn get_room_messages(
let prev_batch = response.end;
let evs = response.chunk.iter().rev();
let list = Message::from_json_events_iter(&room_id, evs)?;
let list = Message::from_json_events_iter(&room_id, evs)
.map_err(RoomMessagesToError::EventsDeserialization)?;
Ok((list, room_id, prev_batch))
}
......@@ -231,7 +229,7 @@ pub fn get_room_messages_from_msg(
room_id: RoomId,
msg: Message,
) -> Result<(Vec<Message>, RoomId, Option<String>), RoomMessagesToError> {
let event_id = msg.id.as_ref().ok_or(Error::BackendError)?;
let event_id = msg.id.as_ref().ok_or(RoomMessagesToError::MessageNotSent)?;
// first of all, we calculate the from param using the context api, then we call the
// normal get_room_messages
......@@ -287,7 +285,6 @@ pub fn send_msg(
let txn_id = msg.get_txn_id();
create_message_event(base, &params, &body, &room_id, "m.room.message", &txn_id)
.map_err::<Error, _>(Into::into)
.and_then(|request| {
let response = HTTP_CLIENT
.get_client()
......@@ -300,11 +297,11 @@ pub fn send_msg(
}
#[derive(Debug)]
pub struct SendTypingError(Error);
pub struct SendTypingError(ReqwestError);
impl<T: Into<Error>> From<T> for SendTypingError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for SendTypingError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -326,10 +323,20 @@ pub fn send_typing(
}
#[derive(Debug)]
pub struct SendMsgRedactionError;
pub enum SendMsgRedactionError {
MessageNotSent,
Reqwest(ReqwestError),
}
impl From<ReqwestError> for SendMsgRedactionError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
impl HandleError for SendMsgRedactionError {
fn handle_error(&self) {
error!("Error deleting message: {:?}", self);
let error = i18n("Error deleting message");
APPOP!(show_error, (error));
}
......@@ -342,7 +349,10 @@ pub fn redact_msg(
) -> Result<(EventId, Option<EventId>), SendMsgRedactionError> {
let room_id = &msg.room;
let txn_id = msg.get_txn_id();
let event_id = msg.id.clone().ok_or(SendMsgRedactionError)?;
let event_id = msg
.id
.as_ref()
.ok_or(SendMsgRedactionError::MessageNotSent)?;
let params = RedactEventParameters { access_token };
......@@ -350,25 +360,18 @@ pub fn redact_msg(
reason: "Deletion requested by the sender".into(),
};
redact_event(base, &params, &body, room_id, &event_id, &txn_id)
.map_err::<Error, _>(Into::into)
.and_then(|request| {
let response = HTTP_CLIENT
.get_client()
.execute(request)?
.json::<RedactEventResponse>()?;
let request = redact_event(base, &params, &body, room_id, event_id, &txn_id)?;
let response: RedactEventResponse = HTTP_CLIENT.get_client().execute(request)?.json()?;
Ok((event_id.clone(), response.event_id))
})
.or(Err(SendMsgRedactionError))
Ok((event_id.clone(), response.event_id))
}
#[derive(Debug)]
pub struct JoinRoomError(Error);
pub struct JoinRoomError(ReqwestError);
impl<T: Into<Error>> From<T> for JoinRoomError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for JoinRoomError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -405,11 +408,11 @@ pub fn join_room(
}
#[derive(Debug)]
pub struct LeaveRoomError(Error);
pub struct LeaveRoomError(ReqwestError);
impl<T: Into<Error>> From<T> for LeaveRoomError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for LeaveRoomError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -429,11 +432,11 @@ pub fn leave_room(
}
#[derive(Debug)]
pub struct MarkedAsReadError(Error);
pub struct MarkedAsReadError(ReqwestError);
impl<T: Into<Error>> From<T> for MarkedAsReadError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for MarkedAsReadError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -458,11 +461,11 @@ pub fn mark_as_read(
Ok((room_id, event_id))
}
#[derive(Debug)]
pub struct SetRoomNameError(Error);
pub struct SetRoomNameError(ReqwestError);
impl<T: Into<Error>> From<T> for SetRoomNameError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for SetRoomNameError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -487,11 +490,11 @@ pub fn set_room_name(
}
#[derive(Debug)]
pub struct SetRoomTopicError(Error);
pub struct SetRoomTopicError(ReqwestError);
impl<T: Into<Error>> From<T> for SetRoomTopicError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for SetRoomTopicError {
fn from(err: ReqwestError) -> Self {
Self(err)
}
}
......@@ -516,17 +519,23 @@ pub fn set_room_topic(
}
#[derive(Debug)]
pub struct SetRoomAvatarError(Error);
pub enum SetRoomAvatarError {
Io(IoError),
Reqwest(ReqwestError),
}
impl<T: Into<Error>> From<T> for SetRoomAvatarError {
fn from(err: T) -> Self {
Self(err.into())
impl From<ReqwestError> for SetRoomAvatarError {
fn from(err: ReqwestError) -> Self {
Self::Reqwest(err)
}
}
impl From<AttachedFileError> for SetRoomAvatarError {
fn from(err: AttachedFileError) -> Self {
Self(err.0)
match err {
AttachedFileError::Io(err) => Self::Io(err),
AttachedFileError::Reqwest(err) => Self::Reqwest(err),
}
}
}
......@@ -552,11 +561,20 @@ pub fn set_room_avatar(