finish moving languages into db, it compiles

This commit is contained in:
Felix Ableitner 2022-06-22 15:07:59 +02:00
parent 9bf41100f8
commit 553a29ba9e
14 changed files with 128 additions and 66 deletions

View file

@ -5,8 +5,9 @@ use lemmy_api_common::{
utils::{blocking, get_local_user_view_from_jwt, send_verification_email}, utils::{blocking, get_local_user_view_from_jwt, send_verification_email},
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::LanguageIdentifier, newtypes::LanguageId,
source::{ source::{
language::Language,
local_user::{LocalUser, LocalUserForm}, local_user::{LocalUser, LocalUserForm},
person::{Person, PersonForm}, person::{Person, PersonForm},
site::Site, site::Site,
@ -118,16 +119,25 @@ impl Perform for SaveUserSettings {
}) })
.await? .await?
.map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?; .map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
let mut discussion_languages: Vec<LanguageIdentifier> = data let discussion_languages: Option<Vec<LanguageId>> =
.discussion_languages if let Some(discussion_languages) = data.discussion_languages.clone() {
.clone() if discussion_languages.len() > 5 {
.into_iter() return Err(LemmyError::from_message("max_languages_is_five"));
.flatten() }
.map(|l| LanguageIdentifier::new(&l))
.collect(); let mut language_ids = vec![];
if discussion_languages.is_empty() { for l in discussion_languages {
discussion_languages = LanguageIdentifier::all_languages() language_ids.push(
} blocking(context.pool(), move |conn| {
Language::read_id_from_code(conn, l)
})
.await??,
);
}
Some(language_ids)
} else {
None
};
let local_user_form = LocalUserForm { let local_user_form = LocalUserForm {
person_id: Some(person_id), person_id: Some(person_id),
@ -146,7 +156,7 @@ impl Perform for SaveUserSettings {
send_notifications_to_email: data.send_notifications_to_email, send_notifications_to_email: data.send_notifications_to_email,
email_verified: None, email_verified: None,
accepted_application: None, accepted_application: None,
discussion_languages: Some(discussion_languages), discussion_languages,
}; };
let local_user_res = blocking(context.pool(), move |conn| { let local_user_res = blocking(context.pool(), move |conn| {

View file

@ -6,6 +6,7 @@ use lemmy_api_common::{
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{
language::Language,
moderator::{ModAdd, ModAddForm}, moderator::{ModAdd, ModAddForm},
person::Person, person::Person,
}, },
@ -60,6 +61,8 @@ impl Perform for LeaveAdmin {
let federated_instances = let federated_instances =
build_federated_instances(context.pool(), &context.settings()).await?; build_federated_instances(context.pool(), &context.settings()).await?;
let all_languages = blocking(context.pool(), Language::read_all).await??;
Ok(GetSiteResponse { Ok(GetSiteResponse {
site_view: Some(site_view), site_view: Some(site_view),
admins, admins,
@ -67,6 +70,7 @@ impl Perform for LeaveAdmin {
version: version::VERSION.to_string(), version: version::VERSION.to_string(),
my_user: None, my_user: None,
federated_instances, federated_instances,
all_languages,
}) })
} }
} }

View file

@ -1,6 +1,7 @@
use crate::sensitive::Sensitive; use crate::sensitive::Sensitive;
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, PersonId, PostId}, newtypes::{CommentId, CommunityId, PersonId, PostId},
source::language::Language,
ListingType, ListingType,
SearchType, SearchType,
SortType, SortType,
@ -163,6 +164,7 @@ pub struct GetSiteResponse {
pub version: String, pub version: String,
pub my_user: Option<MyUserInfo>, pub my_user: Option<MyUserInfo>,
pub federated_instances: Option<FederatedInstances>, // Federation may be disabled pub federated_instances: Option<FederatedInstances>, // Federation may be disabled
pub all_languages: Vec<Language>,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]

View file

@ -19,9 +19,9 @@ use lemmy_apub::{
EndpointType, EndpointType,
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::LanguageIdentifier,
source::{ source::{
community::Community, community::Community,
language::Language,
post::{Post, PostForm, PostLike, PostLikeForm}, post::{Post, PostForm, PostLike, PostLikeForm},
}, },
traits::{Crud, Likeable}, traits::{Crud, Likeable},
@ -92,6 +92,25 @@ impl PerformCrud for CreatePost {
let (embed_title, embed_description, embed_video_url) = metadata_res let (embed_title, embed_description, embed_video_url) = metadata_res
.map(|u| (u.title, u.description, u.embed_video_url)) .map(|u| (u.title, u.description, u.embed_video_url))
.unwrap_or_default(); .unwrap_or_default();
let language = data.language.clone();
let mut language = blocking(context.pool(), move |conn| {
Language::read_id_from_code_opt(conn, language)
})
.await??;
// if user only speaks one language, use that as post language. otherwise, set it as "undetermined"
if language.is_none() {
let user_langs = local_user_view.local_user.discussion_languages;
language = if user_langs.len() == 1 {
Some(user_langs[0])
} else {
Some(
blocking(context.pool(), move |conn| {
Language::read_undetermined(conn)
})
.await??,
)
};
};
let post_form = PostForm { let post_form = PostForm {
name: data.name.trim().to_owned(), name: data.name.trim().to_owned(),
@ -104,7 +123,7 @@ impl PerformCrud for CreatePost {
embed_description, embed_description,
embed_video_url, embed_video_url,
thumbnail_url, thumbnail_url,
language: data.language.as_ref().map(|l| LanguageIdentifier::new(l)), language,
..PostForm::default() ..PostForm::default()
}; };

View file

@ -14,8 +14,10 @@ use lemmy_apub::protocol::activities::{
CreateOrUpdateType, CreateOrUpdateType,
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::LanguageIdentifier, source::{
source::post::{Post, PostForm}, language::Language,
post::{Post, PostForm},
},
traits::Crud, traits::Crud,
utils::naive_now, utils::naive_now,
}; };
@ -75,6 +77,11 @@ impl PerformCrud for EditPost {
let (embed_title, embed_description, embed_video_url) = metadata_res let (embed_title, embed_description, embed_video_url) = metadata_res
.map(|u| (u.title, u.description, u.embed_video_url)) .map(|u| (u.title, u.description, u.embed_video_url))
.unwrap_or_default(); .unwrap_or_default();
let language = data.language.clone();
let language = blocking(context.pool(), move |conn| {
Language::read_id_from_code_opt(conn, language)
})
.await??;
let post_form = PostForm { let post_form = PostForm {
creator_id: orig_post.creator_id.to_owned(), creator_id: orig_post.creator_id.to_owned(),
@ -88,7 +95,7 @@ impl PerformCrud for EditPost {
embed_description, embed_description,
embed_video_url, embed_video_url,
thumbnail_url, thumbnail_url,
language: data.language.as_ref().map(|l| LanguageIdentifier::new(l)), language,
..PostForm::default() ..PostForm::default()
}; };

View file

@ -5,6 +5,7 @@ use lemmy_api_common::{
site::{CreateSite, GetSite, GetSiteResponse, MyUserInfo}, site::{CreateSite, GetSite, GetSiteResponse, MyUserInfo},
utils::{blocking, build_federated_instances, get_local_user_settings_view_from_jwt_opt}, utils::{blocking, build_federated_instances, get_local_user_settings_view_from_jwt_opt},
}; };
use lemmy_db_schema::source::language::Language;
use lemmy_db_views::structs::SiteView; use lemmy_db_views::structs::SiteView;
use lemmy_db_views_actor::structs::{ use lemmy_db_views_actor::structs::{
CommunityBlockView, CommunityBlockView,
@ -123,6 +124,8 @@ impl PerformCrud for GetSite {
let federated_instances = let federated_instances =
build_federated_instances(context.pool(), &context.settings()).await?; build_federated_instances(context.pool(), &context.settings()).await?;
let all_languages = blocking(context.pool(), Language::read_all).await??;
Ok(GetSiteResponse { Ok(GetSiteResponse {
site_view, site_view,
admins, admins,
@ -130,6 +133,7 @@ impl PerformCrud for GetSite {
version: version::VERSION.to_string(), version: version::VERSION.to_string(),
my_user, my_user,
federated_instances, federated_instances,
all_languages,
}) })
} }
} }

View file

@ -14,7 +14,7 @@ use lemmy_apub::{
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::PersonAggregates, aggregates::structs::PersonAggregates,
newtypes::{CommunityId, LanguageIdentifier}, newtypes::CommunityId,
source::{ source::{
community::{ community::{
Community, Community,
@ -149,7 +149,6 @@ impl PerformCrud for Register {
password_encrypted: Some(data.password.to_string()), password_encrypted: Some(data.password.to_string()),
show_nsfw: Some(data.show_nsfw), show_nsfw: Some(data.show_nsfw),
email_verified: Some(false), email_verified: Some(false),
discussion_languages: Some(LanguageIdentifier::all_languages()),
..LocalUserForm::default() ..LocalUserForm::default()
}; };

View file

@ -4,7 +4,7 @@ use crate::{
local_instance, local_instance,
objects::{read_from_string_or_source_opt, verify_is_remote_object}, objects::{read_from_string_or_source_opt, verify_is_remote_object},
protocol::{ protocol::{
objects::page::{Attachment, AttributedTo, Language, Page, PageType}, objects::page::{Attachment, AttributedTo, LanguageTag, Page, PageType},
ImageObject, ImageObject,
Source, Source,
}, },
@ -20,9 +20,9 @@ use chrono::NaiveDateTime;
use lemmy_api_common::{request::fetch_site_data, utils::blocking}; use lemmy_api_common::{request::fetch_site_data, utils::blocking};
use lemmy_db_schema::{ use lemmy_db_schema::{
self, self,
newtypes::LanguageIdentifier,
source::{ source::{
community::Community, community::Community,
language::Language,
moderator::{ModLockPost, ModLockPostForm, ModStickyPost, ModStickyPostForm}, moderator::{ModLockPost, ModLockPostForm, ModStickyPost, ModStickyPostForm},
person::Person, person::Person,
post::{Post, PostForm}, post::{Post, PostForm},
@ -99,6 +99,11 @@ impl ApubObject for ApubPost {
Community::read(conn, community_id) Community::read(conn, community_id)
}) })
.await??; .await??;
let language = self.language;
let language = blocking(context.pool(), move |conn| {
Language::read_from_id(conn, language)
})
.await??;
let page = Page { let page = Page {
kind: PageType::Page, kind: PageType::Page,
@ -116,7 +121,7 @@ impl ApubObject for ApubPost {
comments_enabled: Some(!self.locked), comments_enabled: Some(!self.locked),
sensitive: Some(self.nsfw), sensitive: Some(self.nsfw),
stickied: Some(self.stickied), stickied: Some(self.stickied),
language: Language::new(self.language.clone()), language: LanguageTag::new(language),
published: Some(convert_datetime(self.published)), published: Some(convert_datetime(self.published)),
updated: self.updated.map(convert_datetime), updated: self.updated.map(convert_datetime),
}; };
@ -180,9 +185,11 @@ impl ApubObject for ApubPost {
let body_slurs_removed = let body_slurs_removed =
read_from_string_or_source_opt(&page.content, &page.media_type, &page.source) read_from_string_or_source_opt(&page.content, &page.media_type, &page.source)
.map(|s| remove_slurs(&s, &context.settings().slur_regex())); .map(|s| remove_slurs(&s, &context.settings().slur_regex()));
let language = page let language = page.language.map(|l| l.identifier);
.language let language = blocking(context.pool(), move |conn| {
.map(|l| LanguageIdentifier::new(&l.identifier)); Language::read_id_from_code_opt(conn, language)
})
.await??;
PostForm { PostForm {
name: page.name.clone(), name: page.name.clone(),

View file

@ -16,7 +16,7 @@ use activitypub_federation::{
use activitystreams_kinds::link::LinkType; use activitystreams_kinds::link::LinkType;
use chrono::{DateTime, FixedOffset}; use chrono::{DateTime, FixedOffset};
use itertools::Itertools; use itertools::Itertools;
use lemmy_db_schema::newtypes::{DbUrl, LanguageIdentifier}; use lemmy_db_schema::{newtypes::DbUrl, source::language::Language};
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -62,25 +62,25 @@ pub struct Page {
pub(crate) stickied: Option<bool>, pub(crate) stickied: Option<bool>,
pub(crate) published: Option<DateTime<FixedOffset>>, pub(crate) published: Option<DateTime<FixedOffset>>,
pub(crate) updated: Option<DateTime<FixedOffset>>, pub(crate) updated: Option<DateTime<FixedOffset>>,
pub(crate) language: Option<Language>, pub(crate) language: Option<LanguageTag>,
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct Language { pub(crate) struct LanguageTag {
pub(crate) identifier: String, pub(crate) identifier: String,
pub(crate) name: String, pub(crate) name: String,
} }
impl Language { impl LanguageTag {
pub(crate) fn new(lang: LanguageIdentifier) -> Option<Language> { pub(crate) fn new(lang: Language) -> Option<LanguageTag> {
if lang.is_undetermined() { // undetermined
if lang.code == "und" {
None None
} else { } else {
// TODO: need to get the language name Some(LanguageTag {
Some(Language { identifier: lang.code,
identifier: lang.into_inner(), name: lang.name,
name: "todo".to_string(),
}) })
} }
} }

View file

@ -1,5 +1,5 @@
use crate::source::language::Language; use crate::{newtypes::LanguageId, source::language::Language};
use diesel::{result::Error, PgConnection, RunQueryDsl}; use diesel::{result::Error, PgConnection, RunQueryDsl, *};
impl Language { impl Language {
pub fn read_all(conn: &PgConnection) -> Result<Vec<Language>, Error> { pub fn read_all(conn: &PgConnection) -> Result<Vec<Language>, Error> {
@ -7,9 +7,30 @@ impl Language {
language.load::<Self>(conn) language.load::<Self>(conn)
} }
pub fn read_from_code(code_: &str, conn: &PgConnection) -> Result<Language, Error> { pub fn read_from_id(conn: &PgConnection, id_: LanguageId) -> Result<Language, Error> {
use crate::schema::language::dsl::*; use crate::schema::language::dsl::*;
language.find(code.eq(code_)).load::<Self>(conn) language.filter(id.eq(id_)).first::<Self>(conn)
}
pub fn read_id_from_code(conn: &PgConnection, code_: String) -> Result<LanguageId, Error> {
use crate::schema::language::dsl::*;
Ok(language.filter(code.eq(code_)).first::<Self>(conn)?.id)
}
pub fn read_id_from_code_opt(
conn: &PgConnection,
code_: Option<String>,
) -> Result<Option<LanguageId>, Error> {
if let Some(code_) = code_ {
Ok(Some(Language::read_id_from_code(conn, code_)?))
} else {
Ok(None)
}
}
pub fn read_undetermined(conn: &PgConnection) -> Result<LanguageId, Error> {
use crate::schema::language::dsl::*;
Ok(language.filter(code.eq("und")).first::<Self>(conn)?.id)
} }
} }
@ -25,7 +46,9 @@ mod tests {
let all = Language::read_all(&conn).unwrap(); let all = Language::read_all(&conn).unwrap();
assert_eq!(123, all.len()); assert_eq!(184, all.len());
assert_eq!("xy", all[5].code); assert_eq!("ak", all[5].code);
assert_eq!("lv", all[99].code);
assert_eq!("yi", all[179].code);
} }
} }

View file

@ -162,7 +162,7 @@ table! {
show_new_post_notifs -> Bool, show_new_post_notifs -> Bool,
email_verified -> Bool, email_verified -> Bool,
accepted_application -> Bool, accepted_application -> Bool,
discussion_languages -> Array<Text>, discussion_languages -> Array<Int4>,
} }
} }
@ -362,7 +362,7 @@ table! {
thumbnail_url -> Nullable<Text>, thumbnail_url -> Nullable<Text>,
ap_id -> Varchar, ap_id -> Varchar,
local -> Bool, local -> Bool,
language -> Varchar, language -> Int4,
} }
} }

View file

@ -1,6 +1,9 @@
use crate::newtypes::LanguageId; use crate::newtypes::LanguageId;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "full")]
use crate::schema::language;
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "full", derive(Queryable, Identifiable))] #[cfg_attr(feature = "full", derive(Queryable, Identifiable))]
#[cfg_attr(feature = "full", table_name = "language")] #[cfg_attr(feature = "full", table_name = "language")]

View file

@ -2,7 +2,7 @@ use crate::structs::{LocalUserView, PostView};
use diesel::{dsl::*, pg::Pg, result::Error, *}; use diesel::{dsl::*, pg::Pg, result::Error, *};
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::PostAggregates, aggregates::structs::PostAggregates,
newtypes::{CommunityId, DbUrl, LanguageIdentifier, PersonId, PostId}, newtypes::{CommunityId, DbUrl, LanguageId, PersonId, PostId},
schema::{ schema::{
community, community,
community_block, community_block,
@ -165,7 +165,7 @@ pub struct PostQueryBuilder<'a> {
show_bot_accounts: Option<bool>, show_bot_accounts: Option<bool>,
show_read_posts: Option<bool>, show_read_posts: Option<bool>,
saved_only: Option<bool>, saved_only: Option<bool>,
languages: Option<Vec<LanguageIdentifier>>, languages: Option<Vec<LanguageId>>,
page: Option<i64>, page: Option<i64>,
limit: Option<i64>, limit: Option<i64>,
} }
@ -497,7 +497,7 @@ mod tests {
use diesel::PgConnection; use diesel::PgConnection;
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::PostAggregates, aggregates::structs::PostAggregates,
newtypes::LanguageIdentifier, newtypes::LanguageId,
source::{ source::{
community::*, community::*,
community_block::{CommunityBlock, CommunityBlockForm}, community_block::{CommunityBlock, CommunityBlockForm},
@ -562,7 +562,7 @@ mod tests {
name: "blocked_person_post".to_string(), name: "blocked_person_post".to_string(),
creator_id: inserted_blocked_person.id, creator_id: inserted_blocked_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
language: Some(LanguageIdentifier::new("en")), language: Some(LanguageId(1)),
..PostForm::default() ..PostForm::default()
}; };
@ -581,7 +581,7 @@ mod tests {
name: post_name, name: post_name,
creator_id: inserted_person.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
language: Some(LanguageIdentifier::new("fr")), language: Some(LanguageId(2)),
..PostForm::default() ..PostForm::default()
}; };
@ -643,7 +643,7 @@ mod tests {
thumbnail_url: None, thumbnail_url: None,
ap_id: inserted_post.ap_id.to_owned(), ap_id: inserted_post.ap_id.to_owned(),
local: true, local: true,
language: LanguageIdentifier::new("fr"), language: LanguageId(2),
}, },
my_vote: None, my_vote: None,
creator: PersonSafe { creator: PersonSafe {
@ -838,7 +838,7 @@ mod tests {
.listing_type(ListingType::Community) .listing_type(ListingType::Community)
.sort(SortType::New) .sort(SortType::New)
.community_id(data.inserted_community.id); .community_id(data.inserted_community.id);
let fr = LanguageIdentifier::new("fr"); let fr = LanguageId(2);
read_post_listing_french.languages = Some(vec![fr]); read_post_listing_french.languages = Some(vec![fr]);
let read_post_listing_french = read_post_listing_french.list().unwrap(); let read_post_listing_french = read_post_listing_french.list().unwrap();

View file

@ -13,11 +13,9 @@ use lemmy_apub::{
EndpointType, EndpointType,
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::LanguageIdentifier,
source::{ source::{
comment::Comment, comment::Comment,
community::{Community, CommunityForm}, community::{Community, CommunityForm},
local_user::LocalUser,
person::{Person, PersonForm}, person::{Person, PersonForm},
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
@ -42,7 +40,6 @@ pub fn run_advanced_migrations(
post_thumbnail_url_updates_2020_07_27(conn, protocol_and_hostname)?; post_thumbnail_url_updates_2020_07_27(conn, protocol_and_hostname)?;
apub_columns_2021_02_02(conn)?; apub_columns_2021_02_02(conn)?;
instance_actor_2022_01_28(conn, protocol_and_hostname)?; instance_actor_2022_01_28(conn, protocol_and_hostname)?;
language_tags_2022_05_11(conn)?;
Ok(()) Ok(())
} }
@ -312,16 +309,3 @@ fn instance_actor_2022_01_28(
} }
Ok(()) Ok(())
} }
fn language_tags_2022_05_11(conn: &PgConnection) -> Result<(), LemmyError> {
use lemmy_db_schema::schema::local_user::dsl::*;
let users = local_user.load::<LocalUser>(conn)?;
for u in &users {
let all_languages = LanguageIdentifier::all_languages();
diesel::update(local_user.find(u.id))
.set((discussion_languages.eq(all_languages),))
.get_result::<LocalUser>(conn)?;
}
Ok(())
}