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<(), 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(Error::Blocking(BlockingError::More))
86 } else if message["mode"].as_u64().unwrap() == 7 {
87 Err(Error::Blocking(BlockingError::TextInput))
88 } else {
89 Ok(())
90 }
91 }
92 "menu" => {
93 if message["tag"] == "pickup" {
94 Err(Error::Blocking(BlockingError::Pickup))
95 } else if message["tag"] == "acquirement" {
96 Err(Error::Blocking(BlockingError::Acquirement(message.clone())))
97 } else if message["tag"] == "use_item" {
98 match message["title"]["text"].as_str().unwrap() {
99 x if x.contains("Identify which item?") => {
100 Err(Error::Blocking(BlockingError::Identify(message.clone())))
101 }
102 x if x.contains("Enchant which weapon?") => Err(Error::Blocking(
103 BlockingError::EnchantWeapon(message.clone()),
104 )),
105 x if x.contains("Enchant which item?") => {
106 Err(Error::Blocking(BlockingError::EnchantItem(message.clone())))
107 }
108 x if x.contains("Brand which weapon?") => {
109 Err(Error::Blocking(BlockingError::BrandWeapon(message.clone())))
110 }
111 _ => Ok(()),
112 }
113 } else {
114 Ok(())
115 }
116 }
117 "txt" => {
118 let lines_obj = message.as_object().unwrap()["lines"].as_object().unwrap();
119
120 if lines_obj.contains_key("0")
121 && lines_obj[&("0".to_string())]
122 .as_str()
123 .unwrap()
124 .to_owned()
125 .contains("Select the skills to train")
126 {
127 return Err(Error::Blocking(BlockingError::Skill));
128 }
129
130 Ok(())
131 }
132 "msgs" => {
133 if !message.as_object().unwrap().contains_key("messages") {
134 Ok(())
135 } else {
136 for text_obj in message["messages"].as_array().unwrap() {
137 let text = text_obj["text"].as_str().unwrap();
138
139 if text.contains("You die...") {
140 return Err(Error::Blocking(BlockingError::Died));
141 }
142
143 if text.contains("Blink to where?") {
144 return Err(Error::Blocking(BlockingError::Blink));
145 }
146
147 if text.contains("Really read the scroll of noise?") {
148 return Err(Error::Blocking(BlockingError::Noise));
149 }
150
151 if text.contains("Keep equipping yourself?") {
152 return Err(Error::Blocking(BlockingError::Equipping));
153 }
154
155 if text.contains("Keep disrobing?") {
156 return Err(Error::Blocking(BlockingError::Disrobing));
157 }
158 }
159 Ok(())
160 }
161 }
162 "login_fail" => Err(Error::LoginFailed),
163 "register_fail" => Err(Error::RegisterFailed),
164 "ui-push" => {
165 if !message.as_object().unwrap().contains_key("type") {
166 Ok(())
167 } else {
168 if message["type"] == "seed-selection" {
169 return Err(Error::Blocking(BlockingError::SeedSelection));
170 } else if message["type"] == "newgame-choice" {
171 return Err(Error::Blocking(BlockingError::NewGameChoice));
172 }
173 Ok(())
174 }
175 }
176 _ => Ok(()),
177 }
178}