Keep a show from an OPML when the OPML drops it (#280)
A show inside a subscribed OPML went when the OPML stopped listing it (orphaned only if it had downloads), and went for you when you left the OPML. Keep, in its settings, is a per-person flag on the subscription: when the OPML drops a kept show, or nobody subscribes to the OPML any more, it becomes a catalogue entry outside the OPML, taking the OPML's settings while it is there, and stays on the lists of those who kept it. Whoever had it only through the OPML loses it as before. Leaving the OPML yourself leaves what you kept on your list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -110,6 +110,10 @@ async fn create_missing(orm: &sea_orm::DatabaseConnection) -> Result<()> {
|
||||
let sql = "ALTER TABLE users ADD COLUMN typesafe_key TEXT";
|
||||
orm.execute_unprepared(sql).await.with_context(|| sql.to_owned())?;
|
||||
}
|
||||
if orm.execute_unprepared("SELECT kept FROM subscriptions LIMIT 0").await.is_err() {
|
||||
let sql = "ALTER TABLE subscriptions ADD COLUMN kept BOOLEAN NOT NULL DEFAULT false";
|
||||
orm.execute_unprepared(sql).await.with_context(|| sql.to_owned())?;
|
||||
}
|
||||
if orm.execute_unprepared("SELECT description FROM signals LIMIT 0").await.is_err() {
|
||||
// Every verdict so far answered the old question, any one keyword on its own, which put
|
||||
// a game's remaster in AI Development (#259): all of them are asked again.
|
||||
@@ -1794,6 +1798,40 @@ impl Db {
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// The feeds from a list this person keeps should the list drop them (#280).
|
||||
pub async fn kept_feeds(&self, user_id: i64) -> Result<std::collections::HashSet<String>> {
|
||||
Ok(subscriptions::Entity::find()
|
||||
.filter(subscriptions::Column::UserId.eq(user_id))
|
||||
.filter(subscriptions::Column::Kept.eq(true))
|
||||
.all(&self.orm)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|s| s.feed_id)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// False when they do not subscribe to it, as `set_pinned`.
|
||||
pub async fn set_kept(&self, user_id: i64, feed_id: &str, on: bool) -> Result<bool> {
|
||||
let r = subscriptions::Entity::update_many()
|
||||
.col_expr(subscriptions::Column::Kept, Expr::val(on).into())
|
||||
.filter(subscriptions::Column::UserId.eq(user_id))
|
||||
.filter(subscriptions::Column::FeedId.eq(feed_id))
|
||||
.exec(&self.orm)
|
||||
.await?;
|
||||
Ok(r.rows_affected > 0)
|
||||
}
|
||||
|
||||
/// Who subscribes to a feed, and whether each keeps it (#280).
|
||||
pub async fn subscribers_of(&self, feed_id: &str) -> Result<Vec<(i64, bool)>> {
|
||||
Ok(subscriptions::Entity::find()
|
||||
.filter(subscriptions::Column::FeedId.eq(feed_id))
|
||||
.all(&self.orm)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|s| (s.user_id, s.kept))
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// False when they do not subscribe to it, since there is then no row in their list to pin.
|
||||
/// Whether a feed or an entry names `url` as its artwork: the only addresses /api/art will
|
||||
/// fetch, so the web server cannot be pointed at anything else.
|
||||
|
||||
Reference in New Issue
Block a user