From e4a81d6552022d259b935b2fed8864642f75af8e Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Thu, 14 Nov 2024 22:15:18 +0330 Subject: [PATCH 01/31] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 575a8a5..07dc95a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Docker Image CI](https://github.com/NatiqQuran/nq-api/actions/workflows/docker-image.yml/badge.svg)](https://github.com/NatiqQuran/nq-api/actions/workflows/docker-image.yml) [![Rust](https://github.com/NatiqQuran/nq-api/actions/workflows/rust.yml/badge.svg)](https://github.com/NatiqQuran/nq-api/actions/workflows/rust.yml) -Natiq Quran open API +Natiq Quran open API \ # Docker @@ -25,4 +25,4 @@ cargo build --release ./target/release/nq-api ``` -Api will listen to 0.0.0.0:8080 +API will listen to 0.0.0.0:8080 From 27d3a3c50339a54b2869101e8fbd0c41562e6b59 Mon Sep 17 00:00:00 2001 From: al-abd Date: Thu, 14 Nov 2024 23:19:39 +0330 Subject: [PATCH 02/31] ReCommit dev updates --- .../00000000000003_create_mushaf/up.sql | 1 - .../00000000000005_create_quran_surahs/up.sql | 2 -- .../up.sql | 2 ++ src/main.rs | 1 + src/models.rs | 11 +++---- src/routers/quran/ayah/ayah_add.rs | 4 +++ src/routers/quran/ayah/ayah_edit.rs | 20 +++++++++++-- src/routers/quran/ayah/ayah_list.rs | 13 +++++++++ src/routers/quran/ayah/mod.rs | 3 +- src/routers/quran/mushaf/mod.rs | 1 - src/routers/quran/mushaf/mushaf_add.rs | 1 - src/routers/quran/mushaf/mushaf_edit.rs | 3 +- src/routers/quran/surah/mod.rs | 13 +++++---- src/routers/quran/surah/surah_add.rs | 2 -- src/routers/quran/surah/surah_edit.rs | 7 ++--- src/routers/quran/surah/surah_view.rs | 29 ++++++++++++------- src/schema.rs | 29 +++++++++++++++++-- 17 files changed, 100 insertions(+), 42 deletions(-) diff --git a/migrations/00000000000003_create_mushaf/up.sql b/migrations/00000000000003_create_mushaf/up.sql index ab7201a..04aba83 100644 --- a/migrations/00000000000003_create_mushaf/up.sql +++ b/migrations/00000000000003_create_mushaf/up.sql @@ -5,7 +5,6 @@ CREATE TABLE quran_mushafs ( short_name VARCHAR(200), name VARCHAR(400), source VARCHAR(300), - bismillah_text TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT mushaf_fk_user_id_rel FOREIGN KEY(creator_user_id) REFERENCES app_users(id), diff --git a/migrations/00000000000005_create_quran_surahs/up.sql b/migrations/00000000000005_create_quran_surahs/up.sql index c775f90..6172691 100644 --- a/migrations/00000000000005_create_quran_surahs/up.sql +++ b/migrations/00000000000005_create_quran_surahs/up.sql @@ -5,8 +5,6 @@ CREATE TABLE quran_surahs ( name VARCHAR(50) NOT NULL, period VARCHAR(50), number serial NOT NULL, - bismillah_status BOOLEAN NOT NULL, - bismillah_as_first_ayah BOOLEAN NOT NULL, mushaf_id serial NOT NULL, name_pronunciation TEXT, name_translation_phrase TEXT, diff --git a/migrations/2023-02-19-100955_create_quran_ayahs/up.sql b/migrations/2023-02-19-100955_create_quran_ayahs/up.sql index 89e0803..3383d46 100644 --- a/migrations/2023-02-19-100955_create_quran_ayahs/up.sql +++ b/migrations/2023-02-19-100955_create_quran_ayahs/up.sql @@ -5,6 +5,8 @@ CREATE TABLE quran_ayahs ( surah_id serial NOT NULL, ayah_number serial NOT NULL, sajdah VARCHAR(20), + is_bismillah BOOLEAN NOT NULL, + bismillah_text TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT quran_ayahs_id PRIMARY KEY (id), diff --git a/src/main.rs b/src/main.rs index 78efd78..4da9c5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -206,6 +206,7 @@ async fn main() -> std::io::Result<()> { .service( web::scope("/text").service( web::resource("/{translation_uuid}") + .wrap(AuthZ::new(auth_z_controller.clone())) .wrap(TokenAuth::new(user_id_from_token.clone(), false)) .route(web::get().to(translation_text_view::translation_text_view)) .route( diff --git a/src/models.rs b/src/models.rs index abdaecc..08825c8 100644 --- a/src/models.rs +++ b/src/models.rs @@ -246,6 +246,8 @@ pub struct QuranAyah { pub ayah_number: i32, pub sajdah: Option, + pub is_bismillah: bool, + pub bismillah_text: Option, #[serde(skip_serializing)] pub created_at: NaiveDateTime, @@ -260,6 +262,8 @@ pub struct NewQuranAyah { pub surah_id: i32, pub ayah_number: i32, pub sajdah: Option, + pub is_bismillah: bool, + pub bismillah_text: Option, } #[derive(Clone, Selectable, Identifiable, Associations, Queryable, PartialEq, Debug, Serialize)] @@ -303,8 +307,6 @@ pub struct QuranSurah { pub name: String, pub period: Option, pub number: i32, - pub bismillah_status: bool, - pub bismillah_as_first_ayah: bool, pub mushaf_id: i32, pub name_pronunciation: Option, @@ -325,8 +327,6 @@ pub struct NewQuranSurah { pub name: String, pub period: Option, pub number: i32, - pub bismillah_status: bool, - pub bismillah_as_first_ayah: bool, pub mushaf_id: i32, pub name_pronunciation: Option, pub name_translation_phrase: Option, @@ -346,8 +346,6 @@ pub struct QuranMushaf { pub name: Option, pub source: Option, - pub bismillah_text: Option, - #[serde(skip_serializing)] pub created_at: NaiveDateTime, #[serde(skip_serializing)] @@ -361,7 +359,6 @@ pub struct NewQuranMushaf<'a> { pub short_name: Option<&'a str>, pub name: Option<&'a str>, pub source: Option<&'a str>, - pub bismillah_text: Option, } #[derive(Deserialize, Serialize, Clone, Validate, Identifiable, Queryable, Debug, Selectable)] diff --git a/src/routers/quran/ayah/ayah_add.rs b/src/routers/quran/ayah/ayah_add.rs index 63dab9c..4dc1653 100644 --- a/src/routers/quran/ayah/ayah_add.rs +++ b/src/routers/quran/ayah/ayah_add.rs @@ -15,6 +15,8 @@ pub struct AyahWithText { pub surah_uuid: String, pub sajdah: Option, pub text: String, + pub is_bismillah: bool, + pub bismillah_text: Option, } /// Add's a new ayah @@ -59,6 +61,8 @@ pub async fn ayah_add( sajdah: new_ayah.sajdah.map(|sajdah| sajdah.to_string()), ayah_number: (latest_ayah_number + 1) as i32, creator_user_id: user, + is_bismillah: new_ayah.is_bismillah, + bismillah_text: new_ayah.bismillah_text, } .insert_into(quran_ayahs) .get_result(&mut conn)?; diff --git a/src/routers/quran/ayah/ayah_edit.rs b/src/routers/quran/ayah/ayah_edit.rs index 7ab2cc4..5d827bc 100644 --- a/src/routers/quran/ayah/ayah_edit.rs +++ b/src/routers/quran/ayah/ayah_edit.rs @@ -1,5 +1,5 @@ use crate::error::RouterError; -use crate::DbPool; +use crate::{AyahBismillah, DbPool}; use actix_web::web; use diesel::prelude::*; use uuid::Uuid; @@ -13,7 +13,8 @@ pub async fn ayah_edit( pool: web::Data, ) -> Result<&'static str, RouterError> { use crate::schema::quran_ayahs::dsl::{ - ayah_number, quran_ayahs, sajdah as ayah_sajdah, uuid as ayah_uuid, + ayah_number, bismillah_text, is_bismillah, quran_ayahs, sajdah as ayah_sajdah, + uuid as ayah_uuid, }; let new_ayah = new_ayah.into_inner(); @@ -28,6 +29,21 @@ pub async fn ayah_edit( .set(( ayah_number.eq(new_ayah.ayah_number), ayah_sajdah.eq(new_sajdah), + is_bismillah.eq(new_ayah + .bismillah + .clone() + .unwrap_or(AyahBismillah { + is_ayah: false, + text: None, + }) + .is_ayah), + bismillah_text.eq(new_ayah + .bismillah + .unwrap_or(AyahBismillah { + is_ayah: false, + text: None, + }) + .text), )) .execute(&mut conn)?; diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index 2383b6c..f01d70b 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -2,6 +2,7 @@ use crate::error::{RouterError, RouterErrorDetailBuilder}; use crate::filter::Filter; use crate::models::QuranAyah; use crate::routers::multip; +use crate::AyahBismillah; use crate::{ routers::quran::surah::{AyahTy, Format, SimpleAyah}, DbPool, @@ -44,6 +45,18 @@ pub async fn ayah_list( number: a.ayah_number as u32, uuid: a.uuid, sajdah: a.sajdah, + bismillah: match (a.is_bismillah, a.bismillah_text) { + (true, None) => Some(AyahBismillah { + is_ayah: true, + text: None, + }), + (false, Some(text)) => Some(AyahBismillah { + is_ayah: false, + text: Some(text), + }), + (false, None) => None, + (_, _) => None, + }, }); let final_ayahs = ayahs_as_map diff --git a/src/routers/quran/ayah/mod.rs b/src/routers/quran/ayah/mod.rs index 928c075..153e087 100644 --- a/src/routers/quran/ayah/mod.rs +++ b/src/routers/quran/ayah/mod.rs @@ -11,7 +11,7 @@ use uuid::Uuid; use crate::{ filter::{Filters, Order}, - Format, + AyahBismillah, Format, }; #[derive(Deserialize, Serialize)] @@ -64,6 +64,7 @@ pub struct AyahWithContent { pub struct SimpleAyah { pub ayah_number: i32, pub sajdah: Option, + pub bismillah: Option, } #[derive(Deserialize, Clone)] diff --git a/src/routers/quran/mushaf/mod.rs b/src/routers/quran/mushaf/mod.rs index b24a287..f56ce83 100644 --- a/src/routers/quran/mushaf/mod.rs +++ b/src/routers/quran/mushaf/mod.rs @@ -22,7 +22,6 @@ pub struct SimpleMushaf { short_name: String, name: String, source: String, - bismillah_text: Option, } #[derive(Deserialize)] diff --git a/src/routers/quran/mushaf/mushaf_add.rs b/src/routers/quran/mushaf/mushaf_add.rs index b8b146e..1c0f741 100644 --- a/src/routers/quran/mushaf/mushaf_add.rs +++ b/src/routers/quran/mushaf/mushaf_add.rs @@ -31,7 +31,6 @@ pub async fn mushaf_add( creator_user_id: user, name: Some(&new_mushaf.name), source: Some(&new_mushaf.source), - bismillah_text: new_mushaf.bismillah_text, } .insert_into(quran_mushafs) .execute(&mut conn)?; diff --git a/src/routers/quran/mushaf/mushaf_edit.rs b/src/routers/quran/mushaf/mushaf_edit.rs index 834fa23..7e9fb51 100644 --- a/src/routers/quran/mushaf/mushaf_edit.rs +++ b/src/routers/quran/mushaf/mushaf_edit.rs @@ -13,7 +13,7 @@ pub async fn mushaf_edit( pool: web::Data, ) -> Result<&'static str, RouterError> { use crate::schema::quran_mushafs::dsl::{ - bismillah_text, quran_mushafs, name as mushaf_name, short_name as mushaf_short_name, + name as mushaf_name, quran_mushafs, short_name as mushaf_short_name, source as mushaf_source, uuid as mushaf_uuid, }; @@ -28,7 +28,6 @@ pub async fn mushaf_edit( mushaf_name.eq(new_mushaf.name), mushaf_short_name.eq(new_mushaf.short_name), mushaf_source.eq(new_mushaf.source), - bismillah_text.eq(new_mushaf.bismillah_text), )) .execute(&mut conn)?; diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index 1bc51b8..ee25ffc 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -62,12 +62,19 @@ impl PartialOrd for SimpleAyahSurah { } } +#[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug, Deserialize)] +pub struct AyahBismillah { + pub is_ayah: bool, + pub text: Option, +} + /// The Ayah type that will return in the response #[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug)] pub struct SimpleAyah { pub number: u32, pub uuid: Uuid, pub sajdah: Option, + pub bismillah: Option, } /// it contains ayah info and the content @@ -177,10 +184,8 @@ pub struct SingleSurahResponse { pub names: Vec, pub period: Option, pub number: i32, - pub bismillah_status: bool, - pub bismillah_as_first_ayah: bool, - pub bismillah_text: Option, pub number_of_ayahs: i64, + pub bismillah: Option, } /// The response type for /surah @@ -203,7 +208,5 @@ pub struct SimpleSurah { pub name_transliteration: Option, pub period: Option, pub number: i32, - pub bismillah_status: bool, - pub bismillah_as_first_ayah: bool, pub mushaf_uuid: Uuid, } diff --git a/src/routers/quran/surah/surah_add.rs b/src/routers/quran/surah/surah_add.rs index 58e3232..3aa3f0a 100644 --- a/src/routers/quran/surah/surah_add.rs +++ b/src/routers/quran/surah/surah_add.rs @@ -61,8 +61,6 @@ pub async fn surah_add( period: new_surah.period, number: (latest_surah_number + 1) as i32, mushaf_id: mushaf, - bismillah_status: new_surah.bismillah_status, - bismillah_as_first_ayah: new_surah.bismillah_as_first_ayah, name_pronunciation: new_surah.name_pronunciation, name_translation_phrase: new_surah.name_translation_phrase, name_transliteration: new_surah.name_transliteration, diff --git a/src/routers/quran/surah/surah_edit.rs b/src/routers/quran/surah/surah_edit.rs index d8144a8..c5b3735 100644 --- a/src/routers/quran/surah/surah_edit.rs +++ b/src/routers/quran/surah/surah_edit.rs @@ -14,9 +14,8 @@ pub async fn surah_edit( ) -> Result<&'static str, RouterError> { use crate::schema::quran_mushafs::dsl::{id as mushaf_id, quran_mushafs, uuid as mushaf_uuid}; use crate::schema::quran_surahs::dsl::{ - bismillah_as_first_ayah, bismillah_status, mushaf_id as surah_mushaf_id, name, - name_pronunciation, name_translation_phrase, name_transliteration, number, period, - quran_surahs, uuid as surah_uuid, + mushaf_id as surah_mushaf_id, name, name_pronunciation, name_translation_phrase, + name_transliteration, number, period, quran_surahs, uuid as surah_uuid, }; let new_surah = new_surah.into_inner(); @@ -37,8 +36,6 @@ pub async fn surah_edit( number.eq(new_surah.number), surah_mushaf_id.eq(mushaf), name.eq(new_surah.name), - bismillah_status.eq(new_surah.bismillah_status), - bismillah_as_first_ayah.eq(new_surah.bismillah_as_first_ayah), period.eq(new_surah.period), name_pronunciation.eq(new_surah.name_pronunciation), name_translation_phrase.eq(new_surah.name_translation_phrase), diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index 958d341..8a91f77 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -1,4 +1,6 @@ -use super::{Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse}; +use super::{ + AyahBismillah, Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse, +}; use crate::models::{QuranAyah, QuranMushaf, QuranSurah}; use crate::routers::multip; use crate::{error::RouterError, DbPool}; @@ -39,6 +41,18 @@ pub async fn surah_view( number: ayah.ayah_number as u32, uuid: ayah.uuid, sajdah: ayah.sajdah, + bismillah: match (ayah.is_bismillah, ayah.bismillah_text) { + (true, None) => Some(AyahBismillah { + is_ayah: true, + text: None, + }), + (false, Some(text)) => Some(AyahBismillah { + is_ayah: false, + text: Some(text), + }), + (false, None) => None, + (_, _) => None, + }, }); let final_ayahs = ayahs_as_map @@ -62,12 +76,6 @@ pub async fn surah_view( .filter(mushaf_id.eq(surah.mushaf_id)) .get_result::(&mut conn)?; - let mushaf_bismillah_text = if surah.bismillah_as_first_ayah { - None - } else { - mushaf.bismillah_text.clone() // this is Option - }; - let translation = if let Some(ref phrase) = surah.name_translation_phrase { let mut p = app_phrases.left_join(app_phrase_translations).into_boxed(); @@ -88,6 +96,10 @@ pub async fn surah_view( surah: SingleSurahResponse { uuid: surah.uuid, mushaf: SingleSurahMushaf::from(mushaf), + bismillah: match final_ayahs.first().unwrap() { + AyahTy::Text(at) => at.ayah.bismillah.clone(), + AyahTy::Words(at) => at.ayah.bismillah.clone(), + }, names: vec![SurahName { arabic: surah.name, translation, @@ -97,9 +109,6 @@ pub async fn surah_view( }], period: surah.period, number: surah.number, - bismillah_status: surah.bismillah_status, - bismillah_as_first_ayah: surah.bismillah_as_first_ayah, - bismillah_text: mushaf_bismillah_text, number_of_ayahs: final_ayahs.len() as i64, }, ayahs: final_ayahs, diff --git a/src/schema.rs b/src/schema.rs index fc2ac9c..659f5eb 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -4,6 +4,7 @@ diesel::table! { app_accounts (id) { id -> Int4, uuid -> Uuid, + #[max_length = 30] username -> Varchar, account_type -> Text, } @@ -38,11 +39,13 @@ diesel::table! { app_error_logs (id) { id -> Int4, uuid -> Uuid, + #[max_length = 256] error_name -> Varchar, status_code -> Int4, message -> Text, detail -> Nullable, account_id -> Nullable, + #[max_length = 64] request_token -> Nullable, request_user_agent -> Nullable, request_ipv4 -> Cidr, @@ -63,7 +66,9 @@ diesel::table! { uuid -> Uuid, creator_user_id -> Int4, account_id -> Int4, + #[max_length = 300] name -> Varchar, + #[max_length = 8] language -> Varchar, } } @@ -76,6 +81,7 @@ diesel::table! { owner_account_id -> Int4, profile_image -> Nullable, established_date -> Date, + #[max_length = 11] national_id -> Varchar, created_at -> Timestamptz, updated_at -> Timestamptz, @@ -88,7 +94,9 @@ diesel::table! { uuid -> Uuid, creator_user_id -> Int4, permission_id -> Int4, + #[max_length = 450] name -> Varchar, + #[max_length = 255] value -> Varchar, created_at -> Timestamptz, updated_at -> Timestamptz, @@ -101,7 +109,9 @@ diesel::table! { uuid -> Uuid, creator_user_id -> Int4, account_id -> Int4, + #[max_length = 255] object -> Varchar, + #[max_length = 255] action -> Varchar, created_at -> Timestamptz, updated_at -> Timestamptz, @@ -114,6 +124,7 @@ diesel::table! { uuid -> Uuid, phrase_id -> Int4, text -> Text, + #[max_length = 3] language -> Varchar, created_at -> Timestamptz, updated_at -> Timestamptz, @@ -134,6 +145,7 @@ diesel::table! { app_tokens (id) { id -> Int4, account_id -> Int4, + #[max_length = 64] token_hash -> Varchar, terminated -> Bool, terminated_by_id -> Int4, @@ -148,8 +160,11 @@ diesel::table! { account_id -> Int4, creator_user_id -> Int4, primary_name -> Bool, + #[max_length = 100] first_name -> Varchar, + #[max_length = 200] last_name -> Varchar, + #[max_length = 4] language -> Varchar, } } @@ -160,6 +175,7 @@ diesel::table! { account_id -> Int4, birthday -> Nullable, profile_image -> Nullable, + #[max_length = 4] language -> Nullable, created_at -> Timestamptz, updated_at -> Timestamptz, @@ -184,7 +200,10 @@ diesel::table! { creator_user_id -> Int4, surah_id -> Int4, ayah_number -> Int4, + #[max_length = 20] sajdah -> Nullable, + is_bismillah -> Bool, + bismillah_text -> Nullable, created_at -> Timestamptz, updated_at -> Timestamptz, } @@ -195,10 +214,12 @@ diesel::table! { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, + #[max_length = 200] short_name -> Nullable, + #[max_length = 400] name -> Nullable, + #[max_length = 300] source -> Nullable, - bismillah_text -> Nullable, created_at -> Timestamptz, updated_at -> Timestamptz, } @@ -209,11 +230,11 @@ diesel::table! { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, + #[max_length = 50] name -> Varchar, + #[max_length = 50] period -> Nullable, number -> Int4, - bismillah_status -> Bool, - bismillah_as_first_ayah -> Bool, mushaf_id -> Int4, name_pronunciation -> Nullable, name_translation_phrase -> Nullable, @@ -230,8 +251,10 @@ diesel::table! { mushaf_id -> Int4, creator_user_id -> Int4, translator_account_id -> Int4, + #[max_length = 5] language -> Varchar, release_date -> Nullable, + #[max_length = 300] source -> Nullable, approved -> Bool, bismillah -> Text, From 8476674e643aa2fe0a44a51d7af65ffcfddccb18 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 21 Nov 2024 16:54:13 +0330 Subject: [PATCH 03/31] New updated --- src/main.rs | 6 +- src/models.rs | 17 ++--- src/routers/translation/mod.rs | 12 ++-- ...t_delete.rs => translation_ayah_delete.rs} | 10 +-- ...t_modify.rs => translation_ayah_modify.rs} | 58 ++++++++------- .../translation/translation_ayah_view.rs | 71 +++++++++++++++++++ src/routers/translation/translation_edit.rs | 3 +- src/routers/translation/translation_list.rs | 5 -- .../translation/translation_text_view.rs | 56 --------------- src/routers/translation/translation_view.rs | 21 +++--- src/schema.rs | 12 ++-- 11 files changed, 147 insertions(+), 124 deletions(-) rename src/routers/translation/{translation_text_delete.rs => translation_ayah_delete.rs} (83%) rename src/routers/translation/{translation_text_modify.rs => translation_ayah_modify.rs} (53%) create mode 100644 src/routers/translation/translation_ayah_view.rs delete mode 100644 src/routers/translation/translation_text_view.rs diff --git a/src/main.rs b/src/main.rs index 90a46b4..67ff275 100644 --- a/src/main.rs +++ b/src/main.rs @@ -207,7 +207,7 @@ async fn main() -> std::io::Result<()> { web::scope("/text") .route( "/{translation_uuid}", - web::get().to(translation_text_view::translation_text_view), + web::get().to(translation_ayah_view::translation_ayah_view), ) .service( web::resource("/{translation_uuid}") @@ -215,11 +215,11 @@ async fn main() -> std::io::Result<()> { .wrap(TokenAuth::new(user_id_from_token.clone(), true)) .route( web::post() - .to(translation_text_modify::translation_text_modify), + .to(translation_ayah_modify::translation_ayah_modify), ) .route( web::delete() - .to(translation_text_delete::translation_text_delete), + .to(translation_ayah_delete::translation_ayah_delete), ), ), ), diff --git a/src/models.rs b/src/models.rs index 08825c8..70b0d14 100644 --- a/src/models.rs +++ b/src/models.rs @@ -465,10 +465,6 @@ pub struct Translation { /// translation content status pub approved: bool, - /// Translated Bissmillah - #[serde(skip_serializing)] - pub bismillah: String, - #[serde(skip_serializing)] pub created_at: NaiveDateTime, #[serde(skip_serializing)] @@ -498,10 +494,10 @@ pub struct NewTranslation { Selectable, QueryableByName, )] -#[diesel(table_name = quran_translations_text)] +#[diesel(table_name = quran_translations_ayahs)] #[diesel(belongs_to(Translation))] #[diesel(belongs_to(QuranAyah, foreign_key = ayah_id))] -pub struct TranslationText { +pub struct TranslationAyah { #[serde(skip_serializing)] pub id: i32, pub uuid: Uuid, @@ -517,6 +513,10 @@ pub struct TranslationText { pub text: String, + /// Translated Bissmillah + #[serde(skip_serializing)] + pub bismillah: Option, + #[serde(skip_serializing)] pub created_at: NaiveDateTime, #[serde(skip_serializing)] @@ -524,12 +524,13 @@ pub struct TranslationText { } #[derive(Insertable)] -#[diesel(table_name = quran_translations_text)] -pub struct NewTranslationText<'a> { +#[diesel(table_name = quran_translations_ayahs)] +pub struct NewTranslationAyah<'a> { pub creator_user_id: i32, pub translation_id: i32, pub ayah_id: i32, pub text: &'a String, + pub bismillah: Option, } #[derive(Deserialize, Serialize, Clone, Validate, Identifiable, Queryable, Debug, Selectable)] diff --git a/src/routers/translation/mod.rs b/src/routers/translation/mod.rs index 1e949ec..9d655a8 100644 --- a/src/routers/translation/mod.rs +++ b/src/routers/translation/mod.rs @@ -1,10 +1,10 @@ pub mod translation_add; +pub mod translation_ayah_delete; +pub mod translation_ayah_modify; +pub mod translation_ayah_view; pub mod translation_delete; pub mod translation_edit; pub mod translation_list; -pub mod translation_text_delete; -pub mod translation_text_modify; -pub mod translation_text_view; pub mod translation_view; use chrono::NaiveDate; @@ -43,6 +43,7 @@ pub struct TranslationAyah { text_uuid: Option, number: u32, surah_number: u32, + bismillah: Option, text: Option, } @@ -53,7 +54,6 @@ pub struct ViewableTranslation { pub release_date: Option, pub source: Option, pub status: TranslationStatus, - pub bismillah: String, pub translator: TranslatorData, pub ayahs: Vec, } @@ -64,12 +64,12 @@ pub struct EditableSimpleTranslation { pub language: String, pub release_date: Option, pub source: Option, - pub bismillah: String, } #[derive(Serialize, Deserialize)] -pub struct SimpleTranslationText { +pub struct SimpleTranslationAyah { pub text: String, + pub bismillah: Option, } #[derive(Serialize, Deserialize, Clone)] diff --git a/src/routers/translation/translation_text_delete.rs b/src/routers/translation/translation_ayah_delete.rs similarity index 83% rename from src/routers/translation/translation_text_delete.rs rename to src/routers/translation/translation_ayah_delete.rs index fab63ad..7c7451f 100644 --- a/src/routers/translation/translation_text_delete.rs +++ b/src/routers/translation/translation_ayah_delete.rs @@ -10,8 +10,8 @@ pub struct TextDeleteQuery { ayah_uuid: Uuid, } -/// Delete single translation_text -pub async fn translation_text_delete( +/// Delete single translation_ayah +pub async fn translation_ayah_delete( path: web::Path, pool: web::Data, query: web::Query, @@ -20,8 +20,8 @@ pub async fn translation_text_delete( use crate::schema::quran_translations::dsl::{ id as translations_id, quran_translations, uuid as translation_uuid, }; - use crate::schema::quran_translations_text::dsl::{ - ayah_id as text_ayah_id, quran_translations_text, translation_id as text_translation_id, + use crate::schema::quran_translations_ayahs::dsl::{ + ayah_id as text_ayah_id, quran_translations_ayahs, translation_id as text_translation_id, }; let path = path.into_inner(); @@ -43,7 +43,7 @@ pub async fn translation_text_delete( .get_result(&mut conn)?; diesel::delete( - quran_translations_text + quran_translations_ayahs .filter(text_ayah_id.eq(ayah)) .filter(text_translation_id.eq(translation)), ) diff --git a/src/routers/translation/translation_text_modify.rs b/src/routers/translation/translation_ayah_modify.rs similarity index 53% rename from src/routers/translation/translation_text_modify.rs rename to src/routers/translation/translation_ayah_modify.rs index c5ff9d9..6d745ee 100644 --- a/src/routers/translation/translation_text_modify.rs +++ b/src/routers/translation/translation_ayah_modify.rs @@ -1,18 +1,18 @@ -use crate::translation_text_view::TextViewQuery; -use crate::{error::RouterError, models::NewTranslationText, DbPool}; +use crate::translation_ayah_view::TextViewQuery; +use crate::{error::RouterError, models::NewTranslationAyah, DbPool}; use actix_web::web; use diesel::select; use diesel::{dsl::exists, prelude::*}; use uuid::Uuid; -use super::SimpleTranslationText; +use super::SimpleTranslationAyah; /// Modify translation text, /// /// If the translation to an ayah exists updated it, /// otherwise add. -pub async fn translation_text_modify( - new_translation_text: web::Json, +pub async fn translation_ayah_modify( + new_translation_ayah: web::Json, pool: web::Data, data: web::ReqData, // translatio uuid @@ -20,16 +20,18 @@ pub async fn translation_text_modify( query: web::Query, ) -> Result<&'static str, RouterError> { use crate::schema::app_users::dsl::{account_id as user_acc_id, app_users, id as user_id}; - use crate::schema::quran_ayahs::dsl::{id as ayah_id, quran_ayahs, uuid as ayah_uuid}; + use crate::schema::quran_ayahs::dsl::{ + bismillah_text, id as ayah_id, quran_ayahs, uuid as ayah_uuid, + }; use crate::schema::quran_translations::dsl::{ id as translation_id, quran_translations, uuid as translation_uuid, }; - use crate::schema::quran_translations_text::dsl::{ - ayah_id as text_ayah_id, quran_translations_text, text as text_content, - translation_id as text_translation_id, + use crate::schema::quran_translations_ayahs::dsl::{ + ayah_id as text_ayah_id, bismillah as translation_ayah_bismillah, quran_translations_ayahs, + text as text_content, translation_id as text_translation_id, }; - let new_translation_text = new_translation_text.into_inner(); + let new_translation_ayah = new_translation_ayah.into_inner(); let path = path.into_inner(); let creator_id = data.into_inner(); let query = query.into_inner(); @@ -44,26 +46,33 @@ pub async fn translation_text_modify( .get_result(&mut conn)?; // Get the translation text ayah id - let ayah: i32 = quran_ayahs + let (a_id, a_bismillah_text): (i32, Option) = quran_ayahs .filter(ayah_uuid.eq(query.ayah_uuid)) - .select(ayah_id) + .select((ayah_id, bismillah_text)) .get_result(&mut conn)?; - // Now check if the translation_text exists + if a_bismillah_text.is_none() && new_translation_ayah.bismillah.is_some() { + return Err(RouterError::from_predefined("NO_BISMILLAH")); + } + + // Now check if the translation_ayah exists let text: bool = select(exists( - quran_translations_text - .filter(text_ayah_id.eq(ayah)) + quran_translations_ayahs + .filter(text_ayah_id.eq(a_id)) .filter(text_translation_id.eq(translation)), )) .get_result(&mut conn)?; // TODO: use (on conflict do update) if text { - // This means the translation_text exists, we just need to update it - diesel::update(quran_translations_text) - .filter(text_ayah_id.eq(ayah)) + // This means the translation_ayah exists, we just need to update it + diesel::update(quran_translations_ayahs) + .filter(text_ayah_id.eq(a_id)) .filter(text_translation_id.eq(translation)) - .set((text_content.eq(new_translation_text.text),)) + .set(( + text_content.eq(new_translation_ayah.text), + translation_ayah_bismillah.eq(new_translation_ayah.bismillah), + )) .execute(&mut conn)?; Ok("Updated") @@ -74,14 +83,15 @@ pub async fn translation_text_modify( .select(user_id) .get_result(&mut conn)?; - // This means user wants to add a new translation_text - NewTranslationText { + // This means user wants to add a new translation_ayah + NewTranslationAyah { creator_user_id: user, - text: &new_translation_text.text, + text: &new_translation_ayah.text, translation_id: translation, - ayah_id: ayah, + ayah_id: a_id, + bismillah: new_translation_ayah.bismillah, } - .insert_into(quran_translations_text) + .insert_into(quran_translations_ayahs) .execute(&mut conn)?; Ok("Added") diff --git a/src/routers/translation/translation_ayah_view.rs b/src/routers/translation/translation_ayah_view.rs new file mode 100644 index 0000000..af4b26b --- /dev/null +++ b/src/routers/translation/translation_ayah_view.rs @@ -0,0 +1,71 @@ +use crate::error::RouterError; +use crate::models::TranslationAyah; +use crate::DbPool; +use ::uuid::Uuid; +use actix_web::web; +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize)] +pub struct TextViewQuery { + pub ayah_uuid: Uuid, +} + +#[derive(Deserialize, Serialize)] +pub struct TranslationAyahData { + pub uuid: Uuid, + pub text: String, + pub bismillah: Option, + pub has_bismillah: bool, +} + +/// Return's a single translation_ayah +pub async fn translation_ayah_view( + path: web::Path, + pool: web::Data, + query: web::Query, +) -> Result, RouterError> { + use crate::schema::quran_ayahs::dsl::{ + bismillah_text, id as ayah_id, quran_ayahs, uuid as ayah_uuid, + }; + use crate::schema::quran_translations::dsl::{ + id as translations_id, quran_translations, uuid as translation_uuid, + }; + use crate::schema::quran_translations_ayahs::dsl::{ + ayah_id as text_ayah_id, quran_translations_ayahs, translation_id as text_translation_id, + }; + + let path = path.into_inner(); + let query = query.into_inner(); + + web::block(move || { + let mut conn = pool.get().unwrap(); + + // Get the translation by uuid + let translation: i32 = quran_translations + .filter(translation_uuid.eq(path)) + .select(translations_id) + .get_result(&mut conn)?; + + // Get the ayah by uuid + let (a_id, a_bismillah_text): (i32, Option) = quran_ayahs + .filter(ayah_uuid.eq(query.ayah_uuid)) + .select((ayah_id, bismillah_text)) + .get_result(&mut conn)?; + + // Get the single translation_ayah from the database + let translation_ayah: TranslationAyah = quran_translations_ayahs + .filter(text_ayah_id.eq(a_id)) + .filter(text_translation_id.eq(translation)) + .get_result(&mut conn)?; + + Ok(web::Json(TranslationAyahData { + uuid: translation_ayah.uuid, + text: translation_ayah.text, + bismillah: translation_ayah.bismillah, + has_bismillah: a_bismillah_text.is_some(), + })) + }) + .await + .unwrap() +} diff --git a/src/routers/translation/translation_edit.rs b/src/routers/translation/translation_edit.rs index 3b7ba6b..067990f 100644 --- a/src/routers/translation/translation_edit.rs +++ b/src/routers/translation/translation_edit.rs @@ -11,7 +11,7 @@ pub async fn translation_edit( pool: web::Data, ) -> Result<&'static str, RouterError> { use crate::schema::quran_translations::dsl::{ - bismillah as translation_bismillah, language as translation_language, quran_translations, + language as translation_language, quran_translations, release_date as translation_release_date, source as translation_source, uuid as translation_uuid, }; @@ -27,7 +27,6 @@ pub async fn translation_edit( translation_source.eq(new_translation.source), translation_release_date.eq(new_translation.release_date), translation_language.eq(new_translation.language), - translation_bismillah.eq(new_translation.bismillah), )) .execute(&mut conn)?; diff --git a/src/routers/translation/translation_list.rs b/src/routers/translation/translation_list.rs index 57b6729..3310e49 100644 --- a/src/routers/translation/translation_list.rs +++ b/src/routers/translation/translation_list.rs @@ -29,9 +29,6 @@ pub struct TranslationItem { /// translation content status pub approved: bool, - /// Translated Bissmillah - pub bismillah: String, - pub translator: TranslatorData, } @@ -95,7 +92,6 @@ pub async fn translation_list( .map( |(t, a_u, username, first_name, last_name)| TranslationItem { uuid: t.uuid, - bismillah: t.bismillah, source: t.source, language: t.language, approved: t.approved, @@ -126,7 +122,6 @@ pub async fn translation_list( .map( |(t, a_u, username, first_name, last_name)| TranslationItem { uuid: t.uuid, - bismillah: t.bismillah, source: t.source, language: t.language, approved: t.approved, diff --git a/src/routers/translation/translation_text_view.rs b/src/routers/translation/translation_text_view.rs deleted file mode 100644 index 579dbe7..0000000 --- a/src/routers/translation/translation_text_view.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::error::RouterError; -use crate::models::TranslationText; -use crate::DbPool; -use ::uuid::Uuid; -use actix_web::web; -use diesel::prelude::*; -use serde::Deserialize; - -#[derive(Deserialize)] -pub struct TextViewQuery { - pub ayah_uuid: Uuid, -} - -/// Return's a single translation_text -pub async fn translation_text_view( - path: web::Path, - pool: web::Data, - query: web::Query, -) -> Result, RouterError> { - use crate::schema::quran_ayahs::dsl::{id as ayah_id, quran_ayahs, uuid as ayah_uuid}; - use crate::schema::quran_translations::dsl::{ - id as translations_id, quran_translations, uuid as translation_uuid, - }; - use crate::schema::quran_translations_text::dsl::{ - ayah_id as text_ayah_id, quran_translations_text, translation_id as text_translation_id, - }; - - let path = path.into_inner(); - let query = query.into_inner(); - - web::block(move || { - let mut conn = pool.get().unwrap(); - - // Get the translation by uuid - let translation: i32 = quran_translations - .filter(translation_uuid.eq(path)) - .select(translations_id) - .get_result(&mut conn)?; - - // Get the ayah by uuid - let ayah: i32 = quran_ayahs - .filter(ayah_uuid.eq(query.ayah_uuid)) - .select(ayah_id) - .get_result(&mut conn)?; - - // Get the single translation_text from the database - let translation_text: TranslationText = quran_translations_text - .filter(text_ayah_id.eq(ayah)) - .filter(text_translation_id.eq(translation)) - .get_result(&mut conn)?; - - Ok(web::Json(translation_text)) - }) - .await - .unwrap() -} diff --git a/src/routers/translation/translation_view.rs b/src/routers/translation/translation_view.rs index fac5014..bf55d5f 100644 --- a/src/routers/translation/translation_view.rs +++ b/src/routers/translation/translation_view.rs @@ -33,9 +33,9 @@ pub async fn translation_view( uuid as surah_table_uuid, }; use crate::schema::quran_translations::dsl::{quran_translations, uuid as translation_uuid}; - use crate::schema::quran_translations_text::dsl::{ - quran_translations_text, text as translation_text, translation_id, - uuid as translation_text_uuid, + use crate::schema::quran_translations_ayahs::dsl::{ + bismillah as translation_ayah_bismillah, quran_translations_ayahs, + text as translation_ayah, translation_id, uuid as translation_ayah_uuid, }; let path = path.into_inner(); @@ -66,7 +66,7 @@ pub async fn translation_view( .get_result::<(Uuid, String, Option, Option)>(&mut conn)?; let mut ayahs = quran_surahs - .inner_join(quran_ayahs.left_outer_join(quran_translations_text)) + .inner_join(quran_ayahs.left_outer_join(quran_translations_ayahs)) .internal_into_boxed(); if let Some(uuid) = query.surah_uuid { @@ -82,18 +82,21 @@ pub async fn translation_view( ) .order(ayah_number.asc()) .select(( - translation_text.nullable(), + translation_ayah.nullable(), ayah_uuid, ayah_number, surah_number, - translation_text_uuid.nullable(), + translation_ayah_uuid.nullable(), + translation_ayah_bismillah.nullable(), )) - .get_results::<(Option, Uuid, i32, i32, Option)>(&mut conn)?; + .get_results::<(Option, Uuid, i32, i32, Option, Option)>( + &mut conn, + )?; let mut result_ayahs = vec![]; let mut status = TranslationStatus::Ok; - for (text, a_uuid, a_number, s_number, text_uuid) in result { + for (text, a_uuid, a_number, s_number, text_uuid, bismillah) in result { if text_uuid.is_none() { status = TranslationStatus::Incomplete; } @@ -103,6 +106,7 @@ pub async fn translation_view( surah_number: s_number as u32, number: a_number as u32, text_uuid, + bismillah, }); } @@ -123,7 +127,6 @@ pub async fn translation_view( first_name: translator.2, last_name: translator.3, }, - bismillah: translation.bismillah, })) }) .await diff --git a/src/schema.rs b/src/schema.rs index 659f5eb..a6f34fe 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -257,20 +257,20 @@ diesel::table! { #[max_length = 300] source -> Nullable, approved -> Bool, - bismillah -> Text, created_at -> Timestamptz, updated_at -> Timestamptz, } } diesel::table! { - quran_translations_text (id) { + quran_translations_ayahs (id) { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, translation_id -> Int4, ayah_id -> Int4, text -> Text, + bismillah -> Nullable, created_at -> Timestamptz, updated_at -> Timestamptz, } @@ -312,9 +312,9 @@ diesel::joinable!(quran_surahs -> quran_mushafs (mushaf_id)); diesel::joinable!(quran_translations -> app_accounts (translator_account_id)); diesel::joinable!(quran_translations -> app_users (creator_user_id)); diesel::joinable!(quran_translations -> quran_mushafs (mushaf_id)); -diesel::joinable!(quran_translations_text -> app_users (creator_user_id)); -diesel::joinable!(quran_translations_text -> quran_ayahs (ayah_id)); -diesel::joinable!(quran_translations_text -> quran_translations (translation_id)); +diesel::joinable!(quran_translations_ayahs -> app_users (creator_user_id)); +diesel::joinable!(quran_translations_ayahs -> quran_ayahs (ayah_id)); +diesel::joinable!(quran_translations_ayahs -> quran_translations (translation_id)); diesel::joinable!(quran_words -> app_users (creator_user_id)); diesel::joinable!(quran_words -> quran_ayahs (ayah_id)); @@ -337,6 +337,6 @@ diesel::allow_tables_to_appear_in_same_query!( quran_mushafs, quran_surahs, quran_translations, - quran_translations_text, + quran_translations_ayahs, quran_words, ); From 1d358cd9dcb303b925b13799df05d8889db43e82 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 21 Nov 2024 16:54:25 +0330 Subject: [PATCH 04/31] tables updated --- migrations/2023-03-12-100253_create_translation/up.sql | 1 - .../2023-03-12-100301_create_translation_ayahs/down.sql | 1 + .../up.sql | 7 ++++--- .../2023-03-12-100301_create_translation_text/down.sql | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 migrations/2023-03-12-100301_create_translation_ayahs/down.sql rename migrations/{2023-03-12-100301_create_translation_text => 2023-03-12-100301_create_translation_ayahs}/up.sql (75%) delete mode 100644 migrations/2023-03-12-100301_create_translation_text/down.sql diff --git a/migrations/2023-03-12-100253_create_translation/up.sql b/migrations/2023-03-12-100253_create_translation/up.sql index 268acc0..bd746e7 100644 --- a/migrations/2023-03-12-100253_create_translation/up.sql +++ b/migrations/2023-03-12-100253_create_translation/up.sql @@ -8,7 +8,6 @@ CREATE TABLE quran_translations ( release_date DATE, source VARCHAR(300), approved BOOLEAN DEFAULT FALSE NOT NULL, - bismillah TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT translation_fk_user_id_rel FOREIGN KEY(creator_user_id) REFERENCES app_users(id), diff --git a/migrations/2023-03-12-100301_create_translation_ayahs/down.sql b/migrations/2023-03-12-100301_create_translation_ayahs/down.sql new file mode 100644 index 0000000..473ccff --- /dev/null +++ b/migrations/2023-03-12-100301_create_translation_ayahs/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_translations_ayahs; diff --git a/migrations/2023-03-12-100301_create_translation_text/up.sql b/migrations/2023-03-12-100301_create_translation_ayahs/up.sql similarity index 75% rename from migrations/2023-03-12-100301_create_translation_text/up.sql rename to migrations/2023-03-12-100301_create_translation_ayahs/up.sql index 50259e8..02a288d 100644 --- a/migrations/2023-03-12-100301_create_translation_text/up.sql +++ b/migrations/2023-03-12-100301_create_translation_ayahs/up.sql @@ -1,14 +1,15 @@ -CREATE TABLE quran_translations_text ( +CREATE TABLE quran_translations_ayahs ( id serial NOT NULL, uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, creator_user_id serial NOT NULL, translation_id serial NOT NULL, ayah_id serial NOT NULL, text TEXT NOT NULL, + bismillah TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - CONSTRAINT translation_text_id PRIMARY KEY (id), + CONSTRAINT translation_ayah_id PRIMARY KEY (id), CONSTRAINT fk_translation FOREIGN KEY(translation_id) REFERENCES quran_translations(id) on delete cascade, - CONSTRAINT translation_text_fk_user_id_rel FOREIGN KEY(creator_user_id) REFERENCES app_users(id), + CONSTRAINT translation_ayah_fk_user_id_rel FOREIGN KEY(creator_user_id) REFERENCES app_users(id), CONSTRAINT fk_ayah FOREIGN KEY(ayah_id) REFERENCES quran_ayahs(id) on delete cascade ); diff --git a/migrations/2023-03-12-100301_create_translation_text/down.sql b/migrations/2023-03-12-100301_create_translation_text/down.sql deleted file mode 100644 index e16f11d..0000000 --- a/migrations/2023-03-12-100301_create_translation_text/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE quran_translations_text; From c3d624c5f8a5bd2f923d11d9800f86aa146da803 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 21 Nov 2024 16:55:05 +0330 Subject: [PATCH 05/31] new error code added, formated --- error_codes.json | 172 ++++++++++++++++++++++++----------------------- 1 file changed, 88 insertions(+), 84 deletions(-) diff --git a/error_codes.json b/error_codes.json index 4d28d88..2ab0777 100644 --- a/error_codes.json +++ b/error_codes.json @@ -1,86 +1,90 @@ { - "INTERNAL_ERROR": { - "status_code": 500, - "message": "Internal Error!" - }, - "NOT_FOUND": { - "status_code": 404, - "message": "Not found!" - }, - "ACTION_NOT_FOUND": { - "status_code": 404, - "message": "Not found!" - }, - "SEND_CODE_INTERNAL_ERROR": { - "status_code": 500, - "message": "Internal error when sending verification code!" - }, - "VERIFY_CODE_NOT_SENDED": { - "status_code": 410, - "message": "No verification code is sended to this email!" - }, - "VERIFY_CODE_NOT_VALID": { - "status_code": 400, - "message": "Verification code is not valid!" - }, - "VERIFY_CODE_ALREADY_USED": { - "status_code": 410, - "message": "Verification code is already used!" - }, - "VERIFY_CODE_EXPIRED": { - "status_code": 410, - "message": "Verification code is expired!" - }, - "CANT_GENERATE_TOKEN": { - "status_code": 500, - "message": "Can't generate token!" - }, - "ORGANIZATION_NAME_NOT_AVAILABLE": { - "status_code": 404, - "message": "Organization name is already in use by another account!" - }, - "PERMISSION_CONDITION_VALUE_NOT_VALID": { - "status_code": 400, - "message": "Permission condition value is not valid!" - }, - "AUTHZ_CONDITION_VALUE_NOT_DEFINED": { - "status_code": 404, - "message": "Authz condition value is not defined!" - }, - "MODEL_ATTRIBUTE_NOT_DEFINED": { - "status_code": 404, - "message": "Model attribute value is not defined!" - }, - "VALIDATION_ERROR": { - "status_code": 400, - "message": "Request data is not valid" - }, - "FILTER_SORT_VALUE_NOT_DEFINED": { - "status_code": 404, - "message": "Filter sort value is not defined!" - }, - "AUTHN_TOKEN_NOT_FOUND": { - "status_code": 401, - "message": "Token required!" - }, - "AUTHN_TOKEN_INVALID": { - "status_code": 401, - "message": "Token invalid!" - }, - "AUTHZ_PERMISSION_DENIED": { - "status_code": 403, - "message": "Permission denied!" - }, - "UUID_ERROR": { - "status_code": 400, - "message": "Invalid UUID!" - }, - "PHRASE_NOT_FOUND": { - "status_code": 404, - "message": "Phrase not found!" - }, - "BAD_PATH": { - "status_code": 400, - "message": "Path format is not correct!" - } + "INTERNAL_ERROR": { + "status_code": 500, + "message": "Internal Error!" + }, + "NOT_FOUND": { + "status_code": 404, + "message": "Not found!" + }, + "ACTION_NOT_FOUND": { + "status_code": 404, + "message": "Not found!" + }, + "SEND_CODE_INTERNAL_ERROR": { + "status_code": 500, + "message": "Internal error when sending verification code!" + }, + "VERIFY_CODE_NOT_SENDED": { + "status_code": 410, + "message": "No verification code is sended to this email!" + }, + "VERIFY_CODE_NOT_VALID": { + "status_code": 400, + "message": "Verification code is not valid!" + }, + "VERIFY_CODE_ALREADY_USED": { + "status_code": 410, + "message": "Verification code is already used!" + }, + "VERIFY_CODE_EXPIRED": { + "status_code": 410, + "message": "Verification code is expired!" + }, + "CANT_GENERATE_TOKEN": { + "status_code": 500, + "message": "Can't generate token!" + }, + "ORGANIZATION_NAME_NOT_AVAILABLE": { + "status_code": 404, + "message": "Organization name is already in use by another account!" + }, + "PERMISSION_CONDITION_VALUE_NOT_VALID": { + "status_code": 400, + "message": "Permission condition value is not valid!" + }, + "AUTHZ_CONDITION_VALUE_NOT_DEFINED": { + "status_code": 404, + "message": "Authz condition value is not defined!" + }, + "MODEL_ATTRIBUTE_NOT_DEFINED": { + "status_code": 404, + "message": "Model attribute value is not defined!" + }, + "VALIDATION_ERROR": { + "status_code": 400, + "message": "Request data is not valid" + }, + "FILTER_SORT_VALUE_NOT_DEFINED": { + "status_code": 404, + "message": "Filter sort value is not defined!" + }, + "AUTHN_TOKEN_NOT_FOUND": { + "status_code": 401, + "message": "Token required!" + }, + "AUTHN_TOKEN_INVALID": { + "status_code": 401, + "message": "Token invalid!" + }, + "AUTHZ_PERMISSION_DENIED": { + "status_code": 403, + "message": "Permission denied!" + }, + "UUID_ERROR": { + "status_code": 400, + "message": "Invalid UUID!" + }, + "PHRASE_NOT_FOUND": { + "status_code": 404, + "message": "Phrase not found!" + }, + "BAD_PATH": { + "status_code": 400, + "message": "Path format is not correct!" + }, + "NO_BISMILLAH": { + "status_code": 400, + "message": "Doesn't have bismillah!" + } } From b1502babe3174d56850d82bef639cab08891f707 Mon Sep 17 00:00:00 2001 From: nyzd Date: Fri, 29 Nov 2024 14:29:38 +0330 Subject: [PATCH 06/31] bug fix --- src/routers/quran/surah/mod.rs | 41 ++++++++++++++++++++++++++- src/routers/quran/surah/surah_view.rs | 5 +--- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index ee25ffc..bd1c9d1 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -68,6 +68,12 @@ pub struct AyahBismillah { pub text: Option, } +#[derive(Serialize, Clone, Debug)] +pub struct AyahBismillahInSurah { + pub is_first_ayah: bool, + pub text: String, +} + /// The Ayah type that will return in the response #[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug)] pub struct SimpleAyah { @@ -99,6 +105,39 @@ pub enum AyahTy { Words(AyahWithWords), } +impl AyahTy { + pub fn format_bismillah_for_surah(&self) -> Option { + match self { + AyahTy::Text(at) => at.ayah.bismillah.clone().map(|bismillah| { + if bismillah.is_ayah { + AyahBismillahInSurah { + is_first_ayah: true, + text: at.text.clone(), + } + } else { + AyahBismillahInSurah { + is_first_ayah: false, + text: bismillah.text.unwrap_or(String::new()), + } + } + }), + AyahTy::Words(at) => at.ayah.bismillah.clone().map(|bismillah| { + if bismillah.is_ayah { + AyahBismillahInSurah { + is_first_ayah: true, + text: at.words.join("").clone(), + } + } else { + AyahBismillahInSurah { + is_first_ayah: false, + text: bismillah.text.unwrap_or(String::new()), + } + } + }), + } + } +} + /// The final response body #[derive(Serialize, Clone, Debug)] pub struct QuranResponseData { @@ -185,7 +224,7 @@ pub struct SingleSurahResponse { pub period: Option, pub number: i32, pub number_of_ayahs: i64, - pub bismillah: Option, + pub bismillah: Option, } /// The response type for /surah diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index 8a91f77..d9741a2 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -96,10 +96,7 @@ pub async fn surah_view( surah: SingleSurahResponse { uuid: surah.uuid, mushaf: SingleSurahMushaf::from(mushaf), - bismillah: match final_ayahs.first().unwrap() { - AyahTy::Text(at) => at.ayah.bismillah.clone(), - AyahTy::Words(at) => at.ayah.bismillah.clone(), - }, + bismillah: final_ayahs.first().unwrap().format_bismillah_for_surah(), names: vec![SurahName { arabic: surah.name, translation, From 72615048bcdd6471e6b3bdc7fd8b451151def8d5 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 5 Dec 2024 16:32:47 +0330 Subject: [PATCH 07/31] new table added --- .../down.sql | 1 + .../up.sql | 12 ++++++++++++ src/schema.rs | 17 +++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql create mode 100644 migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql diff --git a/migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql b/migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql new file mode 100644 index 0000000..51e2759 --- /dev/null +++ b/migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_ayah_divide; diff --git a/migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql b/migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql new file mode 100644 index 0000000..f28e86f --- /dev/null +++ b/migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql @@ -0,0 +1,12 @@ +CREATE TABLE quran_ayah_divide ( + id serial NOT NULL, + uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, + creator_user_id serial NOT NULL, + ayah_id serial NOT NULL, + divider_account_id serial, + type VARCHAR(256) NOT NULL, + CONSTRAINT ayah_divide_id PRIMARY KEY (id), + CONSTRAINT fk_quran_ayah_divider_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), + CONSTRAINT fk_divide_ayah FOREIGN KEY (ayah_id) REFERENCES quran_ayahs (id) on delete cascade, + CONSTRAINT fk_ayah_divide_account_rel FOREIGN KEY (divider_account_id) REFERENCES app_accounts (id) +); diff --git a/src/schema.rs b/src/schema.rs index a6f34fe..e658404 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -193,6 +193,19 @@ diesel::table! { } } +diesel::table! { + quran_ayah_divide (id) { + id -> Int4, + uuid -> Uuid, + creator_user_id -> Int4, + ayah_id -> Int4, + divider_account_id -> Int4, + #[sql_name = "type"] + #[max_length = 256] + type_ -> Varchar, + } +} + diesel::table! { quran_ayahs (id) { id -> Int4, @@ -304,6 +317,9 @@ diesel::joinable!(app_tokens -> app_accounts (account_id)); diesel::joinable!(app_user_names -> app_accounts (account_id)); diesel::joinable!(app_user_names -> app_users (creator_user_id)); diesel::joinable!(app_users -> app_accounts (account_id)); +diesel::joinable!(quran_ayah_divide -> app_accounts (divider_account_id)); +diesel::joinable!(quran_ayah_divide -> app_users (creator_user_id)); +diesel::joinable!(quran_ayah_divide -> quran_ayahs (ayah_id)); diesel::joinable!(quran_ayahs -> app_users (creator_user_id)); diesel::joinable!(quran_ayahs -> quran_surahs (surah_id)); diesel::joinable!(quran_mushafs -> app_users (creator_user_id)); @@ -333,6 +349,7 @@ diesel::allow_tables_to_appear_in_same_query!( app_user_names, app_users, app_verify_codes, + quran_ayah_divide, quran_ayahs, quran_mushafs, quran_surahs, From ba64b3c8390101b9a1c80f51bda152806e3da753 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 5 Dec 2024 23:24:10 +0330 Subject: [PATCH 08/31] new table added --- .../down.sql | 1 + .../up.sql | 12 ++++++++++++ src/schema.rs | 17 +++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 migrations/2024-12-05-184846_create_quran_word_divide/down.sql create mode 100644 migrations/2024-12-05-184846_create_quran_word_divide/up.sql diff --git a/migrations/2024-12-05-184846_create_quran_word_divide/down.sql b/migrations/2024-12-05-184846_create_quran_word_divide/down.sql new file mode 100644 index 0000000..7e05afe --- /dev/null +++ b/migrations/2024-12-05-184846_create_quran_word_divide/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_word_divide; diff --git a/migrations/2024-12-05-184846_create_quran_word_divide/up.sql b/migrations/2024-12-05-184846_create_quran_word_divide/up.sql new file mode 100644 index 0000000..b2148b1 --- /dev/null +++ b/migrations/2024-12-05-184846_create_quran_word_divide/up.sql @@ -0,0 +1,12 @@ +CREATE TABLE quran_word_divide ( + id serial NOT NULL, + uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, + creator_user_id serial NOT NULL, + word_id serial NOT NULL, + divider_account_id serial, + type VARCHAR(256) NOT NULL, + CONSTRAINT word_divide_id PRIMARY KEY (id), + CONSTRAINT fk_quran_word_divider_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), + CONSTRAINT fk_divide_word FOREIGN KEY (word_id) REFERENCES quran_words (id) on delete cascade, + CONSTRAINT fk_word_divide_account_rel FOREIGN KEY (divider_account_id) REFERENCES app_accounts (id) +); diff --git a/src/schema.rs b/src/schema.rs index e658404..e11d601 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -289,6 +289,19 @@ diesel::table! { } } +diesel::table! { + quran_word_divide (id) { + id -> Int4, + uuid -> Uuid, + creator_user_id -> Int4, + word_id -> Int4, + divider_account_id -> Int4, + #[sql_name = "type"] + #[max_length = 256] + type_ -> Varchar, + } +} + diesel::table! { quran_words (id) { id -> Int4, @@ -331,6 +344,9 @@ diesel::joinable!(quran_translations -> quran_mushafs (mushaf_id)); diesel::joinable!(quran_translations_ayahs -> app_users (creator_user_id)); diesel::joinable!(quran_translations_ayahs -> quran_ayahs (ayah_id)); diesel::joinable!(quran_translations_ayahs -> quran_translations (translation_id)); +diesel::joinable!(quran_word_divide -> app_accounts (divider_account_id)); +diesel::joinable!(quran_word_divide -> app_users (creator_user_id)); +diesel::joinable!(quran_word_divide -> quran_words (word_id)); diesel::joinable!(quran_words -> app_users (creator_user_id)); diesel::joinable!(quran_words -> quran_ayahs (ayah_id)); @@ -355,5 +371,6 @@ diesel::allow_tables_to_appear_in_same_query!( quran_surahs, quran_translations, quran_translations_ayahs, + quran_word_divide, quran_words, ); From 8c5b192e8fa2b534580ad4d9455d500ab1b3944c Mon Sep 17 00:00:00 2001 From: nyzd Date: Fri, 6 Dec 2024 01:11:44 +0330 Subject: [PATCH 09/31] Tables name changed --- .../down.sql | 1 - .../down.sql | 1 + .../up.sql | 2 +- .../down.sql | 1 - .../down.sql | 1 + .../up.sql | 2 +- src/schema.rs | 64 +++++++++---------- 7 files changed, 36 insertions(+), 36 deletions(-) delete mode 100644 migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql create mode 100644 migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql rename migrations/{2024-12-05-083921_create_quran_ayah_divide => 2024-12-05-083921_create_quran_ayahs_divide}/up.sql (94%) delete mode 100644 migrations/2024-12-05-184846_create_quran_word_divide/down.sql create mode 100644 migrations/2024-12-05-184846_create_quran_words_divide/down.sql rename migrations/{2024-12-05-184846_create_quran_word_divide => 2024-12-05-184846_create_quran_words_divide}/up.sql (94%) diff --git a/migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql b/migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql deleted file mode 100644 index 51e2759..0000000 --- a/migrations/2024-12-05-083921_create_quran_ayah_divide/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE quran_ayah_divide; diff --git a/migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql b/migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql new file mode 100644 index 0000000..4d04afa --- /dev/null +++ b/migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_ayahs_divide; diff --git a/migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql b/migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql similarity index 94% rename from migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql rename to migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql index f28e86f..3a59c78 100644 --- a/migrations/2024-12-05-083921_create_quran_ayah_divide/up.sql +++ b/migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql @@ -1,4 +1,4 @@ -CREATE TABLE quran_ayah_divide ( +CREATE TABLE quran_ayahs_divide ( id serial NOT NULL, uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, creator_user_id serial NOT NULL, diff --git a/migrations/2024-12-05-184846_create_quran_word_divide/down.sql b/migrations/2024-12-05-184846_create_quran_word_divide/down.sql deleted file mode 100644 index 7e05afe..0000000 --- a/migrations/2024-12-05-184846_create_quran_word_divide/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE quran_word_divide; diff --git a/migrations/2024-12-05-184846_create_quran_words_divide/down.sql b/migrations/2024-12-05-184846_create_quran_words_divide/down.sql new file mode 100644 index 0000000..996421d --- /dev/null +++ b/migrations/2024-12-05-184846_create_quran_words_divide/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_words_divide; diff --git a/migrations/2024-12-05-184846_create_quran_word_divide/up.sql b/migrations/2024-12-05-184846_create_quran_words_divide/up.sql similarity index 94% rename from migrations/2024-12-05-184846_create_quran_word_divide/up.sql rename to migrations/2024-12-05-184846_create_quran_words_divide/up.sql index b2148b1..6d62b03 100644 --- a/migrations/2024-12-05-184846_create_quran_word_divide/up.sql +++ b/migrations/2024-12-05-184846_create_quran_words_divide/up.sql @@ -1,4 +1,4 @@ -CREATE TABLE quran_word_divide ( +CREATE TABLE quran_words_divide ( id serial NOT NULL, uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, creator_user_id serial NOT NULL, diff --git a/src/schema.rs b/src/schema.rs index e11d601..500bcbb 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -193,19 +193,6 @@ diesel::table! { } } -diesel::table! { - quran_ayah_divide (id) { - id -> Int4, - uuid -> Uuid, - creator_user_id -> Int4, - ayah_id -> Int4, - divider_account_id -> Int4, - #[sql_name = "type"] - #[max_length = 256] - type_ -> Varchar, - } -} - diesel::table! { quran_ayahs (id) { id -> Int4, @@ -222,6 +209,19 @@ diesel::table! { } } +diesel::table! { + quran_ayahs_divide (id) { + id -> Int4, + uuid -> Uuid, + creator_user_id -> Int4, + ayah_id -> Int4, + divider_account_id -> Int4, + #[sql_name = "type"] + #[max_length = 256] + type_ -> Varchar, + } +} + diesel::table! { quran_mushafs (id) { id -> Int4, @@ -290,27 +290,27 @@ diesel::table! { } diesel::table! { - quran_word_divide (id) { + quran_words (id) { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, - word_id -> Int4, - divider_account_id -> Int4, - #[sql_name = "type"] - #[max_length = 256] - type_ -> Varchar, + ayah_id -> Int4, + word -> Text, + created_at -> Timestamptz, + updated_at -> Timestamptz, } } diesel::table! { - quran_words (id) { + quran_words_divide (id) { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, - ayah_id -> Int4, - word -> Text, - created_at -> Timestamptz, - updated_at -> Timestamptz, + word_id -> Int4, + divider_account_id -> Int4, + #[sql_name = "type"] + #[max_length = 256] + type_ -> Varchar, } } @@ -330,11 +330,11 @@ diesel::joinable!(app_tokens -> app_accounts (account_id)); diesel::joinable!(app_user_names -> app_accounts (account_id)); diesel::joinable!(app_user_names -> app_users (creator_user_id)); diesel::joinable!(app_users -> app_accounts (account_id)); -diesel::joinable!(quran_ayah_divide -> app_accounts (divider_account_id)); -diesel::joinable!(quran_ayah_divide -> app_users (creator_user_id)); -diesel::joinable!(quran_ayah_divide -> quran_ayahs (ayah_id)); diesel::joinable!(quran_ayahs -> app_users (creator_user_id)); diesel::joinable!(quran_ayahs -> quran_surahs (surah_id)); +diesel::joinable!(quran_ayahs_divide -> app_accounts (divider_account_id)); +diesel::joinable!(quran_ayahs_divide -> app_users (creator_user_id)); +diesel::joinable!(quran_ayahs_divide -> quran_ayahs (ayah_id)); diesel::joinable!(quran_mushafs -> app_users (creator_user_id)); diesel::joinable!(quran_surahs -> app_users (creator_user_id)); diesel::joinable!(quran_surahs -> quran_mushafs (mushaf_id)); @@ -344,11 +344,11 @@ diesel::joinable!(quran_translations -> quran_mushafs (mushaf_id)); diesel::joinable!(quran_translations_ayahs -> app_users (creator_user_id)); diesel::joinable!(quran_translations_ayahs -> quran_ayahs (ayah_id)); diesel::joinable!(quran_translations_ayahs -> quran_translations (translation_id)); -diesel::joinable!(quran_word_divide -> app_accounts (divider_account_id)); -diesel::joinable!(quran_word_divide -> app_users (creator_user_id)); -diesel::joinable!(quran_word_divide -> quran_words (word_id)); diesel::joinable!(quran_words -> app_users (creator_user_id)); diesel::joinable!(quran_words -> quran_ayahs (ayah_id)); +diesel::joinable!(quran_words_divide -> app_accounts (divider_account_id)); +diesel::joinable!(quran_words_divide -> app_users (creator_user_id)); +diesel::joinable!(quran_words_divide -> quran_words (word_id)); diesel::allow_tables_to_appear_in_same_query!( app_accounts, @@ -365,12 +365,12 @@ diesel::allow_tables_to_appear_in_same_query!( app_user_names, app_users, app_verify_codes, - quran_ayah_divide, quran_ayahs, + quran_ayahs_divide, quran_mushafs, quran_surahs, quran_translations, quran_translations_ayahs, - quran_word_divide, quran_words, + quran_words_divide, ); From 67a62a78dbdcd7150b4cbc86628bc76ccf15c0c1 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 19 Dec 2024 17:18:43 +0330 Subject: [PATCH 10/31] new update --- .../00000000000001_create_app_accounts/up.sql | 5 +- .../down.sql | 1 + .../up.sql | 11 ++ .../down.sql | 1 - .../up.sql | 12 -- .../down.sql | 1 + .../up.sql | 12 ++ .../down.sql | 1 - .../up.sql | 12 -- src/models.rs | 2 +- src/routers/quran/ayah/ayah_list.rs | 50 +++--- src/routers/quran/ayah/mod.rs | 1 + src/routers/quran/surah/mod.rs | 143 +++++++++++++++++- src/routers/quran/surah/surah_view.rs | 59 +++++--- src/schema.rs | 30 ++-- 15 files changed, 246 insertions(+), 95 deletions(-) create mode 100644 migrations/2024-12-05-083921_create_quran_ayahs_breakers/down.sql create mode 100644 migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql delete mode 100644 migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql delete mode 100644 migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql create mode 100644 migrations/2024-12-05-184846_create_quran_words_breakers/down.sql create mode 100644 migrations/2024-12-05-184846_create_quran_words_breakers/up.sql delete mode 100644 migrations/2024-12-05-184846_create_quran_words_divide/down.sql delete mode 100644 migrations/2024-12-05-184846_create_quran_words_divide/up.sql diff --git a/migrations/00000000000001_create_app_accounts/up.sql b/migrations/00000000000001_create_app_accounts/up.sql index 82c9a36..99c216b 100644 --- a/migrations/00000000000001_create_app_accounts/up.sql +++ b/migrations/00000000000001_create_app_accounts/up.sql @@ -1,8 +1,7 @@ CREATE TABLE app_accounts ( - id serial NOT NULL, + id serial PRIMARY KEY, uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, username VARCHAR(30) NOT NULL, account_type TEXT NOT NULL, - CONSTRAINT app_accounts_id PRIMARY KEY (id), - UNIQUE(username) + UNIQUE (username) ); diff --git a/migrations/2024-12-05-083921_create_quran_ayahs_breakers/down.sql b/migrations/2024-12-05-083921_create_quran_ayahs_breakers/down.sql new file mode 100644 index 0000000..59d1e7a --- /dev/null +++ b/migrations/2024-12-05-083921_create_quran_ayahs_breakers/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_ayahs_breakers; diff --git a/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql b/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql new file mode 100644 index 0000000..a1a395c --- /dev/null +++ b/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql @@ -0,0 +1,11 @@ +CREATE TABLE quran_ayahs_breakers ( + id serial, + uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, + creator_user_id serial NOT NULL, + ayah_id serial NOT NULL, + owner_account_id INT REFERENCES app_accounts (id), + name VARCHAR(256) NOT NULL, + CONSTRAINT ayah_break_id PRIMARY KEY (id), + CONSTRAINT fk_quran_ayah_break_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), + CONSTRAINT fk_break_ayah FOREIGN KEY (ayah_id) REFERENCES quran_ayahs (id) on delete cascade +); diff --git a/migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql b/migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql deleted file mode 100644 index 4d04afa..0000000 --- a/migrations/2024-12-05-083921_create_quran_ayahs_divide/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE quran_ayahs_divide; diff --git a/migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql b/migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql deleted file mode 100644 index 3a59c78..0000000 --- a/migrations/2024-12-05-083921_create_quran_ayahs_divide/up.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE quran_ayahs_divide ( - id serial NOT NULL, - uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, - creator_user_id serial NOT NULL, - ayah_id serial NOT NULL, - divider_account_id serial, - type VARCHAR(256) NOT NULL, - CONSTRAINT ayah_divide_id PRIMARY KEY (id), - CONSTRAINT fk_quran_ayah_divider_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), - CONSTRAINT fk_divide_ayah FOREIGN KEY (ayah_id) REFERENCES quran_ayahs (id) on delete cascade, - CONSTRAINT fk_ayah_divide_account_rel FOREIGN KEY (divider_account_id) REFERENCES app_accounts (id) -); diff --git a/migrations/2024-12-05-184846_create_quran_words_breakers/down.sql b/migrations/2024-12-05-184846_create_quran_words_breakers/down.sql new file mode 100644 index 0000000..cf72559 --- /dev/null +++ b/migrations/2024-12-05-184846_create_quran_words_breakers/down.sql @@ -0,0 +1 @@ +DROP TABLE quran_words_breakers; diff --git a/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql b/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql new file mode 100644 index 0000000..40a7ef9 --- /dev/null +++ b/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql @@ -0,0 +1,12 @@ +CREATE TABLE quran_words_breakers ( + id serial NOT NULL, + uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, + creator_user_id serial NOT NULL, + word_id serial NOT NULL, + owner_account_id INT, + name VARCHAR(256) NOT NULL, + CONSTRAINT word_break_id PRIMARY KEY (id), + CONSTRAINT fk_quran_word_break_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), + CONSTRAINT fk_break_word FOREIGN KEY (word_id) REFERENCES quran_words (id) on delete cascade, + CONSTRAINT fk_word_break_owner_account_rel FOREIGN KEY (owner_account_id) REFERENCES app_accounts (id) +); diff --git a/migrations/2024-12-05-184846_create_quran_words_divide/down.sql b/migrations/2024-12-05-184846_create_quran_words_divide/down.sql deleted file mode 100644 index 996421d..0000000 --- a/migrations/2024-12-05-184846_create_quran_words_divide/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE quran_words_divide; diff --git a/migrations/2024-12-05-184846_create_quran_words_divide/up.sql b/migrations/2024-12-05-184846_create_quran_words_divide/up.sql deleted file mode 100644 index 6d62b03..0000000 --- a/migrations/2024-12-05-184846_create_quran_words_divide/up.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE quran_words_divide ( - id serial NOT NULL, - uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, - creator_user_id serial NOT NULL, - word_id serial NOT NULL, - divider_account_id serial, - type VARCHAR(256) NOT NULL, - CONSTRAINT word_divide_id PRIMARY KEY (id), - CONSTRAINT fk_quran_word_divider_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), - CONSTRAINT fk_divide_word FOREIGN KEY (word_id) REFERENCES quran_words (id) on delete cascade, - CONSTRAINT fk_word_divide_account_rel FOREIGN KEY (divider_account_id) REFERENCES app_accounts (id) -); diff --git a/src/models.rs b/src/models.rs index 70b0d14..2fa852e 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,4 +1,4 @@ -use crate::schema::*; +use crate::{schema::*, AyahBismillah}; use chrono::{NaiveDate, NaiveDateTime}; use diesel::{ deserialize::QueryableByName, Associations, Identifiable, Insertable, Queryable, Selectable, diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index f01d70b..9d93713 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -2,7 +2,7 @@ use crate::error::{RouterError, RouterErrorDetailBuilder}; use crate::filter::Filter; use crate::models::QuranAyah; use crate::routers::multip; -use crate::AyahBismillah; +use crate::{calculate_break, AyahBismillah}; use crate::{ routers::quran::surah::{AyahTy, Format, SimpleAyah}, DbPool, @@ -21,6 +21,13 @@ pub async fn ayah_list( use crate::schema::quran_mushafs::dsl::{quran_mushafs, short_name as mushaf_short_name}; use crate::schema::quran_surahs::dsl::quran_surahs; use crate::schema::quran_words::dsl::{quran_words, word as q_word}; + use crate::schema::quran_words_breakers::dsl::{ + quran_words_breakers, word_id as break_word_id, + }; + + use crate::schema::quran_ayahs_breakers::dsl::{ + quran_ayahs_breakers, type_ as ayah_break_type, + }; let pool = pool.into_inner(); @@ -36,35 +43,34 @@ pub async fn ayah_list( let ayahs = filtered_ayahs .left_outer_join(quran_surahs.left_outer_join(quran_mushafs)) - .inner_join(quran_words) + .left_join(quran_ayahs_breakers) + .inner_join(quran_words.left_join(quran_words_breakers)) .filter(mushaf_short_name.eq(query.mushaf)) - .select((QuranAyah::as_select(), q_word)) - .get_results::<(QuranAyah, String)>(&mut conn)?; + .select(( + QuranAyah::as_select(), + q_word, + break_word_id.nullable(), + ayah_break_type.nullable(), + )) + .get_results::<(QuranAyah, String, Option, Option)>(&mut conn)?; - let ayahs_as_map = multip(ayahs, |a| SimpleAyah { - number: a.ayah_number as u32, - uuid: a.uuid, - sajdah: a.sajdah, - bismillah: match (a.is_bismillah, a.bismillah_text) { - (true, None) => Some(AyahBismillah { - is_ayah: true, - text: None, - }), - (false, Some(text)) => Some(AyahBismillah { - is_ayah: false, - text: Some(text), - }), - (false, None) => None, - (_, _) => None, - }, - }); + let result = calculate_break(ayahs); + + let ayahs_as_map = multip(result, |a| a); let final_ayahs = ayahs_as_map .into_iter() .map(|(ayah, words)| match query.format { Some(Format::Text) | None => AyahTy::Text(crate::AyahWithText { + hizb: ayah.hizb, + juz: ayah.juz, + page: ayah.page, ayah, - text: words.join(" "), + text: words + .into_iter() + .map(|w| w.word) + .collect::>() + .join(" "), }), Some(Format::Word) => AyahTy::Words(crate::AyahWithWords { ayah, words }), }) diff --git a/src/routers/quran/ayah/mod.rs b/src/routers/quran/ayah/mod.rs index 153e087..091d9a9 100644 --- a/src/routers/quran/ayah/mod.rs +++ b/src/routers/quran/ayah/mod.rs @@ -71,6 +71,7 @@ pub struct SimpleAyah { pub struct AyahListQuery { mushaf: String, format: Option, + break_data: Option, sort: Option, order: Option, diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index bd1c9d1..8e3f23a 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -8,7 +8,7 @@ use std::hash::Hash; use crate::{ filter::{Filters, Order}, - models::QuranMushaf, + models::{QuranAyah, QuranMushaf}, }; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -68,6 +68,119 @@ pub struct AyahBismillah { pub text: Option, } +impl AyahBismillah { + pub fn from_ayah_fields(is_bismillah: bool, bismillah_text: Option) -> Option { + match (is_bismillah, bismillah_text) { + (true, None) => Some(Self { + is_ayah: true, + text: None, + }), + (false, Some(text)) => Some(Self { + is_ayah: false, + text: Some(text), + }), + (false, None) => None, + (_, _) => None, + } + } +} + +pub fn calculate_break( + input: Vec<(QuranAyah, String, Option, Option)>, +) -> Vec<(SimpleAyah, AyahWord)> { + // WARNINIG: This only works for line type of word breakers + let mut result: Vec<(SimpleAyah, AyahWord)> = vec![]; + let mut word_line_count = 1; + let mut ayah_page_count = 1; + let mut ayah_juz_count = 1; + let mut ayah_hizb_count = 1; + for (ayah, word, maybe_word_break_id, maybe_ayah_break_type) in input { + if let Some(ayah_break_type_s) = maybe_ayah_break_type.clone() { + match ayah_break_type_s.as_str() { + "juz" => { + ayah_juz_count += 1; + } + "hizb" => { + ayah_hizb_count += 1; + } + "page" => { + ayah_page_count += 1; + word_line_count = 0; + } + + _ => {} + } + } + + if let Some(_) = maybe_word_break_id { + result.push(( + SimpleAyah { + number: ayah.ayah_number as u32, + uuid: ayah.uuid, + sajdah: ayah.sajdah, + bismillah: AyahBismillah::from_ayah_fields( + ayah.is_bismillah, + ayah.bismillah_text.clone(), + ), + hizb: if maybe_ayah_break_type.is_some() { + Some(ayah_hizb_count) + } else { + None + }, + juz: if maybe_ayah_break_type.is_some() { + Some(ayah_juz_count) + } else { + None + }, + + page: if maybe_ayah_break_type.is_some() { + Some(ayah_page_count) + } else { + None + }, + }, + AyahWord { + line: Some(word_line_count), + word, + }, + )); + + word_line_count += 1; + } else { + result.push(( + SimpleAyah { + number: ayah.ayah_number as u32, + uuid: ayah.uuid, + sajdah: ayah.sajdah, + bismillah: AyahBismillah::from_ayah_fields( + ayah.is_bismillah, + ayah.bismillah_text.clone(), + ), + hizb: if maybe_ayah_break_type.is_some() { + Some(ayah_hizb_count) + } else { + None + }, + juz: if maybe_ayah_break_type.is_some() { + Some(ayah_juz_count) + } else { + None + }, + + page: if maybe_ayah_break_type.is_some() { + Some(ayah_page_count) + } else { + None + }, + }, + AyahWord { line: None, word }, + )); + } + } + + result +} + #[derive(Serialize, Clone, Debug)] pub struct AyahBismillahInSurah { pub is_first_ayah: bool, @@ -81,6 +194,9 @@ pub struct SimpleAyah { pub uuid: Uuid, pub sajdah: Option, pub bismillah: Option, + pub hizb: Option, + pub juz: Option, + pub page: Option, } /// it contains ayah info and the content @@ -89,13 +205,28 @@ pub struct AyahWithText { #[serde(flatten)] pub ayah: SimpleAyah, pub text: String, + + #[serde(skip_serializing_if = "Option::is_none")] + pub hizb: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub juz: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub page: Option, +} + +#[derive(Serialize, Clone, Debug)] +pub struct AyahWord { + pub word: String, + + #[serde(skip_serializing_if = "Option::is_none")] + pub line: Option, } #[derive(Serialize, Clone, Debug)] pub struct AyahWithWords { #[serde(flatten)] pub ayah: SimpleAyah, - pub words: Vec, + pub words: Vec, } #[derive(Serialize, Clone, Debug)] @@ -125,7 +256,13 @@ impl AyahTy { if bismillah.is_ayah { AyahBismillahInSurah { is_first_ayah: true, - text: at.words.join("").clone(), + text: at + .words + .clone() + .into_iter() + .map(|w| w.word) + .collect::>() + .join(" "), } } else { AyahBismillahInSurah { diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index d9741a2..8a9b021 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -1,10 +1,11 @@ use super::{ - AyahBismillah, Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse, + calculate_break, AyahBismillah, Format, GetSurahQuery, QuranResponseData, SimpleAyah, + SingleSurahResponse, }; use crate::models::{QuranAyah, QuranMushaf, QuranSurah}; use crate::routers::multip; use crate::{error::RouterError, DbPool}; -use crate::{AyahTy, SingleSurahMushaf, SurahName}; +use crate::{AyahTy, AyahWord, SingleSurahMushaf, SurahName}; use actix_web::web; use diesel::prelude::*; use uuid::Uuid; @@ -24,6 +25,13 @@ pub async fn surah_view( use crate::schema::quran_surahs::dsl::quran_surahs; use crate::schema::quran_surahs::dsl::uuid as surah_uuid; use crate::schema::quran_words::dsl::{quran_words, word as q_word}; + use crate::schema::quran_words_breakers::dsl::{ + quran_words_breakers, word_id as break_word_id, + }; + + use crate::schema::quran_ayahs_breakers::dsl::{ + quran_ayahs_breakers, type_ as ayah_break_type, + }; let query = query.into_inner(); let requested_surah_uuid = path.into_inner(); @@ -31,36 +39,39 @@ pub async fn surah_view( web::block(move || { let mut conn = pool.get().unwrap(); - let result = quran_surahs + let ayahs_words = quran_surahs .filter(surah_uuid.eq(requested_surah_uuid)) - .inner_join(quran_ayahs.inner_join(quran_words)) - .select((QuranAyah::as_select(), q_word)) - .load::<(QuranAyah, String)>(&mut conn)?; + .inner_join( + quran_ayahs + .inner_join(quran_words.left_join(quran_words_breakers)) + .left_join(quran_ayahs_breakers), + ) + .select(( + QuranAyah::as_select(), + q_word, + break_word_id.nullable(), + ayah_break_type.nullable(), + )) + .load::<(QuranAyah, String, Option, Option)>(&mut conn)?; - let ayahs_as_map = multip(result, |ayah| SimpleAyah { - number: ayah.ayah_number as u32, - uuid: ayah.uuid, - sajdah: ayah.sajdah, - bismillah: match (ayah.is_bismillah, ayah.bismillah_text) { - (true, None) => Some(AyahBismillah { - is_ayah: true, - text: None, - }), - (false, Some(text)) => Some(AyahBismillah { - is_ayah: false, - text: Some(text), - }), - (false, None) => None, - (_, _) => None, - }, - }); + println!("{:?}", ayahs_words); + + let result = calculate_break(ayahs_words); + let ayahs_as_map = multip(result, |ayah| ayah); let final_ayahs = ayahs_as_map .into_iter() .map(|(ayah, words)| match query.format { Format::Text => AyahTy::Text(crate::AyahWithText { + hizb: ayah.hizb, + juz: ayah.juz, + page: ayah.page, ayah, - text: words.join(" "), + text: words + .into_iter() + .map(|w| w.word) + .collect::>() + .join(" "), }), Format::Word => AyahTy::Words(crate::AyahWithWords { ayah, words }), }) diff --git a/src/schema.rs b/src/schema.rs index 500bcbb..044bc87 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -210,15 +210,14 @@ diesel::table! { } diesel::table! { - quran_ayahs_divide (id) { + quran_ayahs_breakers (id) { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, ayah_id -> Int4, - divider_account_id -> Int4, - #[sql_name = "type"] + owner_account_id -> Nullable, #[max_length = 256] - type_ -> Varchar, + name -> Varchar, } } @@ -302,15 +301,14 @@ diesel::table! { } diesel::table! { - quran_words_divide (id) { + quran_words_breakers (id) { id -> Int4, uuid -> Uuid, creator_user_id -> Int4, word_id -> Int4, - divider_account_id -> Int4, - #[sql_name = "type"] + owner_account_id -> Nullable, #[max_length = 256] - type_ -> Varchar, + name -> Varchar, } } @@ -332,9 +330,9 @@ diesel::joinable!(app_user_names -> app_users (creator_user_id)); diesel::joinable!(app_users -> app_accounts (account_id)); diesel::joinable!(quran_ayahs -> app_users (creator_user_id)); diesel::joinable!(quran_ayahs -> quran_surahs (surah_id)); -diesel::joinable!(quran_ayahs_divide -> app_accounts (divider_account_id)); -diesel::joinable!(quran_ayahs_divide -> app_users (creator_user_id)); -diesel::joinable!(quran_ayahs_divide -> quran_ayahs (ayah_id)); +diesel::joinable!(quran_ayahs_breakers -> app_accounts (owner_account_id)); +diesel::joinable!(quran_ayahs_breakers -> app_users (creator_user_id)); +diesel::joinable!(quran_ayahs_breakers -> quran_ayahs (ayah_id)); diesel::joinable!(quran_mushafs -> app_users (creator_user_id)); diesel::joinable!(quran_surahs -> app_users (creator_user_id)); diesel::joinable!(quran_surahs -> quran_mushafs (mushaf_id)); @@ -346,9 +344,9 @@ diesel::joinable!(quran_translations_ayahs -> quran_ayahs (ayah_id)); diesel::joinable!(quran_translations_ayahs -> quran_translations (translation_id)); diesel::joinable!(quran_words -> app_users (creator_user_id)); diesel::joinable!(quran_words -> quran_ayahs (ayah_id)); -diesel::joinable!(quran_words_divide -> app_accounts (divider_account_id)); -diesel::joinable!(quran_words_divide -> app_users (creator_user_id)); -diesel::joinable!(quran_words_divide -> quran_words (word_id)); +diesel::joinable!(quran_words_breakers -> app_accounts (owner_account_id)); +diesel::joinable!(quran_words_breakers -> app_users (creator_user_id)); +diesel::joinable!(quran_words_breakers -> quran_words (word_id)); diesel::allow_tables_to_appear_in_same_query!( app_accounts, @@ -366,11 +364,11 @@ diesel::allow_tables_to_appear_in_same_query!( app_users, app_verify_codes, quran_ayahs, - quran_ayahs_divide, + quran_ayahs_breakers, quran_mushafs, quran_surahs, quran_translations, quran_translations_ayahs, quran_words, - quran_words_divide, + quran_words_breakers, ); From 4ae05a4e5184ac6a277c8cf45431408aa4f88e28 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 26 Dec 2024 18:41:56 +0330 Subject: [PATCH 11/31] tables updated --- migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql | 2 ++ migrations/2024-12-05-184846_create_quran_words_breakers/up.sql | 2 ++ 2 files changed, 4 insertions(+) diff --git a/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql b/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql index a1a395c..49ed013 100644 --- a/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql +++ b/migrations/2024-12-05-083921_create_quran_ayahs_breakers/up.sql @@ -5,6 +5,8 @@ CREATE TABLE quran_ayahs_breakers ( ayah_id serial NOT NULL, owner_account_id INT REFERENCES app_accounts (id), name VARCHAR(256) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT ayah_break_id PRIMARY KEY (id), CONSTRAINT fk_quran_ayah_break_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), CONSTRAINT fk_break_ayah FOREIGN KEY (ayah_id) REFERENCES quran_ayahs (id) on delete cascade diff --git a/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql b/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql index 40a7ef9..9792358 100644 --- a/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql +++ b/migrations/2024-12-05-184846_create_quran_words_breakers/up.sql @@ -5,6 +5,8 @@ CREATE TABLE quran_words_breakers ( word_id serial NOT NULL, owner_account_id INT, name VARCHAR(256) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT word_break_id PRIMARY KEY (id), CONSTRAINT fk_quran_word_break_creator_user_id FOREIGN KEY (creator_user_id) REFERENCES app_users (id), CONSTRAINT fk_break_word FOREIGN KEY (word_id) REFERENCES quran_words (id) on delete cascade, From 9207dfd6d8cbd003351d710f0444c604e413142b Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 26 Dec 2024 18:42:19 +0330 Subject: [PATCH 12/31] New update --- src/main.rs | 1 + src/models.rs | 74 +++++++++++- src/routers/mod.rs | 28 +++++ src/routers/quran/ayah/ayah_list.rs | 4 +- src/routers/quran/surah/mod.rs | 156 ++++++++++---------------- src/routers/quran/surah/surah_view.rs | 28 ++--- src/schema.rs | 4 + 7 files changed, 179 insertions(+), 116 deletions(-) diff --git a/src/main.rs b/src/main.rs index f3cd53f..681f299 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,6 +59,7 @@ pub type DbPool = Pool>; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); +/// Predefined NQ-api errors that is loadeded from (static) file has life time of static. pub static FIXED_ERROR_RESPONSES: OnceLock = OnceLock::new(); pub const FIXED_ERROR_JSON: &str = include_str!("../error_codes.json"); diff --git a/src/models.rs b/src/models.rs index 2fa852e..c795970 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,4 +1,4 @@ -use crate::{schema::*, AyahBismillah}; +use crate::schema::*; use chrono::{NaiveDate, NaiveDateTime}; use diesel::{ deserialize::QueryableByName, Associations, Identifiable, Insertable, Queryable, Selectable, @@ -231,6 +231,11 @@ pub struct NewEmployee { Associations, Clone, Debug, + Eq, + Ord, + PartialOrd, + Hash, + PartialEq, )] #[diesel(belongs_to(QuranSurah, foreign_key = surah_id))] #[diesel(table_name = quran_ayahs)] @@ -637,3 +642,70 @@ pub struct NewPhraseTranslation<'a> { pub text: &'a str, pub language: &'a str, } + +#[derive( + Deserialize, + Serialize, + Clone, + Validate, + Identifiable, + Queryable, + Debug, + Associations, + Selectable, + Eq, + Hash, + PartialEq, +)] +#[diesel(table_name = quran_ayahs_breakers)] +#[diesel(belongs_to(QuranAyah, foreign_key = ayah_id))] +pub struct QuranAyahBreaker { + #[serde(skip_serializing)] + id: i32, + uuid: Uuid, + + #[serde(skip_serializing)] + owner_account_id: i32, + + #[serde(skip_serializing)] + ayah_id: i32, + + pub name: String, + + #[serde(skip_serializing)] + pub created_at: NaiveDateTime, + #[serde(skip_serializing)] + pub updated_at: NaiveDateTime, +} + +#[derive( + Deserialize, + Serialize, + Clone, + Validate, + Identifiable, + Queryable, + Debug, + Associations, + Selectable, +)] +#[diesel(table_name = quran_words_breakers)] +#[diesel(belongs_to(QuranWord, foreign_key = word_id))] +pub struct QuranWordBreaker { + #[serde(skip_serializing)] + id: i32, + uuid: Uuid, + + #[serde(skip_serializing)] + owner_account_id: i32, + + #[serde(skip_serializing)] + word_id: i32, + + name: String, + + #[serde(skip_serializing)] + pub created_at: NaiveDateTime, + #[serde(skip_serializing)] + pub updated_at: NaiveDateTime, +} diff --git a/src/routers/mod.rs b/src/routers/mod.rs index 1fd7c8a..2612130 100644 --- a/src/routers/mod.rs +++ b/src/routers/mod.rs @@ -31,3 +31,31 @@ where map } + +/// a BTreeMap (We want the elements be in order) +pub fn maybe_multip( + vector: Vec<(T, Option)>, + insert_data_type: F, +) -> BTreeMap> +where + T: Sized + Clone, + U: Sized + Clone, + NT: Sized + Eq + Hash + Ord, + F: Fn(T) -> NT, +{ + let mut map: BTreeMap> = BTreeMap::new(); + for item in vector { + map.entry(insert_data_type(item.clone().0)) + .and_modify(|c| { + if let Some(value) = item.1.clone() { + c.push(value.clone()) + } + }) + .or_insert(match item.1 { + Some(val) => vec![val], + None => vec![], + }); + } + + map +} diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index 9d93713..fc83060 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -26,7 +26,7 @@ pub async fn ayah_list( }; use crate::schema::quran_ayahs_breakers::dsl::{ - quran_ayahs_breakers, type_ as ayah_break_type, + quran_ayahs_breakers, name as ayah_break_name, }; let pool = pool.into_inner(); @@ -50,7 +50,7 @@ pub async fn ayah_list( QuranAyah::as_select(), q_word, break_word_id.nullable(), - ayah_break_type.nullable(), + ayah_break_name.nullable(), )) .get_results::<(QuranAyah, String, Option, Option)>(&mut conn)?; diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index 8e3f23a..1e979a6 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -4,14 +4,18 @@ pub mod surah_edit; pub mod surah_list; pub mod surah_view; -use std::hash::Hash; +use std::{ + collections::{BTreeMap, HashMap}, + hash::Hash, +}; use crate::{ filter::{Filters, Order}, - models::{QuranAyah, QuranMushaf}, + models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranWordBreaker}, + routers::{maybe_multip, multip}, }; use serde::{Deserialize, Serialize}; -use uuid::Uuid; +use uuid::{fmt::Simple, Uuid}; /// The quran text format Each word has its own uuid #[derive(Debug, Clone, Deserialize)] @@ -85,100 +89,54 @@ impl AyahBismillah { } } +/// input: Vec<(Ayah, Breaks(name))> pub fn calculate_break( - input: Vec<(QuranAyah, String, Option, Option)>, -) -> Vec<(SimpleAyah, AyahWord)> { - // WARNINIG: This only works for line type of word breakers - let mut result: Vec<(SimpleAyah, AyahWord)> = vec![]; - let mut word_line_count = 1; - let mut ayah_page_count = 1; - let mut ayah_juz_count = 1; - let mut ayah_hizb_count = 1; - for (ayah, word, maybe_word_break_id, maybe_ayah_break_type) in input { - if let Some(ayah_break_type_s) = maybe_ayah_break_type.clone() { - match ayah_break_type_s.as_str() { - "juz" => { - ayah_juz_count += 1; - } - "hizb" => { - ayah_hizb_count += 1; - } - "page" => { - ayah_page_count += 1; - word_line_count = 0; - } - - _ => {} - } + input: Vec<( + QuranAyah, + String, + Option, + Option, + )>, +) -> Vec<(SimpleAyah, Vec)> { + let ayahs_with_breakers = input + .into_iter() + .map(|(ayah, _, _, breaker)| (ayah, breaker)) + .collect::)>>(); + let ayah_breakers: BTreeMap> = + maybe_multip(ayahs_with_breakers, |ayah| ayah); + + let mut simple_ayahs = vec![]; + // Calculate breakers + for (ayah, breakers) in ayah_breakers.into_iter() { + let mut breakers_map: HashMap = HashMap::new(); + for breaker in breakers { + breakers_map + .entry(breaker) + .and_modify(|v| *v += 1) + .or_insert(0); } - if let Some(_) = maybe_word_break_id { - result.push(( - SimpleAyah { - number: ayah.ayah_number as u32, - uuid: ayah.uuid, - sajdah: ayah.sajdah, - bismillah: AyahBismillah::from_ayah_fields( - ayah.is_bismillah, - ayah.bismillah_text.clone(), - ), - hizb: if maybe_ayah_break_type.is_some() { - Some(ayah_hizb_count) - } else { - None - }, - juz: if maybe_ayah_break_type.is_some() { - Some(ayah_juz_count) - } else { - None - }, - - page: if maybe_ayah_break_type.is_some() { - Some(ayah_page_count) - } else { - None - }, - }, - AyahWord { - line: Some(word_line_count), - word, - }, - )); - - word_line_count += 1; - } else { - result.push(( - SimpleAyah { - number: ayah.ayah_number as u32, - uuid: ayah.uuid, - sajdah: ayah.sajdah, - bismillah: AyahBismillah::from_ayah_fields( - ayah.is_bismillah, - ayah.bismillah_text.clone(), - ), - hizb: if maybe_ayah_break_type.is_some() { - Some(ayah_hizb_count) - } else { - None - }, - juz: if maybe_ayah_break_type.is_some() { - Some(ayah_juz_count) - } else { - None - }, - - page: if maybe_ayah_break_type.is_some() { - Some(ayah_page_count) - } else { - None - }, - }, - AyahWord { line: None, word }, - )); - } + let breakers = breakers_map + .into_iter() + .map(|(key, value)| Breaker { + name: key.name, + number: value, + }) + .collect::>(); + + simple_ayahs.push(SimpleAyah { + bismillah: AyahBismillah::from_ayah_fields(ayah.is_bismillah, ayah.bismillah_text), + breakers: if breakers.is_empty() { + None + } else { + Some(breakers) + }, + number: ayah.ayah_number as u32, + sajdah: ayah.sajdah, + uuid: ayah.uuid, + }); } - - result + todo!() } #[derive(Serialize, Clone, Debug)] @@ -187,6 +145,12 @@ pub struct AyahBismillahInSurah { pub text: String, } +#[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug)] +pub struct Breaker { + pub name: String, + pub number: u32, +} + /// The Ayah type that will return in the response #[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug)] pub struct SimpleAyah { @@ -194,9 +158,7 @@ pub struct SimpleAyah { pub uuid: Uuid, pub sajdah: Option, pub bismillah: Option, - pub hizb: Option, - pub juz: Option, - pub page: Option, + pub breakers: Option>, } /// it contains ayah info and the content @@ -219,7 +181,7 @@ pub struct AyahWord { pub word: String, #[serde(skip_serializing_if = "Option::is_none")] - pub line: Option, + pub breakers: Option>, } #[derive(Serialize, Clone, Debug)] diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index 8a9b021..c5baecd 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -1,8 +1,5 @@ -use super::{ - calculate_break, AyahBismillah, Format, GetSurahQuery, QuranResponseData, SimpleAyah, - SingleSurahResponse, -}; -use crate::models::{QuranAyah, QuranMushaf, QuranSurah}; +use super::{Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse}; +use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah}; use crate::routers::multip; use crate::{error::RouterError, DbPool}; use crate::{AyahTy, AyahWord, SingleSurahMushaf, SurahName}; @@ -25,13 +22,9 @@ pub async fn surah_view( use crate::schema::quran_surahs::dsl::quran_surahs; use crate::schema::quran_surahs::dsl::uuid as surah_uuid; use crate::schema::quran_words::dsl::{quran_words, word as q_word}; - use crate::schema::quran_words_breakers::dsl::{ - quran_words_breakers, word_id as break_word_id, - }; + use crate::schema::quran_words_breakers::dsl::{name as word_break_name, quran_words_breakers}; - use crate::schema::quran_ayahs_breakers::dsl::{ - quran_ayahs_breakers, type_ as ayah_break_type, - }; + use crate::schema::quran_ayahs_breakers::dsl::{name as ayah_break_name, quran_ayahs_breakers}; let query = query.into_inner(); let requested_surah_uuid = path.into_inner(); @@ -49,12 +42,15 @@ pub async fn surah_view( .select(( QuranAyah::as_select(), q_word, - break_word_id.nullable(), - ayah_break_type.nullable(), + Option::::as_select(), + Option::::as_select(), )) - .load::<(QuranAyah, String, Option, Option)>(&mut conn)?; - - println!("{:?}", ayahs_words); + .load::<( + QuranAyah, + String, + Option, + Option, + )>(&mut conn)?; let result = calculate_break(ayahs_words); let ayahs_as_map = multip(result, |ayah| ayah); diff --git a/src/schema.rs b/src/schema.rs index 044bc87..68a9d87 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -218,6 +218,8 @@ diesel::table! { owner_account_id -> Nullable, #[max_length = 256] name -> Varchar, + created_at -> Timestamptz, + updated_at -> Timestamptz, } } @@ -309,6 +311,8 @@ diesel::table! { owner_account_id -> Nullable, #[max_length = 256] name -> Varchar, + created_at -> Timestamptz, + updated_at -> Timestamptz, } } From 01bf2d2d3bc6c9b55077d04b7174d5fb73b17a82 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 2 Jan 2025 18:22:22 +0330 Subject: [PATCH 13/31] new update --- src/models.rs | 15 ++- src/routers/mod.rs | 20 +++- src/routers/quran/ayah/ayah_list.rs | 29 +++--- src/routers/quran/surah/mod.rs | 140 +++++++++++++++++--------- src/routers/quran/surah/surah_view.rs | 12 +-- 5 files changed, 139 insertions(+), 77 deletions(-) diff --git a/src/models.rs b/src/models.rs index c795970..dc33a75 100644 --- a/src/models.rs +++ b/src/models.rs @@ -665,11 +665,14 @@ pub struct QuranAyahBreaker { uuid: Uuid, #[serde(skip_serializing)] - owner_account_id: i32, + creator_user_id: i32, #[serde(skip_serializing)] ayah_id: i32, + #[serde(skip_serializing)] + owner_account_id: Option, + pub name: String, #[serde(skip_serializing)] @@ -688,6 +691,9 @@ pub struct QuranAyahBreaker { Debug, Associations, Selectable, + PartialEq, + Eq, + Hash, )] #[diesel(table_name = quran_words_breakers)] #[diesel(belongs_to(QuranWord, foreign_key = word_id))] @@ -697,12 +703,15 @@ pub struct QuranWordBreaker { uuid: Uuid, #[serde(skip_serializing)] - owner_account_id: i32, + creator_user_id: i32, #[serde(skip_serializing)] word_id: i32, - name: String, + #[serde(skip_serializing)] + owner_account_id: Option, + + pub name: String, #[serde(skip_serializing)] pub created_at: NaiveDateTime, diff --git a/src/routers/mod.rs b/src/routers/mod.rs index 2612130..1616383 100644 --- a/src/routers/mod.rs +++ b/src/routers/mod.rs @@ -8,7 +8,7 @@ pub mod quran; pub mod translation; pub mod user; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::hash::Hash; /// finds the relatives in the vector @@ -41,11 +41,11 @@ where T: Sized + Clone, U: Sized + Clone, NT: Sized + Eq + Hash + Ord, - F: Fn(T) -> NT, + F: Fn(usize, T) -> NT, { let mut map: BTreeMap> = BTreeMap::new(); - for item in vector { - map.entry(insert_data_type(item.clone().0)) + for (index, item) in vector.into_iter().enumerate() { + map.entry(insert_data_type(index, item.clone().0)) .and_modify(|c| { if let Some(value) = item.1.clone() { c.push(value.clone()) @@ -59,3 +59,15 @@ where map } + +pub fn count(data: Vec) -> HashMap +where + T: Sized + Hash + Eq, +{ + let mut map: HashMap = HashMap::new(); + for v in data { + map.entry(v).and_modify(|v| *v += 1).or_insert(1); + } + + map +} diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index fc83060..7b9f8b5 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -1,8 +1,9 @@ +use crate::calculate_breaks; use crate::error::{RouterError, RouterErrorDetailBuilder}; use crate::filter::Filter; -use crate::models::QuranAyah; +use crate::models::{QuranAyah, QuranAyahBreaker, QuranWordBreaker}; use crate::routers::multip; -use crate::{calculate_break, AyahBismillah}; +use crate::AyahBismillah; use crate::{ routers::quran::surah::{AyahTy, Format, SimpleAyah}, DbPool, @@ -25,9 +26,7 @@ pub async fn ayah_list( quran_words_breakers, word_id as break_word_id, }; - use crate::schema::quran_ayahs_breakers::dsl::{ - quran_ayahs_breakers, name as ayah_break_name, - }; + use crate::schema::quran_ayahs_breakers::dsl::{name as ayah_break_name, quran_ayahs_breakers}; let pool = pool.into_inner(); @@ -41,7 +40,7 @@ pub async fn ayah_list( Err(err) => return Err(err.log_to_db(pool, error_detail)), }; - let ayahs = filtered_ayahs + let ayahs_words = filtered_ayahs .left_outer_join(quran_surahs.left_outer_join(quran_mushafs)) .left_join(quran_ayahs_breakers) .inner_join(quran_words.left_join(quran_words_breakers)) @@ -49,22 +48,22 @@ pub async fn ayah_list( .select(( QuranAyah::as_select(), q_word, - break_word_id.nullable(), - ayah_break_name.nullable(), + Option::::as_select(), + Option::::as_select(), )) - .get_results::<(QuranAyah, String, Option, Option)>(&mut conn)?; - - let result = calculate_break(ayahs); + .get_results::<( + QuranAyah, + String, + Option, + Option, + )>(&mut conn)?; - let ayahs_as_map = multip(result, |a| a); + let ayahs_as_map = calculate_breaks(ayahs_words); let final_ayahs = ayahs_as_map .into_iter() .map(|(ayah, words)| match query.format { Some(Format::Text) | None => AyahTy::Text(crate::AyahWithText { - hizb: ayah.hizb, - juz: ayah.juz, - page: ayah.page, ayah, text: words .into_iter() diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index 1e979a6..1d59b38 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -12,7 +12,7 @@ use std::{ use crate::{ filter::{Filters, Order}, models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranWordBreaker}, - routers::{maybe_multip, multip}, + routers::{count, maybe_multip, multip}, }; use serde::{Deserialize, Serialize}; use uuid::{fmt::Simple, Uuid}; @@ -89,54 +89,107 @@ impl AyahBismillah { } } +fn calculate_word_break(word: String, breakers: Vec) -> AyahWord { + // WARNING TODO: Hash and Eq impl for QuranWordBreaker is expensive + let breakers_map = count(breakers); + + let breakers = breakers_map + .into_iter() + .map(|(key, value)| Breaker { + name: key.name, + number: value, + }) + .collect::>(); + + AyahWord { + word, + breakers: if breakers.is_empty() { + None + } else { + Some(breakers) + }, + } +} + +pub fn calculate_words_break(input: Vec<(String, Option)>) -> Vec { + #[derive(PartialEq, PartialOrd, Eq, Ord, Hash)] + struct TempWordTy { + id: usize, + word: String, + } + + // WARNING TODO: Change the |word| word, Could not be unique + let word_breakers = maybe_multip(input, |index, word| TempWordTy { id: index, word }); + + word_breakers + .into_iter() + .map(|(word, breakers)| calculate_word_break(word.word, breakers)) + .collect() +} + +fn calculate_ayah_break(ayah: QuranAyah, breakers: Vec) -> SimpleAyah { + let breakers_map = count(breakers); + + let breakers = breakers_map + .into_iter() + .map(|(key, value)| Breaker { + name: key.name, + number: value, + }) + .collect::>(); + + SimpleAyah { + bismillah: AyahBismillah::from_ayah_fields(ayah.is_bismillah, ayah.bismillah_text), + breakers: if breakers.is_empty() { + None + } else { + Some(breakers) + }, + number: ayah.ayah_number as u32, + sajdah: ayah.sajdah, + uuid: ayah.uuid, + } +} + /// input: Vec<(Ayah, Breaks(name))> -pub fn calculate_break( +/// +/// Calculates ayahs breaks, and returns Vec of SimpleAyah's +pub fn calculate_ayahs_break(input: Vec<(QuranAyah, Option)>) -> Vec { + let ayah_breakers = maybe_multip(input, |index, ayah| (index, ayah)); + + ayah_breakers + .into_iter() + .map(|(ayah, breakers)| calculate_ayah_break(ayah.1, breakers)) + .collect() +} + +pub fn calculate_breaks( input: Vec<( QuranAyah, String, Option, Option, )>, -) -> Vec<(SimpleAyah, Vec)> { - let ayahs_with_breakers = input +) -> BTreeMap> { + let ayahs = input + .clone() .into_iter() - .map(|(ayah, _, _, breaker)| (ayah, breaker)) - .collect::)>>(); - let ayah_breakers: BTreeMap> = - maybe_multip(ayahs_with_breakers, |ayah| ayah); - - let mut simple_ayahs = vec![]; - // Calculate breakers - for (ayah, breakers) in ayah_breakers.into_iter() { - let mut breakers_map: HashMap = HashMap::new(); - for breaker in breakers { - breakers_map - .entry(breaker) - .and_modify(|v| *v += 1) - .or_insert(0); - } + .map(|(ayah, _, _, br)| (ayah, br)) + .collect(); - let breakers = breakers_map - .into_iter() - .map(|(key, value)| Breaker { - name: key.name, - number: value, - }) - .collect::>(); - - simple_ayahs.push(SimpleAyah { - bismillah: AyahBismillah::from_ayah_fields(ayah.is_bismillah, ayah.bismillah_text), - breakers: if breakers.is_empty() { - None - } else { - Some(breakers) - }, - number: ayah.ayah_number as u32, - sajdah: ayah.sajdah, - uuid: ayah.uuid, - }); - } - todo!() + let ayahs_breaks = calculate_ayahs_break(ayahs); + + let words = input + .into_iter() + .map(|(_, word, br, _)| (word, br)) + .collect(); + + let words_breaks = calculate_words_break(words); + + let ayahs_words: Vec<(SimpleAyah, AyahWord)> = + ayahs_breaks.into_iter().zip(words_breaks).collect(); + + multip(ayahs_words, |ayah| ayah) } #[derive(Serialize, Clone, Debug)] @@ -167,13 +220,6 @@ pub struct AyahWithText { #[serde(flatten)] pub ayah: SimpleAyah, pub text: String, - - #[serde(skip_serializing_if = "Option::is_none")] - pub hizb: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub juz: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub page: Option, } #[derive(Serialize, Clone, Debug)] diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index c5baecd..fde1866 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -1,8 +1,8 @@ use super::{Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse}; -use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah}; +use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah, QuranWordBreaker}; use crate::routers::multip; +use crate::{calculate_breaks, AyahTy, AyahWord, SingleSurahMushaf, SurahName}; use crate::{error::RouterError, DbPool}; -use crate::{AyahTy, AyahWord, SingleSurahMushaf, SurahName}; use actix_web::web; use diesel::prelude::*; use uuid::Uuid; @@ -52,16 +52,12 @@ pub async fn surah_view( Option, )>(&mut conn)?; - let result = calculate_break(ayahs_words); - let ayahs_as_map = multip(result, |ayah| ayah); + let result = calculate_breaks(ayahs_words); - let final_ayahs = ayahs_as_map + let final_ayahs = result .into_iter() .map(|(ayah, words)| match query.format { Format::Text => AyahTy::Text(crate::AyahWithText { - hizb: ayah.hizb, - juz: ayah.juz, - page: ayah.page, ayah, text: words .into_iter() From d6144e08bd119fed7ddd6c37554a7654241a56a2 Mon Sep 17 00:00:00 2001 From: nyzd Date: Mon, 13 Jan 2025 18:05:19 +0330 Subject: [PATCH 14/31] new update --- src/models.rs | 17 +++- src/routers/mod.rs | 44 +--------- src/routers/quran/ayah/ayah_list.rs | 91 ++++++++++++++------ src/routers/quran/surah/mod.rs | 118 ++------------------------ src/routers/quran/surah/surah_view.rs | 93 ++++++++++++++------ 5 files changed, 158 insertions(+), 205 deletions(-) diff --git a/src/models.rs b/src/models.rs index dc33a75..ce5e8b7 100644 --- a/src/models.rs +++ b/src/models.rs @@ -271,7 +271,20 @@ pub struct NewQuranAyah { pub bismillah_text: Option, } -#[derive(Clone, Selectable, Identifiable, Associations, Queryable, PartialEq, Debug, Serialize)] +#[derive( + Clone, + Selectable, + Identifiable, + Associations, + Queryable, + PartialEq, + Debug, + Serialize, + Hash, + Ord, + PartialOrd, + Eq, +)] #[diesel(belongs_to(QuranAyah, foreign_key = ayah_id))] #[diesel(table_name = quran_words)] pub struct QuranWord { @@ -668,7 +681,7 @@ pub struct QuranAyahBreaker { creator_user_id: i32, #[serde(skip_serializing)] - ayah_id: i32, + pub ayah_id: i32, #[serde(skip_serializing)] owner_account_id: Option, diff --git a/src/routers/mod.rs b/src/routers/mod.rs index 1616383..5810ebe 100644 --- a/src/routers/mod.rs +++ b/src/routers/mod.rs @@ -8,13 +8,13 @@ pub mod quran; pub mod translation; pub mod user; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use std::hash::Hash; /// finds the relatives in the vector /// Vec<(Obj1, Obj2)> /// This will collect the Obj2 that related to the Obj1 and returns -/// a BTreeMap (We want the elements be in order) +/// a BTreeMap (We want the elements to be in order) pub fn multip(vector: Vec<(T, U)>, insert_data_type: F) -> BTreeMap> where T: Sized + Clone, @@ -31,43 +31,3 @@ where map } - -/// a BTreeMap (We want the elements be in order) -pub fn maybe_multip( - vector: Vec<(T, Option)>, - insert_data_type: F, -) -> BTreeMap> -where - T: Sized + Clone, - U: Sized + Clone, - NT: Sized + Eq + Hash + Ord, - F: Fn(usize, T) -> NT, -{ - let mut map: BTreeMap> = BTreeMap::new(); - for (index, item) in vector.into_iter().enumerate() { - map.entry(insert_data_type(index, item.clone().0)) - .and_modify(|c| { - if let Some(value) = item.1.clone() { - c.push(value.clone()) - } - }) - .or_insert(match item.1 { - Some(val) => vec![val], - None => vec![], - }); - } - - map -} - -pub fn count(data: Vec) -> HashMap -where - T: Sized + Hash + Eq, -{ - let mut map: HashMap = HashMap::new(); - for v in data { - map.entry(v).and_modify(|v| *v += 1).or_insert(1); - } - - map -} diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index 7b9f8b5..e50ddbd 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -1,13 +1,14 @@ -use crate::calculate_breaks; +use std::collections::HashMap; + use crate::error::{RouterError, RouterErrorDetailBuilder}; use crate::filter::Filter; -use crate::models::{QuranAyah, QuranAyahBreaker, QuranWordBreaker}; +use crate::models::{QuranAyah, QuranAyahBreaker, QuranWord}; use crate::routers::multip; -use crate::AyahBismillah; use crate::{ - routers::quran::surah::{AyahTy, Format, SimpleAyah}, + routers::quran::surah::{AyahTy, AyahWord, Format, SimpleAyah}, DbPool, }; +use crate::{AyahBismillah, Breaker}; use actix_web::{web, HttpRequest}; use diesel::prelude::*; @@ -19,14 +20,11 @@ pub async fn ayah_list( web::Query(query): web::Query, req: HttpRequest, ) -> Result>, RouterError> { + use crate::schema::quran_ayahs_breakers::dsl::quran_ayahs_breakers; use crate::schema::quran_mushafs::dsl::{quran_mushafs, short_name as mushaf_short_name}; use crate::schema::quran_surahs::dsl::quran_surahs; - use crate::schema::quran_words::dsl::{quran_words, word as q_word}; - use crate::schema::quran_words_breakers::dsl::{ - quran_words_breakers, word_id as break_word_id, - }; - - use crate::schema::quran_ayahs_breakers::dsl::{name as ayah_break_name, quran_ayahs_breakers}; + use crate::schema::quran_words::dsl::quran_words; + use crate::schema::quran_words_breakers::dsl::quran_words_breakers; let pool = pool.into_inner(); @@ -35,6 +33,29 @@ pub async fn ayah_list( web::block(move || { let mut conn = pool.get().unwrap(); + // [{ayah_id, name}...] + // Also need to count name + let breakers: Vec = quran_ayahs_breakers.get_results(&mut conn)?; + let mut breakers = breakers.into_iter(); + + let mut breakers_count: HashMap = HashMap::new(); + let mut map = HashMap::>::new(); + + while let Some(breaker) = breakers.next() { + breakers_count + .entry(breaker.name) + .and_modify(|v| *v += 1) + .or_insert(1); + + let val = breakers_count + .clone() + .into_iter() + .map(|(k, v)| Breaker { name: k, number: v }) + .collect::>(); + + map.entry(breaker.ayah_id).insert_entry(val); + } + let filtered_ayahs = match QuranAyah::filter(Box::from(query.clone())) { Ok(filtered) => filtered, Err(err) => return Err(err.log_to_db(pool, error_detail)), @@ -42,24 +63,32 @@ pub async fn ayah_list( let ayahs_words = filtered_ayahs .left_outer_join(quran_surahs.left_outer_join(quran_mushafs)) - .left_join(quran_ayahs_breakers) .inner_join(quran_words.left_join(quran_words_breakers)) .filter(mushaf_short_name.eq(query.mushaf)) - .select(( - QuranAyah::as_select(), - q_word, - Option::::as_select(), - Option::::as_select(), - )) - .get_results::<( - QuranAyah, - String, - Option, - Option, - )>(&mut conn)?; - - let ayahs_as_map = calculate_breaks(ayahs_words); + .select((QuranAyah::as_select(), QuranWord::as_select())) + .get_results::<(QuranAyah, QuranWord)>(&mut conn)?; + + let ayahs_words = ayahs_words + .into_iter() + .map(|(ayah, word)| { + ( + SimpleAyah { + id: ayah.id as u32, + uuid: ayah.uuid, + bismillah: AyahBismillah::from_ayah_fields( + ayah.is_bismillah, + ayah.bismillah_text, + ), + breakers: map.get(&ayah.id).clone().cloned(), + number: ayah.ayah_number as u32, + sajdah: ayah.sajdah, + }, + word, + ) + }) + .collect::>(); + let ayahs_as_map = multip(ayahs_words, |a| a); let final_ayahs = ayahs_as_map .into_iter() .map(|(ayah, words)| match query.format { @@ -71,7 +100,17 @@ pub async fn ayah_list( .collect::>() .join(" "), }), - Some(Format::Word) => AyahTy::Words(crate::AyahWithWords { ayah, words }), + Some(Format::Word) => AyahTy::Words(crate::AyahWithWords { + ayah: ayah.clone(), + words: words + .into_iter() + .map(|w| AyahWord { + ayah_id: ayah.id, + breakers: None, + word: w.word, + }) + .collect(), + }), }) .collect::>(); diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index 1d59b38..9f564eb 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -4,18 +4,14 @@ pub mod surah_edit; pub mod surah_list; pub mod surah_view; -use std::{ - collections::{BTreeMap, HashMap}, - hash::Hash, -}; +use std::hash::Hash; use crate::{ filter::{Filters, Order}, - models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranWordBreaker}, - routers::{count, maybe_multip, multip}, + models::QuranMushaf, }; use serde::{Deserialize, Serialize}; -use uuid::{fmt::Simple, Uuid}; +use uuid::Uuid; /// The quran text format Each word has its own uuid #[derive(Debug, Clone, Deserialize)] @@ -89,109 +85,6 @@ impl AyahBismillah { } } -fn calculate_word_break(word: String, breakers: Vec) -> AyahWord { - // WARNING TODO: Hash and Eq impl for QuranWordBreaker is expensive - let breakers_map = count(breakers); - - let breakers = breakers_map - .into_iter() - .map(|(key, value)| Breaker { - name: key.name, - number: value, - }) - .collect::>(); - - AyahWord { - word, - breakers: if breakers.is_empty() { - None - } else { - Some(breakers) - }, - } -} - -pub fn calculate_words_break(input: Vec<(String, Option)>) -> Vec { - #[derive(PartialEq, PartialOrd, Eq, Ord, Hash)] - struct TempWordTy { - id: usize, - word: String, - } - - // WARNING TODO: Change the |word| word, Could not be unique - let word_breakers = maybe_multip(input, |index, word| TempWordTy { id: index, word }); - - word_breakers - .into_iter() - .map(|(word, breakers)| calculate_word_break(word.word, breakers)) - .collect() -} - -fn calculate_ayah_break(ayah: QuranAyah, breakers: Vec) -> SimpleAyah { - let breakers_map = count(breakers); - - let breakers = breakers_map - .into_iter() - .map(|(key, value)| Breaker { - name: key.name, - number: value, - }) - .collect::>(); - - SimpleAyah { - bismillah: AyahBismillah::from_ayah_fields(ayah.is_bismillah, ayah.bismillah_text), - breakers: if breakers.is_empty() { - None - } else { - Some(breakers) - }, - number: ayah.ayah_number as u32, - sajdah: ayah.sajdah, - uuid: ayah.uuid, - } -} - -/// input: Vec<(Ayah, Breaks(name))> -/// -/// Calculates ayahs breaks, and returns Vec of SimpleAyah's -pub fn calculate_ayahs_break(input: Vec<(QuranAyah, Option)>) -> Vec { - let ayah_breakers = maybe_multip(input, |index, ayah| (index, ayah)); - - ayah_breakers - .into_iter() - .map(|(ayah, breakers)| calculate_ayah_break(ayah.1, breakers)) - .collect() -} - -pub fn calculate_breaks( - input: Vec<( - QuranAyah, - String, - Option, - Option, - )>, -) -> BTreeMap> { - let ayahs = input - .clone() - .into_iter() - .map(|(ayah, _, _, br)| (ayah, br)) - .collect(); - - let ayahs_breaks = calculate_ayahs_break(ayahs); - - let words = input - .into_iter() - .map(|(_, word, br, _)| (word, br)) - .collect(); - - let words_breaks = calculate_words_break(words); - - let ayahs_words: Vec<(SimpleAyah, AyahWord)> = - ayahs_breaks.into_iter().zip(words_breaks).collect(); - - multip(ayahs_words, |ayah| ayah) -} - #[derive(Serialize, Clone, Debug)] pub struct AyahBismillahInSurah { pub is_first_ayah: bool, @@ -207,6 +100,8 @@ pub struct Breaker { /// The Ayah type that will return in the response #[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug)] pub struct SimpleAyah { + #[serde(skip_serializing)] + pub id: u32, pub number: u32, pub uuid: Uuid, pub sajdah: Option, @@ -224,6 +119,9 @@ pub struct AyahWithText { #[derive(Serialize, Clone, Debug)] pub struct AyahWord { + #[serde(skip_serializing)] + pub ayah_id: u32, + pub word: String, #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index fde1866..69791cc 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -1,8 +1,10 @@ -use super::{Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse}; -use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah, QuranWordBreaker}; +use std::collections::HashMap; + +use super::{AyahWord, Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse}; +use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah, QuranWord}; use crate::routers::multip; -use crate::{calculate_breaks, AyahTy, AyahWord, SingleSurahMushaf, SurahName}; use crate::{error::RouterError, DbPool}; +use crate::{AyahBismillah, AyahTy, Breaker, SingleSurahMushaf, SurahName}; use actix_web::web; use diesel::prelude::*; use uuid::Uuid; @@ -18,13 +20,11 @@ pub async fn surah_view( }; use crate::schema::app_phrases::dsl::{app_phrases, phrase as p_phrase}; use crate::schema::quran_ayahs::dsl::quran_ayahs; + use crate::schema::quran_ayahs_breakers::dsl::quran_ayahs_breakers; use crate::schema::quran_mushafs::dsl::{id as mushaf_id, quran_mushafs}; use crate::schema::quran_surahs::dsl::quran_surahs; use crate::schema::quran_surahs::dsl::uuid as surah_uuid; - use crate::schema::quran_words::dsl::{quran_words, word as q_word}; - use crate::schema::quran_words_breakers::dsl::{name as word_break_name, quran_words_breakers}; - - use crate::schema::quran_ayahs_breakers::dsl::{name as ayah_break_name, quran_ayahs_breakers}; + use crate::schema::quran_words::dsl::quran_words; let query = query.into_inner(); let requested_surah_uuid = path.into_inner(); @@ -32,29 +32,62 @@ pub async fn surah_view( web::block(move || { let mut conn = pool.get().unwrap(); + // [{ayah_id, name}...] + // Also need to count name + let breakers: Vec = quran_ayahs_breakers.get_results(&mut conn)?; + let mut breakers = breakers.into_iter(); + + let mut breakers_count: HashMap = HashMap::new(); + let mut map = HashMap::>::new(); + + while let Some(breaker) = breakers.next() { + breakers_count + .entry(breaker.name) + .and_modify(|v| *v += 1) + .or_insert(1); + + let val = breakers_count + .clone() + .into_iter() + .map(|(k, v)| Breaker { name: k, number: v }) + .collect::>(); + + map.entry(breaker.ayah_id).insert_entry(val); + } + let ayahs_words = quran_surahs .filter(surah_uuid.eq(requested_surah_uuid)) .inner_join( quran_ayahs - .inner_join(quran_words.left_join(quran_words_breakers)) + .inner_join(quran_words) .left_join(quran_ayahs_breakers), ) - .select(( - QuranAyah::as_select(), - q_word, - Option::::as_select(), - Option::::as_select(), - )) - .load::<( - QuranAyah, - String, - Option, - Option, - )>(&mut conn)?; - - let result = calculate_breaks(ayahs_words); - - let final_ayahs = result + .select((QuranAyah::as_select(), QuranWord::as_select())) + .load::<(QuranAyah, QuranWord)>(&mut conn)?; + + let ayahs_words = ayahs_words + .into_iter() + .map(|(ayah, word)| { + ( + SimpleAyah { + id: ayah.id as u32, + uuid: ayah.uuid, + bismillah: AyahBismillah::from_ayah_fields( + ayah.is_bismillah, + ayah.bismillah_text, + ), + breakers: map.get(&ayah.id).clone().cloned(), + number: ayah.ayah_number as u32, + sajdah: ayah.sajdah, + }, + word, + ) + }) + .collect::>(); + + let ayahs_as_map = multip(ayahs_words, |a| a); + + let final_ayahs = ayahs_as_map .into_iter() .map(|(ayah, words)| match query.format { Format::Text => AyahTy::Text(crate::AyahWithText { @@ -65,7 +98,17 @@ pub async fn surah_view( .collect::>() .join(" "), }), - Format::Word => AyahTy::Words(crate::AyahWithWords { ayah, words }), + Format::Word => AyahTy::Words(crate::AyahWithWords { + ayah: ayah.clone(), + words: words + .into_iter() + .map(|w| AyahWord { + ayah_id: ayah.id, + breakers: None, + word: w.word, + }) + .collect(), + }), }) .collect::>(); From 8fecc5ad2f6952e7f95ad0742f89a2242c9401d9 Mon Sep 17 00:00:00 2001 From: nyzd Date: Tue, 14 Jan 2025 14:27:59 +0330 Subject: [PATCH 15/31] bug fix --- src/routers/quran/surah/mod.rs | 3 +++ src/routers/translation/mod.rs | 2 +- src/routers/translation/translation_list.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index 9f564eb..51c989f 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -104,8 +104,11 @@ pub struct SimpleAyah { pub id: u32, pub number: u32, pub uuid: Uuid, + #[serde(skip_serializing_if = "Option::is_none")] pub sajdah: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub bismillah: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub breakers: Option>, } diff --git a/src/routers/translation/mod.rs b/src/routers/translation/mod.rs index 9d655a8..90651d8 100644 --- a/src/routers/translation/mod.rs +++ b/src/routers/translation/mod.rs @@ -76,7 +76,7 @@ pub struct SimpleTranslationAyah { pub struct TranslationListQuery { language: Option, mushaf: String, - translator_account: Option, + translator_account_uuid: Option, sort: Option, order: Option, diff --git a/src/routers/translation/translation_list.rs b/src/routers/translation/translation_list.rs index 3310e49..3865774 100644 --- a/src/routers/translation/translation_list.rs +++ b/src/routers/translation/translation_list.rs @@ -74,7 +74,7 @@ pub async fn translation_list( translations_list = translations_list.filter(translation_lang.eq(lang)); } - let translations_list = if let Some(translator_uuid) = query.translator_account { + let translations_list = if let Some(translator_uuid) = query.translator_account_uuid { translations_list .inner_join(app_accounts.left_join(app_user_names)) .filter(translation_mushaf_id.eq(mushafid)) From a808407311ed7190ed0fbfe697310af431ac1ae9 Mon Sep 17 00:00:00 2001 From: nyzd Date: Sun, 26 Jan 2025 16:22:16 +0330 Subject: [PATCH 16/31] Full update --- src/routers/quran/ayah/ayah_list.rs | 1 - src/routers/quran/ayah/ayah_view.rs | 66 ++++++++++++++++++++------- src/routers/quran/ayah/mod.rs | 16 ++++--- src/routers/quran/surah/mod.rs | 45 ++---------------- src/routers/quran/surah/surah_list.rs | 2 +- src/routers/quran/surah/surah_view.rs | 12 ++--- 6 files changed, 69 insertions(+), 73 deletions(-) diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index e50ddbd..e1f26a8 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -105,7 +105,6 @@ pub async fn ayah_list( words: words .into_iter() .map(|w| AyahWord { - ayah_id: ayah.id, breakers: None, word: w.word, }) diff --git a/src/routers/quran/ayah/ayah_view.rs b/src/routers/quran/ayah/ayah_view.rs index 6cea7e4..bf3b35e 100644 --- a/src/routers/quran/ayah/ayah_view.rs +++ b/src/routers/quran/ayah/ayah_view.rs @@ -1,21 +1,30 @@ -use super::SimpleWord; +use super::{AyahWithContentSurah, SimpleWord}; use crate::error::RouterError; -use crate::models::{QuranAyah, QuranWord}; -use crate::{AyahWithContent, DbPool, Sajdah}; +use crate::models::{QuranAyah, QuranMushaf, QuranSurah, QuranWord}; +use crate::{routers::quran::surah::SurahName, AyahWithContent, DbPool, Sajdah, SingleSurahMushaf}; use ::uuid::Uuid; use actix_web::web; use diesel::prelude::*; +use serde::Deserialize; + +#[derive(Debug, Clone, Deserialize)] +pub struct GetAyahQuery { + lang_code: Option, +} /// Return's a single ayah pub async fn ayah_view( path: web::Path, + web::Query(query): web::Query, pool: web::Data, ) -> Result, RouterError> { - use crate::schema::quran_ayahs::dsl::{quran_ayahs, uuid as ayah_uuid}; - use crate::schema::quran_mushafs::dsl::{id as mushaf_id, quran_mushafs, uuid as mushaf_uuid}; - use crate::schema::quran_surahs::dsl::{ - id as surah_id, mushaf_id as surah_mushaf_id, quran_surahs, uuid as surah_uuid, + use crate::schema::app_phrase_translations::dsl::{ + app_phrase_translations, language as p_t_lang, text as p_t_text, }; + use crate::schema::app_phrases::dsl::{app_phrases, phrase as p_phrase}; + use crate::schema::quran_ayahs::dsl::{quran_ayahs, uuid as ayah_uuid}; + use crate::schema::quran_mushafs::dsl::{id as mushaf_id, quran_mushafs}; + use crate::schema::quran_surahs::dsl::{id as surah_id, quran_surahs}; use crate::schema::quran_words::dsl::{ayah_id, id as word_id, quran_words}; let requested_ayah_uuid = path.into_inner(); @@ -28,16 +37,31 @@ pub async fn ayah_view( .filter(ayah_uuid.eq(requested_ayah_uuid)) .get_result(&mut conn)?; - let surah: (Uuid, i32) = quran_surahs + // Get the surah + let surah = quran_surahs .filter(surah_id.eq(quran_ayah.surah_id)) - .select((surah_uuid, surah_mushaf_id)) - .get_result(&mut conn)?; + .get_result::(&mut conn)?; - let mushaf: Uuid = quran_mushafs - .filter(mushaf_id.eq(surah.1)) - .select(mushaf_uuid) - .get_result(&mut conn)?; + // Get the mushaf + let mushaf = quran_mushafs + .filter(mushaf_id.eq(surah.id)) + .get_result::(&mut conn)?; + + let translation = if let Some(ref phrase) = surah.name_translation_phrase { + let mut p = app_phrases.left_join(app_phrase_translations).into_boxed(); + + if let Some(ref l) = query.lang_code { + p = p.filter(p_t_lang.eq(l)); + } else { + p = p.filter(p_t_lang.eq("en")); + } + p.filter(p_phrase.eq(phrase)) + .select(p_t_text.nullable()) + .get_result(&mut conn)? + } else { + None + }; let words: Vec = quran_words .filter(ayah_id.eq(quran_ayah.id)) .order(word_id.asc()) @@ -59,9 +83,17 @@ pub async fn ayah_view( .join(" "); Ok(web::Json(AyahWithContent { - uuid: quran_ayah.uuid, - surah: surah.0, - mushaf, + surah: AyahWithContentSurah { + uuid: surah.uuid, + names: vec![SurahName { + arabic: surah.name, + translation, + translation_phrase: surah.name_translation_phrase, + pronunciation: surah.name_pronunciation, + transliteration: surah.name_transliteration, + }], + }, + mushaf: SingleSurahMushaf::from(mushaf), sajdah: Sajdah::from_option_string(quran_ayah.sajdah), ayah_number: quran_ayah.ayah_number, words: words_simple, diff --git a/src/routers/quran/ayah/mod.rs b/src/routers/quran/ayah/mod.rs index 091d9a9..703e87e 100644 --- a/src/routers/quran/ayah/mod.rs +++ b/src/routers/quran/ayah/mod.rs @@ -11,7 +11,7 @@ use uuid::Uuid; use crate::{ filter::{Filters, Order}, - AyahBismillah, Format, + AyahBismillah, Format, SingleSurahMushaf, SurahName, }; #[derive(Deserialize, Serialize)] @@ -49,11 +49,16 @@ pub struct SimpleWord { word: String, } -#[derive(Serialize, Deserialize)] -pub struct AyahWithContent { +#[derive(Serialize)] +pub struct AyahWithContentSurah { uuid: Uuid, - mushaf: Uuid, - surah: Uuid, + names: Vec, +} + +#[derive(Serialize)] +pub struct AyahWithContent { + mushaf: SingleSurahMushaf, + surah: AyahWithContentSurah, ayah_number: i32, sajdah: Option, text: String, @@ -71,7 +76,6 @@ pub struct SimpleAyah { pub struct AyahListQuery { mushaf: String, format: Option, - break_data: Option, sort: Option, order: Option, diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index 51c989f..e34166d 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -27,41 +27,6 @@ impl Default for Format { } } -// This is for Surah router -// which is faster than SimpleAyah in sorting -#[derive(Eq, Serialize, Clone, Debug)] -pub struct SimpleAyahSurah { - pub number: u32, - pub uuid: Uuid, - pub sajdah: Option, -} - -// WARNING: Only hashing 'number' ? -// This can lead to collisions in hashmap if the number is not unique -impl Hash for SimpleAyahSurah { - fn hash(&self, state: &mut H) { - self.number.hash(state); - } -} - -impl Ord for SimpleAyahSurah { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.number.cmp(&other.number) - } -} - -impl PartialEq for SimpleAyahSurah { - fn eq(&self, other: &Self) -> bool { - self.number == other.number - } -} - -impl PartialOrd for SimpleAyahSurah { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.number.cmp(&other.number)) - } -} - #[derive(Hash, Ord, PartialOrd, PartialEq, Eq, Serialize, Clone, Debug, Deserialize)] pub struct AyahBismillah { pub is_ayah: bool, @@ -102,8 +67,8 @@ pub struct Breaker { pub struct SimpleAyah { #[serde(skip_serializing)] pub id: u32, - pub number: u32, pub uuid: Uuid, + pub number: u32, #[serde(skip_serializing_if = "Option::is_none")] pub sajdah: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -122,9 +87,6 @@ pub struct AyahWithText { #[derive(Serialize, Clone, Debug)] pub struct AyahWord { - #[serde(skip_serializing)] - pub ayah_id: u32, - pub word: String, #[serde(skip_serializing_if = "Option::is_none")] @@ -264,12 +226,11 @@ impl From for SingleSurahMushaf { /// The response type for /surah/{id} #[derive(Serialize, Clone, Debug)] pub struct SingleSurahResponse { - pub uuid: Uuid, pub mushaf: SingleSurahMushaf, + pub number: u32, + pub number_of_ayahs: u32, pub names: Vec, pub period: Option, - pub number: i32, - pub number_of_ayahs: i64, pub bismillah: Option, } diff --git a/src/routers/quran/surah/surah_list.rs b/src/routers/quran/surah/surah_list.rs index 5dd1eb8..48f8622 100644 --- a/src/routers/quran/surah/surah_list.rs +++ b/src/routers/quran/surah/surah_list.rs @@ -1,9 +1,9 @@ +use super::SurahName; use super::{SurahListQuery, SurahListResponse}; use crate::error::RouterErrorDetailBuilder; use crate::filter::Filter; use crate::models::{QuranAyah, QuranMushaf, QuranSurah}; use crate::schema::quran_ayahs::surah_id; -use crate::SurahName; use crate::{error::RouterError, DbPool}; use actix_web::{web, HttpRequest}; use diesel::dsl::count; diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index 69791cc..e4975ca 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -1,10 +1,12 @@ use std::collections::HashMap; -use super::{AyahWord, Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse}; +use super::{ + AyahWord, Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse, SurahName, +}; use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah, QuranWord}; use crate::routers::multip; use crate::{error::RouterError, DbPool}; -use crate::{AyahBismillah, AyahTy, Breaker, SingleSurahMushaf, SurahName}; +use crate::{AyahBismillah, AyahTy, Breaker, SingleSurahMushaf}; use actix_web::web; use diesel::prelude::*; use uuid::Uuid; @@ -103,7 +105,6 @@ pub async fn surah_view( words: words .into_iter() .map(|w| AyahWord { - ayah_id: ayah.id, breakers: None, word: w.word, }) @@ -140,7 +141,6 @@ pub async fn surah_view( Ok(web::Json(QuranResponseData { surah: SingleSurahResponse { - uuid: surah.uuid, mushaf: SingleSurahMushaf::from(mushaf), bismillah: final_ayahs.first().unwrap().format_bismillah_for_surah(), names: vec![SurahName { @@ -151,8 +151,8 @@ pub async fn surah_view( transliteration: surah.name_transliteration, }], period: surah.period, - number: surah.number, - number_of_ayahs: final_ayahs.len() as i64, + number: surah.number as u32, + number_of_ayahs: final_ayahs.len() as u32, }, ayahs: final_ayahs, })) From 6925b8ce6016027a934eb615ba480bf4eb848657 Mon Sep 17 00:00:00 2001 From: nyzd Date: Sun, 26 Jan 2025 17:58:22 +0330 Subject: [PATCH 17/31] Search terms added to surah --- src/models.rs | 3 +++ src/routers/quran/surah/mod.rs | 3 +++ src/routers/quran/surah/surah_add.rs | 7 +++++++ src/routers/quran/surah/surah_edit.rs | 10 +++++++++- src/routers/quran/surah/surah_list.rs | 7 +++++++ src/routers/quran/surah/surah_view.rs | 6 ++++++ src/schema.rs | 1 + 7 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/models.rs b/src/models.rs index ce5e8b7..f50fa9d 100644 --- a/src/models.rs +++ b/src/models.rs @@ -332,6 +332,8 @@ pub struct QuranSurah { pub name_transliteration: Option, + pub search_terms: Option>>, + #[serde(skip_serializing)] pub created_at: NaiveDateTime, #[serde(skip_serializing)] @@ -349,6 +351,7 @@ pub struct NewQuranSurah { pub name_pronunciation: Option, pub name_translation_phrase: Option, pub name_transliteration: Option, + pub search_terms: Option>>, } #[derive(Deserialize, Serialize, Clone, Validate, Identifiable, Queryable, Selectable, Debug)] diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index e34166d..b0844a2 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -232,6 +232,7 @@ pub struct SingleSurahResponse { pub names: Vec, pub period: Option, pub bismillah: Option, + pub search_terms: Option>, } /// The response type for /surah @@ -242,6 +243,7 @@ pub struct SurahListResponse { pub period: Option, pub number_of_ayahs: i64, pub names: Vec, + pub search_terms: Option>, } // TODO: Remove number. number must be generated at api runtime @@ -253,6 +255,7 @@ pub struct SimpleSurah { pub name_translation_phrase: Option, pub name_transliteration: Option, pub period: Option, + pub search_terms: Option>, pub number: i32, pub mushaf_uuid: Uuid, } diff --git a/src/routers/quran/surah/surah_add.rs b/src/routers/quran/surah/surah_add.rs index 3aa3f0a..efb801d 100644 --- a/src/routers/quran/surah/surah_add.rs +++ b/src/routers/quran/surah/surah_add.rs @@ -54,6 +54,12 @@ pub async fn surah_add( } } + let search_terms = new_surah.search_terms.map(|v| { + v.into_iter() + .map(|s| Some(s)) + .collect::>>() + }); + // Add a new surah NewQuranSurah { creator_user_id: user, @@ -64,6 +70,7 @@ pub async fn surah_add( name_pronunciation: new_surah.name_pronunciation, name_translation_phrase: new_surah.name_translation_phrase, name_transliteration: new_surah.name_transliteration, + search_terms, } .insert_into(quran_surahs) .execute(&mut conn)?; diff --git a/src/routers/quran/surah/surah_edit.rs b/src/routers/quran/surah/surah_edit.rs index c5b3735..82c954c 100644 --- a/src/routers/quran/surah/surah_edit.rs +++ b/src/routers/quran/surah/surah_edit.rs @@ -15,7 +15,8 @@ pub async fn surah_edit( use crate::schema::quran_mushafs::dsl::{id as mushaf_id, quran_mushafs, uuid as mushaf_uuid}; use crate::schema::quran_surahs::dsl::{ mushaf_id as surah_mushaf_id, name, name_pronunciation, name_translation_phrase, - name_transliteration, number, period, quran_surahs, uuid as surah_uuid, + name_transliteration, number, period, quran_surahs, search_terms as surah_search_terms, + uuid as surah_uuid, }; let new_surah = new_surah.into_inner(); @@ -31,6 +32,12 @@ pub async fn surah_edit( .select(mushaf_id) .get_result(&mut conn)?; + let search_terms = new_surah.search_terms.map(|v| { + v.into_iter() + .map(|s| Some(s)) + .collect::>>() + }); + diesel::update(quran_surahs.filter(surah_uuid.eq(target_surah_uuid))) .set(( number.eq(new_surah.number), @@ -40,6 +47,7 @@ pub async fn surah_edit( name_pronunciation.eq(new_surah.name_pronunciation), name_translation_phrase.eq(new_surah.name_translation_phrase), name_transliteration.eq(new_surah.name_transliteration), + surah_search_terms.eq(search_terms), )) .execute(&mut conn)?; diff --git a/src/routers/quran/surah/surah_list.rs b/src/routers/quran/surah/surah_list.rs index 48f8622..7c90d99 100644 --- a/src/routers/quran/surah/surah_list.rs +++ b/src/routers/quran/surah/surah_list.rs @@ -81,6 +81,12 @@ pub async fn surah_list( None }; + let surah_search_terms = surah.search_terms.map(|st| { + st.into_iter() + .map(|s| s.unwrap_or(String::new())) + .collect::>() + }); + SurahListResponse { uuid: surah.uuid, names: vec![SurahName { @@ -93,6 +99,7 @@ pub async fn surah_list( number: surah.number, period: surah.period, number_of_ayahs, + search_terms: surah_search_terms, } }) .collect::>(); diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index e4975ca..6a5677a 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -138,6 +138,11 @@ pub async fn surah_view( } else { None }; + let surah_search_terms = surah.search_terms.map(|st| { + st.into_iter() + .map(|s| s.unwrap_or(String::new())) + .collect::>() + }); Ok(web::Json(QuranResponseData { surah: SingleSurahResponse { @@ -153,6 +158,7 @@ pub async fn surah_view( period: surah.period, number: surah.number as u32, number_of_ayahs: final_ayahs.len() as u32, + search_terms: surah_search_terms, }, ayahs: final_ayahs, })) diff --git a/src/schema.rs b/src/schema.rs index 68a9d87..9321614 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -253,6 +253,7 @@ diesel::table! { name_pronunciation -> Nullable, name_translation_phrase -> Nullable, name_transliteration -> Nullable, + search_terms -> Nullable>>, created_at -> Timestamptz, updated_at -> Timestamptz, } From ad13e0c8dd325bf8bc77706e27683db79579816b Mon Sep 17 00:00:00 2001 From: nyzd Date: Sun, 26 Jan 2025 17:58:37 +0330 Subject: [PATCH 18/31] search term column --- migrations/00000000000005_create_quran_surahs/up.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/migrations/00000000000005_create_quran_surahs/up.sql b/migrations/00000000000005_create_quran_surahs/up.sql index 6172691..a2722ca 100644 --- a/migrations/00000000000005_create_quran_surahs/up.sql +++ b/migrations/00000000000005_create_quran_surahs/up.sql @@ -9,6 +9,7 @@ CREATE TABLE quran_surahs ( name_pronunciation TEXT, name_translation_phrase TEXT, name_transliteration TEXT, + search_terms TEXT ARRAY, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT quran_surahs_id PRIMARY KEY (id), From a7a41126be1ed0916d2ad8b0a98c87e580deddca Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 6 Feb 2025 15:57:04 +0330 Subject: [PATCH 19/31] Order fixed --- src/routers/quran/ayah/ayah_list.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index e1f26a8..c15c4db 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -20,9 +20,10 @@ pub async fn ayah_list( web::Query(query): web::Query, req: HttpRequest, ) -> Result>, RouterError> { + use crate::schema::quran_ayahs::dsl::ayah_number; use crate::schema::quran_ayahs_breakers::dsl::quran_ayahs_breakers; use crate::schema::quran_mushafs::dsl::{quran_mushafs, short_name as mushaf_short_name}; - use crate::schema::quran_surahs::dsl::quran_surahs; + use crate::schema::quran_surahs::dsl::{number as quran_surah_number, quran_surahs}; use crate::schema::quran_words::dsl::quran_words; use crate::schema::quran_words_breakers::dsl::quran_words_breakers; @@ -65,6 +66,7 @@ pub async fn ayah_list( .left_outer_join(quran_surahs.left_outer_join(quran_mushafs)) .inner_join(quran_words.left_join(quran_words_breakers)) .filter(mushaf_short_name.eq(query.mushaf)) + .order((quran_surah_number.asc(), ayah_number.asc())) .select((QuranAyah::as_select(), QuranWord::as_select())) .get_results::<(QuranAyah, QuranWord)>(&mut conn)?; From 99495c5417133fbd08f80b99c52447eae98250f8 Mon Sep 17 00:00:00 2001 From: nyzd Date: Thu, 6 Feb 2025 17:19:39 +0330 Subject: [PATCH 20/31] word breakers --- src/models.rs | 2 +- src/routers/quran/ayah/ayah_list.rs | 30 +++++++++++++++++++++++++-- src/routers/quran/surah/mod.rs | 4 +++- src/routers/quran/surah/surah_view.rs | 30 +++++++++++++++++++++++++-- src/routers/quran/word/mod.rs | 9 ++++++-- 5 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/models.rs b/src/models.rs index f50fa9d..e437a84 100644 --- a/src/models.rs +++ b/src/models.rs @@ -722,7 +722,7 @@ pub struct QuranWordBreaker { creator_user_id: i32, #[serde(skip_serializing)] - word_id: i32, + pub word_id: i32, #[serde(skip_serializing)] owner_account_id: Option, diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index c15c4db..09c3bf9 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -2,8 +2,9 @@ use std::collections::HashMap; use crate::error::{RouterError, RouterErrorDetailBuilder}; use crate::filter::Filter; -use crate::models::{QuranAyah, QuranAyahBreaker, QuranWord}; +use crate::models::{QuranAyah, QuranAyahBreaker, QuranWord, QuranWordBreaker}; use crate::routers::multip; +use crate::routers::quran::word::WordBreaker; use crate::{ routers::quran::surah::{AyahTy, AyahWord, Format, SimpleAyah}, DbPool, @@ -57,6 +58,29 @@ pub async fn ayah_list( map.entry(breaker.ayah_id).insert_entry(val); } + // TODO: this gets every word's breaker. (not efficient) + let words_breakers = if matches!(query.format, Some(Format::Word)) { + let breakers: Vec = quran_words_breakers.get_results(&mut conn)?; + let mut breakers = breakers.into_iter(); + // (i32) + let mut collected_breakers: HashMap> = HashMap::new(); + + while let Some(breaker) = breakers.next() { + collected_breakers + .entry(breaker.word_id) + .and_modify(|v| { + v.push(WordBreaker { + name: breaker.name.clone(), + }) + }) + .or_insert(vec![WordBreaker { name: breaker.name }]); + } + + Some(collected_breakers) + } else { + None + }; + let filtered_ayahs = match QuranAyah::filter(Box::from(query.clone())) { Ok(filtered) => filtered, Err(err) => return Err(err.log_to_db(pool, error_detail)), @@ -64,6 +88,7 @@ pub async fn ayah_list( let ayahs_words = filtered_ayahs .left_outer_join(quran_surahs.left_outer_join(quran_mushafs)) + // TODO: currently we dont use quran_words_breakers join .inner_join(quran_words.left_join(quran_words_breakers)) .filter(mushaf_short_name.eq(query.mushaf)) .order((quran_surah_number.asc(), ayah_number.asc())) @@ -107,7 +132,8 @@ pub async fn ayah_list( words: words .into_iter() .map(|w| AyahWord { - breakers: None, + // TODO: Very expensive operation. remove .clone() + breakers: words_breakers.clone().unwrap().get(&w.id).clone().cloned(), word: w.word, }) .collect(), diff --git a/src/routers/quran/surah/mod.rs b/src/routers/quran/surah/mod.rs index b0844a2..1229a75 100644 --- a/src/routers/quran/surah/mod.rs +++ b/src/routers/quran/surah/mod.rs @@ -13,6 +13,8 @@ use crate::{ use serde::{Deserialize, Serialize}; use uuid::Uuid; +use super::word::WordBreaker; + /// The quran text format Each word has its own uuid #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "lowercase")] @@ -90,7 +92,7 @@ pub struct AyahWord { pub word: String, #[serde(skip_serializing_if = "Option::is_none")] - pub breakers: Option>, + pub breakers: Option>, } #[derive(Serialize, Clone, Debug)] diff --git a/src/routers/quran/surah/surah_view.rs b/src/routers/quran/surah/surah_view.rs index 6a5677a..23f6cf8 100644 --- a/src/routers/quran/surah/surah_view.rs +++ b/src/routers/quran/surah/surah_view.rs @@ -3,8 +3,11 @@ use std::collections::HashMap; use super::{ AyahWord, Format, GetSurahQuery, QuranResponseData, SimpleAyah, SingleSurahResponse, SurahName, }; -use crate::models::{QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah, QuranWord}; +use crate::models::{ + QuranAyah, QuranAyahBreaker, QuranMushaf, QuranSurah, QuranWord, QuranWordBreaker, +}; use crate::routers::multip; +use crate::routers::quran::word::WordBreaker; use crate::{error::RouterError, DbPool}; use crate::{AyahBismillah, AyahTy, Breaker, SingleSurahMushaf}; use actix_web::web; @@ -27,6 +30,7 @@ pub async fn surah_view( use crate::schema::quran_surahs::dsl::quran_surahs; use crate::schema::quran_surahs::dsl::uuid as surah_uuid; use crate::schema::quran_words::dsl::quran_words; + use crate::schema::quran_words_breakers::dsl::quran_words_breakers; let query = query.into_inner(); let requested_surah_uuid = path.into_inner(); @@ -89,6 +93,28 @@ pub async fn surah_view( let ayahs_as_map = multip(ayahs_words, |a| a); + let words_breakers = if matches!(query.format, Format::Word) { + let breakers: Vec = quran_words_breakers.get_results(&mut conn)?; + let mut breakers = breakers.into_iter(); + // (i32) + let mut collected_breakers: HashMap> = HashMap::new(); + + while let Some(breaker) = breakers.next() { + collected_breakers + .entry(breaker.word_id) + .and_modify(|v| { + v.push(WordBreaker { + name: breaker.name.clone(), + }) + }) + .or_insert(vec![WordBreaker { name: breaker.name }]); + } + + Some(collected_breakers) + } else { + None + }; + let final_ayahs = ayahs_as_map .into_iter() .map(|(ayah, words)| match query.format { @@ -105,7 +131,7 @@ pub async fn surah_view( words: words .into_iter() .map(|w| AyahWord { - breakers: None, + breakers: words_breakers.clone().unwrap().get(&w.id).clone().cloned(), word: w.word, }) .collect(), diff --git a/src/routers/quran/word/mod.rs b/src/routers/quran/word/mod.rs index 8e38bec..acd7c6e 100644 --- a/src/routers/quran/word/mod.rs +++ b/src/routers/quran/word/mod.rs @@ -1,11 +1,16 @@ +pub mod word_add; pub mod word_delete; pub mod word_edit; pub mod word_view; -pub mod word_add; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; #[derive(Deserialize)] pub struct SimpleWord { pub word: String, } + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct WordBreaker { + pub name: String, +} From a22291a42299e7b685c6a7038da16884244b9e91 Mon Sep 17 00:00:00 2001 From: nyzd Date: Sat, 22 Feb 2025 18:03:35 +0330 Subject: [PATCH 21/31] filter: surah added to ayah and bug fix --- src/routers/quran/ayah/ayah_list.rs | 21 +++++++++++++-------- src/routers/quran/ayah/ayah_view.rs | 2 +- src/routers/quran/ayah/mod.rs | 1 + src/routers/quran/word/word_view.rs | 12 ++++++++++-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index 09c3bf9..42d5329 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use super::AyahListQuery; use crate::error::{RouterError, RouterErrorDetailBuilder}; use crate::filter::Filter; use crate::models::{QuranAyah, QuranAyahBreaker, QuranWord, QuranWordBreaker}; @@ -13,8 +14,6 @@ use crate::{AyahBismillah, Breaker}; use actix_web::{web, HttpRequest}; use diesel::prelude::*; -use super::AyahListQuery; - /// Returns the list of ayahs pub async fn ayah_list( pool: web::Data, @@ -24,7 +23,9 @@ pub async fn ayah_list( use crate::schema::quran_ayahs::dsl::ayah_number; use crate::schema::quran_ayahs_breakers::dsl::quran_ayahs_breakers; use crate::schema::quran_mushafs::dsl::{quran_mushafs, short_name as mushaf_short_name}; - use crate::schema::quran_surahs::dsl::{number as quran_surah_number, quran_surahs}; + use crate::schema::quran_surahs::dsl::{ + number as quran_surah_number, quran_surahs, uuid as surahs_uuid, + }; use crate::schema::quran_words::dsl::quran_words; use crate::schema::quran_words_breakers::dsl::quran_words_breakers; @@ -86,14 +87,18 @@ pub async fn ayah_list( Err(err) => return Err(err.log_to_db(pool, error_detail)), }; - let ayahs_words = filtered_ayahs + let mut ayahs_words = filtered_ayahs .left_outer_join(quran_surahs.left_outer_join(quran_mushafs)) - // TODO: currently we dont use quran_words_breakers join - .inner_join(quran_words.left_join(quran_words_breakers)) + .inner_join(quran_words) .filter(mushaf_short_name.eq(query.mushaf)) .order((quran_surah_number.asc(), ayah_number.asc())) - .select((QuranAyah::as_select(), QuranWord::as_select())) - .get_results::<(QuranAyah, QuranWord)>(&mut conn)?; + .select((QuranAyah::as_select(), QuranWord::as_select())); + + if let Some(surah_uuid) = query.surah_uuid { + ayahs_words = ayahs_words.filter(surahs_uuid.eq(surah_uuid)); + } + + let ayahs_words = ayahs_words.get_results(&mut conn)?; let ayahs_words = ayahs_words .into_iter() diff --git a/src/routers/quran/ayah/ayah_view.rs b/src/routers/quran/ayah/ayah_view.rs index bf3b35e..dae84b5 100644 --- a/src/routers/quran/ayah/ayah_view.rs +++ b/src/routers/quran/ayah/ayah_view.rs @@ -44,7 +44,7 @@ pub async fn ayah_view( // Get the mushaf let mushaf = quran_mushafs - .filter(mushaf_id.eq(surah.id)) + .filter(mushaf_id.eq(surah.mushaf_id)) .get_result::(&mut conn)?; let translation = if let Some(ref phrase) = surah.name_translation_phrase { diff --git a/src/routers/quran/ayah/mod.rs b/src/routers/quran/ayah/mod.rs index 703e87e..7e5b857 100644 --- a/src/routers/quran/ayah/mod.rs +++ b/src/routers/quran/ayah/mod.rs @@ -76,6 +76,7 @@ pub struct SimpleAyah { pub struct AyahListQuery { mushaf: String, format: Option, + surah_uuid: Option, sort: Option, order: Option, diff --git a/src/routers/quran/word/word_view.rs b/src/routers/quran/word/word_view.rs index 63ba0fd..6c0dded 100644 --- a/src/routers/quran/word/word_view.rs +++ b/src/routers/quran/word/word_view.rs @@ -4,12 +4,18 @@ use crate::DbPool; use ::uuid::Uuid; use actix_web::web; use diesel::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +pub struct WordViewResponse { + word: String, +} /// Return's a single word pub async fn word_view( path: web::Path, pool: web::Data, -) -> Result, RouterError> { +) -> Result, RouterError> { use crate::schema::quran_words::dsl::{quran_words, uuid as word_uuid}; let requested_word_uuid = path.into_inner(); @@ -22,7 +28,9 @@ pub async fn word_view( .filter(word_uuid.eq(requested_word_uuid)) .get_result(&mut conn)?; - Ok(web::Json(quran_word)) + Ok(web::Json(WordViewResponse { + word: quran_word.word, + })) }) .await .unwrap() From 7eec9f86b244e569c24a13a1dae9fe845e7f183b Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Sun, 23 Feb 2025 16:08:01 +0330 Subject: [PATCH 22/31] Update docker-image.yml --- .github/workflows/docker-image.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 62f9d14..e9a45ff 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -2,9 +2,15 @@ name: Docker Image CI on: push: - branches: [ "main" ] + branches: + - "main" + - "test" + - "dev" pull_request: - branches: [ "main" ] + branches: + - "main" + - "test" + - "dev" jobs: From e8bf2362a29429e9ce6b5f93554a708eda9b5d1a Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Sun, 23 Feb 2025 16:12:42 +0330 Subject: [PATCH 23/31] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index e2c5b85..00b30e8 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -2,8 +2,10 @@ name: docker-publish on: push: - branches: + branches: - "main" + - "test" + - "dev" jobs: build: From 3d32ce296b89ff9e599894385d92086a152fa2a2 Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Sun, 23 Feb 2025 16:14:44 +0330 Subject: [PATCH 24/31] Update rust.yml --- .github/workflows/rust.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2655312..b29cf50 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,9 +2,15 @@ name: Rust on: push: - branches: [ "main" ] + branches: + - "main" + - "test" + - "dev" pull_request: - branches: [ "main" ] + branches: + - "main" + - "test" + - "dev" env: CARGO_TERM_COLOR: always From a9c2bf3c56503df40985e3bda8c84eb71a9b7da1 Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Sun, 23 Feb 2025 16:37:21 +0330 Subject: [PATCH 25/31] other branches on docker --- .github/workflows/docker-image.yml | 9 ++++++++- .github/workflows/docker-publish.yml | 20 +++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index e9a45ff..98aa1f4 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -20,5 +20,12 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Build the Docker image - run: docker build . --file Dockerfile --tag natiq-api:$(date +%s) + run: | + if [ "${GITHUB_REF}" == "refs/heads/main" ]; then + TAG="$(date +%s)" + else + TAG="${GITHUB_REF##*/}" + fi + docker build . --file Dockerfile --tag natiq-api:$TAG \ No newline at end of file diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 00b30e8..8b3a17a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -10,24 +10,26 @@ on: jobs: build: runs-on: ubuntu-latest + steps: - - - name: Checkout + - name: Checkout uses: actions/checkout@v3 - - - name: Login to Docker Hub + + - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - - name: Set up Docker Buildx + + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - - name: Build and push + + - name: Build and push uses: docker/build-push-action@v3 with: context: . file: ./Dockerfile push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/nq-api:latest + tags: | + ${{ secrets.DOCKER_HUB_USERNAME }}/nq-api:latest + ${{ secrets.DOCKER_HUB_USERNAME }}/nq-api:${{ github.ref_name }} From f020508ced842a2ec09bf1b0b0bc959421dd017a Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Sun, 23 Feb 2025 16:38:32 +0330 Subject: [PATCH 26/31] other branches on docker --- .github/workflows/docker-image.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 98aa1f4..196be7c 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -15,7 +15,6 @@ on: jobs: build: - runs-on: ubuntu-latest steps: @@ -23,9 +22,9 @@ jobs: - name: Build the Docker image run: | - if [ "${GITHUB_REF}" == "refs/heads/main" ]; then - TAG="$(date +%s)" + if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then + TAG="latest" else TAG="${GITHUB_REF##*/}" fi - docker build . --file Dockerfile --tag natiq-api:$TAG \ No newline at end of file + docker build . --file Dockerfile --tag natiq-api:$TAG From eddf456233d545515651c746172895cc4c901f3d Mon Sep 17 00:00:00 2001 From: Al-Abd Date: Sun, 23 Feb 2025 17:27:53 +0330 Subject: [PATCH 27/31] publish latest on main branch only --- .github/workflows/docker-publish.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8b3a17a..c9ad1b4 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -24,12 +24,20 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + - name: Set Docker tags + id: set_tags + run: | + base_tag="${{ secrets.DOCKER_HUB_USERNAME }}/nq-api" + if [[ "${GITHUB_REF##*/}" == "main" ]]; then + echo "tags=${base_tag}:latest" >> $GITHUB_ENV + else + echo "tags=${base_tag}:${GITHUB_REF##*/}" >> $GITHUB_ENV + fi + - name: Build and push uses: docker/build-push-action@v3 with: context: . file: ./Dockerfile push: true - tags: | - ${{ secrets.DOCKER_HUB_USERNAME }}/nq-api:latest - ${{ secrets.DOCKER_HUB_USERNAME }}/nq-api:${{ github.ref_name }} + tags: ${{ env.tags }} From 81cbebc0579060604eb9bfc8cc082e5d37181404 Mon Sep 17 00:00:00 2001 From: silence0ne Date: Sat, 8 Mar 2025 13:07:19 +0330 Subject: [PATCH 28/31] Routers ayah updated --- open-api.json | 140 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 118 insertions(+), 22 deletions(-) diff --git a/open-api.json b/open-api.json index f583a8c..47084a3 100644 --- a/open-api.json +++ b/open-api.json @@ -1265,10 +1265,34 @@ "description": "Full text of the ayah" }, "words": { - "type": "string", + "type": "array", "nullable": false, + "items": { + "type": "string", + "example": "In", + "description": "A word in the ayah" + }, "example": ["In", "the", "name", "of", "Allah", "..."], "description": "List of words contained in the ayah" + }, + "breakers": { + "description": "List of breakers for the ayah, if any", + "type": "array", + "nullable": true, + "items": { + "description": "List of breakers associated with the ayah", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the breaker" + }, + "number": { + "type": "integer", + "description": "The occurrence number of the breaker" + } + } + } } }, "required": ["number", "uuid", "sajdah", "text", "words"] @@ -1293,9 +1317,20 @@ "nullable": false, "description": "The text of the ayah.", "example": "In the name of Allah, the Most Gracious, the Most Merciful." + }, + "is_bismillah": { + "type": "boolean", + "nullable": false, + "description": "Indicates if the ayah is Bismillah." + }, + "bismillah_text": { + "type": "string", + "nullable": true, + "description": "The text of Bismillah if applicable.", + "example": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ" } }, - "required": ["surah_uuid", "text"] + "required": ["surah_uuid", "text", "is_bismillah"] }, "AyahViewResponseData": { "type": "object", @@ -1303,7 +1338,6 @@ "uuid": { "type": "string", "format": "uuid", - "example": "uuid-of-ayah", "description": "Unique identifier for the ayah" }, "mushaf": { @@ -1313,23 +1347,64 @@ "description": "Unique identifier for the mushaf" }, "surah": { - "type": "string", - "format": "uuid", - "example": "uuid-of-surah", - "description": "Unique identifier for the surah" + "type": "object", + "properties": { + "uuid": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the surah" + }, + "names": { + "type": "array", + "description": "List of surah names in different languages", + "items": { + "type": "object", + "properties": { + "arabic": { + "type": "string", + "example": "الفاتحة", + "description": "Arabic name of the surah" + }, + "translation": { + "type": "string", + "nullable": true, + "description": "Translation of the surah name in the selected language" + }, + "translation_phrase": { + "type": "string", + "nullable": true, + "description": "Phrase used for the translation of the surah name" + }, + "pronunciation": { + "type": "string", + "nullable": true, + "description": "Pronunciation of the surah name" + }, + "transliteration": { + "type": "string", + "nullable": true, + "description": "Transliteration of the surah name" + } + }, + "required": ["arabic"] + } + } + }, + "description": "Details of the surah associated with the ayah" }, "ayah_number": { "type": "integer", - "description": "Ayah number within the surah54" + "description": "Ayah number within the surah" }, "sajdah": { "type": "string", "enum": ["vajib", "mostahab"], + "nullable": true, "description": "Indicates whether the ayah has a sajdah" }, "text": { "type": "string", - "example": "هُدًى وَبُشْرَىٰ لِلْمُؤْمِنِينَ", + "example": "الٓمٓ", "description": "The full text of the ayah" }, "words": { @@ -1345,7 +1420,7 @@ }, "word": { "type": "string", - "example": "هُدًى", + "example": "الٓمٓ", "description": "The word text" } }, @@ -1370,16 +1445,36 @@ "type": "integer", "format": "int64", "nullable": false, - "description": "Number of ayah" + "description": "Number of ayah", + "example": 5 }, - "sajdeh": { + "sajdah": { "type": "string", - "nullable": false, + "nullable": true, "enum": ["mostahab", "vajib"], - "example": "vajib | mustahab | null", - "description": "Ayah have sajdeh or no" + "example": "vajib", + "description": "Ayah has sajdah or not" + }, + "bismillah": { + "type": "object", + "nullable": true, + "properties": { + "is_ayah": { + "type": "boolean", + "nullable": false, + "description": "Indicates whether the ayah contains Bismillah", + "example": true + }, + "text": { + "type": "string", + "nullable": true, + "description": "The optional text for Bismillah in the ayah", + "example": "In the name of Allah" + } + } } - } + }, + "required": ["ayah_number"] }, "WordAddRequestData": { "type": "object", @@ -3340,7 +3435,7 @@ "in": "query", "required": false, "name": "format", - "description": "The format of the ayahs.", + "description": "The format in which the ayahs should be returned. Possible values: 'text' (plain text) or 'word' (word by word).", "schema": { "type": "string", "enum": ["text", "word"] @@ -3350,7 +3445,7 @@ "in": "query", "required": false, "name": "sort", - "description": "Sort the list by the specified field.", + "description": "The field by which the list of ayahs should be sorted. Possible values: 'number', 'createTime', or 'updateTime'.", "schema": { "type": "string", "enum": ["number", "createTime", "updateTime"] @@ -3360,7 +3455,7 @@ "in": "query", "required": false, "name": "order", - "description": "Order of the sorting.", + "description": "Order of the sorting. Possible values: 'asc' (ascending) or 'desc' (descending).", "schema": { "type": "string", "enum": ["asc", "desc"] @@ -3370,7 +3465,7 @@ "in": "query", "required": false, "name": "from", - "description": "Starting point of the list (pagination).", + "description": "The starting index for pagination (used to limit the number of ayahs returned).", "schema": { "type": "integer", "format": "int64" @@ -3380,7 +3475,7 @@ "in": "query", "required": false, "name": "to", - "description": "Ending point of the list (pagination).", + "description": "The ending index for pagination (used to limit the number of ayahs returned).", "schema": { "type": "integer", "format": "int64" @@ -3448,7 +3543,8 @@ "required": true, "name": "ayah_uuid", "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], From e4e4f1201eacc34d0627eda1f41b871fd52e854b Mon Sep 17 00:00:00 2001 From: silence0ne Date: Sat, 8 Mar 2025 16:51:02 +0330 Subject: [PATCH 29/31] Router mushaf,surah,word, translation --- open-api.json | 363 ++++++++++++++++++++++++-------------------------- 1 file changed, 172 insertions(+), 191 deletions(-) diff --git a/open-api.json b/open-api.json index 47084a3..33bed06 100644 --- a/open-api.json +++ b/open-api.json @@ -918,10 +918,13 @@ "uuid": { "type": "string", "format": "uuid", + "nullable": false, "description": "Unique identifier for the surah." }, "number": { "type": "integer", + "format": "int32", + "nullable": false, "description": "Surah number." }, "period": { @@ -949,20 +952,40 @@ }, "translation_phrase": { "type": "string", + "nullable": true, "description": "A phrase that translates the meaning of the surah." }, "translation": { "type": "string", + "nullable": true, "description": "Translation of the surah name." }, "transliteration": { "type": "string", + "nullable": true, "description": "Transliteration of the surah name." } - } + }, + "required": ["arabic"] + } + }, + "search_terms": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "description": "Search terms associated with the surah." } } - } + }, + "required": [ + "uuid", + "number", + "period", + "number_of_ayahs", + "names", + "search_terms" + ] } }, "SurahAddRequestData": { @@ -971,47 +994,42 @@ "name": { "type": "string", "description": "The surah name.", - "example": "الفاتحة" + "example": "الفاتحة", + "nullable": false }, "period": { "type": "string", "description": "Indicates whether the surah is Makki or Madani.", - "example": "makki" + "example": "makki", + "nullable": false }, "number": { "type": "number", "description": "The number of the surah in the Mushaf.", - "example": 1 + "nullable": false }, "mushaf_uuid": { "type": "string", "description": "The UUID of the Mushaf in which the surah belongs.", - "example": "f9339c7a-749a-408e-a03e-a22cd87fe3a1" - }, - "bismillah_status": { - "type": "boolean", - "description": "Determines whether Bismillah exists in the surah.", - "example": true - }, - "bismillah_as_first_ayah": { - "type": "boolean", - "description": "Determines if Bismillah is the first ayah of the surah.", - "example": false + "nullable": false }, "name_translation_phrase": { "type": "string", "description": "The translation phrase for the surah name in the desired language.", - "example": "Al-Fatiha" + "example": "Al-Fatiha", + "nullable": true }, "name_pronunciation": { "type": "string", "description": "The pronunciation of the surah name in Arabic.", - "example": "Al-Fatiha" + "example": "Al-Fatiha", + "nullable": true }, "name_transliteration": { "type": "string", "description": "The transliteration of the surah name from Arabic to Latin.", - "example": "Al-Fatiha" + "example": "Al-Fatiha", + "nullable": true } }, "required": ["name", "period", "number", "mushaf_uuid"] @@ -1019,19 +1037,12 @@ "SurahViewResponseData": { "type": "object", "properties": { - "uuid": { - "type": "string", - "format": "uuid", - "nullable": false, - "description": "UUID of the surah" - }, "mushaf": { "type": "object", "properties": { "uuid": { "type": "string", "format": "uuid", - "nullable": false, "description": "UUID of the mushaf", "example": "f9339c7a-749a-408e-a03e-a22cd87fe3a1" }, @@ -1050,7 +1061,8 @@ "description": "Source of the mushaf", "example": "tanzil" } - } + }, + "required": ["uuid"] }, "names": { "type": "array", @@ -1082,92 +1094,128 @@ "description": "Transliteration of the surah name", "example": "Al-Fātiḥa" } - } + }, + "required": ["arabic"] } }, "period": { "type": "string", "enum": ["makki", "madani"], "description": "Period of the surah (e.g., Makki or Madani)", - "example": "Makki" + "example": "makki" }, "number": { "type": "integer", - "format": "int64", - "example": 1, - "description": "Surah number" - }, - "bismillah_status": { - "type": "boolean", - "description": "Indicates if the surah contains 'Bismillah'", - "example": true - }, - "bismillah_as_first_ayah": { - "type": "boolean", - "description": "Indicates if 'Bismillah' is the first ayah of the surah", - "example": true + "description": "Surah number", + "example": 1 }, - "bismillah_text": { - "type": "string", - "description": "Text of 'Bismillah' if it is the first ayah", - "example": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ" + "bismillah": { + "type": "object", + "description": "Bismillah information (if present)", + "properties": { + "is_first_ayah": { + "type": "boolean", + "description": "Indicates if 'Bismillah' is the first ayah of the surah", + "example": true + }, + "text": { + "type": "string", + "description": "Text of 'Bismillah'", + "example": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ" + } + }, + "required": ["is_first_ayah", "text"] }, "number_of_ayahs": { "type": "integer", "description": "Number of ayahs in the surah", "example": 7 }, + "search_terms": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Search terms for the surah" + }, "ayahs": { "type": "array", + "description": "List of ayahs in the surah", "items": { - "type": "object", - "properties": { - "number": { - "type": "integer", - "format": "int64", - "nullable": false, - "example": 1, - "description": "Ayah number in the surah" - }, - "uuid": { - "type": "string", - "format": "uuid", - "nullable": false, - "description": "UUID of the ayah" - }, - "sajdah": { - "type": "string", - "enum": ["vajib", "mostahab"], - "nullable": true, - "description": "Indicates if the ayah has sajdah" - }, - "text": { - "type": "string", - "nullable": false, - "description": "Text of the ayah (if format is 'text')", - "example": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ" + "oneOf": [ + { + "type": "object", + "properties": { + "number": { + "type": "integer", + "description": "Ayah number in the surah", + "example": 1 + }, + "uuid": { + "type": "string", + "format": "uuid", + "description": "UUID of the ayah" + }, + "sajdah": { + "type": "string", + "enum": ["vajib", "mostahab"], + "nullable": true, + "description": "Indicates if the ayah has sajdah" + }, + "text": { + "type": "string", + "description": "Text of the ayah", + "example": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ" + } + }, + "required": ["number", "uuid", "text"] }, - "words": { - "type": "string", - "nullable": false, - "example": ["بِسْمِ", "اللَّهِ", "الرَّحْمَنِ", "الرَّحِيمِ"], - "description": "Words of the ayah" + { + "type": "object", + "properties": { + "number": { + "type": "integer", + "description": "Ayah number in the surah", + "example": 1 + }, + "uuid": { + "type": "string", + "format": "uuid", + "description": "UUID of the ayah" + }, + "sajdah": { + "type": "string", + "enum": ["vajib", "mostahab"], + "nullable": true, + "description": "Indicates if the ayah has sajdah" + }, + "words": { + "type": "array", + "description": "Words of the ayah", + "items": { + "type": "string" + }, + "example": [ + "بِسْمِ", + "اللَّهِ", + "الرَّحْمَنِ", + "الرَّحِيمِ" + ] + } + }, + "required": ["number", "uuid", "words"] } - }, - "required": ["number", "uuid", "sajdah", "text", "words"] + ] } } }, "required": [ - "uuid", "mushaf", "names", "period", "number", - "bismillah_status", - "bismillah_as_first_ayah", - "bismillah_text", "number_of_ayahs", + "search_terms", "ayahs" ] }, @@ -1206,36 +1254,27 @@ }, "number": { "type": "integer", - "format": "int64", + "format": "int32", "nullable": false, "description": "The surah number." }, - "bismillah_status": { - "type": "boolean", - "nullable": false, - "description": "Determines if Bismillah is present in the surah.", - "example": true - }, - "bismillah_as_first_ayah": { - "type": "boolean", - "nullable": false, - "description": "Indicates if Bismillah is treated as the first ayah.", - "example": false - }, "mushaf_uuid": { "type": "string", "format": "uuid", "nullable": false, "description": "The UUID of the Mushaf associated with the surah." + }, + "search_terms": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "description": "Search terms related to the surah." + }, + "description": "Optional list of search terms associated with the surah." } }, - "required": [ - "name", - "number", - "bismillah_status", - "bismillah_as_first_ayah", - "mushaf_uuid" - ] + "required": ["name", "number", "mushaf_uuid"] }, "AyahListResponseData": { "type": "object", @@ -1497,19 +1536,6 @@ "WordViewResponseData": { "type": "object", "properties": { - "uuid": { - "type": "string", - "format": "uuid", - "nullable": false, - "description": "Unique identifier for the word" - }, - "creator_user_id": { - "type": "integer", - "format": "int64", - "nullable": false, - "example": "1", - "description": "ID of the user who created the word" - }, "word": { "type": "string", "nullable": false, @@ -1567,25 +1593,16 @@ "description": "Indicates whether the translation content is approved", "example": true }, - "bismillah": { - "type": "string", - "nullable": true, - "description": "Translated Bismillah text", - "example": "In the name of Allah, the Most Gracious, the Most Merciful." - }, "translator": { "type": "object", "properties": { "account_uuid": { "type": "string", "format": "uuid", - "nullable": false, - "description": "Unique identifier of the translator's account", - "example": "f1d1e3b5-55a9-4f9b-96a1-8d3e8b7d9a27" + "description": "Unique identifier of the translator's account" }, "username": { "type": "string", - "nullable": false, "description": "Username of the translator", "example": "translator123" }, @@ -1602,12 +1619,7 @@ "example": "Doe" } }, - "required": [ - "account_uuid", - "username", - "first_name", - "last_name" - ] + "required": ["account_uuid", "username"] } }, "required": [ @@ -1616,7 +1628,6 @@ "release_date", "source", "approved", - "bismillah", "translator" ] } @@ -1664,7 +1675,6 @@ "mushaf_uuid": { "type": "string", "format": "uuid", - "nullable": false, "description": "Unique identifier of the mushaf" }, "language": { @@ -1691,24 +1701,17 @@ "nullable": false, "description": "Translation status" }, - "bismillah": { - "type": "string", - "nullable": false, - "description": "Translated Bismillah text", - "example": "In the name of Allah, the Most Gracious, the Most Merciful." - }, "translator": { "type": "object", "properties": { "account_uuid": { "type": "string", "format": "uuid", - "nullable": false, - "description": "Unique identifier of the translator's account" + "description": "Unique identifier of the translator's account", + "example": "f1d1e3b5-55a9-4f9b-96a1-8d3e8b7d9a27" }, "username": { "type": "string", - "nullable": false, "description": "Username of the translator", "example": "translator123" }, @@ -1736,7 +1739,6 @@ "uuid": { "type": "string", "format": "uuid", - "nullable": false, "description": "Unique identifier of the ayah" }, "text_uuid": { @@ -1747,12 +1749,10 @@ }, "number": { "type": "integer", - "nullable": false, "description": "Ayah number within the surah" }, "surah_number": { "type": "integer", - "nullable": false, "description": "Surah number" }, "text": { @@ -1760,6 +1760,12 @@ "nullable": true, "description": "Translated text of the ayah", "example": "Praise be to Allah, the Lord of all worlds." + }, + "bismillah": { + "type": "string", + "nullable": true, + "description": "Translated Bismillah text", + "example": "In the name of Allah, the Most Gracious, the Most Merciful." } }, "required": ["uuid", "number", "surah_number"] @@ -1771,7 +1777,6 @@ "language", "source", "status", - "bismillah", "translator", "ayahs" ] @@ -1802,47 +1807,35 @@ "nullable": true, "description": "Updated source of the translation", "example": "Tanzil" - }, - "bismillah": { - "type": "string", - "nullable": false, - "description": "Updated translated Bismillah text", - "example": "In the name of Allah, the Most Gracious, the Most Merciful." } }, - "required": ["language", "bismillah"] + "required": ["language"] }, - "TranslationTextViewResponseData": { + "TranslationAyahViewResponseData": { "type": "object", "properties": { "uuid": { "type": "string", "format": "uuid", - "nullable": false, - "description": "Unique identifier for the translation text" - }, - "translation_uuid": { - "type": "string", - "format": "uuid", - "nullable": false, - "description": "UUID of the translation to which this text belongs" + "description": "Unique identifier for the translation ayah" }, - "ayah_uuid": { + "text": { "type": "string", - "format": "uuid", - "nullable": false, - "description": "UUID of the ayah this translation corresponds to" + "description": "Translation text for the ayah" }, - "text": { + "bismillah": { "type": "string", "nullable": true, - "description": "Translated text of the ayah", - "example": "Praise be to Allah, the Lord of all worlds." + "description": "Bismillah text for the translation ayah, if available" + }, + "has_bismillah": { + "type": "boolean", + "description": "Indicates whether the ayah originally had bismillah text" } }, - "required": ["uuid", "translation_uuid", "ayah_uuid", "text"] + "required": ["uuid", "text", "bismillah", " has_bismillah"] }, - "TranslationTextEditRequestData": { + "TranslationAyahEditRequestData": { "type": "object", "properties": { "text": { @@ -1851,26 +1844,14 @@ "example": "Praise be to Allah, the Lord of all worlds.", "description": "Updated or newly added translation text" }, - "translation_uuid": { - "type": "string", - "format": "uuid", - "nullable": false, - "description": "Unique identifier of the translation" - }, - "ayah_uuid": { + "bismillah": { "type": "string", - "format": "uuid", - "nullable": false, - "description": "Unique identifier of the ayah being translated" - }, - "creator_user_id": { - "type": "integer", - "format": "int64", - "nullable": false, - "description": "ID of the user modifying or adding the translation text" + "nullable": true, + "example": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ", + "description": "Bismillah text for the translation if applicable" } }, - "required": ["text", "translation_uuid", "ayah_uuid", "creator_user_id"] + "required": ["text"] }, "PhraseListResponseData": { "type": "array", @@ -4069,7 +4050,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TranslationTextViewResponseData" + "$ref": "#/components/schemas/TranslationAyahViewResponseData" } } } @@ -4098,7 +4079,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TranslationTextEditRequestData" + "$ref": "#/components/schemas/TranslationAyahEditRequestData" } } } From 10ef887d9ad97684a860ad40ce91ad7428d506bb Mon Sep 17 00:00:00 2001 From: silence0ne Date: Sat, 8 Mar 2025 16:53:01 +0330 Subject: [PATCH 30/31] Fixed bug --- open-api.json | 1 + 1 file changed, 1 insertion(+) diff --git a/open-api.json b/open-api.json index 33bed06..061aaa5 100644 --- a/open-api.json +++ b/open-api.json @@ -35,6 +35,7 @@ "properties": { "email": { "type": "string", + "format": "email", "description": "The email address" }, "code": { From 444c474222e79ed407a75adc3a9bc85406eb3d45 Mon Sep 17 00:00:00 2001 From: silence0ne Date: Sat, 8 Mar 2025 17:16:11 +0330 Subject: [PATCH 31/31] 'README.md'Updated. --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 07dc95a..a690015 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ -# nq-api -[![docker-publish](https://github.com/NatiqQuran/nq-api/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/NatiqQuran/nq-api/actions/workflows/docker-publish.yml) -[![Docker Image CI](https://github.com/NatiqQuran/nq-api/actions/workflows/docker-image.yml/badge.svg)](https://github.com/NatiqQuran/nq-api/actions/workflows/docker-image.yml) -[![Rust](https://github.com/NatiqQuran/nq-api/actions/workflows/rust.yml/badge.svg)](https://github.com/NatiqQuran/nq-api/actions/workflows/rust.yml) +# nq-api-rust + +[![docker-publish](https://github.com/NatiqQuran/nq-api-rust/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/NatiqQuran/nq-api-rust/actions/workflows/docker-publish.yml) +[![Docker Image CI](https://github.com/NatiqQuran/nq-api-rust/actions/workflows/docker-image.yml/badge.svg)](https://github.com/NatiqQuran/nq-api-rust/actions/workflows/docker-image.yml) +[![Rust](https://github.com/NatiqQuran/nq-api-rust/actions/workflows/rust.yml/badge.svg)](https://github.com/NatiqQuran/nq-api-rust/actions/workflows/rust.yml) Natiq Quran open API \ # Docker -Start nq-api with docker-compose +Start nq-api-rust with docker-compose ```bash sudo docker compose up @@ -22,7 +23,7 @@ cargo build --release # Run ```bash -./target/release/nq-api +./target/release/nq-api-rust ``` API will listen to 0.0.0.0:8080