1use std::str::Utf8Error;
2
3use serde_json::Value;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
8pub enum Error {
9 #[error("Tungstenite error: {0}")]
10 Websocket(#[from] tungstenite::Error),
11 #[error("Decompress error: {0}")]
12 Decompress(#[from] flate2::DecompressError),
13 #[error("JSON utf8 error: {0}")]
14 Utf8(#[from] Utf8Error),
15 #[error("JSON error: {0}")]
16 JSON(#[from] serde_json::Error),
17 #[error("Blocking error: {0}")]
18 Blocking(#[from] BlockingError),
19 #[error("Failed to login (bad username, password or cookie).")]
20 LoginFailed,
21 #[error("Failed to register.")]
22 RegisterFailed,
23}
24
25#[derive(Error, Debug)]
36pub enum BlockingError {
37 #[error("Custom seed selection menu.")]
38 SeedSelection,
39 #[error("New game choice selection menu.")]
40 NewGameChoice,
41 #[error("Blocking due to 'more' message.")]
42 More,
43 #[error("Blocking due to text input necessary from user (likely for level up message).")]
44 TextInput,
45 #[error("Blocking due to a pickup menu popup.")]
46 Pickup,
47 #[error("Blocking due to a 'acquirement' menu popup.")]
48 Acquirement(Value),
49 #[error("Blocking due to a 'identify' menu popup.")]
50 Identify(Value),
51 #[error("Blocking due to a 'enchant weapon' menu popup.")]
52 EnchantWeapon(Value),
53 #[error("Blocking due to a 'brand item' menu popup.")]
54 EnchantItem(Value),
55 #[error("Blocking due to a 'brand weapon' menu popup.")]
56 BrandWeapon(Value),
57 #[error("Blocking due to a 'skills to train' txt menu.")]
58 Skill,
59 #[error("Blocking due to a 'blink' action.")]
60 Blink,
61 #[error("Blocking due to an 'equipping' action.")]
62 Equipping,
63 #[error("Blocking due to an 'disrobing' action.")]
64 Disrobing,
65 #[error("Blocking due to a 'scroll of noise' read prompt.")]
66 Noise,
67 #[error("Character died.")]
68 Died,
69}
70
71pub(crate) fn blocking_messages(message: &Value) -> Result<(), Box<Error>> {
80 let msg = message["msg"].as_str().unwrap();
81
82 match msg {
83 "input_mode" => {
84 if message["mode"].as_u64().unwrap() == 5 {
85 Err(Box::new(Error::Blocking(BlockingError::More)))
86 } else if message["mode"].as_u64().unwrap() == 7 {
87 Err(Box::new(Error::Blocking(BlockingError::TextInput)))
88 } else {
89 Ok(())
90 }
91 }
92 "menu" => {
93 if message["tag"] == "pickup" {
94 Err(Box::new(Error::Blocking(BlockingError::Pickup)))
95 } else if message["tag"] == "acquirement" {
96 Err(Box::new(Error::Blocking(BlockingError::Acquirement(
97 message.clone(),
98 ))))
99 } else if message["tag"] == "use_item" {
100 match message["title"]["text"].as_str().unwrap() {
101 x if x.contains("Identify which item?") => Err(Box::new(Error::Blocking(
102 BlockingError::Identify(message.clone()),
103 ))),
104 x if x.contains("Enchant which weapon?") => Err(Box::new(Error::Blocking(
105 BlockingError::EnchantWeapon(message.clone()),
106 ))),
107 x if x.contains("Enchant which item?") => Err(Box::new(Error::Blocking(
108 BlockingError::EnchantItem(message.clone()),
109 ))),
110 x if x.contains("Brand which weapon?") => Err(Box::new(Error::Blocking(
111 BlockingError::BrandWeapon(message.clone()),
112 ))),
113 _ => Ok(()),
114 }
115 } else {
116 Ok(())
117 }
118 }
119 "txt" => {
120 let lines_obj = message.as_object().unwrap()["lines"].as_object().unwrap();
121
122 if lines_obj.contains_key("0")
123 && lines_obj[&("0".to_string())]
124 .as_str()
125 .unwrap()
126 .to_owned()
127 .contains("Select the skills to train")
128 {
129 return Err(Box::new(Error::Blocking(BlockingError::Skill)));
130 }
131
132 Ok(())
133 }
134 "msgs" => {
135 if !message.as_object().unwrap().contains_key("messages") {
136 Ok(())
137 } else {
138 for text_obj in message["messages"].as_array().unwrap() {
139 let text = text_obj["text"].as_str().unwrap();
140
141 if text.contains("You die...") {
142 return Err(Box::new(Error::Blocking(BlockingError::Died)));
143 }
144
145 if text.contains("Blink to where?") {
146 return Err(Box::new(Error::Blocking(BlockingError::Blink)));
147 }
148
149 if text.contains("Really read the scroll of noise?") {
150 return Err(Box::new(Error::Blocking(BlockingError::Noise)));
151 }
152
153 if text.contains("Keep equipping yourself?") {
154 return Err(Box::new(Error::Blocking(BlockingError::Equipping)));
155 }
156
157 if text.contains("Keep disrobing?") {
158 return Err(Box::new(Error::Blocking(BlockingError::Disrobing)));
159 }
160 }
161 Ok(())
162 }
163 }
164 "login_fail" => Err(Box::new(Error::LoginFailed)),
165 "register_fail" => Err(Box::new(Error::RegisterFailed)),
166 "ui-push" => {
167 if !message.as_object().unwrap().contains_key("type") {
168 Ok(())
169 } else {
170 if message["type"] == "seed-selection" {
171 return Err(Box::new(Error::Blocking(BlockingError::SeedSelection)));
172 } else if message["type"] == "newgame-choice" {
173 return Err(Box::new(Error::Blocking(BlockingError::NewGameChoice)));
174 }
175 Ok(())
176 }
177 }
178 _ => Ok(()),
179 }
180}