Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #[macro_use] extern crate serde_derive;
- use websocket::{client::sync::Client, stream::sync::NetworkStream};
- use websocket::{ClientBuilder, Message, WebSocketError, OwnedMessage};
- use websocket::header::{Headers, UserAgent};
- use serde_json as json;
- use rand::seq::SliceRandom;
- use rand::Rng;
- use rsgen::{gen_random_string, OutputCharsType};
- use std::error::Error;
- const ZWJ: &str = "";
- #[derive(Serialize)]
- #[serde(tag = "op", content = "data")]
- enum Op {
- Login {
- username_or_email: String,
- password: String,
- },
- Register {
- username: String,
- password: String,
- password_verify: String,
- admin: bool,
- spam_timer: i64,
- spam_timeri: i64,
- },
- CreateCommunity {
- name: String,
- title: String,
- category_id: u32,
- auth: String,
- },
- CreatePost {
- name: String,
- body: String,
- community_id: u32,
- creator_id: u32,
- auth: String,
- },
- }
- #[derive(Deserialize)]
- #[serde(untagged)]
- enum Response {
- Error { error: String },
- Success(ResponseValue),
- }
- #[derive(Deserialize)]
- #[serde(tag = "op")]
- enum ResponseValue {
- Register { jwt: String },
- Login { jwt: String },
- CreateCommunity { community: Community }
- }
- #[derive(Deserialize)]
- struct Community {
- category_id: u32,
- category_name: String,
- creator_id: u32,
- creator_name: String,
- description: Option<String>,
- id: u32,
- name: String,
- number_of_comments: u32,
- number_of_posts: u32,
- number_of_subscribers: u32,
- published: String, // datetime
- removed: bool,
- subscribed: bool,
- title: String,
- updated: Option<String>, // datetime?
- user_id: u32,
- }
- struct Context {
- ws: Client<Box<dyn NetworkStream + Send>>,
- rng: rand::rngs::ThreadRng,
- words: Vec<&'static str>,
- auth: Option<String>,
- }
- impl Context {
- fn new() -> Result<Self, Box<Error>> {
- let mut headers = Headers::new();
- headers.set(UserAgent("Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0".into()));
- Ok(Self {
- ws: ClientBuilder::new("wss://dev.lemmy.ml/service/ws")?
- .custom_headers(&headers)
- .connect(None)?,
- rng: rand::thread_rng(),
- words: include_str!("/usr/share/dict/american-english")
- .lines()
- .filter(|s| s.len() <= 5)
- .filter(|s| s.chars().all(|c| c.is_ascii_alphabetic() && c.is_lowercase()))
- .map(|s| s.trim())
- .collect(),
- auth: None,
- })
- }
- fn run(&mut self) -> Result<(), Box<Error>> {
- loop {
- self.spam()?;
- }
- // std::thread::sleep_ms(500);
- }
- fn spam(&mut self) -> Result<(), Box<Error>> {
- let username = self.generate_name();
- let password = self.generate_name();
- let post = gen_random_string(1024 * 10, OutputCharsType::PrintableAsciiWithSpace);
- self.register(&*username, &*password).or_else(|_| self.login(&*username, &*password))?;
- let community_name = self.generate_name();
- let community_descr = self.generate_name();
- let community_category = self.rng.gen_range(1, 25);
- println!(">>> {}", community_name);
- let community = self.create_community(&*community_name, &*community_descr, community_category)?;
- let num_posts = self.rng.gen_range(1, 21);
- for _ in 0..num_posts {
- let post_name = self.generate_name();
- self.create_post(&community, post_name, &*post)?;
- }
- Ok(())
- }
- fn create_post(&mut self, community: &Community, name: impl Into<String>, body: impl Into<String>) -> Result<(), Box<Error>> {
- let op = Op::CreatePost {
- community_id: community.id,
- creator_id: community.creator_id,
- body: body.into(),
- name: name.into(),
- auth: self.auth.clone().expect("auth"),
- };
- self.ws.send_message(&Message::text(json::to_string(&op)?))?;
- self.recv_string_message()?;
- Ok(())
- }
- fn create_community(&mut self, name: impl Into<String>, title: impl Into<String>, category_id: u32) -> Result<Community, Box<Error>> {
- let op = Op::CreateCommunity {
- name: name.into(),
- title: title.into(),
- category_id,
- auth: self.auth.clone().expect("auth"),
- };
- self.ws.send_message(&Message::text(json::to_string(&op)?))?;
- let community = match self.recv_response()? {
- Response::Success(ResponseValue::CreateCommunity { community }) => community,
- Response::Error { error } => return Err(error)?,
- _ => panic!("unexpected response op"),
- };
- Ok(community)
- }
- fn login(&mut self, username: impl Into<String>, password: impl Into<String>) -> Result<(), Box<Error>> {
- let login = Op::Login {
- username_or_email: username.into(),
- password: password.into(),
- };
- self.ws.send_message(&Message::text(json::to_string(&login)?))?;
- let auth = match self.recv_response()? {
- Response::Success(ResponseValue::Login { jwt }) => jwt,
- Response::Error { error } => return Err(error)?,
- _ => panic!("unexpected response op"),
- };
- self.auth = Some(auth);
- Ok(())
- }
- fn register(&mut self, username: impl Into<String>, password: impl Into<String>) -> Result<(), Box<Error>> {
- let password = password.into();
- let register = Op::Register {
- username: username.into(),
- password: password.clone(),
- password_verify: password,
- admin: false,
- spam_timer: self.rng.gen_range(2000, 10000),
- spam_timeri: self.rng.gen_range(2000, 10000),
- };
- self.ws.send_message(&Message::text(json::to_string(®ister)?))?;
- let auth = match self.recv_response()? {
- Response::Success(ResponseValue::Register { jwt }) => jwt,
- Response::Error { error } => return Err(error)?,
- _ => panic!("unexpected response op"),
- };
- self.auth = Some(auth);
- Ok(())
- }
- fn recv_response(&mut self) -> Result<Response, Box<Error>> {
- let msg = self.recv_string_message()?;
- Ok(json::from_str(&msg)?)
- }
- fn recv_string_message(&mut self) -> Result<String, Box<Error>> {
- let mut n = 0;
- loop {
- let msg = self.ws.recv_message();
- println!("{:?}", msg);
- match msg {
- Err(WebSocketError::NoDataAvailable) => {
- if n <= 10 {
- n += 1;
- continue;
- }
- return Err("Too many NoDataAvailable")?;
- },
- Ok(OwnedMessage::Ping(msg)) => {
- self.ws.send_message(&Message::pong(msg))?;
- continue;
- },
- Ok(OwnedMessage::Text(text)) => return Ok(text),
- _ => unimplemented!("unhandled ws mesage type"),
- }
- }
- }
- fn generate_name(&mut self) -> String {
- let word1 = *self.words.choose(&mut self.rng).expect("random word 1");
- let word2 = *self.words.choose(&mut self.rng).expect("random word 2");
- word1.to_string() + word2
- }
- }
- fn main() {
- color_backtrace::install();
- loop {
- if let Err(e) = Context::new().and_then(|mut c| c.run()) {
- println!("\n\n#!!! Error: {}\n\n", e);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement