| 1 | #![allow(dead_code)] |
| 2 | |
| 3 | use std::time::Duration; |
| 4 | |
| 5 | use macltok::{ |
| 6 | ClientHandle, Event, EventStream, MediaDescriptor, Message, TimelineContent, TimelineDiff, |
| 7 | TimelineEvent, TimelineItem, |
| 8 | }; |
| 9 | |
| 10 | pub async fn receive_until(events: &mut EventStream, predicate: impl Fn(&Event) -> bool) -> Event { |
| 11 | tokio::time::timeout(Duration::from_secs(5), async { |
| 12 | while let Some(event) = events.recv().await { |
| 13 | if predicate(&event) { |
| 14 | return event; |
| 15 | } |
| 16 | } |
| 17 | panic!("event stream closed before the expected event"); |
| 18 | }) |
| 19 | .await |
| 20 | .expect("expected event did not arrive") |
| 21 | } |
| 22 | |
| 23 | /// asks for a shutdown while still draining, since the engine won't answer until its events are out |
| 24 | pub async fn shut_down( |
| 25 | handle: &ClientHandle, |
| 26 | events: &mut EventStream, |
| 27 | running: tokio::task::JoinHandle<Result<macltok::Termination, macltok::EngineError>>, |
| 28 | ) { |
| 29 | let (answer, _) = tokio::join!(handle.shutdown(), async { |
| 30 | receive_until(events, |event| matches!(event, Event::Stopped)).await |
| 31 | }); |
| 32 | answer.unwrap(); |
| 33 | assert_eq!( |
| 34 | running.await.unwrap().unwrap(), |
| 35 | macltok::Termination::ShutDown |
| 36 | ); |
| 37 | } |
| 38 | |
| 39 | pub fn event_messages(event: &Event) -> Vec<&TimelineEvent> { |
| 40 | let items = match event { |
| 41 | Event::TimelineReset { items, .. } => items.iter().collect::<Vec<_>>(), |
| 42 | Event::TimelineChanged { diffs, .. } => diffs.iter().flat_map(diff_items).collect(), |
| 43 | _ => Vec::new(), |
| 44 | }; |
| 45 | items |
| 46 | .into_iter() |
| 47 | .filter_map(|item| match item { |
| 48 | TimelineItem::Event(event) => Some(event.as_ref()), |
| 49 | _ => None, |
| 50 | }) |
| 51 | .collect() |
| 52 | } |
| 53 | |
| 54 | pub fn message(event: &TimelineEvent) -> Option<&Message> { |
| 55 | match &event.content { |
| 56 | TimelineContent::Message(message) => Some(message), |
| 57 | _ => None, |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | pub fn media_of(event: &TimelineEvent) -> Option<&MediaDescriptor> { |
| 62 | match &event.content { |
| 63 | TimelineContent::Message(message) => message.media.as_ref(), |
| 64 | TimelineContent::Sticker { media, .. } => Some(media), |
| 65 | _ => None, |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | pub fn diff_items(diff: &TimelineDiff) -> Vec<&TimelineItem> { |
| 70 | match diff { |
| 71 | TimelineDiff::Append { values } | TimelineDiff::Reset { values } => values.iter().collect(), |
| 72 | TimelineDiff::PushFront { value } |
| 73 | | TimelineDiff::PushBack { value } |
| 74 | | TimelineDiff::Insert { value, .. } |
| 75 | | TimelineDiff::Set { value, .. } => vec![value], |
| 76 | _ => Vec::new(), |
| 77 | } |
| 78 | } |