]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/site.rs
2820e9cd5ccf07324603adf0a0373b294db2608a
[lemmy.git] / crates / db_schema / src / impls / site.rs
1 use crate::{
2   newtypes::{DbUrl, SiteId},
3   schema::site::dsl::{actor_id, id, site},
4   source::{
5     actor_language::SiteLanguage,
6     site::{Site, SiteInsertForm, SiteUpdateForm},
7   },
8   traits::Crud,
9   utils::{get_conn, DbPool},
10 };
11 use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
12 use diesel_async::RunQueryDsl;
13 use url::Url;
14
15 #[async_trait]
16 impl Crud for Site {
17   type InsertForm = SiteInsertForm;
18   type UpdateForm = SiteUpdateForm;
19   type IdType = SiteId;
20
21   /// Use SiteView::read_local, or Site::read_from_apub_id instead
22   async fn read(_pool: &mut DbPool<'_>, _site_id: SiteId) -> Result<Self, Error> {
23     unimplemented!()
24   }
25
26   async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
27     let is_new_site = match &form.actor_id {
28       Some(id_) => Site::read_from_apub_id(pool, id_).await?.is_none(),
29       None => true,
30     };
31     let conn = &mut get_conn(pool).await?;
32
33     // Can't do separate insert/update commands because InsertForm/UpdateForm aren't convertible
34     let site_ = insert_into(site)
35       .values(form)
36       .on_conflict(actor_id)
37       .do_update()
38       .set(form)
39       .get_result::<Self>(conn)
40       .await?;
41
42     // initialize languages if site is newly created
43     if is_new_site {
44       // initialize with all languages
45       SiteLanguage::update(pool, vec![], &site_).await?;
46     }
47     Ok(site_)
48   }
49
50   async fn update(
51     pool: &mut DbPool<'_>,
52     site_id: SiteId,
53     new_site: &Self::UpdateForm,
54   ) -> Result<Self, Error> {
55     let conn = &mut get_conn(pool).await?;
56     diesel::update(site.find(site_id))
57       .set(new_site)
58       .get_result::<Self>(conn)
59       .await
60   }
61
62   async fn delete(pool: &mut DbPool<'_>, site_id: SiteId) -> Result<usize, Error> {
63     let conn = &mut get_conn(pool).await?;
64     diesel::delete(site.find(site_id)).execute(conn).await
65   }
66 }
67
68 impl Site {
69   pub async fn read_from_apub_id(
70     pool: &mut DbPool<'_>,
71     object_id: &DbUrl,
72   ) -> Result<Option<Self>, Error> {
73     let conn = &mut get_conn(pool).await?;
74     Ok(
75       site
76         .filter(actor_id.eq(object_id))
77         .first::<Site>(conn)
78         .await
79         .ok()
80         .map(Into::into),
81     )
82   }
83
84   pub async fn read_remote_sites(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
85     let conn = &mut get_conn(pool).await?;
86     site.order_by(id).offset(1).get_results::<Self>(conn).await
87   }
88
89   /// Instance actor is at the root path, so we simply need to clear the path and other unnecessary
90   /// parts of the url.
91   pub fn instance_actor_id_from_url(mut url: Url) -> Url {
92     url.set_fragment(None);
93     url.set_path("");
94     url.set_query(None);
95     url
96   }
97 }