Commit d8e76b56867c
tarball4 files changed+88-60
@@ -18,7 +18,9 @@ use super::{
1818
};1919
use crate::{2020
CommandOutput, Error, ErrorKind, ImagePackSource, PackCommand, PackImageInfo, PackUsage, Patch,21
- normalise::{ENABLED_ROOMS, ROOM_PACKS, USER_PACK, resolve_pack_id, stored_pack},21
+ normalise::{22
+ ENABLED_ROOMS, ROOM_PACKS, USER_PACK, effective_usage, resolve_pack_id, stored_pack,23
+ },2224
transport::Responder,2325
};2426
@@ -59,6 +61,14 @@ pub(super) async fn edit_pack(
5961
pack: &ImagePackSource,6062
edit: PackEdit,6163
) -> Result<CommandOutput, Error> {64
+ match &edit {65
+ PackEdit::Meta {66
+ usage: Patch::Set(usage),67
+ ..68
+ } => validate_usage(Some(usage))?,69
+ PackEdit::Put { usage, .. } => validate_usage(usage.as_ref())?,70
+ _ => {}71
+ }6272
let current = fetch_pack(client, pack).await?;6373
let mut content = current.clone().unwrap_or_default();6474
let mut output = CommandOutput::Done;@@ -205,6 +215,12 @@ pub(super) async fn run_detached(
205215
max_bytes: usize,206216
command: PackCommand,207217
) -> Result<CommandOutput, Error> {218
+ if let PackCommand::CloneImage { usage, .. }219
+ | PackCommand::CloneSticker { usage, .. }220
+ | PackCommand::ClonePack { usage, .. } = &command221
+ {222
+ validate_usage(usage.as_ref())?;223
+ }208224
match command {209225
PackCommand::SendSticker {210226
room_id,@@ -506,11 +522,25 @@ async fn write_pack(
506522
written.map_err(|source| Error::from_sdk("writing the pack failed", source))507523
}508524
525
+/// values this crate doesn't know ride along untouched, they may mean something to someone509526
fn with_pack_usage(mut image: JsonObject, meta: &JsonObject) -> JsonObject {510
- let usage = known_usage(image.get("usage"))511
- .or_else(|| known_usage(meta.get("usage")))512
- .unwrap_or_else(|| vec![PackUsage::Emoticon, PackUsage::Sticker]);513
- image.insert("usage".to_owned(), usage_json(usage));527
+ if known_usage(image.get("usage")).is_some() {528
+ return image;529
+ }530
+ let mut usage = match meta.get("usage") {531
+ Some(JsonValue::Array(values)) if known_usage(meta.get("usage")).is_some() => {532
+ values.clone()533
+ }534
+ _ => usage_values(effective_usage(None, None)),535
+ };536
+ if let Some(JsonValue::Array(own)) = image.get("usage") {537
+ for value in own {538
+ if !usage.contains(value) {539
+ usage.push(value.clone());540
+ }541
+ }542
+ }543
+ image.insert("usage".to_owned(), usage.into());514544
image515545
}516546
@@ -531,6 +561,17 @@ fn known_usage(value: Option<&JsonValue>) -> Option<Vec<PackUsage>> {
531561
(!usage.is_empty()).then_some(usage)532562
}533563
564
+/// `Some` of nothing would read back as inheriting, which `None` and `Patch::Clear` already say565
+fn validate_usage(usage: Option<&Vec<PackUsage>>) -> Result<(), Error> {566
+ if usage.is_some_and(Vec::is_empty) {567
+ return Err(Error::new(568
+ ErrorKind::Invalid,569
+ "usage needs at least one value, leave it unset to inherit",570
+ ));571
+ }572
+ Ok(())573
+}574
+534575
fn apply_usage(image: &mut JsonObject, usage: Option<Vec<PackUsage>>) {535576
if let Some(usage) = usage {536577
image.insert("usage".to_owned(), usage_json(usage));@@ -585,14 +626,17 @@ fn patch<T>(
585626
}586627
587628
fn usage_json(usage: Vec<PackUsage>) -> JsonValue {629
+ usage_values(usage).into()630
+}631
+632
+fn usage_values(usage: Vec<PackUsage>) -> Vec<JsonValue> {588633
usage589634
.into_iter()590635
.map(|usage| match usage {591
- PackUsage::Emoticon => "emoticon",592
- PackUsage::Sticker => "sticker",636
+ PackUsage::Emoticon => "emoticon".into(),637
+ PackUsage::Sticker => "sticker".into(),593638
})594
- .collect::<Vec<_>>()595
- .into()639
+ .collect()596640
}597641
598642
fn info_json(info: PackImageInfo) -> JsonValue {@@ -624,23 +668,40 @@ fn object(value: JsonValue) -> JsonObject {
624668
}625669
}626670
671
+fn parse(json: &str) -> Result<JsonObject, Error> {672
+ serde_json::from_str(json)673
+ .map_err(|source| Error::with_source(ErrorKind::Server, "the pack is malformed", source))674
+}675
+676
+fn raw<T>(content: &JsonObject) -> Raw<T> {677
+ Raw::new(content)678
+ .expect("a json object always serialises")679
+ .cast_unchecked()680
+}681
+627682
#[cfg(test)]628683
mod tests {629684
use super::*;630685
631686
#[test]632
- fn pack_usage_inherits_known_values_then_defaults() {687
+ fn pack_usage_inherits_known_values_then_defaults_and_keeps_unknown_ones() {633688
let pack = object(json!({ "usage": ["sticker", "unknown"] }));634689
let inherited = with_pack_usage(object(json!({ "usage": [] })), &pack);635
- assert_eq!(inherited.get("usage"), Some(&json!(["sticker"])));690
+ assert_eq!(inherited.get("usage"), Some(&json!(["sticker", "unknown"])));636691
637692
let pack = object(json!({ "usage": ["emoticon"] }));638693
let inherited = with_pack_usage(object(json!({ "usage": ["unknown"] })), &pack);639
- assert_eq!(inherited.get("usage"), Some(&json!(["emoticon"])));694
+ assert_eq!(695
+ inherited.get("usage"),696
+ Some(&json!(["emoticon", "unknown"]))697
+ );640698
641699
let pack = object(json!({ "usage": ["sticker"] }));642700
let inherited = with_pack_usage(object(json!({ "usage": ["emoticon", "unknown"] })), &pack);643
- assert_eq!(inherited.get("usage"), Some(&json!(["emoticon"])));701
+ assert_eq!(702
+ inherited.get("usage"),703
+ Some(&json!(["emoticon", "unknown"]))704
+ );644705
645706
let pack = object(json!({ "usage": [] }));646707
let inherited = with_pack_usage(object(json!({})), &pack);@@ -671,14 +732,3 @@ mod tests {
671732
);672733
}673734
}674
-675
-fn parse(json: &str) -> Result<JsonObject, Error> {676
- serde_json::from_str(json)677
- .map_err(|source| Error::with_source(ErrorKind::Server, "the pack is malformed", source))678
-}679
-680
-fn raw<T>(content: &JsonObject) -> Raw<T> {681
- Raw::new(content)682
- .expect("a json object always serialises")683
- .cast_unchecked()684
-}@@ -184,9 +184,7 @@ fn pack(
184184
mimetype: info.and_then(|info| info.mimetype.clone()),185185
width: info.and_then(|info| info.width).map(u64::from),186186
height: info.and_then(|info| info.height).map(u64::from),187
- usage: usage(&image.usage)188
- .or_else(|| pack_usage.clone())189
- .unwrap_or_else(|| vec![PackUsage::Emoticon, PackUsage::Sticker]),187
+ usage: effective_usage(usage(&image.usage), pack_usage.clone()),190188
})191189
})192190
.collect();@@ -210,6 +208,16 @@ fn pack(
210208
})211209
}212210
211
+/// an image's own known usage, else its pack's, else both. unknown values never count212
+pub(crate) fn effective_usage(213
+ image: Option<Vec<PackUsage>>,214
+ pack: Option<Vec<PackUsage>>,215
+) -> Vec<PackUsage> {216
+ image217
+ .or(pack)218
+ .unwrap_or_else(|| vec![PackUsage::Emoticon, PackUsage::Sticker])219
+}220
+213221
fn usage(usage: &BTreeSet<SourceUsage>) -> Option<Vec<PackUsage>> {214222
let usage: Vec<PackUsage> = usage215223
.iter()@@ -9,7 +9,8 @@ mod timeline;
99
1010
pub(crate) use context::{apply_profiles, normalise_context, resolve_replies};1111
pub(crate) use image_pack::{12
- ENABLED_ROOMS, ROOM_PACKS, USER_PACK, can_edit_packs, image_packs, resolve_pack_id, stored_pack,12
+ ENABLED_ROOMS, ROOM_PACKS, USER_PACK, can_edit_packs, effective_usage, image_packs,13
+ resolve_pack_id, stored_pack,1314
};1415
pub(crate) use link_preview::{ROOM_PREVIEW_URLS, server_preview, url_previews_allowed};1516
pub(crate) use media::{MediaRegistration, MediaScope, MediaSourceInfo};@@ -1038,22 +1038,12 @@ impl ClientHandle {
10381038
}10391039
}10401040
1041
- /// hands back the shortcode it ended up under1041
+ /// hands back the shortcode it ended up under. `usage` overrides what the image had10421042
pub async fn clone_pack_image(10431043
&self,10441044
from_pack: String,10451045
shortcode: String,10461046
to: ImagePackSource,1047
- ) -> Result<String, Error> {1048
- self.clone_pack_image_with_usage(from_pack, shortcode, to, None)1049
- .await1050
- }1051
-1052
- pub async fn clone_pack_image_with_usage(1053
- &self,1054
- from_pack: String,1055
- shortcode: String,1056
- to: ImagePackSource,10571047
usage: Option<Vec<PackUsage>>,10581048
) -> Result<String, Error> {10591049
let (mut shortcodes, _) = self@@ -1076,17 +1066,6 @@ impl ClientHandle {
10761066
event_id: OwnedEventId,10771067
to: ImagePackSource,10781068
shortcode: String,1079
- ) -> Result<String, Error> {1080
- self.clone_sticker_with_usage(room_id, event_id, to, shortcode, None)1081
- .await1082
- }1083
-1084
- pub async fn clone_sticker_with_usage(1085
- &self,1086
- room_id: OwnedRoomId,1087
- event_id: OwnedEventId,1088
- to: ImagePackSource,1089
- shortcode: String,10901069
usage: Option<Vec<PackUsage>>,10911070
) -> Result<String, Error> {10921071
let (mut shortcodes, _) = self@@ -1109,16 +1088,6 @@ impl ClientHandle {
11091088
from_pack: String,11101089
to: ImagePackSource,11111090
display_name: Option<String>,1112
- ) -> Result<Vec<String>, Error> {1113
- self.clone_pack_with_usage(from_pack, to, display_name, None)1114
- .await1115
- }1116
-1117
- pub async fn clone_pack_with_usage(1118
- &self,1119
- from_pack: String,1120
- to: ImagePackSource,1121
- display_name: Option<String>,11221091
usage: Option<Vec<PackUsage>>,11231092
) -> Result<Vec<String>, Error> {11241093
let (_, skipped) = self