1
0
This commit is contained in:
toast 2024-12-08 18:08:44 +11:00
commit 008a028564
7 changed files with 2308 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target/
.env

2132
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

24
Cargo.toml Normal file
View File

@ -0,0 +1,24 @@
[package]
name = "phpbb-abuse"
version = "0.1.0"
edition = "2024"
[dependencies]
chrono = "0.4.38"
mockd = { version = "0.4.30", features = ["all"] }
rand = "0.8.5"
sqlx = { version = "0.8.2", features = [ "runtime-tokio", "postgres" ] }
tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] }
[[bin]]
name = "forum_abuser"
path = "src/main.rs"
[profile.dev]
opt-level = 0
debug = true
[profile.release]
opt-level = 3
debug = false
strip = true

4
run.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
export $(cat .env | xargs)
clear && cargo fmt && cargo run -r

2
rust-toolchain Normal file
View File

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

20
rustfmt.toml Normal file
View File

@ -0,0 +1,20 @@
edition = "2024"
hex_literal_case = "Upper"
binop_separator = "Front"
brace_style = "SameLineWhere"
fn_params_layout = "Vertical"
imports_layout = "Vertical"
imports_granularity = "One"
fn_single_line = true
format_strings = true
max_width = 150
tab_spaces = 2
hard_tabs = false
trailing_comma = "Never"
match_block_trailing_comma = true
reorder_imports = true
reorder_modules = true
reorder_impl_items = true
trailing_semicolon = false
struct_field_align_threshold = 20
condense_wildcard_suffixes = true

124
src/main.rs Normal file
View File

@ -0,0 +1,124 @@
use {
chrono::Utc,
rand::{
Rng,
thread_rng
},
sqlx::{
PgPool,
query
},
std::error::Error,
tokio::time::{
Duration,
sleep
}
};
type AResult<T> = Result<T, Box<dyn Error>>;
async fn post_creation(
pool: &PgPool,
topic_id: i32,
forum_id: i32,
user_id: i32
) -> AResult<()> {
let fake_data = mockd::words::sentence(4);
let time = Utc::now().timestamp();
query!(
"INSERT INTO phpbb_posts (poster_id, topic_id, forum_id, post_time, post_text) VALUES ($1, $2, $3, $4, $5)",
user_id,
topic_id,
forum_id,
time as i32,
fake_data,
)
.execute(pool)
.await?;
println!("[{time}] Post created by {user_id} in topic {topic_id} & forum {forum_id}");
Ok(())
}
async fn random_account(pool: &PgPool) -> AResult<i32> {
let result = query!("SELECT user_id FROM phpbb_users WHERE user_id != 2 ORDER BY RANDOM() LIMIT 1")
.fetch_one(pool)
.await?;
Ok(result.user_id)
}
async fn random_topic(pool: &PgPool) -> AResult<(i32, i32)> {
let result = query!("SELECT topic_id, forum_id FROM phpbb_topics ORDER BY RANDOM() LIMIT 1")
.fetch_one(pool)
.await?;
Ok((result.topic_id, result.forum_id))
}
async fn account_creation(pool: &PgPool) -> AResult<i32> {
let username = mockd::internet::username();
let username_clean = username.to_lowercase().replace(|c: char| !c.is_alphanumeric(), "");
let email = format!("{username}@playground.red").to_lowercase();
let regdate_epoch = Utc::now().timestamp() as i32;
let result = query!(
"
INSERT INTO phpbb_users (
user_type, group_id, username, username_clean, user_email, user_regdate,
user_timezone, user_lang, user_style, user_colour
) VALUES (
3, 2, $1::text, $2::text, $3, $4,
'UTC', 'en', 1, '27C1E8'
) RETURNING user_id
",
username,
username_clean,
email,
regdate_epoch
)
.fetch_one(pool)
.await?;
query!(
"INSERT INTO phpbb_user_group (group_id, user_id, group_leader, user_pending) VALUES (2, $1, 0, 0)",
result.user_id
)
.execute(pool)
.await?;
println!("[{}] Account created for {username}", result.user_id);
Ok(result.user_id)
}
async fn simulate_activity(pool: &PgPool) -> AResult<()> {
let user_id = if thread_rng().gen_bool(0.4) {
random_account(pool).await?
} else {
account_creation(pool).await?
};
let (topic_id, forum_id) = random_topic(pool).await?;
post_creation(pool, topic_id, forum_id, user_id).await?;
sleep(Duration::from_secs(thread_rng().gen_range(5..30))).await;
Ok(())
}
#[tokio::main]
async fn main() {
println!("Starting phpBB activity simulator...");
let connection_uri = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set!");
let database = PgPool::connect(&connection_uri).await.unwrap();
loop {
if let Err(y) = simulate_activity(&database).await {
eprintln!("Activity simulation error: {y}")
}
sleep(Duration::from_secs(thread_rng().gen_range(10..35))).await;
}
}