Create cli binary

Just has `add-feed` command so far.
This commit is contained in:
2023-05-09 00:08:55 -04:00
parent b2a5bf5882
commit 89fdf8f95a
9 changed files with 159 additions and 28 deletions

66
src/bin/cli.rs Normal file
View File

@@ -0,0 +1,66 @@
use anyhow::Result;
use argh::FromArgs;
use dotenvy::dotenv;
use tracing::info;
use sqlx::postgres::PgPoolOptions;
use std::env;
use lib::models::feed::{CreateFeed, FeedType};
use lib::commands::add_feed::add_feed;
#[derive(FromArgs)]
/// CLI for crawlect
struct Args {
#[argh(subcommand)]
commands: Commands,
}
#[derive(FromArgs)]
#[argh(subcommand)]
enum Commands {
AddFeed(AddFeed),
}
#[derive(FromArgs)]
/// Add a feed to the database
#[argh(subcommand, name = "add-feed")]
struct AddFeed {
#[argh(option)]
/// title of the feed (max 255 characters)
title: String,
#[argh(option)]
/// URL of the feed (max 2048 characters)
url: String,
#[argh(option, long = "type")]
/// type of the feed ('rss' or 'atom')
feed_type: FeedType,
#[argh(option)]
/// description of the feed
description: Option<String>,
}
#[tokio::main]
pub async fn main() -> Result<()> {
dotenv().ok();
tracing_subscriber::fmt::init();
let pool = PgPoolOptions::new()
.max_connections(env::var("DATABASE_MAX_CONNECTIONS")?.parse()?)
.connect(&env::var("DATABASE_URL")?)
.await?;
let args: Args = argh::from_env();
if let Commands::AddFeed(add_feed_args) = args.commands {
add_feed(pool, CreateFeed {
title: add_feed_args.title,
url: add_feed_args.url,
feed_type: add_feed_args.feed_type,
description: add_feed_args.description,
}).await?;
}
Ok(())
}

8
src/commands/add_feed.rs Normal file
View File

@@ -0,0 +1,8 @@
use sqlx::PgPool;
use crate::models::feed::{create_feed, CreateFeed, Feed};
use crate::error::Result;
pub async fn add_feed(pool: PgPool, payload: CreateFeed) -> Result<Feed> {
create_feed(pool, payload).await
}

1
src/commands/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod add_feed;

4
src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
pub mod commands;
pub mod error;
pub mod handlers;
pub mod models;

View File

@@ -9,9 +9,7 @@ use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;
use tracing::debug;
mod error;
mod handlers;
mod models;
use lib::handlers;
#[tokio::main]
async fn main() -> anyhow::Result<()> {

View File

@@ -1,3 +1,5 @@
use std::str::FromStr;
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
@@ -13,29 +15,40 @@ pub enum FeedType {
Rss,
}
impl FromStr for FeedType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"atom" => Ok(FeedType::Atom),
"rss" => Ok(FeedType::Rss),
_ => Err(format!("invalid feed type: {}", s)),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Feed {
id: i32,
title: String,
url: String,
pub id: i32,
pub title: String,
pub url: String,
#[serde(rename = "type")]
feed_type: FeedType,
description: Option<String>,
created_at: NaiveDateTime,
updated_at: NaiveDateTime,
deleted_at: Option<NaiveDateTime>,
pub feed_type: FeedType,
pub description: Option<String>,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub deleted_at: Option<NaiveDateTime>,
}
#[derive(Debug, Deserialize, Validate)]
pub struct CreateFeed {
#[validate(length(max = 255))]
title: String,
pub title: String,
#[validate(url)]
url: String,
pub url: String,
#[serde(rename = "type")]
feed_type: FeedType,
pub feed_type: FeedType,
#[validate(length(max = 524288))]
description: Option<String>,
pub description: Option<String>,
}
pub async fn get_feed(pool: PgPool, id: i32) -> Result<Feed> {

View File

@@ -7,26 +7,26 @@ use crate::error::{Error, Result};
#[derive(Debug, Serialize, Deserialize)]
pub struct Item {
id: i32,
title: String,
url: String,
description: Option<String>,
feed_id: i32,
created_at: NaiveDateTime,
updated_at: NaiveDateTime,
deleted_at: Option<NaiveDateTime>,
pub id: i32,
pub title: String,
pub url: String,
pub description: Option<String>,
pub feed_id: i32,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub deleted_at: Option<NaiveDateTime>,
}
#[derive(Debug, Deserialize, Validate)]
pub struct CreateItem {
#[validate(length(max = 255))]
title: String,
pub title: String,
#[validate(url)]
url: String,
pub url: String,
#[validate(length(max = 524288))]
description: Option<String>,
pub description: Option<String>,
#[validate(range(min = 1))]
feed_id: i32,
pub feed_id: i32,
}
pub async fn get_item(pool: PgPool, id: i32) -> Result<Item> {