2026-01-14 16:12:15 -08:00
|
|
|
use std::error::Error;
|
|
|
|
|
use reqwest::{
|
|
|
|
|
IntoUrl,
|
|
|
|
|
Client,
|
|
|
|
|
};
|
|
|
|
|
use rss::Channel as RawChannel;
|
|
|
|
|
|
2026-01-16 13:13:20 -08:00
|
|
|
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
|
|
|
|
|
|
|
|
|
pub struct AdapterOptions {
|
|
|
|
|
database_url: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl AdapterOptions {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
database_url: "sqlite:test.db".to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn database_url(mut self, url: &str) -> Self {
|
|
|
|
|
self.database_url = url.to_string();
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn create(self) -> Result<Adapter> {
|
|
|
|
|
let db = sqlx::sqlite::SqlitePoolOptions::new()
|
|
|
|
|
.connect(&self.database_url).await?;
|
|
|
|
|
|
|
|
|
|
Ok(Adapter { db })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Adapter {
|
|
|
|
|
db: sqlx::SqlitePool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Adapter {
|
|
|
|
|
pub async fn get_all_users(&self) -> Result<Vec<User>> {
|
|
|
|
|
let users_query = sqlx::query!("SELECT id, name FROM users")
|
|
|
|
|
.fetch_all(&self.db).await?;
|
|
|
|
|
|
|
|
|
|
let mut all_users: Vec<User> = Vec::with_capacity(users_query.len());
|
|
|
|
|
|
|
|
|
|
for user in users_query {
|
|
|
|
|
all_users.push(User {
|
|
|
|
|
id: user.id,
|
|
|
|
|
name: user.name,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(all_users)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_pool(&self) -> &sqlx::SqlitePool { &self.db }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct User {
|
|
|
|
|
id: i64,
|
|
|
|
|
name: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl User {
|
|
|
|
|
pub async fn get_by_id(adapter: &Adapter, id: i64) -> Result<Self> {
|
|
|
|
|
let user = sqlx::query!("SELECT name FROM users WHERE id = ?", id)
|
|
|
|
|
.fetch_one(adapter.get_pool()).await?;
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
|
id: id,
|
|
|
|
|
name: user.name,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn create(adapter: &Adapter, name: &str) -> Result<Self> {
|
|
|
|
|
let result = sqlx::query!("INSERT INTO users (name) VALUES (?)", name)
|
|
|
|
|
.execute(adapter.get_pool()).await?;
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
|
id: result.last_insert_rowid(),
|
|
|
|
|
name: name.to_string()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn change_name(
|
|
|
|
|
&mut self, adapter: &Adapter, new_name: &str) -> Result<()> {
|
|
|
|
|
sqlx::query!(
|
|
|
|
|
"UPDATE users SET name = ? WHERE id = ?",
|
|
|
|
|
new_name, self.id
|
|
|
|
|
).execute(adapter.get_pool()).await?;
|
|
|
|
|
|
|
|
|
|
self.name = new_name.to_string();
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn name(&self) -> &str { &self.name }
|
|
|
|
|
pub fn id(&self) -> i64 { self.id }
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-14 16:12:15 -08:00
|
|
|
pub struct Channel {
|
|
|
|
|
pub channel: rss::Channel,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn fetch_channel<T: IntoUrl>(
|
2026-01-16 13:13:20 -08:00
|
|
|
client: &Client, url: T) -> Result<Channel> {
|
2026-01-14 16:12:15 -08:00
|
|
|
let content = client.get(url)
|
|
|
|
|
.send().await?
|
|
|
|
|
.bytes().await?;
|
|
|
|
|
|
|
|
|
|
let raw_channel = RawChannel::read_from(&content[..])?;
|
|
|
|
|
println!("{}", raw_channel.title);
|
|
|
|
|
Ok(Channel { channel: raw_channel })
|
|
|
|
|
}
|