use crate::{ Result, Item, Channel, channel::{ UnparsedChannel, ChannelId, }, user::UserId, }; use sqlx::SqlitePool; pub struct FeedId(pub i64); impl From for FeedId { fn from(id: i64) -> Self { FeedId(id) } } impl From for i64 { fn from(id: FeedId) -> Self { id.0 } } pub struct UnparsedFeed { pub id: i64, pub title: String, pub user_id: i64 } impl UnparsedFeed { pub fn parse(self) -> Result { Ok(Feed { id: FeedId(self.id), title: self.title, user_id: UserId(self.user_id), }) } } pub struct Feed { pub id: FeedId, pub title: String, pub user_id: UserId, } impl Feed { pub async fn create( pool: &SqlitePool, id: UserId, name: &str ) -> Result { let new_feed = sqlx::query_as!( UnparsedFeed, "INSERT INTO feeds (user_id, title) VALUES (?, ?) RETURNING id as `id!`, user_id, title", id.0, name ).fetch_one(pool).await?.parse(); new_feed } pub async fn add_channel( pool: &SqlitePool, id: FeedId, channel_id: ChannelId ) -> Result<()> { sqlx::query!( "INSERT INTO feed_channels (feed_id, channel_id) VALUES (?, ?)", id.0, channel_id.0 ).execute(pool).await?; Ok(()) } pub async fn get_items( pool: &SqlitePool, id: FeedId, limit: u8, offset: u32 ) -> Result> { let items = sqlx::query_as!( Item, "SELECT item_id as id FROM feed_items WHERE feed_id = ? AND archived = FALSE ORDER BY score DESC LIMIT ? OFFSET ?", id.0, limit, offset ).fetch_all(pool).await?; Ok(items) } pub async fn get_channels( pool: &SqlitePool, id: FeedId ) -> Result> { let channels: Result> = sqlx::query_as!( UnparsedChannel, "SELECT c.id as `id!`, c.title, c.link, c.description, c.last_fetched FROM channels c JOIN feed_channels fc on c.id = fc.channel_id WHERE fc.feed_id = ?", id.0 ).fetch_all(pool).await?.into_iter() .map(UnparsedChannel::parse).collect(); channels } }