Skip to content

Commit

Permalink
feat: store scraped votes into db (just p1)
Browse files Browse the repository at this point in the history
  • Loading branch information
JacksonVirgo committed Aug 3, 2024
1 parent 50c1410 commit 14dda4e
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 32 deletions.
8 changes: 6 additions & 2 deletions migrations/0001_initial.sql
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ CREATE TABLE IF NOT EXISTS players (
FOREIGN KEY (thread_id) REFERENCES threads(thread_id) ON DELETE CASCADE
);

# Add a new element to players. replacements TEXT[] NOT NULL DEFAULT '{}

ALTER TABLE players
ADD COLUMN IF NOT EXISTS replacements TEXT[] NOT NULL DEFAULT '{}';

Expand All @@ -60,3 +58,9 @@ CREATE TABLE IF NOT EXISTS votes (
FOREIGN KEY (thread_id) REFERENCES threads(thread_id) ON DELETE CASCADE,
FOREIGN KEY (player_id) REFERENCES players(id) ON DELETE CASCADE
)

ALTER TABLE votes
DROP CONSTRAINT IF EXISTS votes_player_id_fkey;

ALTER TABLE votes
DROP COLUMN IF EXISTS player_id;
37 changes: 15 additions & 22 deletions src/models/votes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ pub struct Vote {

// FKs
pub thread_id: String,
pub player_id: i32,
}

pub struct NewVote {
pub author: String,
pub target: String,
pub post_number: i32,
pub target_correction: Option<String>,
pub thread_id: String,
}

pub enum VoteQuery {
Expand All @@ -26,7 +33,7 @@ pub async fn get_vote(state: &Data<AppState>, id: i32) -> Option<Vote> {
let db = &state.db;
match sqlx::query_as!(
Vote,
r#"SELECT id, author, target, post_number, target_correction, thread_id, player_id FROM votes WHERE id = $1"#,
r#"SELECT id, author, target, post_number, target_correction, thread_id FROM votes WHERE id = $1"#,
id
)
.fetch_one(db)
Expand All @@ -37,44 +44,30 @@ pub async fn get_vote(state: &Data<AppState>, id: i32) -> Option<Vote> {
}
}

pub async fn get_votes(state: &Data<AppState>, query: VoteQuery) -> Option<Vec<Vote>> {
pub async fn get_votes(state: &Data<AppState>, thread_id: &str) -> Option<Vec<Vote>> {
let db = &state.db;
match query {
VoteQuery::Thread(thread_id) => match sqlx::query_as!(
match sqlx::query_as!(
Vote,
r#"SELECT id, author, target, post_number, target_correction, thread_id, player_id FROM votes WHERE thread_id = $1"#,
r#"SELECT id, author, target, post_number, target_correction, thread_id FROM votes WHERE thread_id = $1"#,
thread_id
)
.fetch_all(db)
.await
{
Ok(votes) => Some(votes),
_ => None,
},
VoteQuery::Player(player_id) => match sqlx::query_as!(
Vote,
r#"SELECT id, author, target, post_number, target_correction, thread_id, player_id FROM votes WHERE player_id = $1"#,
player_id
)
.fetch_all(db)
.await
{
Ok(votes) => Some(votes),
_ => None,
}
}
}
}

pub async fn create_vote(state: &Data<AppState>, vote: Vote) -> Option<PgQueryResult> {
pub async fn create_vote(state: &Data<AppState>, vote: NewVote) -> Option<PgQueryResult> {
let db = &state.db;
match sqlx::query!(
"INSERT INTO votes (author, target, post_number, target_correction, thread_id, player_id) VALUES ($1, $2, $3, $4, $5, $6)",
"INSERT INTO votes (author, target, post_number, target_correction, thread_id) VALUES ($1, $2, $3, $4, $5)",
vote.author,
vote.target,
vote.post_number,
vote.target_correction,
vote.thread_id,
vote.player_id
)
.execute(db)
.await
Expand Down
26 changes: 22 additions & 4 deletions src/routes/api/dashboard/vote_data.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ components::buttons::{gen_button, ButtonType, FormSubmitButton}, models::votes::get_votes, utils::{app_state::AppState, url::ForumURL}};
use crate::{ components::buttons::{gen_button, ButtonType, FormSubmitButton}, models::votes::{create_vote, get_votes, NewVote}, utils::{app_state::AppState, url::ForumURL}};
use actix_web::{get, post, web::{self, Data}, HttpResponse, Responder};
use maud::{html, Markup};

Expand Down Expand Up @@ -35,7 +35,7 @@ fn format_table_row(row: TableRow) -> Markup {
async fn vote_data(state: Data<AppState>, path: web::Path<String>) -> impl Responder {
let thread_id = path.into_inner();

let all_votes = match get_votes(&state, crate::models::votes::VoteQuery::Thread(thread_id.clone())).await {
let all_votes = match get_votes(&state, &thread_id).await {
Some(votes) => votes,
None => Vec::new()
};
Expand Down Expand Up @@ -86,17 +86,35 @@ async fn vote_data(state: Data<AppState>, path: web::Path<String>) -> impl Respo
}

#[post("/votes/{thread_id}")]
async fn scrape_votes(_: Data<AppState>, path: web::Path<String>) -> impl Responder {
async fn scrape_votes(state: Data<AppState>, path: web::Path<String>) -> impl Responder {
let thread_id = path.into_inner();
let url = ForumURL::new(thread_id.clone());
let page_data = match url.scrape().await {
let initial_page = match url.scrape().await {
Some(page_data) => page_data,
None => {
println!("Failed to get page data");
return HttpResponse::Found().insert_header(("HX-Redirect", format!("/dashboard/{}?d=2", thread_id))).finish()
}
};

for vote in initial_page.votes {
let vote_copy = vote.clone();
let pg = create_vote(&state, NewVote {
thread_id: thread_id.clone(),
author: vote.author,
target: vote.target,
target_correction: None,
post_number: vote.post_number
}).await;

match pg {
Some(_) => println!("Created vote: {:?}", vote_copy),
None => {
println!("Failed to create vote: {:?}", vote_copy);
}
}
}

HttpResponse::Found()
.insert_header(("HX-Redirect", format!("/dashboard/{}?d=2", thread_id))).finish()
}
14 changes: 10 additions & 4 deletions src/scraping/scraper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct PageData {
pub last_page: i32,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Vote {
pub author: String,
pub target: String,
Expand All @@ -39,6 +39,8 @@ pub async fn get_page_details(url: String) -> Option<PageData> {
let (current_page, last_page) = scrape_pagination(&document);
let votes = scrape_votes(&document);

println!("Found {} votes", votes.len());

match (thread_id, current_page, last_page) {
(Some(thread_id), Some(current_page), Some(last_page)) => Some(PageData {
thread_id,
Expand Down Expand Up @@ -113,7 +115,7 @@ pub fn scrape_header(document: &Document) -> Option<String> {
}

pub fn scrape_votes(document: &Document) -> Vec<Vote> {
let votes: Vec<Vote> = Vec::new();
let mut response: Vec<Vote> = Vec::new();

document.find(Class("post")).for_each(|node| {
let votes: Vec<String> = node
Expand Down Expand Up @@ -155,13 +157,17 @@ pub fn scrape_votes(document: &Document) -> Vec<Vote> {
match (author, post_number) {
(Some(author), Some(post_number)) => {
for vote in votes {
println!("{} voted {} in post {}", author, vote, post_number);
response.push(Vote {
author: author.clone(),
target: vote,
post_number,
})
}
}
_ => (),
}
}
});

votes
response
}

0 comments on commit 14dda4e

Please sign in to comment.