Skip to content

Commit

Permalink
將歌曲移到後端
Browse files Browse the repository at this point in the history
  • Loading branch information
igncp committed Jul 6, 2024
1 parent 0ef7af3 commit aafd14b
Show file tree
Hide file tree
Showing 42 changed files with 455 additions and 558 deletions.
1 change: 1 addition & 0 deletions migrations/05_anki_unique_front/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP INDEX unique_front_user_id;
1 change: 1 addition & 0 deletions migrations/05_anki_unique_front/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE UNIQUE INDEX unique_front_user_id ON ankis(front, user_id);
1 change: 1 addition & 0 deletions migrations/06_songs/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE songs;
10 changes: 10 additions & 0 deletions migrations/06_songs/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE songs (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title VARCHAR(255) NOT NULL,
artist VARCHAR(255) NOT NULL,
language VARCHAR(255) NOT NULL,
video_url VARCHAR(255) NOT NULL,
lyrics TEXT NOT NULL
);

CREATE UNIQUE INDEX songs_title_artist_language ON songs (title, artist, language);
3 changes: 3 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"anki": {
"addNew": "Add new",
"backSide": "Back",
"clear": "Clear",
"close": "Close",
"copyChars": "Copy Characters",
"copyPronunciations": "Copy Pronunciations",
Expand All @@ -19,6 +20,7 @@
"previousPage": "Previous page",
"round": "Anki Round",
"save": "Save",
"saveCardFailed": "Save failed, probably it already exists",
"saveFailed": "Failed to save anki",
"startRound": "Start Round",
"togglePronunciation": "Toggle Pronunciation",
Expand Down Expand Up @@ -91,6 +93,7 @@
"close": "Close",
"created": "Created",
"edit": "Edit",
"filter": "Filter songs",
"lang": "Language",
"language": "Language",
"link": "Link",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"anki": {
"addNew": "Añadir nueva tarjeta",
"backSide": "Parte trasera",
"clear": "Limpiar",
"close": "Cerrar",
"copyChars": "Copiar caracteres",
"copyPronunciations": "Copiar pronunciaciones",
Expand All @@ -19,6 +20,7 @@
"previousPage": "Página anterior",
"round": "Ronda",
"save": "Guardar",
"saveCardFailed": "Error al guardar, probablemente ya existe",
"saveFailed": "Failed to save anki",
"startRound": "Empezar ronda",
"togglePronunciation": "Alternar pronunciación",
Expand Down Expand Up @@ -91,6 +93,7 @@
"close": "Cerrar",
"created": "Creado",
"edit": "Editar",
"filter": "Buscar canciones",
"lang": "Idioma",
"language": "Idioma",
"link": "Enlace",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/jp/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"anki": {
"addNew": "新しい Anki カードを追加",
"backSide": "背面",
"clear": "クリア",
"close": "關閉",
"copyChars": "複製文字字元",
"copyPronunciations": "複製文字發音",
Expand All @@ -19,6 +20,7 @@
"previousPage": "前のページ",
"round": "ラウンド",
"save": "保存",
"saveCardFailed": "保存失敗、おそらくすでに存在しています",
"saveFailed": "保存失敗",
"startRound": "開始 Anki 回合",
"togglePronunciation": "切換顯示發音",
Expand Down Expand Up @@ -91,6 +93,7 @@
"close": "閉じる",
"created": "作成",
"edit": "編集",
"filter": "フィルター",
"lang": "言語",
"language": "言語",
"link": "リンク",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/zh_hant/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"anki": {
"addNew": "添新",
"backSide": "背面",
"clear": "清除文字",
"close": "關閉",
"copyChars": "複製文字字元",
"copyPronunciations": "複製文字發音",
Expand All @@ -19,6 +20,7 @@
"previousPage": "上一頁",
"round": "回合",
"save": "保存",
"saveCardFailed": "保存失敗,可能已經存在",
"saveFailed": "保存失敗",
"startRound": "開始 Anki 回合",
"togglePronunciation": "切換顯示發音",
Expand Down Expand Up @@ -91,6 +93,7 @@
"close": "關閉",
"created": "創建",
"edit": "編輯",
"filter": "過濾",
"lang": "語言",
"language": "語言",
"link": "連結",
Expand Down
13 changes: 8 additions & 5 deletions src/backend/db/anki.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,18 @@ impl Anki {
.unwrap_or(None)
}

pub fn save(&self) {
pub fn save(&self) -> Result<(), ()> {
let connection = &mut establish_connection();

use super::schema::ankis::dsl::*;

diesel::insert_into(ankis)
.values(self)
.execute(connection)
.unwrap();
let result = diesel::insert_into(ankis).values(self).execute(connection);

if result.is_err() {
Err(())
} else {
Ok(())
}
}

pub fn delete(&self) {
Expand Down
3 changes: 2 additions & 1 deletion src/backend/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub use models::{Anki, Text, User};
pub use models::{Anki, Song, Text, User};
pub use utils::establish_connection;

mod anki;
mod models;
mod schema;
mod song;
mod text;
mod user;
mod utils;
12 changes: 11 additions & 1 deletion src/backend/db/models.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use diesel::{deserialize::Queryable, Insertable};
use serde::Serialize;

use super::schema::{ankis, texts, users};
use super::schema::{ankis, songs, texts, users};

#[derive(Serialize, Queryable, Insertable, Debug)]
pub struct User {
Expand Down Expand Up @@ -35,3 +35,13 @@ pub struct Anki {
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}

#[derive(Serialize, Queryable, Insertable, Debug)]
pub struct Song {
pub id: i32,
pub title: String,
pub artist: String,
pub language: String,
pub video_url: String,
pub lyrics: String,
}
12 changes: 12 additions & 0 deletions src/backend/db/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ diesel::table! {
}
}

diesel::table! {
songs (id) {
id -> Integer,
title -> Text,
artist -> Text,
language -> Text,
video_url -> Text,
lyrics -> Text,
}
}

diesel::table! {
texts (id) {
id -> Text,
Expand All @@ -41,6 +52,7 @@ diesel::joinable!(texts -> users (user_id));

diesel::allow_tables_to_appear_in_same_query!(
ankis,
songs,
texts,
users,
);
70 changes: 70 additions & 0 deletions src/backend/db/song.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use super::models::Song;
use super::utils::establish_connection;
use diesel::prelude::*;

impl Song {
fn get_query_filter(
lang: &str,
query: &Option<String>,
) -> Box<
dyn BoxableExpression<
super::schema::songs::table,
diesel::sqlite::Sqlite,
SqlType = diesel::sql_types::Bool,
>,
> {
use super::schema::songs::dsl::*;

if query.is_none() {
return Box::new(language.eq(lang.to_owned()));
}
let query = format!("%{}%", query.clone().unwrap());

let filter = artist.like(query.clone()).or(title.like(query.clone()));

Box::new(filter)
}

pub fn get_all(
lang: String,
items_number: i32,
offset: i32,
query: Option<String>,
) -> Vec<Self> {
let connection = &mut establish_connection();

use super::schema::songs::dsl::*;

songs
.filter(language.eq(&lang))
.filter(Self::get_query_filter(&lang, &query))
.limit(items_number.into())
.offset(offset.into())
.load::<Self>(connection)
.unwrap_or(Vec::new())
}

pub fn get_total(lang: String, query: Option<String>) -> i32 {
let connection = &mut establish_connection();

use super::schema::songs::dsl::*;

songs
.filter(Self::get_query_filter(&lang, &query))
.count()
.get_result(connection)
.unwrap_or(0) as i32
}

pub fn get_by_id(song_id: i32) -> Option<Self> {
let connection = &mut establish_connection();

use super::schema::songs::dsl::*;

songs
.filter(id.eq(song_id))
.first(connection)
.optional()
.unwrap_or(None)
}
}
35 changes: 32 additions & 3 deletions src/backend/gql/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use self::context::GraphQLContext;
use crate::backend::{
db::{Anki, Text},
gql::models::{AnkiGQL, Me, TextGQL, TranslationRequest},
db::{Anki, Song, Text},
gql::models::{AnkiGQL, Me, SongGQL, TextGQL, TranslationRequest},
};
use juniper::{EmptySubscription, FieldResult, RootNode};
use tracing::debug;
Expand Down Expand Up @@ -87,6 +87,31 @@ impl QueryRoot {
Ok(ankis_gql)
}

fn songs(
lang: String,
items_num: Option<i32>,
offset: Option<i32>,
query: Option<String>,
) -> FieldResult<Vec<SongGQL>> {
let songs = Song::get_all(lang, items_num.unwrap_or(10), offset.unwrap_or(0), query);
let songs_gql = songs.iter().map(SongGQL::from_db).collect::<Vec<SongGQL>>();

Ok(songs_gql)
}

fn song(id: i32) -> FieldResult<Option<SongGQL>> {
let song = Song::get_by_id(id);
let song_parsed = song.map(|s| SongGQL::from_db(&s));

Ok(song_parsed)
}

fn songs_total(lang: String, query: Option<String>) -> FieldResult<i32> {
let songs_total = Song::get_total(lang, query);

Ok(songs_total)
}

async fn translation_request(
ctx: &GraphQLContext,
content: String,
Expand Down Expand Up @@ -124,7 +149,11 @@ impl MutationRoot {
if anki.front.is_empty() {
anki.delete();
} else {
anki.save();
let result = anki.save();

if result.is_err() {
return Err("Could not save the record".into());
}
}

Ok(AnkiGQL::from_db(&anki))
Expand Down
25 changes: 24 additions & 1 deletion src/backend/gql/models.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::backend::{
db::{Anki, Text},
db::{Anki, Song, Text},
translation::translate_text,
};
use juniper::GraphQLObject;
Expand Down Expand Up @@ -42,6 +42,16 @@ pub struct TranslationRequest {
current_language: String,
}

#[derive(GraphQLObject)]
pub struct SongGQL {
artist: String,
id: i32,
language: String,
lyrics: String,
title: String,
video_url: String,
}

impl Me {
pub fn new(id: &str, email: &str, can_use_ai: bool) -> Self {
Self {
Expand Down Expand Up @@ -77,6 +87,19 @@ impl AnkiGQL {
}
}

impl SongGQL {
pub fn from_db(song: &Song) -> Self {
Self {
artist: song.artist.to_string(),
id: song.id,
language: song.language.to_string(),
lyrics: song.lyrics.to_string(),
title: song.title.to_string(),
video_url: song.video_url.to_string(),
}
}
}

impl TranslationRequest {
pub fn new(content: &str, current_language: &str) -> Self {
Self {
Expand Down
3 changes: 2 additions & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use chrono::{Duration, Utc};
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use jsonwebtoken::{encode, EncodingKey, Header};
use juniper::http::{graphiql::graphiql_source, GraphQLRequest};
use tracing::{debug, warn};
use tracing::{debug, info, warn};
use uuid::Uuid;

use crate::backend::{
Expand Down Expand Up @@ -179,6 +179,7 @@ pub async fn start_backend() -> std::io::Result<()> {

let connection = &mut db::establish_connection();
connection.run_pending_migrations(MIGRATIONS).unwrap();
info!("Migrations completed");

warn!("Starting the Writing Trainer HTTP server on port http://{address}:{port}");

Expand Down
Loading

0 comments on commit aafd14b

Please sign in to comment.