]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/site.rs
3363edc93b6744f059f61b4e266d1cf183e9f2da
[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: &DbPool, _site_id: SiteId) -> Result<Self, Error> {
23     unimplemented!()
24   }
25
26   async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
27     let conn = &mut get_conn(pool).await?;
28     let is_new_site = match &form.actor_id {
29       Some(id_) => Site::read_from_apub_id(pool, id_).await?.is_none(),
30       None => true,
31     };
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: &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: &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(pool: &DbPool, object_id: &DbUrl) -> Result<Option<Self>, Error> {
70     let conn = &mut get_conn(pool).await?;
71     Ok(
72       site
73         .filter(actor_id.eq(object_id))
74         .first::<Site>(conn)
75         .await
76         .ok()
77         .map(Into::into),
78     )
79   }
80
81   // TODO this needs fixed
82   pub async fn read_remote_sites(pool: &DbPool) -> Result<Vec<Self>, Error> {
83     let conn = &mut get_conn(pool).await?;
84     site.order_by(id).offset(1).get_results::<Self>(conn).await
85   }
86
87   /// Instance actor is at the root path, so we simply need to clear the path and other unnecessary
88   /// parts of the url.
89   pub fn instance_actor_id_from_url(mut url: Url) -> Url {
90     url.set_fragment(None);
91     url.set_path("");
92     url.set_query(None);
93     url
94   }
95 }