use crate::{ Result, Item, Channel, channel::{ UnparsedChannel, ChannelId, }, user::UserId, }; use sqlx::SqlitePool; #[derive(Copy, Clone)] pub struct FeedId(i64); impl From for i64 { fn from(id: FeedId) -> Self { id.0 } } pub struct UnparsedFeed { pub id: i64, pub title: String, } impl UnparsedFeed { pub fn parse(self) -> Result { Ok(Feed { id: FeedId(self.id), title: self.title, }) } } pub struct Feed { id: FeedId, title: String, } impl Feed { pub fn id(&self) -> FeedId { self.id } pub fn title(&self) -> &str { &self.title } pub async fn create( pool: &SqlitePool, id: UserId, name: &str ) -> Result { let int_id = i64::from(id); let new_feed = sqlx::query_as!( UnparsedFeed, "INSERT INTO feeds (user_id, title) VALUES (?, ?) RETURNING id as `id!`, title", int_id, 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 } }