sdk: Add methods for media content

This commit is contained in:
Kévin Commaille 2021-05-25 21:43:01 +02:00
parent 0c8e870bff
commit b805670c8a
No known key found for this signature in database
GPG key ID: 296D60AE1E61661C
3 changed files with 101 additions and 4 deletions

View file

@ -24,7 +24,7 @@ use std::{
use std::{
fmt::{self, Debug},
future::Future,
io::Read,
io::{Cursor, Read},
path::Path,
result::Result as StdResult,
sync::Arc,
@ -41,7 +41,11 @@ use matrix_sdk_base::crypto::{
OutgoingRequests, RoomMessageRequest, ToDeviceRequest,
};
use matrix_sdk_base::{
deserialized_responses::SyncResponse, events::AnyMessageEventContent, identifiers::MxcUri,
crypto::AttachmentDecryptor,
deserialized_responses::SyncResponse,
events::AnyMessageEventContent,
identifiers::MxcUri,
media::{MediaFormat, MediaRequest, MediaType},
BaseClient, BaseClientConfig, SendAccessToken, Session, Store,
};
use mime::{self, Mime};
@ -2465,6 +2469,94 @@ impl Client {
Ok(olm.import_keys(import, |_, _| {}).await?)
}
/// Get a media file's content.
///
/// If the content is encrypted and encryption is enabled, the content will
/// be decrypted.
///
/// # Arguments
///
/// * `request` - The `MediaRequest` of the content.
///
/// * `use_cache` - If we should use the media cache for this request.
pub async fn get_media_content(
&self,
request: &MediaRequest,
use_cache: bool,
) -> Result<Vec<u8>> {
let content = if use_cache {
self.base_client.store().get_media_content(request).await?
} else {
None
};
if let Some(content) = content {
Ok(content)
} else {
let content: Vec<u8> = match &request.media_type {
MediaType::Encrypted(file) => {
let content: Vec<u8> =
self.send(get_content::Request::from_url(&file.url)?, None).await?.file;
#[cfg(feature = "encryption")]
let content = {
let mut cursor = Cursor::new(content);
let mut reader =
AttachmentDecryptor::new(&mut cursor, file.clone().into())?;
let mut decrypted = Vec::new();
reader.read_to_end(&mut decrypted)?;
decrypted
};
content
}
MediaType::Uri(uri) => {
if let MediaFormat::Thumbnail(size) = &request.format {
self.send(
get_content_thumbnail::Request::from_url(
&uri,
size.width,
size.height,
)?,
None,
)
.await?
.file
} else {
self.send(get_content::Request::from_url(&uri)?, None).await?.file
}
}
};
if use_cache {
self.base_client.store().add_media_content(request, content.clone()).await?;
}
Ok(content)
}
}
/// Remove a media file's content from the store.
///
/// # Arguments
///
/// * `request` - The `MediaRequest` of the content.
pub async fn remove_media_content(&self, request: &MediaRequest) -> Result<()> {
Ok(self.base_client.store().remove_media_content(request).await?)
}
/// Delete all the media content corresponding to the given
/// uri from the store.
///
/// # Arguments
///
/// * `uri` - The `MxcUri` of the files.
pub async fn remove_media_content_for_uri(&self, uri: &MxcUri) -> Result<()> {
Ok(self.base_client.store().remove_media_content_for_uri(&uri).await?)
}
}
#[cfg(test)]

View file

@ -18,7 +18,7 @@ use std::io::Error as IoError;
use http::StatusCode;
#[cfg(feature = "encryption")]
use matrix_sdk_base::crypto::store::CryptoStoreError;
use matrix_sdk_base::crypto::{store::CryptoStoreError, DecryptorError};
use matrix_sdk_base::{Error as MatrixError, StoreError};
use matrix_sdk_common::{
api::{
@ -122,6 +122,11 @@ pub enum Error {
#[error(transparent)]
CryptoStoreError(#[from] CryptoStoreError),
/// An error occurred during decryption.
#[cfg(feature = "encryption")]
#[error(transparent)]
DecryptorError(#[from] DecryptorError),
/// An error occured in the state store.
#[error(transparent)]
StateStore(#[from] StoreError),

View file

@ -81,7 +81,7 @@ pub use bytes::{Bytes, BytesMut};
#[cfg_attr(feature = "docs", doc(cfg(encryption)))]
pub use matrix_sdk_base::crypto::{EncryptionInfo, LocalTrust};
pub use matrix_sdk_base::{
Error as BaseError, Room as BaseRoom, RoomInfo, RoomMember as BaseRoomMember, RoomType,
media, Error as BaseError, Room as BaseRoom, RoomInfo, RoomMember as BaseRoomMember, RoomType,
Session, StateChanges, StoreError,
};
pub use matrix_sdk_common::*;