post_archiver/manager/
collection.rs1use rusqlite::{params, OptionalExtension};
2
3use crate::{Collection, CollectionId, FileMetaId, Post, PostId};
4
5use super::{PostArchiverConnection, PostArchiverManager};
6
7impl<T> PostArchiverManager<T>
11where
12 T: PostArchiverConnection,
13{
14 pub fn list_collections(&self) -> Result<Vec<crate::Collection>, rusqlite::Error> {
20 let mut stmt = self.conn().prepare_cached("SELECT * FROM collections")?;
21 let collections = stmt.query_map([], Collection::from_row)?;
22 collections.collect()
23 }
24
25 pub fn find_collection(&self, source: &str) -> Result<Option<CollectionId>, rusqlite::Error> {
31 if let Some(id) = self.cache.collections.get(source) {
32 return Ok(Some(*id));
33 }
34
35 let mut stmt = self
36 .conn()
37 .prepare_cached("SELECT id FROM collections WHERE source = ?")?;
38 let id = stmt.query_row([source], |row| row.get(0)).optional();
39
40 if let Ok(Some(id)) = id {
41 self.cache.collections.insert(source.to_string(), id);
42 }
43
44 id
45 }
46 pub fn get_collection(&self, id: &CollectionId) -> Result<Option<Collection>, rusqlite::Error> {
56 let mut stmt = self
57 .conn()
58 .prepare_cached("SELECT * FROM collections WHERE id = ?")?;
59
60 stmt.query_row([id], crate::Collection::from_row).optional()
61 }
62}
63
64impl<T> PostArchiverManager<T>
68where
69 T: PostArchiverConnection,
70{
71 pub fn add_collection(
81 &self,
82 name: String,
83 source: Option<String>,
84 thumb: Option<FileMetaId>,
85 ) -> Result<CollectionId, rusqlite::Error> {
86 let mut stmt = self.conn().prepare_cached(
87 "INSERT INTO collections (name, source, thumb) VALUES (?, ?, ?) RETURNING id",
88 )?;
89 let id = stmt.query_row(params![name, source, thumb], |row| row.get(0))?;
90
91 if let Some(source) = &source {
92 self.cache.collections.insert(source.clone(), id);
93 }
94 Ok(id)
95 }
96
97 pub fn remove_collection(&self, id: CollectionId) -> Result<(), rusqlite::Error> {
105 let mut stmt = self
106 .conn()
107 .prepare_cached("DELETE FROM collection_posts WHERE collection = ?")?;
108 stmt.execute([id])?;
109 Ok(())
110 }
111
112 pub fn set_collection_name(
118 &self,
119 id: CollectionId,
120 name: String,
121 ) -> Result<(), rusqlite::Error> {
122 let mut stmt = self
123 .conn()
124 .prepare_cached("UPDATE collections SET name = ? WHERE id = ?")?;
125 stmt.execute(params![name, id])?;
126 Ok(())
127 }
128
129 pub fn set_collection_source(
137 &self,
138 id: CollectionId,
139 source: Option<String>,
140 ) -> Result<(), rusqlite::Error> {
141 let mut stmt = self
142 .conn()
143 .prepare_cached("UPDATE collections SET source = ? WHERE id = ?")?;
144 stmt.execute(params![&source, id])?;
145 if let Some(source) = source {
146 self.cache.collections.insert(source, id);
147 }
148 Ok(())
149 }
150
151 pub fn set_collection_thumb(
159 &self,
160 id: CollectionId,
161 thumb: Option<String>,
162 ) -> Result<(), rusqlite::Error> {
163 let mut stmt = self
164 .conn()
165 .prepare_cached("UPDATE collections SET thumb = ? WHERE id = ?")?;
166 stmt.execute(params![thumb, id])?;
167 Ok(())
168 }
169
170 pub fn set_collection_thumb_by_latest(&self, id: CollectionId) -> Result<(), rusqlite::Error> {
177 let mut stmt = self.conn().prepare_cached(
178 "UPDATE collections SET thumb = (
179 SELECT posts.thumb FROM posts
180 INNER JOIN collection_posts ON collection_posts.post = posts.id
181 WHERE collection_posts.collection = ? AND posts.thumb IS NOT NULL
182 ORDER BY posts.updated DESC LIMIT 1
183 ) WHERE id = ?",
184 )?;
185 stmt.execute(params![id, id])?;
186 Ok(())
187 }
188}
189
190impl<T> PostArchiverManager<T>
194where
195 T: PostArchiverConnection,
196{
197 pub fn list_post_collections(&self, post: &PostId) -> Result<Vec<Collection>, rusqlite::Error> {
203 let mut stmt = self
204 .conn()
205 .prepare_cached("SELECT collections.* FROM collections INNER JOIN collection_posts ON collection_posts.collection = collections.id WHERE collection_posts.post = ?")?;
206 let collections = stmt.query_map([post], crate::Collection::from_row)?;
207 collections.collect()
208 }
209
210 pub fn list_collection_posts(
216 &self,
217 collection: &CollectionId,
218 ) -> Result<Vec<Post>, rusqlite::Error> {
219 let mut stmt = self
220 .conn()
221 .prepare_cached("SELECT posts.* FROM posts INNER JOIN collection_posts ON collection_posts.post = posts.id WHERE collection_posts.collection = ?")?;
222 let posts = stmt.query_map([collection], Post::from_row)?;
223 posts.collect()
224 }
225}
226
227impl Post {
228 pub fn collections(
234 &self,
235 manager: &PostArchiverManager,
236 ) -> Result<Vec<Collection>, rusqlite::Error> {
237 manager.list_post_collections(&self.id)
238 }
239}
240
241impl Collection {
242 pub fn posts(&self, manager: &PostArchiverManager) -> Result<Vec<Post>, rusqlite::Error> {
248 manager.list_collection_posts(&self.id)
249 }
250}