Advertisement
Guest User

Untitled

a guest
May 7th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.49 KB | None | 0 0
  1. #[macro_use] extern crate serde_derive;
  2. use websocket::{client::sync::Client, stream::sync::NetworkStream};
  3. use websocket::{ClientBuilder, Message, WebSocketError, OwnedMessage};
  4. use websocket::header::{Headers, UserAgent};
  5. use serde_json as json;
  6. use rand::seq::SliceRandom;
  7. use rand::Rng;
  8. use rsgen::{gen_random_string, OutputCharsType};
  9. use std::error::Error;
  10.  
  11. const ZWJ: &str = "‍";
  12.  
  13. #[derive(Serialize)]
  14. #[serde(tag = "op", content = "data")]
  15. enum Op {
  16. Login {
  17. username_or_email: String,
  18. password: String,
  19. },
  20. Register {
  21. username: String,
  22. password: String,
  23. password_verify: String,
  24. admin: bool,
  25. spam_timer: i64,
  26. spam_timeri: i64,
  27. },
  28. CreateCommunity {
  29. name: String,
  30. title: String,
  31. category_id: u32,
  32. auth: String,
  33. },
  34. CreatePost {
  35. name: String,
  36. body: String,
  37. community_id: u32,
  38. creator_id: u32,
  39. auth: String,
  40. },
  41. }
  42.  
  43. #[derive(Deserialize)]
  44. #[serde(untagged)]
  45. enum Response {
  46. Error { error: String },
  47. Success(ResponseValue),
  48. }
  49.  
  50.  
  51. #[derive(Deserialize)]
  52. #[serde(tag = "op")]
  53. enum ResponseValue {
  54. Register { jwt: String },
  55. Login { jwt: String },
  56. CreateCommunity { community: Community }
  57. }
  58.  
  59. #[derive(Deserialize)]
  60. struct Community {
  61. category_id: u32,
  62. category_name: String,
  63. creator_id: u32,
  64. creator_name: String,
  65. description: Option<String>,
  66. id: u32,
  67. name: String,
  68. number_of_comments: u32,
  69. number_of_posts: u32,
  70. number_of_subscribers: u32,
  71. published: String, // datetime
  72. removed: bool,
  73. subscribed: bool,
  74. title: String,
  75. updated: Option<String>, // datetime?
  76. user_id: u32,
  77. }
  78.  
  79. struct Context {
  80. ws: Client<Box<dyn NetworkStream + Send>>,
  81. rng: rand::rngs::ThreadRng,
  82. words: Vec<&'static str>,
  83. auth: Option<String>,
  84. }
  85.  
  86. impl Context {
  87. fn new() -> Result<Self, Box<Error>> {
  88. let mut headers = Headers::new();
  89. headers.set(UserAgent("Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0".into()));
  90.  
  91. Ok(Self {
  92. ws: ClientBuilder::new("wss://dev.lemmy.ml/service/ws")?
  93. .custom_headers(&headers)
  94. .connect(None)?,
  95. rng: rand::thread_rng(),
  96. words: include_str!("/usr/share/dict/american-english")
  97. .lines()
  98. .filter(|s| s.len() <= 5)
  99. .filter(|s| s.chars().all(|c| c.is_ascii_alphabetic() && c.is_lowercase()))
  100. .map(|s| s.trim())
  101. .collect(),
  102. auth: None,
  103. })
  104. }
  105.  
  106. fn run(&mut self) -> Result<(), Box<Error>> {
  107. loop {
  108. self.spam()?;
  109. }
  110. // std::thread::sleep_ms(500);
  111. }
  112.  
  113. fn spam(&mut self) -> Result<(), Box<Error>> {
  114. let username = self.generate_name();
  115. let password = self.generate_name();
  116. let post = gen_random_string(1024 * 10, OutputCharsType::PrintableAsciiWithSpace);
  117.  
  118. self.register(&*username, &*password).or_else(|_| self.login(&*username, &*password))?;
  119.  
  120. let community_name = self.generate_name();
  121. let community_descr = self.generate_name();
  122. let community_category = self.rng.gen_range(1, 25);
  123.  
  124. println!(">>> {}", community_name);
  125.  
  126. let community = self.create_community(&*community_name, &*community_descr, community_category)?;
  127. let num_posts = self.rng.gen_range(1, 21);
  128.  
  129. for _ in 0..num_posts {
  130. let post_name = self.generate_name();
  131. self.create_post(&community, post_name, &*post)?;
  132. }
  133.  
  134. Ok(())
  135. }
  136.  
  137. fn create_post(&mut self, community: &Community, name: impl Into<String>, body: impl Into<String>) -> Result<(), Box<Error>> {
  138. let op = Op::CreatePost {
  139. community_id: community.id,
  140. creator_id: community.creator_id,
  141. body: body.into(),
  142. name: name.into(),
  143. auth: self.auth.clone().expect("auth"),
  144. };
  145. self.ws.send_message(&Message::text(json::to_string(&op)?))?;
  146. self.recv_string_message()?;
  147.  
  148. Ok(())
  149. }
  150.  
  151. fn create_community(&mut self, name: impl Into<String>, title: impl Into<String>, category_id: u32) -> Result<Community, Box<Error>> {
  152. let op = Op::CreateCommunity {
  153. name: name.into(),
  154. title: title.into(),
  155. category_id,
  156. auth: self.auth.clone().expect("auth"),
  157. };
  158. self.ws.send_message(&Message::text(json::to_string(&op)?))?;
  159. let community = match self.recv_response()? {
  160. Response::Success(ResponseValue::CreateCommunity { community }) => community,
  161. Response::Error { error } => return Err(error)?,
  162. _ => panic!("unexpected response op"),
  163. };
  164.  
  165. Ok(community)
  166. }
  167.  
  168. fn login(&mut self, username: impl Into<String>, password: impl Into<String>) -> Result<(), Box<Error>> {
  169. let login = Op::Login {
  170. username_or_email: username.into(),
  171. password: password.into(),
  172. };
  173. self.ws.send_message(&Message::text(json::to_string(&login)?))?;
  174. let auth = match self.recv_response()? {
  175. Response::Success(ResponseValue::Login { jwt }) => jwt,
  176. Response::Error { error } => return Err(error)?,
  177. _ => panic!("unexpected response op"),
  178. };
  179.  
  180. self.auth = Some(auth);
  181.  
  182. Ok(())
  183. }
  184.  
  185. fn register(&mut self, username: impl Into<String>, password: impl Into<String>) -> Result<(), Box<Error>> {
  186. let password = password.into();
  187. let register = Op::Register {
  188. username: username.into(),
  189. password: password.clone(),
  190. password_verify: password,
  191. admin: false,
  192. spam_timer: self.rng.gen_range(2000, 10000),
  193. spam_timeri: self.rng.gen_range(2000, 10000),
  194. };
  195. self.ws.send_message(&Message::text(json::to_string(&register)?))?;
  196. let auth = match self.recv_response()? {
  197. Response::Success(ResponseValue::Register { jwt }) => jwt,
  198. Response::Error { error } => return Err(error)?,
  199. _ => panic!("unexpected response op"),
  200. };
  201.  
  202. self.auth = Some(auth);
  203.  
  204. Ok(())
  205. }
  206.  
  207. fn recv_response(&mut self) -> Result<Response, Box<Error>> {
  208. let msg = self.recv_string_message()?;
  209. Ok(json::from_str(&msg)?)
  210. }
  211.  
  212. fn recv_string_message(&mut self) -> Result<String, Box<Error>> {
  213. let mut n = 0;
  214. loop {
  215. let msg = self.ws.recv_message();
  216. println!("{:?}", msg);
  217.  
  218. match msg {
  219. Err(WebSocketError::NoDataAvailable) => {
  220. if n <= 10 {
  221. n += 1;
  222. continue;
  223. }
  224. return Err("Too many NoDataAvailable")?;
  225. },
  226. Ok(OwnedMessage::Ping(msg)) => {
  227. self.ws.send_message(&Message::pong(msg))?;
  228. continue;
  229. },
  230. Ok(OwnedMessage::Text(text)) => return Ok(text),
  231. _ => unimplemented!("unhandled ws mesage type"),
  232. }
  233. }
  234. }
  235.  
  236. fn generate_name(&mut self) -> String {
  237. let word1 = *self.words.choose(&mut self.rng).expect("random word 1");
  238. let word2 = *self.words.choose(&mut self.rng).expect("random word 2");
  239. word1.to_string() + word2
  240. }
  241. }
  242.  
  243. fn main() {
  244. color_backtrace::install();
  245.  
  246. loop {
  247. if let Err(e) = Context::new().and_then(|mut c| c.run()) {
  248. println!("\n\n#!!! Error: {}\n\n", e);
  249. }
  250. }
  251. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement