use tokio::sync::{RwLock, Semaphore};
use crate::config::ConfigProxy;
use crate::database::DatabaseExt;
use crate::feed_api::portal::{Portal, PortalResult};
use crate::models::{
Article, ArticleFilter, ArticleID, Category, CategoryID, CategoryMapping, Feed, FeedID, FeedMapping, Headline, Tag, TagID, Tagging,
};
use std::sync::Arc;
pub struct DefaultPortal {
db: Arc<Box<dyn DatabaseExt>>,
config: Arc<RwLock<ConfigProxy>>,
download_semaphore: Arc<Semaphore>,
}
unsafe impl Send for DefaultPortal {}
unsafe impl Sync for DefaultPortal {}
impl DefaultPortal {
pub fn new(db: Arc<Box<dyn DatabaseExt>>, config: Arc<RwLock<ConfigProxy>>, download_semaphore: Arc<Semaphore>) -> DefaultPortal {
DefaultPortal {
db,
config,
download_semaphore,
}
}
}
impl Portal for DefaultPortal {
fn get_headlines(&self, ids: &[ArticleID]) -> PortalResult<Vec<Headline>> {
let articles = self.get_articles(ids)?;
let headlines = articles.iter().map(Headline::from_article).collect();
Ok(headlines)
}
fn get_article(&self, id: &ArticleID) -> PortalResult<Article> {
let article = self.db.read_article(id)?;
Ok(article)
}
fn get_articles(&self, ids: &[ArticleID]) -> PortalResult<Vec<Article>> {
let articles = self.db.read_articles(ArticleFilter {
limit: Some(ids.len() as i64),
ids: Some(ids.into()),
..ArticleFilter::default()
})?;
Ok(articles)
}
fn get_article_exists(&self, id: &ArticleID) -> PortalResult<bool> {
let exists = self.db.article_exists(id)?;
Ok(exists)
}
fn get_article_ids_unread_feed(&self, feed_id: &FeedID) -> PortalResult<Vec<ArticleID>> {
let articles = self.db.read_articles(ArticleFilter::feed_unread(feed_id))?;
Ok(articles.iter().map(|article| article.article_id.clone()).collect())
}
fn get_article_ids_unread_category(&self, category_id: &CategoryID) -> PortalResult<Vec<ArticleID>> {
let articles = self.db.read_articles(ArticleFilter::category_unread(category_id))?;
Ok(articles.iter().map(|article| article.article_id.clone()).collect())
}
fn get_article_ids_unread_all(&self) -> PortalResult<Vec<ArticleID>> {
let articles = self.db.read_articles(ArticleFilter::all_unread())?;
Ok(articles.iter().map(|article| article.article_id.clone()).collect())
}
fn get_article_ids_marked_all(&self) -> PortalResult<Vec<ArticleID>> {
let articles = self.db.read_articles(ArticleFilter::all_marked())?;
Ok(articles.iter().map(|article| article.article_id.clone()).collect())
}
fn get_feeds(&self) -> PortalResult<Vec<Feed>> {
let feeds = self.db.read_feeds()?;
Ok(feeds)
}
fn get_categories(&self) -> PortalResult<Vec<Category>> {
let categories = self.db.read_categories()?;
Ok(categories)
}
fn get_feed_mappings(&self) -> PortalResult<Vec<FeedMapping>> {
let mappings = self.db.read_feed_mappings(None, None)?;
Ok(mappings)
}
fn get_category_mappings(&self) -> PortalResult<Vec<CategoryMapping>> {
let mappings = self.db.read_category_mappings(None, None)?;
Ok(mappings)
}
fn get_tags(&self) -> PortalResult<Vec<Tag>> {
let tags = self.db.read_tags()?;
Ok(tags)
}
fn get_taggings(&self, article_id: Option<&ArticleID>, tag_id: Option<&TagID>) -> PortalResult<Vec<Tagging>> {
let taggings = self.db.read_taggings(article_id, tag_id)?;
Ok(taggings)
}
fn get_config(&self) -> Arc<RwLock<ConfigProxy>> {
self.config.clone()
}
fn get_download_semaphore(&self) -> Arc<Semaphore> {
self.download_semaphore.clone()
}
}