apply_text_fixture/
apply_text_fixture.rs1use wechat_profile::*;
4fn run() -> Result<()> {
5 let a = std::env::args().skip(1).collect::<Vec<_>>();
6 if a.len() != 3 {
7 return Err(ProfileError::InvalidQuery);
8 }
9 let location = ProfileLocation::new(&a[0])?;
10 let keys = KeyFile::load(&a[1])?;
11 let input: IncomingText =
12 serde_json::from_slice(&std::fs::read(&a[2])?).map_err(|_| ProfileError::InvalidQuery)?;
13 let options = WriteOptions {
14 exclusive_ownership_confirmed: true,
15 allow_plaintext: false,
16 durable_intent_id: "explicit-disposable-fixture-validation".into(),
17 };
18 let first = apply_incoming_text(&location, &keys, &input, &options)?;
19 let retry = apply_incoming_text(&location, &keys, &input, &options)?;
20 let read = mark_read_messages(
21 &location,
22 &keys,
23 &input.peer,
24 std::slice::from_ref(&first.source_id),
25 &options,
26 )?;
27 let read_retry = mark_read_messages(
28 &location,
29 &keys,
30 &input.peer,
31 std::slice::from_ref(&first.source_id),
32 &options,
33 )?;
34 let reader = ProfileReader::open(
35 location,
36 keys,
37 ReadOptions {
38 stopped_or_consistent_snapshot: true,
39 ..Default::default()
40 },
41 )?;
42 let page = reader.messages(&MessageQuery {
43 chat: Some(input.peer),
44 limit: Some(200),
45 ..Default::default()
46 })?;
47 let found = page
48 .items
49 .iter()
50 .find(|v| v.id == first.source_id)
51 .ok_or(ProfileError::InvalidMetadata)?;
52 let exact = found.content.text.as_deref() == Some(input.content.as_str())
53 && found.source.text.as_deref() == Some(input.source_xml.as_str())
54 && found.server_message_id.as_deref() == Some(input.server_message_id.as_str());
55 if !exact || retry.message_inserted || read_retry.removed_unread_rows != 0 {
56 return Err(ProfileError::InvalidMetadata);
57 }
58 println!(
59 "{}",
60 serde_json::json!({"newTextInserted":first.message_inserted,"retryInsertedDuplicate":retry.message_inserted,"exactBodySourceAndServerIdentity":exact,"removedUnreadRows":read.removed_unread_rows,"readRetryRemovedRows":read_retry.removed_unread_rows,"unreadBefore":read.unread_count_before,"unreadAfter":read.unread_count_after,"crossDatabaseAtomic":first.cross_database_atomic,"networkUsed":false,"officialRuntimeUsed":false})
61 );
62 Ok(())
63}
64fn main() {
65 if let Err(e) = run() {
66 eprintln!("{e}");
67 std::process::exit(1);
68 }
69}