sl_chat_log_parser/
avatar_messages.rs

1//! Avatar related messages (those sent by an avatar as well as some system messages about an avatar like coming online or entering chat range)
2
3use chumsky::error::Simple;
4use chumsky::prelude::{any, choice, just};
5use chumsky::Parser;
6
7/// represents a Second Life avatar related message
8#[derive(Debug, Clone, PartialEq)]
9pub enum AvatarMessage {
10    /// a message about the avatar whispering, saying or shouting something
11    Chat {
12        /// how "loud" the message was (whisper, say, shout or region say)
13        volume: sl_types::chat::ChatVolume,
14        /// the chat message
15        message: String,
16    },
17    /// an emote (chat message starting with /me in the log)
18    Emote {
19        /// how "loud" the message was (whisper, say, shout or region say)
20        volume: sl_types::chat::ChatVolume,
21        /// the chat message without the /me
22        message: String,
23    },
24    /// a message about an avatar coming online
25    CameOnline,
26    /// a message about an avatar going offline
27    WentOffline,
28    /// a message about an avatar entering an area of significance
29    EnteredArea {
30        /// the area of significance
31        area: sl_types::radar::Area,
32        /// the distance where the avatar entered the area
33        distance: Option<sl_types::map::Distance>,
34    },
35    /// a message about an avatar leaving an area of significance
36    LeftArea {
37        /// the area of significance
38        area: sl_types::radar::Area,
39    },
40}
41
42/// parse a Second Life avatar chat message
43///
44/// # Errors
45///
46/// returns an error if the parser fails
47fn avatar_chat_message_parser() -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
48    any()
49        .repeated()
50        .collect::<String>()
51        .try_map(|s, _span: std::ops::Range<usize>| {
52            let (v, s) = sl_types::chat::ChatVolume::volume_and_message(s.to_string());
53            Ok(AvatarMessage::Chat {
54                volume: v,
55                message: s,
56            })
57        })
58}
59
60/// parse a Second Life avatar emote message
61///
62/// # Errors
63///
64/// returns an error if the parser fails
65fn avatar_emote_message_parser() -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
66    just("/me ")
67        .ignore_then(any().repeated().collect::<String>())
68        .try_map(|s, _span: std::ops::Range<usize>| {
69            let (v, s) = sl_types::chat::ChatVolume::volume_and_message(s);
70            Ok(AvatarMessage::Emote {
71                volume: v,
72                message: s,
73            })
74        })
75}
76
77/// parse a message about an avatar coming online
78///
79/// # Errors
80///
81/// returns an error if the parser fails
82pub(crate) fn avatar_came_online_message_parser(
83) -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
84    just("is online.").map(|_| AvatarMessage::CameOnline)
85}
86
87/// parse a message about an avatar going offline
88///
89/// # Errors
90///
91/// returns an error if the parser fails
92pub(crate) fn avatar_went_offline_message_parser(
93) -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
94    just("is offline.").map(|_| AvatarMessage::WentOffline)
95}
96
97/// parse a message about an avatar entering an area of significance
98///
99/// # Errors
100///
101/// returns an error if the parser fails
102pub(crate) fn avatar_entered_area_message_parser(
103) -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
104    just("entered ")
105        .ignore_then(sl_types::radar::area_parser())
106        .then(
107            just(" (")
108                .ignore_then(sl_types::map::distance_parser())
109                .then_ignore(just(")"))
110                .or_not(),
111        )
112        .then_ignore(just("."))
113        .try_map(|(area, distance), _span: std::ops::Range<usize>| {
114            Ok(AvatarMessage::EnteredArea { area, distance })
115        })
116}
117
118/// parse a message about an avatar leaving an area of significance
119///
120/// # Errors
121///
122/// returns an error if the parser fails
123pub(crate) fn avatar_left_area_message_parser(
124) -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
125    just("left ")
126        .ignore_then(sl_types::radar::area_parser())
127        .then_ignore(just("."))
128        .try_map(|area, _span: std::ops::Range<usize>| Ok(AvatarMessage::LeftArea { area }))
129}
130
131/// parse a Second Life avatar message
132///
133/// # Errors
134///
135/// returns an error if the parser fails
136#[must_use]
137pub fn avatar_message_parser() -> impl Parser<char, AvatarMessage, Error = Simple<char>> {
138    choice([
139        avatar_came_online_message_parser().boxed(),
140        avatar_went_offline_message_parser().boxed(),
141        avatar_entered_area_message_parser().boxed(),
142        avatar_left_area_message_parser().boxed(),
143        avatar_emote_message_parser().boxed(),
144        avatar_chat_message_parser().boxed(),
145    ])
146}