Skip to content

Commit

Permalink
Write routes using the library
Browse files Browse the repository at this point in the history
  • Loading branch information
parksb committed Aug 29, 2024
1 parent 8abec5d commit 181bc37
Show file tree
Hide file tree
Showing 12 changed files with 587 additions and 684 deletions.
609 changes: 331 additions & 278 deletions Cargo.lock

Large diffs are not rendered by default.

15 changes: 2 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,12 @@ edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
rusqlite = "0.28"
sea-query = "0"
sea-query-rusqlite = { version = "0", features = ["with-chrono"] }
rss = "2.0"
atom_syndication = "0.12"
reqwest = { version = "0.11", features = ["blocking"] }
sha1_smol = { version = "1", features = ["std"] }
thiserror = "1.0"
regex = "1.9"
scraper = "0.18.1"
clap = { version = "4.0", features = ["derive"] }
log = "0.4"
pretty_env_logger = "0.4"
tokio = { version = "1.0", features = ["full"] }
axum = "0.7"
daemonize = "0.5"
rand = "0.8.5"
toml = "0.8.19"
jsonwebtoken = "9.3.0"
thiserror = "1.0"
collie = { path = "../lib/collie", features = ["auth"] }
93 changes: 93 additions & 0 deletions src/adapter/feed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use axum::{
extract::{Path, State},
http::StatusCode,
Json,
};
use collie::{
model::feed::{self, Feed, FeedToCreate, FeedToUpdate},
producer::{
syndication::{fetch_content, fetch_feed_title, find_feed_link, Feed as SyndicationFeed},
worker::create_new_items,
},
};

use crate::serve::AppState;

pub async fn create(
State(AppState { conn, config }): State<AppState>,
Json(arg): Json<FeedToCreate>,
) -> (StatusCode, Json<bool>) {
if arg.link.is_empty() {
return (StatusCode::BAD_REQUEST, Json(false));
}

let proxy = config.producer.proxy;
let html_content = fetch_content(&arg.link, proxy.as_deref()).unwrap();
let is_feed = html_content.parse::<SyndicationFeed>().is_ok();

let link = if is_feed {
arg.link.clone()
} else if let Some(rss_link) = find_feed_link(&html_content).unwrap() {
rss_link
} else {
return (StatusCode::BAD_REQUEST, Json(false));
};

let title = match fetch_feed_title(&link, proxy.as_deref()) {
Ok(title) => title,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
};

let arg = FeedToCreate {
title,
link,
fetch_old_items: arg.fetch_old_items,
};

match feed::create(&conn, &arg) {
Ok(_) => {
let _ = create_new_items(&conn, proxy.as_deref());
(StatusCode::OK, Json(true))
}
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
}
}

pub async fn read_all(
State(AppState { conn, .. }): State<AppState>,
) -> (StatusCode, Json<Vec<Feed>>) {
match feed::read_all(&conn) {
Ok(feeds) => (StatusCode::OK, Json(feeds)),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(vec![])),
}
}

pub async fn read(
State(AppState { conn, .. }): State<AppState>,
Path(id): Path<i32>,
) -> (StatusCode, Json<Option<Feed>>) {
match feed::read(&conn, id) {
Ok(feed) => (StatusCode::OK, Json(feed)),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(None)),
}
}

pub async fn update(
State(AppState { conn, .. }): State<AppState>,
Json(arg): Json<FeedToUpdate>,
) -> (StatusCode, Json<bool>) {
match feed::update(&conn, &arg) {
Ok(_) => (StatusCode::OK, Json(true)),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
}
}

pub async fn delete(
State(AppState { conn, .. }): State<AppState>,
Path(id): Path<i32>,
) -> (StatusCode, Json<bool>) {
match feed::delete(&conn, id) {
Ok(_) => (StatusCode::OK, Json(true)),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
}
}
80 changes: 80 additions & 0 deletions src/adapter/item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use axum::{extract::State, http::StatusCode, Json};
use collie::model::item::{
self, Item, ItemReadOption, ItemToCreate, ItemToUpdate, ItemToUpdateAll,
};

use crate::serve::AppState;

pub async fn create(
State(AppState { conn, .. }): State<AppState>,
Json(arg): Json<ItemToCreate>,
) -> (StatusCode, Json<bool>) {
match item::create(&conn, &arg) {
Ok(count) => {
if count > 0 {
(StatusCode::OK, Json(true))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Json(false))
}
}
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
}
}

pub async fn read_all(
State(AppState { conn, .. }): State<AppState>,
Json(arg): Json<ItemReadOption>,
) -> (StatusCode, Json<Vec<Item>>) {
match item::read_all(&conn, &arg) {
Ok(items) => (StatusCode::OK, Json(items)),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(vec![])),
}
}

pub async fn count_all(
State(AppState { conn, .. }): State<AppState>,
Json(arg): Json<ItemReadOption>,
) -> (StatusCode, Json<i64>) {
match item::count_all(&conn, &arg) {
Ok(count) => {
if count > 0 {
(StatusCode::OK, Json(count))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Json(0))
}
}
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(0)),
}
}

pub async fn update(
State(AppState { conn, .. }): State<AppState>,
Json(arg): Json<ItemToUpdate>,
) -> (StatusCode, Json<bool>) {
match item::update(&conn, &arg) {
Ok(count) => {
if count > 0 {
(StatusCode::OK, Json(true))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Json(false))
}
}
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
}
}

pub async fn update_all(
State(AppState { conn, .. }): State<AppState>,
Json(arg): Json<ItemToUpdateAll>,
) -> (StatusCode, Json<bool>) {
match item::update_all(&conn, &arg) {
Ok(count) => {
if count > 0 {
(StatusCode::OK, Json(true))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Json(false))
}
}
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(false)),
}
}
11 changes: 9 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@ use std::path::PathBuf;

use serde::Deserialize;

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
pub stage: String,
pub database: DatabaseConfig,
pub producer: ProducerConfig,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Clone)]
pub struct DatabaseConfig {
pub path: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct ProducerConfig {
pub polling_frequency: u64,
pub proxy: Option<String>,
}

pub fn from(path: &PathBuf) -> Config {
let config = std::fs::read_to_string(path).expect("Failed to read config file.");
toml::from_str(&config).expect("Failed to parse config file.")
Expand Down
43 changes: 0 additions & 43 deletions src/core/auth/key.rs

This file was deleted.

51 changes: 0 additions & 51 deletions src/core/auth/token.rs

This file was deleted.

31 changes: 4 additions & 27 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::io;

#[allow(dead_code)]
#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand All @@ -15,9 +13,6 @@ pub enum Error {
#[error("forbidden")]
Forbidden,

#[error("unauthorized")]
Unauthorized,

#[error("failed to parse syndication feed")]
SyndicationParsingFailure,

Expand All @@ -34,33 +29,15 @@ pub enum Error {
Unknown,

#[error(transparent)]
RusqliteError {
CollieCore {
#[from]
source: rusqlite::Error,
source: collie::error::Error,
},

#[error(transparent)]
SeaQueryError {
#[from]
source: sea_query::error::Error,
},

#[error(transparent)]
ReqwestError {
#[from]
source: reqwest::Error,
},

#[error(transparent)]
IoError {
#[from]
source: io::Error,
},

#[error("failed to ")]
JsonWebToken {
CollieAuth {
#[from]
source: jsonwebtoken::errors::Error,
source: collie::auth::error::Error,
},
}

Expand Down
Loading

0 comments on commit 181bc37

Please sign in to comment.