mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 21:38:07 -05:00
Compare commits
77
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5971d95a80 | ||
|
|
602de6d736 | ||
|
|
de8eb05db6 | ||
|
|
996f8ce05b | ||
|
|
b4afec5c26 | ||
|
|
ab1f81036f | ||
|
|
4a806e7d67 | ||
|
|
c811296bdc | ||
|
|
6033289a36 | ||
|
|
90ec14b8d0 | ||
|
|
e18b86a55a | ||
|
|
6c320dd329 | ||
|
|
fd95aaff8c | ||
|
|
8afd10c864 | ||
|
|
0e62fe9d08 | ||
|
|
dda2e0840d | ||
|
|
b26276cfda | ||
|
|
eedbc346fe | ||
|
|
7976f68fd0 | ||
|
|
f327dfcdbb | ||
|
|
f4176bf84a | ||
|
|
43b6808f23 | ||
|
|
330f24413d | ||
|
|
af6370eea1 | ||
|
|
3a4ca7b548 | ||
|
|
f7d5ad496c | ||
|
|
8a6678c7f5 | ||
|
|
f76928d001 | ||
|
|
32cfb10323 | ||
|
|
d9b1c8c36b | ||
|
|
fc122cb996 | ||
|
|
08d3c389b9 | ||
|
|
1a3b02b5d2 | ||
|
|
e0e85fed5f | ||
|
|
092745166e | ||
|
|
024b4d769c | ||
|
|
ea859bfc1e | ||
|
|
92e0b1e9f4 | ||
|
|
d52d3f993a | ||
|
|
0033af73ce | ||
|
|
514f80b884 | ||
|
|
74c548c02f | ||
|
|
5fe09a182f | ||
|
|
4856ac28aa | ||
|
|
404853e129 | ||
|
|
b5fcc3cdfa | ||
|
|
300ac56ab7 | ||
|
|
e32f8094e5 | ||
|
|
e986a44e9d | ||
|
|
642e17a77d | ||
|
|
36f3003576 | ||
|
|
4993410740 | ||
|
|
f99b5a92b8 | ||
|
|
b9f604dd18 | ||
|
|
130e0daa08 | ||
|
|
e6f5ecb980 | ||
|
|
2e3ff8a730 | ||
|
|
cda690773f | ||
|
|
91d0a1da8f | ||
|
|
8c7b100150 | ||
|
|
ac13be2900 | ||
|
|
b55435d992 | ||
|
|
28770ef736 | ||
|
|
ae5eea53fe | ||
|
|
894084fba6 | ||
|
|
241f648baf | ||
|
|
e4756a4f2c | ||
|
|
9c8ee8dbbb | ||
|
|
8072d13596 | ||
|
|
1d937ab981 | ||
|
|
496ccd68f1 | ||
|
|
72fdd75568 | ||
|
|
fba7d2a1eb | ||
|
|
347fe685cd | ||
|
|
32331f9890 | ||
|
|
65d6f178bc | ||
|
|
d9d166e500 |
@@ -75,4 +75,5 @@ TTS_HIFIGAN_SUPERRES_VOCODER_MODEL_FILENAME=hifigan_superres_twilight_33000.pt
|
||||
|
||||
# Development key. Permissible to check in.
|
||||
NEWRELIC_API_KEY=c402be1c4c4216ec83d0cfc0851520cfFFFFNRAL
|
||||
STORYTELLER_ROOT="/home/tensor/code/storyteller/"
|
||||
|
||||
#STORYTELLER_ROOT="/home/tensor/code/storyteller/" # Put this in .env-secrets so that not everyone gets this setting.
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::favorites::FavoriteToken`,\n\n f.entity_type as `entity_type: enums::by_table::favorites::favorite_entity_type::FavoriteEntityType`,\n f.entity_token,\n\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n\n f.created_at,\n f.updated_at,\n f.deleted_at\n\nFROM\n favorites AS f\nJOIN users AS u\n ON f.user_token = u.token\nWHERE\n f.token = ?\n ",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::user_bookmarks::UserBookmarkToken`,\n\n f.entity_type as `entity_type: enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType`,\n f.entity_token,\n\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n\n f.created_at,\n f.updated_at,\n f.deleted_at\n\nFROM\n user_bookmarks AS f\nJOIN users AS u\n ON f.user_token = u.token\nWHERE\n f.token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::favorites::FavoriteToken",
|
||||
"name": "token: tokens::tokens::user_bookmarks::UserBookmarkToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "entity_type: enums::by_table::favorites::favorite_entity_type::FavoriteEntityType",
|
||||
"name": "entity_type: enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -120,5 +120,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "f1ef63978793e7da5bd5e1a486254dd436db8021c8f049efa41f43cf7ce75f1d"
|
||||
"hash": "02136088e16742de2154cd9e84eeebbdb76045ad26aeb1c517a54c296bf31087"
|
||||
}
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::favorites::FavoriteToken`,\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n\n f.created_at,\n f.updated_at,\n f.deleted_at\n\nFROM\n favorites AS f\nJOIN users AS u\n ON f.user_token = u.token\nWHERE\n f.entity_type = ?\n AND f.entity_token = ?\n AND f.deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT 50\n ",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::user_bookmarks::UserBookmarkToken`,\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n\n f.created_at,\n f.updated_at,\n f.deleted_at\n\nFROM\n user_bookmarks AS f\nJOIN users AS u\n ON f.user_token = u.token\nWHERE\n f.entity_type = ?\n AND f.entity_token = ?\n AND f.deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT 50\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::favorites::FavoriteToken",
|
||||
"name": "token: tokens::tokens::user_bookmarks::UserBookmarkToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -98,5 +98,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "99cff649bf75f5b05330e7db8536ecc832affbae7c9710e158099079609e5e16"
|
||||
"hash": "1c1ef2195e81362d0eb023ede236c6fa65ede80d9efcaa4996694ce32c12cc0c"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n UPDATE model_weights\n SET\n title = ?,\n description_markdown = ?,\n maybe_thumbnail_token = ?,\n description_rendered_html = ?,\n creator_set_visibility = ?,\n version = version + 1\n WHERE token = ?\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 6
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4ed42766cc0ca2234b7bc1837d645d05198d483564b39a2a8b8034df25e287a4"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nUPDATE user_bookmarks\nSET\ndeleted_at = CURRENT_TIMESTAMP,\nversion = version + 1\nWHERE\ntoken = ?\nAND user_token = ?\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "576e5a72e385d44a1e53dc473dd0b5a04e33d7c6b9c38bef96f275b064a12386"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nUPDATE favorites\nSET\ndeleted_at = CURRENT_TIMESTAMP,\nversion = version + 1\nWHERE\ntoken = ?\nAND user_token = ?\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6a9fc0a3d983eb1d2bdf7d4c80904d73b9f4a649098fc0ba78cbc20cfde12437"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO favorites\nSET\n token = ?,\n user_token = ?,\n entity_type = ?,\n entity_token = ?\n\nON DUPLICATE KEY UPDATE\n deleted_at = NULL,\n version = version + 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "72eaa9124662acf0ed354b868fcdfe33c94b61046c30940f55cdc73789f94041"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n UPDATE model_weights\n SET\n title = COALESCE(?, title),\n description_markdown = COALESCE(?, description_markdown),\n maybe_thumbnail_token = COALESCE(?, maybe_thumbnail_token),\n description_rendered_html = COALESCE(?, description_rendered_html),\n creator_set_visibility = COALESCE(?, creator_set_visibility),\n version = version + 1\n WHERE token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 6
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "81df77a84fee48398e8a07e053b0393a0e341caf652c18c7160dd0a59247a19a"
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::favorites::FavoriteToken`,\n f.entity_type as `entity_type: enums::by_table::favorites::favorite_entity_type::FavoriteEntityType`,\n f.entity_token,\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n f.created_at,\n f.updated_at,\n f.deleted_at,\n\n media_files.media_type as `maybe_media_file_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n media_files.origin_product_category as `maybe_media_file_origin_category: enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory`,\n\n tts_models.title as maybe_descriptive_text_tts_model_title,\n tts_results.raw_inference_text as maybe_descriptive_text_tts_result_inference_text,\n users.display_name as maybe_descriptive_text_user_display_name,\n voice_conversion_models.title as maybe_descriptive_text_voice_conversion_model_title,\n zs_voices.title as maybe_descriptive_text_zs_voice_title\n\nFROM\n favorites AS f\nJOIN users AS u\n ON f.user_token = u.token\n\nLEFT OUTER JOIN media_files ON media_files.token = f.entity_token\nLEFT OUTER JOIN tts_models ON tts_models.token = f.entity_token\nLEFT OUTER JOIN tts_results ON tts_results.token = f.entity_token\nLEFT OUTER JOIN users ON users.token = f.entity_token\nLEFT OUTER JOIN voice_conversion_models ON voice_conversion_models.token = f.entity_token\nLEFT OUTER JOIN zs_voices ON zs_voices.token = f.entity_token\n\nWHERE\n u.username = ?\n AND f.entity_type = ?\n AND f.deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT 50\n ",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::user_bookmarks::UserBookmarkToken`,\n f.entity_type as `entity_type: enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType`,\n f.entity_token,\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n f.created_at,\n f.updated_at,\n f.deleted_at,\n\n media_files.media_type as `maybe_media_file_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n media_files.origin_product_category as `maybe_media_file_origin_category: enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory`,\n\n tts_models.title as maybe_descriptive_text_tts_model_title,\n tts_results.raw_inference_text as maybe_descriptive_text_tts_result_inference_text,\n users.display_name as maybe_descriptive_text_user_display_name,\n voice_conversion_models.title as maybe_descriptive_text_voice_conversion_model_title,\n zs_voices.title as maybe_descriptive_text_zs_voice_title\n\nFROM\n user_bookmarks AS f\nJOIN users AS u\n ON f.user_token = u.token\n\nLEFT OUTER JOIN media_files ON media_files.token = f.entity_token\nLEFT OUTER JOIN tts_models ON tts_models.token = f.entity_token\nLEFT OUTER JOIN tts_results ON tts_results.token = f.entity_token\nLEFT OUTER JOIN users ON users.token = f.entity_token\nLEFT OUTER JOIN voice_conversion_models ON voice_conversion_models.token = f.entity_token\nLEFT OUTER JOIN zs_voices ON zs_voices.token = f.entity_token\n\nWHERE\n u.username = ?\n AND f.entity_type = ?\n AND f.deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT 50\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::favorites::FavoriteToken",
|
||||
"name": "token: tokens::tokens::user_bookmarks::UserBookmarkToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "entity_type: enums::by_table::favorites::favorite_entity_type::FavoriteEntityType",
|
||||
"name": "entity_type: enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -197,5 +197,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "4214d8e86b81eb0138a34702ce12960ee007ca602a7bd64b68924515f8fbb038"
|
||||
"hash": "d9c00b3c78ed6ec31b281c7ea5fb1efd0cfa6b20899151f9e7f1a122c1f7a70e"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO user_bookmarks\nSET\n token = ?,\n user_token = ?,\n entity_type = ?,\n entity_token = ?\n\nON DUPLICATE KEY UPDATE\n deleted_at = NULL,\n version = version + 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "e8f3bb68896d316498b52fdaaf4c352624b79bd4e097f57db5ad59f53fd66995"
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::favorites::FavoriteToken`,\n f.entity_type as `entity_type: enums::by_table::favorites::favorite_entity_type::FavoriteEntityType`,\n f.entity_token,\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n f.created_at,\n f.updated_at,\n f.deleted_at,\n\n media_files.media_type as `maybe_media_file_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n media_files.origin_product_category as `maybe_media_file_origin_category: enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory`,\n\n tts_models.title as maybe_descriptive_text_tts_model_title,\n tts_results.raw_inference_text as maybe_descriptive_text_tts_result_inference_text,\n users.display_name as maybe_descriptive_text_user_display_name,\n voice_conversion_models.title as maybe_descriptive_text_voice_conversion_model_title,\n zs_voices.title as maybe_descriptive_text_zs_voice_title\n\nFROM\n favorites AS f\nJOIN users AS u\n ON f.user_token = u.token\n\nLEFT OUTER JOIN media_files ON media_files.token = f.entity_token\nLEFT OUTER JOIN tts_models ON tts_models.token = f.entity_token\nLEFT OUTER JOIN tts_results ON tts_results.token = f.entity_token\nLEFT OUTER JOIN users ON users.token = f.entity_token\nLEFT OUTER JOIN voice_conversion_models ON voice_conversion_models.token = f.entity_token\nLEFT OUTER JOIN zs_voices ON zs_voices.token = f.entity_token\n\nWHERE\n u.username = ?\n AND f.deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT 50\n ",
|
||||
"query": "\nSELECT\n f.token as `token: tokens::tokens::user_bookmarks::UserBookmarkToken`,\n f.entity_type as `entity_type: enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType`,\n f.entity_token,\n f.user_token as `user_token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name as user_display_name,\n u.email_gravatar_hash as user_gravatar_hash,\n f.created_at,\n f.updated_at,\n f.deleted_at,\n\n media_files.media_type as `maybe_media_file_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n media_files.origin_product_category as `maybe_media_file_origin_category: enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory`,\n\n tts_models.title as maybe_descriptive_text_tts_model_title,\n tts_results.raw_inference_text as maybe_descriptive_text_tts_result_inference_text,\n users.display_name as maybe_descriptive_text_user_display_name,\n voice_conversion_models.title as maybe_descriptive_text_voice_conversion_model_title,\n zs_voices.title as maybe_descriptive_text_zs_voice_title\n\nFROM\n user_bookmarks AS f\nJOIN users AS u\n ON f.user_token = u.token\n\nLEFT OUTER JOIN media_files ON media_files.token = f.entity_token\nLEFT OUTER JOIN tts_models ON tts_models.token = f.entity_token\nLEFT OUTER JOIN tts_results ON tts_results.token = f.entity_token\nLEFT OUTER JOIN users ON users.token = f.entity_token\nLEFT OUTER JOIN voice_conversion_models ON voice_conversion_models.token = f.entity_token\nLEFT OUTER JOIN zs_voices ON zs_voices.token = f.entity_token\n\nWHERE\n u.username = ?\n AND f.deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT 50\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::favorites::FavoriteToken",
|
||||
"name": "token: tokens::tokens::user_bookmarks::UserBookmarkToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "entity_type: enums::by_table::favorites::favorite_entity_type::FavoriteEntityType",
|
||||
"name": "entity_type: enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -197,5 +197,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "c33f8df5a9ed1991366d6078460d9e936a5470d1794ea319d6cf19b0f5338fd4"
|
||||
"hash": "eea9531d5261833b93baadee8b99449362c074fc2397e23ecd175b6a0425b16b"
|
||||
}
|
||||
Generated
+637
-214
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -86,8 +86,9 @@ members = [
|
||||
"crates/service/plugins/users",
|
||||
|
||||
# Vendored code
|
||||
"crates/vendor/limitation",
|
||||
"crates/vendor/newrelic-telemetry-sdk-rust",
|
||||
|
||||
# Vendored code
|
||||
"my-workspace-hack",
|
||||
# cargo-hakari workspace hack (compilation speedup hack)
|
||||
"crates/my-workspace-hack",
|
||||
]
|
||||
|
||||
@@ -29,7 +29,9 @@ Web API Overview
|
||||
* `tts-inference-job` - (*deprecated*) Async TTS inference of Tacotron2 models only
|
||||
* `w2l-download-job` - (*deprecated*) Async download of videos and images
|
||||
* `w2l-inference-job` - (*deprecated*) Async W2L inference
|
||||
|
||||
* Documentation Server:
|
||||
* `docs` - this will run a local swagger server with the endpoints that you have access to, http://127.0.0.1:8989/api-docs/openapi.json use this to port everything over to the post man.
|
||||
|
||||
### PowerStream
|
||||
|
||||
* [PowerStream](https://power.stream) (deprecated) is powered by the following applications:
|
||||
|
||||
@@ -380,3 +380,16 @@ of this error message. You can essentially ignore it.
|
||||
### [Fix] Can't connect to local MySQL after install on Ubuntu
|
||||
|
||||
- If MySql in local dev can't be connected to, [reset the accounts](https://linuxconfig.org/how-to-reset-root-mysql-mariadb-password-on-ubuntu-20-04-focal-fossa-linux).
|
||||
|
||||
### API Server
|
||||
```
|
||||
cargo run --bin docs
|
||||
```
|
||||
This setups an api server with swagger docs to show you responses and requests with each associated endpoint
|
||||
It is run at http://127.0.0.1:8989/
|
||||
To obtain the json for the postman collection go to this url http://127.0.0.1:8989/api-docs/openapi.json
|
||||
We use this: `https://github.com/juhaku/utoipa`
|
||||
The documentation example is in:
|
||||
`crates/service/web/storyteller_web/src/http_server/endpoints/voice_designer/inference/enqueue_tts_request.rs`
|
||||
Write into the api doc to:
|
||||
`crates/service/web/storyteller_web/src/api_doc.rs`
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE user_bookmarks;
|
||||
@@ -0,0 +1,46 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Favorites that can be attached to just about anything.
|
||||
-- This is a polymorphic table and can apply to a wide variety of entities.
|
||||
CREATE TABLE user_bookmarks
|
||||
(
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- User making the favorite
|
||||
user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The type of entity the favorite applies to
|
||||
entity_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The token of the entity the favorite applies to
|
||||
entity_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP NULL,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY index_entity_type_entity_token (entity_type, entity_token),
|
||||
KEY index_user_token_entity_token (user_token, entity_type),
|
||||
KEY index_user_token (user_token),
|
||||
KEY index_created_at (created_at),
|
||||
KEY index_user_deleted_at (deleted_at)
|
||||
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_bin;
|
||||
@@ -17,7 +17,9 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
crockford = { path = "../../lib/crockford" }
|
||||
errors = { path = "../../lib/errors" }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
# (none yet)
|
||||
|
||||
@@ -2,4 +2,5 @@ pub mod media_files;
|
||||
pub mod media_uploads;
|
||||
pub mod public_path;
|
||||
pub mod voice_conversion_results;
|
||||
pub mod zs_voices;
|
||||
pub mod zs_voices;
|
||||
pub mod weight_uploads;
|
||||
@@ -0,0 +1,77 @@
|
||||
use crockford::crockford_entropy_lower;
|
||||
// TODO Thoughts NOTE:
|
||||
// I am wondering if it be easier if we just had a single struct and impl to handle downloads from public and private buckets.
|
||||
// essentially, the only difference is the prefix and file postfix and the path of where the file goes and the path will be constructed from there.
|
||||
// then you can tie in the downloader as a single object that can be used for both public and private buckets.
|
||||
|
||||
use crate::public::public_path::PublicPath;
|
||||
use crate::util::hashed_directory_path_long_string::hashed_directory_path_long_string;
|
||||
|
||||
const WEIGHT_UPLOAD_DIRECTORY : &str = "/weight_upload";
|
||||
|
||||
/// Directory for user media uploads.
|
||||
/// Each uploaded file gets its own directory so that we can store the original
|
||||
/// file alongside re-processed derivatives.
|
||||
#[derive(Clone)]
|
||||
pub struct WeightUploadDirectory {
|
||||
object_hash: String,
|
||||
directory: String,
|
||||
}
|
||||
|
||||
impl PublicPath for WeightUploadDirectory {}
|
||||
|
||||
impl WeightUploadDirectory {
|
||||
|
||||
pub fn generate_new() -> Self {
|
||||
let entropy = crockford_entropy_lower(32);
|
||||
Self::from_object_hash(&entropy)
|
||||
}
|
||||
|
||||
pub fn from_object_hash(object_hash: &str) -> Self {
|
||||
// TODO: Path construction could be cleaner.
|
||||
let middle = hashed_directory_path_long_string(object_hash);
|
||||
let directory = format!("{}/{}{}", WEIGHT_UPLOAD_DIRECTORY, middle, object_hash);
|
||||
Self {
|
||||
object_hash: object_hash.to_string(),
|
||||
directory,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_directory_path_str(&self) -> &str {
|
||||
&self.directory
|
||||
}
|
||||
|
||||
pub fn get_object_hash(&self) -> &str {
|
||||
&self.object_hash
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::public::weight_uploads::directory::WeightUploadDirectory;
|
||||
|
||||
#[test]
|
||||
pub fn generate_new_entropy() {
|
||||
let directory = WeightUploadDirectory::generate_new();
|
||||
assert_eq!(directory.get_object_hash().len(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_directory_path_str() {
|
||||
let directory = WeightUploadDirectory::from_object_hash("abcdefghijk");
|
||||
assert_eq!(directory.get_directory_path_str(), "/weight_upload/a/b/c/d/e/abcdefghijk");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_directory_path_str_short_name() {
|
||||
let directory = WeightUploadDirectory::from_object_hash("foo");
|
||||
assert_eq!(directory.get_directory_path_str(), "/weight_upload/f/o/foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_object_hash() {
|
||||
let hash = "abcdefghijk";
|
||||
let directory = WeightUploadDirectory::from_object_hash(hash);
|
||||
assert_eq!(directory.get_object_hash(), hash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod directory;
|
||||
pub mod original_file;
|
||||
@@ -0,0 +1,99 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crockford::crockford_entropy_lower;
|
||||
|
||||
use crate::public::weight_uploads::directory::WeightUploadDirectory;
|
||||
use crate::public::public_path::PublicPath;
|
||||
|
||||
const ORIGINAL_FILE_BASENAME : &str = "original_upload.bin";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WeightUploadOriginalFilePath {
|
||||
directory: WeightUploadDirectory,
|
||||
full_object_path: String,
|
||||
}
|
||||
|
||||
impl PublicPath for WeightUploadOriginalFilePath {}
|
||||
|
||||
impl WeightUploadOriginalFilePath {
|
||||
|
||||
pub fn generate_new() -> Self {
|
||||
let entropy = crockford_entropy_lower(32);
|
||||
Self::from_object_hash(&entropy)
|
||||
}
|
||||
|
||||
pub fn from_object_hash(hash: &str) -> Self {
|
||||
// TODO: Path construction could be cleaner.
|
||||
let directory = WeightUploadDirectory::from_object_hash(hash);
|
||||
let full_object_path = format!("{}/{}", directory.get_directory_path_str(), ORIGINAL_FILE_BASENAME);
|
||||
Self {
|
||||
directory,
|
||||
full_object_path,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_full_object_path_str(&self) -> &str {
|
||||
&self.full_object_path
|
||||
}
|
||||
|
||||
pub fn to_full_object_pathbuf(&self) -> PathBuf {
|
||||
PathBuf::from(&self.full_object_path)
|
||||
}
|
||||
|
||||
pub fn get_directory(&self) -> &WeightUploadDirectory {
|
||||
&self.directory
|
||||
}
|
||||
|
||||
pub fn get_object_hash(&self) -> &str {
|
||||
&self.directory.get_object_hash()
|
||||
}
|
||||
|
||||
pub fn get_basename() -> &'static str {
|
||||
ORIGINAL_FILE_BASENAME
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
use crate::public::weight_uploads::original_file::WeightUploadOriginalFilePath;
|
||||
|
||||
#[test]
|
||||
pub fn generate_new_entropy() {
|
||||
let file = WeightUploadOriginalFilePath::generate_new();
|
||||
assert_eq!(file.get_object_hash().len(), 32);
|
||||
assert_eq!(file.get_directory().get_object_hash().len(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str() {
|
||||
let file = WeightUploadOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
assert_eq!(file.get_full_object_path_str(), "/weight_upload/a/b/c/d/e/abcdefghijk/original_upload.bin");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn to_full_object_pathbuf() {
|
||||
let file = WeightUploadOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
assert_eq!(file.to_full_object_pathbuf(), PathBuf::from("/weight_upload/a/b/c/d/e/abcdefghijk/original_upload.bin"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str_short_name() {
|
||||
let file = WeightUploadOriginalFilePath::from_object_hash("foo");
|
||||
assert_eq!(file.get_full_object_path_str(), "/weight_upload/f/o/foo/original_upload.bin");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str_starts_with_directory() {
|
||||
let file = WeightUploadOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
let full_path = file.get_full_object_path_str();
|
||||
assert!(full_path.starts_with(file.get_directory().get_directory_path_str()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_object_hash() {
|
||||
let hash = "abcdefghijk";
|
||||
let file = WeightUploadOriginalFilePath::from_object_hash(hash);
|
||||
assert_eq!(file.get_object_hash(), hash);
|
||||
}
|
||||
}
|
||||
@@ -13,18 +13,20 @@ name = "enums"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
|
||||
# MySql Database
|
||||
# "offline" supports typesafe builds without a live database
|
||||
# "rustls" doesn't appear to work with IP addresses, per:
|
||||
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "sqlite", "runtime-tokio-native-tls", "chrono" ] }
|
||||
sqlx-core = { version = "0.7.2" }
|
||||
sqlx-mysql= { version = "0.7.2" }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
utoipa = { version = "4", features = ["chrono","actix_extras"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
/// Used in the `favorites` table in a `VARCHAR(32)` field named `entity_type`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
pub enum FavoriteEntityType {
|
||||
/// User
|
||||
#[serde(rename = "user")]
|
||||
User,
|
||||
|
||||
/// TTS model (architecture does not matter)
|
||||
#[serde(rename = "tts_model")]
|
||||
TtsModel,
|
||||
|
||||
/// TTS result (architecture does not matter)
|
||||
#[serde(rename = "tts_result")]
|
||||
TtsResult,
|
||||
|
||||
/// W2L template
|
||||
#[serde(rename = "w2l_template")]
|
||||
W2lTemplate,
|
||||
|
||||
/// W2L result
|
||||
#[serde(rename = "w2l_result")]
|
||||
W2lResult,
|
||||
|
||||
/// MediaFile
|
||||
#[serde(rename = "media_file")]
|
||||
MediaFile,
|
||||
|
||||
/// VoiceConversionModel
|
||||
#[serde(rename = "voice_conversion_model")]
|
||||
VoiceConversionModel,
|
||||
|
||||
/// ZsVoice
|
||||
#[serde(rename = "zs_voice")]
|
||||
ZsVoice,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(FavoriteEntityType);
|
||||
impl_mysql_enum_coders!(FavoriteEntityType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl FavoriteEntityType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::User => "user",
|
||||
Self::TtsModel => "tts_model",
|
||||
Self::TtsResult => "tts_result",
|
||||
Self::W2lTemplate => "w2l_template",
|
||||
Self::W2lResult => "w2l_result",
|
||||
Self::MediaFile => "media_file",
|
||||
Self::VoiceConversionModel => "voice_conversion_model",
|
||||
Self::ZsVoice => "zs_voice",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"user" => Ok(Self::User),
|
||||
"tts_model" => Ok(Self::TtsModel),
|
||||
"tts_result" => Ok(Self::TtsResult),
|
||||
"w2l_template" => Ok(Self::W2lTemplate),
|
||||
"w2l_result" => Ok(Self::W2lResult),
|
||||
"media_file" => Ok(Self::MediaFile),
|
||||
"voice_conversion_model" => Ok(Self::VoiceConversionModel),
|
||||
"zs_voice" => Ok(Self::ZsVoice),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::favorites::favorite_entity_type::FavoriteEntityType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(FavoriteEntityType::User, "user");
|
||||
assert_serialization(FavoriteEntityType::TtsModel, "tts_model");
|
||||
assert_serialization(FavoriteEntityType::TtsResult, "tts_result");
|
||||
assert_serialization(FavoriteEntityType::W2lTemplate, "w2l_template");
|
||||
assert_serialization(FavoriteEntityType::W2lResult, "w2l_result");
|
||||
assert_serialization(FavoriteEntityType::MediaFile, "media_file");
|
||||
assert_serialization(FavoriteEntityType::VoiceConversionModel, "voice_conversion_model");
|
||||
assert_serialization(FavoriteEntityType::ZsVoice, "zs_voice");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
assert_eq!(FavoriteEntityType::User.to_str(), "user");
|
||||
assert_eq!(FavoriteEntityType::TtsModel.to_str(), "tts_model");
|
||||
assert_eq!(FavoriteEntityType::TtsResult.to_str(), "tts_result");
|
||||
assert_eq!(FavoriteEntityType::W2lTemplate.to_str(), "w2l_template");
|
||||
assert_eq!(FavoriteEntityType::W2lResult.to_str(), "w2l_result");
|
||||
assert_eq!(FavoriteEntityType::MediaFile.to_str(), "media_file");
|
||||
assert_eq!(FavoriteEntityType::VoiceConversionModel.to_str(), "voice_conversion_model");
|
||||
assert_eq!(FavoriteEntityType::ZsVoice.to_str(), "zs_voice");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(FavoriteEntityType::from_str("user").unwrap(), FavoriteEntityType::User);
|
||||
assert_eq!(FavoriteEntityType::from_str("tts_model").unwrap(), FavoriteEntityType::TtsModel);
|
||||
assert_eq!(FavoriteEntityType::from_str("tts_result").unwrap(), FavoriteEntityType::TtsResult);
|
||||
assert_eq!(FavoriteEntityType::from_str("w2l_template").unwrap(), FavoriteEntityType::W2lTemplate);
|
||||
assert_eq!(FavoriteEntityType::from_str("w2l_result").unwrap(), FavoriteEntityType::W2lResult);
|
||||
assert_eq!(FavoriteEntityType::from_str("media_file").unwrap(), FavoriteEntityType::MediaFile);
|
||||
assert_eq!(FavoriteEntityType::from_str("voice_conversion_model").unwrap(), FavoriteEntityType::VoiceConversionModel);
|
||||
assert_eq!(FavoriteEntityType::from_str("zs_voice").unwrap(), FavoriteEntityType::ZsVoice);
|
||||
assert!(FavoriteEntityType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
pub mod favorite_entity_type;
|
||||
@@ -13,10 +13,11 @@ use strum::EnumIter;
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default)]
|
||||
pub enum InferenceCategory {
|
||||
/// Eg. SadTalker and possibly Wav2Lip
|
||||
#[serde(rename = "lipsync_animation")]
|
||||
#[default]
|
||||
LipsyncAnimation,
|
||||
|
||||
#[serde(rename = "text_to_speech")]
|
||||
|
||||
@@ -21,6 +21,11 @@ pub enum IdCategory {
|
||||
#[serde(rename = "lipsync_animation")]
|
||||
LipsyncAnimationResult,
|
||||
|
||||
/// Results from tacotron2
|
||||
/// Applies for RVC and SVC
|
||||
#[serde(rename = "tts_result")]
|
||||
TtsResult,
|
||||
|
||||
/// Results from voice conversion (which may live in the media_files table)
|
||||
/// Applies for RVC and SVC
|
||||
#[serde(rename = "voice_conversion")]
|
||||
@@ -52,6 +57,7 @@ impl IdCategory {
|
||||
match self {
|
||||
Self::MediaFile => "media_file",
|
||||
Self::LipsyncAnimationResult => "lipsync_animation",
|
||||
Self::TtsResult => "tts_result",
|
||||
Self::VoiceConversionResult => "voice_conversion",
|
||||
Self::ZeroShotVoiceDataset => "zs_dataset",
|
||||
Self::ZeroShotVoiceEmbedding => "zs_voice",
|
||||
@@ -64,6 +70,7 @@ impl IdCategory {
|
||||
match value {
|
||||
"media_file" => Ok(Self::MediaFile),
|
||||
"lipsync_animation" => Ok(Self::LipsyncAnimationResult),
|
||||
"tts_result" => Ok(Self::TtsResult),
|
||||
"voice_conversion" => Ok(Self::VoiceConversionResult),
|
||||
"zs_dataset" => Ok(Self::ZeroShotVoiceDataset),
|
||||
"zs_voice" => Ok(Self::ZeroShotVoiceEmbedding),
|
||||
@@ -79,6 +86,7 @@ impl IdCategory {
|
||||
BTreeSet::from([
|
||||
Self::MediaFile,
|
||||
Self::LipsyncAnimationResult,
|
||||
Self::TtsResult,
|
||||
Self::VoiceConversionResult,
|
||||
Self::ZeroShotTtsResult,
|
||||
Self::ZeroShotVoiceDataset,
|
||||
@@ -100,6 +108,7 @@ mod tests {
|
||||
fn test_serialization() {
|
||||
assert_serialization(IdCategory::MediaFile, "media_file");
|
||||
assert_serialization(IdCategory::LipsyncAnimationResult, "lipsync_animation");
|
||||
assert_serialization(IdCategory::TtsResult, "tts_result");
|
||||
assert_serialization(IdCategory::VoiceConversionResult, "voice_conversion");
|
||||
assert_serialization(IdCategory::ZeroShotVoiceDataset, "zs_dataset");
|
||||
assert_serialization(IdCategory::ZeroShotVoiceEmbedding, "zs_voice");
|
||||
@@ -111,6 +120,7 @@ mod tests {
|
||||
fn to_str() {
|
||||
assert_eq!(IdCategory::MediaFile.to_str(), "media_file");
|
||||
assert_eq!(IdCategory::LipsyncAnimationResult.to_str(), "lipsync_animation");
|
||||
assert_eq!(IdCategory::TtsResult.to_str(), "tts_result");
|
||||
assert_eq!(IdCategory::VoiceConversionResult.to_str(), "voice_conversion");
|
||||
assert_eq!(IdCategory::ZeroShotVoiceDataset.to_str(), "zs_dataset");
|
||||
assert_eq!(IdCategory::ZeroShotVoiceEmbedding.to_str(), "zs_voice");
|
||||
@@ -122,6 +132,7 @@ mod tests {
|
||||
fn from_str() {
|
||||
assert_eq!(IdCategory::from_str("media_file").unwrap(), IdCategory::MediaFile);
|
||||
assert_eq!(IdCategory::from_str("lipsync_animation").unwrap(), IdCategory::LipsyncAnimationResult);
|
||||
assert_eq!(IdCategory::from_str("tts_result").unwrap(), IdCategory::TtsResult);
|
||||
assert_eq!(IdCategory::from_str("voice_conversion").unwrap(), IdCategory::VoiceConversionResult);
|
||||
assert_eq!(IdCategory::from_str("zs_dataset").unwrap(), IdCategory::ZeroShotVoiceDataset);
|
||||
assert_eq!(IdCategory::from_str("zs_voice").unwrap(), IdCategory::ZeroShotVoiceEmbedding);
|
||||
@@ -133,9 +144,10 @@ mod tests {
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
let mut variants = IdCategory::all_variants();
|
||||
assert_eq!(variants.len(), 7);
|
||||
assert_eq!(variants.len(), 8);
|
||||
assert_eq!(variants.pop_first(), Some(IdCategory::MediaFile));
|
||||
assert_eq!(variants.pop_first(), Some(IdCategory::LipsyncAnimationResult));
|
||||
assert_eq!(variants.pop_first(), Some(IdCategory::TtsResult));
|
||||
assert_eq!(variants.pop_first(), Some(IdCategory::VoiceConversionResult));
|
||||
assert_eq!(variants.pop_first(), Some(IdCategory::ZeroShotTtsResult));
|
||||
assert_eq!(variants.pop_first(), Some(IdCategory::ZeroShotVoiceDataset));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
@@ -29,6 +30,7 @@ pub enum MediaFileOriginCategory {
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(MediaFileOriginCategory);
|
||||
impl_mysql_enum_coders!(MediaFileOriginCategory);
|
||||
impl_mysql_from_row!(MediaFileOriginCategory);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl MediaFileOriginCategory {
|
||||
|
||||
@@ -24,6 +24,10 @@ pub enum MediaFileOriginModelType {
|
||||
/// so-vits-svc voice conversion models
|
||||
#[serde(rename = "so_vits_svc")]
|
||||
SoVitsSvc,
|
||||
|
||||
#[serde(rename = "tacotron2")]
|
||||
Tacotron2,
|
||||
|
||||
#[serde(rename = "vall_e_x")]
|
||||
VallEX,
|
||||
}
|
||||
@@ -31,6 +35,7 @@ pub enum MediaFileOriginModelType {
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(MediaFileOriginModelType);
|
||||
impl_mysql_enum_coders!(MediaFileOriginModelType);
|
||||
impl_mysql_from_row!(MediaFileOriginModelType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl MediaFileOriginModelType {
|
||||
@@ -39,6 +44,7 @@ impl MediaFileOriginModelType {
|
||||
Self::RvcV2 => "rvc_v2",
|
||||
Self::SadTalker => "sad_talker",
|
||||
Self::SoVitsSvc => "so_vits_svc",
|
||||
Self::Tacotron2 => "tacotron2",
|
||||
Self::VallEX => "vall_e_x"
|
||||
}
|
||||
}
|
||||
@@ -48,6 +54,7 @@ impl MediaFileOriginModelType {
|
||||
"rvc_v2" => Ok(Self::RvcV2),
|
||||
"sad_talker" => Ok(Self::SadTalker),
|
||||
"so_vits_svc" => Ok(Self::SoVitsSvc),
|
||||
"tacotron2" => Ok(Self::Tacotron2),
|
||||
"vall_e_x" => Ok(Self::VallEX),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
@@ -60,6 +67,7 @@ impl MediaFileOriginModelType {
|
||||
Self::RvcV2,
|
||||
Self::SadTalker,
|
||||
Self::SoVitsSvc,
|
||||
Self::Tacotron2,
|
||||
Self::VallEX
|
||||
])
|
||||
}
|
||||
@@ -83,6 +91,7 @@ mod tests {
|
||||
assert_eq!(MediaFileOriginModelType::RvcV2.to_str(), "rvc_v2");
|
||||
assert_eq!(MediaFileOriginModelType::SadTalker.to_str(), "sad_talker");
|
||||
assert_eq!(MediaFileOriginModelType::SoVitsSvc.to_str(), "so_vits_svc");
|
||||
assert_eq!(MediaFileOriginModelType::Tacotron2.to_str(), "tacotron2");
|
||||
assert_eq!(MediaFileOriginModelType::VallEX.to_str(), "vall_e_x");
|
||||
}
|
||||
|
||||
@@ -91,17 +100,19 @@ mod tests {
|
||||
assert_eq!(MediaFileOriginModelType::from_str("rvc_v2").unwrap(), MediaFileOriginModelType::RvcV2);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("sad_talker").unwrap(), MediaFileOriginModelType::SadTalker);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("so_vits_svc").unwrap(), MediaFileOriginModelType::SoVitsSvc);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("tacotron2").unwrap(), MediaFileOriginModelType::Tacotron2);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("vall_e_x").unwrap(), MediaFileOriginModelType::VallEX);
|
||||
assert!(MediaFileOriginModelType::from_str("foo").is_err());
|
||||
assert!(MediaFileOriginModelType::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = MediaFileOriginModelType::all_variants();
|
||||
assert_eq!(variants.len(), 4);
|
||||
assert_eq!(variants.len(), 5);
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::RvcV2));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::SadTalker));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::SoVitsSvc));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::Tacotron2));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::VallEX));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ pub enum MediaFileOriginProductCategory {
|
||||
#[serde(rename = "face_animator")]
|
||||
FaceAnimator,
|
||||
|
||||
/// Text to speech (Tacotron2, not voice designer / VallE-X)
|
||||
#[serde(rename = "tts")]
|
||||
TextToSpeech,
|
||||
|
||||
// TODO: This should be a temporary category until we migrate the DB to remove this default value
|
||||
/// Unknown which product is attached to the file (generated the file, the file was
|
||||
/// uploaded on behalf of, etc.)
|
||||
@@ -39,12 +43,14 @@ pub enum MediaFileOriginProductCategory {
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(MediaFileOriginProductCategory);
|
||||
impl_mysql_enum_coders!(MediaFileOriginProductCategory);
|
||||
impl_mysql_from_row!(MediaFileOriginProductCategory);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl MediaFileOriginProductCategory {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::FaceAnimator => "face_animator",
|
||||
Self::TextToSpeech => "tts",
|
||||
Self::Unknown => "unknown",
|
||||
Self::VoiceConversion => "voice_conversion",
|
||||
Self::ZeroShotVoice => "zs_voice",
|
||||
@@ -54,6 +60,7 @@ impl MediaFileOriginProductCategory {
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"face_animator" => Ok(Self::FaceAnimator),
|
||||
"tts" => Ok(Self::TextToSpeech),
|
||||
"unknown" => Ok(Self::Unknown),
|
||||
"voice_conversion" => Ok(Self::VoiceConversion),
|
||||
"zs_voice" => Ok(Self::ZeroShotVoice),
|
||||
@@ -66,6 +73,7 @@ impl MediaFileOriginProductCategory {
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
Self::FaceAnimator,
|
||||
Self::TextToSpeech,
|
||||
Self::Unknown,
|
||||
Self::VoiceConversion,
|
||||
Self::ZeroShotVoice,
|
||||
@@ -84,6 +92,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(MediaFileOriginProductCategory::FaceAnimator, "face_animator");
|
||||
assert_serialization(MediaFileOriginProductCategory::TextToSpeech, "tts");
|
||||
assert_serialization(MediaFileOriginProductCategory::Unknown, "unknown");
|
||||
assert_serialization(MediaFileOriginProductCategory::VoiceConversion, "voice_conversion");
|
||||
assert_serialization(MediaFileOriginProductCategory::ZeroShotVoice, "zs_voice");
|
||||
@@ -92,6 +101,7 @@ mod tests {
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(MediaFileOriginProductCategory::FaceAnimator.to_str(), "face_animator");
|
||||
assert_eq!(MediaFileOriginProductCategory::TextToSpeech.to_str(), "tts");
|
||||
assert_eq!(MediaFileOriginProductCategory::Unknown.to_str(), "unknown");
|
||||
assert_eq!(MediaFileOriginProductCategory::VoiceConversion.to_str(), "voice_conversion");
|
||||
assert_eq!(MediaFileOriginProductCategory::ZeroShotVoice.to_str(), "zs_voice");
|
||||
@@ -100,6 +110,7 @@ mod tests {
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("face_animator").unwrap(), MediaFileOriginProductCategory::FaceAnimator);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("tts").unwrap(), MediaFileOriginProductCategory::TextToSpeech);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("unknown").unwrap(), MediaFileOriginProductCategory::Unknown);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("voice_conversion").unwrap(), MediaFileOriginProductCategory::VoiceConversion);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("zs_voice").unwrap(), MediaFileOriginProductCategory::ZeroShotVoice);
|
||||
@@ -108,8 +119,9 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = MediaFileOriginProductCategory::all_variants();
|
||||
assert_eq!(variants.len(), 4);
|
||||
assert_eq!(variants.len(), 5);
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::FaceAnimator));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::TextToSpeech));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::Unknown));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VoiceConversion));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::ZeroShotVoice));
|
||||
|
||||
@@ -25,6 +25,7 @@ pub enum MediaFileType {
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(MediaFileType);
|
||||
impl_mysql_enum_coders!(MediaFileType);
|
||||
impl_mysql_from_row!(MediaFileType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl MediaFileType {
|
||||
|
||||
@@ -20,6 +20,9 @@ pub enum MediaUploadType {
|
||||
|
||||
/// Video files: mp4, etc.
|
||||
Video,
|
||||
|
||||
// Binary files: safetensors ... weights, etc.
|
||||
Binary,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
@@ -33,6 +36,7 @@ impl MediaUploadType {
|
||||
Self::Audio => "audio",
|
||||
Self::Image => "image",
|
||||
Self::Video => "video",
|
||||
Self::Binary => "binary",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +45,7 @@ impl MediaUploadType {
|
||||
"audio" => Ok(Self::Audio),
|
||||
"image" => Ok(Self::Image),
|
||||
"video" => Ok(Self::Video),
|
||||
"binary" => Ok(Self::Binary),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -56,6 +61,7 @@ mod tests {
|
||||
assert_serialization(MediaUploadType::Audio, "audio");
|
||||
assert_serialization(MediaUploadType::Image, "image");
|
||||
assert_serialization(MediaUploadType::Video, "video");
|
||||
assert_serialization(MediaUploadType::Binary, "binary");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -63,6 +69,7 @@ mod tests {
|
||||
assert_eq!(MediaUploadType::Audio.to_str(), "audio");
|
||||
assert_eq!(MediaUploadType::Image.to_str(), "image");
|
||||
assert_eq!(MediaUploadType::Video.to_str(), "video");
|
||||
assert_eq!(MediaUploadType::Binary.to_str(), "binary");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -70,6 +77,7 @@ mod tests {
|
||||
assert_eq!(MediaUploadType::from_str("audio").unwrap(), MediaUploadType::Audio);
|
||||
assert_eq!(MediaUploadType::from_str("image").unwrap(), MediaUploadType::Image);
|
||||
assert_eq!(MediaUploadType::from_str("video").unwrap(), MediaUploadType::Video);
|
||||
assert_eq!(MediaUploadType::from_str("binary").unwrap(), MediaUploadType::Binary);
|
||||
assert!(MediaUploadType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub mod media_uploads;
|
||||
pub mod model_categories;
|
||||
pub mod trending_model_analytics;
|
||||
pub mod tts_models;
|
||||
pub mod user_bookmarks;
|
||||
pub mod user_ratings;
|
||||
pub mod voice_conversion_models;
|
||||
pub mod voice_conversion_results;
|
||||
@@ -19,4 +20,3 @@ pub mod model_weights;
|
||||
pub mod tts_render_tasks;
|
||||
pub mod web_rendition_targets;
|
||||
pub mod web_scraping_targets;
|
||||
pub mod favorites;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod weights_types;
|
||||
pub mod weights_category;
|
||||
pub mod weights_file_type;
|
||||
@@ -5,8 +5,10 @@ use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
|
||||
use utoipa::ToSchema;
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
pub enum WeightsCategory {
|
||||
#[serde(rename = "image_generation")]
|
||||
ImageGeneration,
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
// TODO we will need to scan the checkpoints for malicious code. We can't just trust the file extension.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
pub enum WeightsFileType {
|
||||
#[serde(rename = "checkpoint")]
|
||||
Checkpoint,
|
||||
#[serde(rename = "safetensors")]
|
||||
SafeTensors,
|
||||
}
|
||||
|
||||
impl WeightsFileType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Checkpoint => "checkpoint",
|
||||
Self::SafeTensors => "safetensors",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"checkpoint" => Ok(Self::Checkpoint),
|
||||
"safetensors" => Ok(Self::SafeTensors),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
BTreeSet::from([
|
||||
Self::Checkpoint,
|
||||
Self::SafeTensors,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(WeightsFileType);
|
||||
impl_mysql_enum_coders!(WeightsFileType);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
assert_eq!(WeightsFileType::Checkpoint.to_str(), "checkpoint");
|
||||
assert_eq!(WeightsFileType::SafeTensors.to_str(), "safetensors");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(WeightsFileType::from_str("checkpoint").unwrap(), WeightsFileType::Checkpoint);
|
||||
assert_eq!(WeightsFileType::from_str("safetensors").unwrap(), WeightsFileType::SafeTensors);
|
||||
assert!(WeightsFileType::from_str("invalid").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_variants() {
|
||||
let variants = WeightsFileType::all_variants();
|
||||
assert_eq!(variants.len(), 2);
|
||||
assert!(variants.contains(&WeightsFileType::Checkpoint));
|
||||
assert!(variants.contains(&WeightsFileType::SafeTensors));
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ use std::collections::BTreeSet;
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
pub enum WeightsType {
|
||||
#[serde(rename = "hifigan_tt2")]
|
||||
HifiganTacotron2,
|
||||
@@ -23,6 +23,8 @@ pub enum WeightsType {
|
||||
Tacotron2,
|
||||
#[serde(rename = "loRA")]
|
||||
LoRA,
|
||||
#[serde(rename = "vall_e")]
|
||||
VallE,
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +38,7 @@ impl WeightsType {
|
||||
Self::SoVitsSvc => "so_vits_svc",
|
||||
Self::Tacotron2 => "tt2",
|
||||
Self::LoRA => "loRA",
|
||||
Self::VallE => "vall_e",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +51,7 @@ impl WeightsType {
|
||||
"so_vits_svc" => Ok(Self::SoVitsSvc),
|
||||
"tt2" => Ok(Self::Tacotron2),
|
||||
"loRA" => Ok(Self::LoRA),
|
||||
"vall_e" => Ok(Self::VallE),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -61,6 +65,7 @@ impl WeightsType {
|
||||
Self::SoVitsSvc,
|
||||
Self::Tacotron2,
|
||||
Self::LoRA,
|
||||
Self::VallE
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -82,6 +87,7 @@ mod tests {
|
||||
assert_eq!(WeightsType::SoVitsSvc.to_str(), "so_vits_svc");
|
||||
assert_eq!(WeightsType::Tacotron2.to_str(), "tt2");
|
||||
assert_eq!(WeightsType::LoRA.to_str(), "loRA");
|
||||
assert_eq!(WeightsType::VallE.to_str(), "vall_e");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -93,13 +99,14 @@ mod tests {
|
||||
assert_eq!(WeightsType::from_str("so_vits_svc").unwrap(), WeightsType::SoVitsSvc);
|
||||
assert_eq!(WeightsType::from_str("tt2").unwrap(), WeightsType::Tacotron2);
|
||||
assert_eq!(WeightsType::from_str("loRA").unwrap(), WeightsType::LoRA);
|
||||
assert_eq!(WeightsType::from_str("vall_e").unwrap(), WeightsType::VallE);
|
||||
assert!(WeightsType::from_str("invalid").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_variants() {
|
||||
let variants = WeightsType::all_variants();
|
||||
assert_eq!(variants.len(), 7);
|
||||
assert_eq!(variants.len(), 8);
|
||||
assert!(variants.contains(&WeightsType::HifiganTacotron2));
|
||||
assert!(variants.contains(&WeightsType::RvcV2));
|
||||
assert!(variants.contains(&WeightsType::StableDiffusion15));
|
||||
@@ -107,5 +114,6 @@ mod tests {
|
||||
assert!(variants.contains(&WeightsType::SoVitsSvc));
|
||||
assert!(variants.contains(&WeightsType::Tacotron2));
|
||||
assert!(variants.contains(&WeightsType::LoRA));
|
||||
assert!(variants.contains(&WeightsType::VallE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod user_bookmark_entity_type;
|
||||
@@ -0,0 +1,128 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
/// Used in the `user_bookmarks` table in a `VARCHAR(32)` field named `entity_type`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
pub enum UserBookmarkEntityType {
|
||||
/// User
|
||||
#[serde(rename = "user")]
|
||||
User,
|
||||
|
||||
/// TTS model (architecture does not matter)
|
||||
#[serde(rename = "tts_model")]
|
||||
TtsModel,
|
||||
|
||||
/// TTS result (architecture does not matter)
|
||||
#[serde(rename = "tts_result")]
|
||||
TtsResult,
|
||||
|
||||
/// W2L template
|
||||
#[serde(rename = "w2l_template")]
|
||||
W2lTemplate,
|
||||
|
||||
/// W2L result
|
||||
#[serde(rename = "w2l_result")]
|
||||
W2lResult,
|
||||
|
||||
/// MediaFile
|
||||
#[serde(rename = "media_file")]
|
||||
MediaFile,
|
||||
|
||||
/// VoiceConversionModel
|
||||
#[serde(rename = "voice_conversion_model")]
|
||||
VoiceConversionModel,
|
||||
|
||||
/// ZsVoice
|
||||
#[serde(rename = "zs_voice")]
|
||||
ZsVoice,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(UserBookmarkEntityType);
|
||||
impl_mysql_enum_coders!(UserBookmarkEntityType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl UserBookmarkEntityType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::User => "user",
|
||||
Self::TtsModel => "tts_model",
|
||||
Self::TtsResult => "tts_result",
|
||||
Self::W2lTemplate => "w2l_template",
|
||||
Self::W2lResult => "w2l_result",
|
||||
Self::MediaFile => "media_file",
|
||||
Self::VoiceConversionModel => "voice_conversion_model",
|
||||
Self::ZsVoice => "zs_voice",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"user" => Ok(Self::User),
|
||||
"tts_model" => Ok(Self::TtsModel),
|
||||
"tts_result" => Ok(Self::TtsResult),
|
||||
"w2l_template" => Ok(Self::W2lTemplate),
|
||||
"w2l_result" => Ok(Self::W2lResult),
|
||||
"media_file" => Ok(Self::MediaFile),
|
||||
"voice_conversion_model" => Ok(Self::VoiceConversionModel),
|
||||
"zs_voice" => Ok(Self::ZsVoice),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(UserBookmarkEntityType::User, "user");
|
||||
assert_serialization(UserBookmarkEntityType::TtsModel, "tts_model");
|
||||
assert_serialization(UserBookmarkEntityType::TtsResult, "tts_result");
|
||||
assert_serialization(UserBookmarkEntityType::W2lTemplate, "w2l_template");
|
||||
assert_serialization(UserBookmarkEntityType::W2lResult, "w2l_result");
|
||||
assert_serialization(UserBookmarkEntityType::MediaFile, "media_file");
|
||||
assert_serialization(UserBookmarkEntityType::VoiceConversionModel, "voice_conversion_model");
|
||||
assert_serialization(UserBookmarkEntityType::ZsVoice, "zs_voice");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
assert_eq!(UserBookmarkEntityType::User.to_str(), "user");
|
||||
assert_eq!(UserBookmarkEntityType::TtsModel.to_str(), "tts_model");
|
||||
assert_eq!(UserBookmarkEntityType::TtsResult.to_str(), "tts_result");
|
||||
assert_eq!(UserBookmarkEntityType::W2lTemplate.to_str(), "w2l_template");
|
||||
assert_eq!(UserBookmarkEntityType::W2lResult.to_str(), "w2l_result");
|
||||
assert_eq!(UserBookmarkEntityType::MediaFile.to_str(), "media_file");
|
||||
assert_eq!(UserBookmarkEntityType::VoiceConversionModel.to_str(), "voice_conversion_model");
|
||||
assert_eq!(UserBookmarkEntityType::ZsVoice.to_str(), "zs_voice");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(UserBookmarkEntityType::from_str("user").unwrap(), UserBookmarkEntityType::User);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("tts_model").unwrap(), UserBookmarkEntityType::TtsModel);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("tts_result").unwrap(), UserBookmarkEntityType::TtsResult);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("w2l_template").unwrap(), UserBookmarkEntityType::W2lTemplate);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("w2l_result").unwrap(), UserBookmarkEntityType::W2lResult);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("media_file").unwrap(), UserBookmarkEntityType::MediaFile);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("voice_conversion_model").unwrap(), UserBookmarkEntityType::VoiceConversionModel);
|
||||
assert_eq!(UserBookmarkEntityType::from_str("zs_voice").unwrap(), UserBookmarkEntityType::ZsVoice);
|
||||
assert!(UserBookmarkEntityType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,12 @@ impl_mysql_enum_coders!(JobStatusPlus);
|
||||
|
||||
// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders`
|
||||
|
||||
impl Default for JobStatusPlus {
|
||||
fn default() -> Self {
|
||||
Self::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl JobStatusPlus {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
@@ -86,6 +92,11 @@ mod tests {
|
||||
mod explicit_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_default() {
|
||||
assert_eq!(JobStatusPlus::default(), JobStatusPlus::Pending);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(JobStatusPlus::Pending, "pending");
|
||||
|
||||
@@ -15,9 +15,10 @@ use strum::EnumIter;
|
||||
/// See also: https://docs.rs/sqlx/0.4.0-beta.1/sqlx/trait.Type.html
|
||||
///
|
||||
/// *DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY!*
|
||||
///
|
||||
|
||||
use utoipa::ToSchema;
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, sqlx::Type)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, sqlx::Type,ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[sqlx(rename_all = "lowercase")]
|
||||
pub enum Visibility {
|
||||
@@ -38,6 +39,7 @@ pub enum Visibility {
|
||||
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(Visibility);
|
||||
impl_mysql_from_row!(Visibility);
|
||||
|
||||
// For reference, here's what the serde implementation might be if manually written.
|
||||
// This may be useful for designing composite types in the future:
|
||||
|
||||
@@ -32,3 +32,4 @@ mod macros;
|
||||
|
||||
pub mod by_table;
|
||||
pub mod common;
|
||||
pub mod traits;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
/// Implement `MySqlFromRow` on a type.
|
||||
macro_rules! impl_mysql_from_row {
|
||||
($t:ident) => {
|
||||
|
||||
// Try to convert a MySQL row and named field into the value type (for non-nullable fields).
|
||||
impl crate::traits::mysql_from_row::MySqlFromRow<$t> for $t {
|
||||
fn try_from_mysql_row(row: &sqlx_mysql::MySqlRow, field_name: &str) -> Result<$t, sqlx::Error> {
|
||||
use sqlx::{Error, Row};
|
||||
|
||||
// NB(bt,2023-12-05): For now only string encodings are considered.
|
||||
// We may want to revisit in the future if we deal with binary data.
|
||||
let value : String = row.try_get(field_name)?;
|
||||
|
||||
let output_type = Self::from_str(&value)
|
||||
.map_err(|err| {
|
||||
Error::ColumnDecode {
|
||||
index: format!("mysql_from_row failure on field {}: {:?}", field_name, err),
|
||||
source: format!("mysql_from_row failure on field {}: {:?}", field_name, err).into(),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(output_type)
|
||||
}
|
||||
|
||||
// Try to convert a MySQL row and named field into the value type (for nullable fields).
|
||||
fn try_from_mysql_row_nullable(row: &sqlx_mysql::MySqlRow, field_name: &str) -> Result<Option<$t>, sqlx::Error> {
|
||||
use sqlx::{Error, Row};
|
||||
|
||||
// NB(bt,2023-12-05): For now only string encodings are considered.
|
||||
// We may want to revisit in the future if we deal with binary data.
|
||||
// NB(2): Nullable fields decode as Option<T>.
|
||||
let maybe_value : Option<String> = row.try_get(field_name)?;
|
||||
|
||||
let value = match maybe_value {
|
||||
Some(value) => value,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let output_type = Self::from_str(&value)
|
||||
.map_err(|err| {
|
||||
Error::ColumnDecode {
|
||||
index: format!("mysql_from_row failure on field {}: {:?}", field_name, err),
|
||||
source: format!("mysql_from_row failure on field {}: {:?}", field_name, err).into(),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(Some(output_type))
|
||||
}
|
||||
}
|
||||
|
||||
//// TODO: Tests.
|
||||
//#[cfg(test)]
|
||||
//#[test]
|
||||
//fn test_name() {
|
||||
// use strum::IntoEnumIterator;
|
||||
// for variant in $t::iter() {
|
||||
// assert_eq!(format!("{}", variant), variant.to_str());
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#[macro_use] pub mod impl_enum_display_and_debug_using_to_str;
|
||||
#[macro_use] pub mod impl_mysql_enum_coders;
|
||||
#[macro_use] pub mod impl_mysql_from_row;
|
||||
#[macro_use] pub mod impl_sqlite_enum_coders;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod mysql_from_row;
|
||||
@@ -0,0 +1,11 @@
|
||||
use sqlx_mysql::MySqlRow;
|
||||
|
||||
/// This is a trait (in conjunction with the macro implementation) that makes up for sqlx's
|
||||
/// QueryBuilder not playing well with FromRow implementation or derivation of named types.
|
||||
pub trait MySqlFromRow<T> {
|
||||
|
||||
/// Attempt to parse a named column from a MySqlRow into the type.
|
||||
fn try_from_mysql_row(row: &MySqlRow, field_name: &str) -> Result<T, sqlx::Error>;
|
||||
|
||||
fn try_from_mysql_row_nullable(row: &MySqlRow, field_name: &str) -> Result<Option<T>, sqlx::Error>;
|
||||
}
|
||||
@@ -17,8 +17,11 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
# (none)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
@@ -26,7 +29,6 @@ serde_derive = "1.0.125"
|
||||
|
||||
# MySql Database
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# Test serialization
|
||||
|
||||
@@ -13,6 +13,13 @@ name = "tokens"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
|
||||
# Internal
|
||||
# (none)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
@@ -20,13 +27,10 @@ serde_derive = "1.0.125"
|
||||
# Random
|
||||
rand = "0.8.5"
|
||||
|
||||
# MySql Database
|
||||
# "offline" supports typesafe builds without a live database
|
||||
# "rustls" doesn't appear to work with IP addresses, per:
|
||||
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
|
||||
sqlx-core = { version = "0.7.2" }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
utoipa = { version = "4", features = ["chrono","actix_extras"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ pub(crate) enum TokenPrefix {
|
||||
Comment,
|
||||
DownloadJob,
|
||||
EmailSenderJob,
|
||||
Favorite,
|
||||
InferenceJob,
|
||||
MediaFile,
|
||||
MediaUpload,
|
||||
@@ -36,6 +35,7 @@ pub(crate) enum TokenPrefix {
|
||||
PasswordReset,
|
||||
TtsRenderTask, // NB: aichatbot / sqlite
|
||||
User,
|
||||
UserBookmark,
|
||||
UserSession,
|
||||
VoiceConversionModel,
|
||||
VoiceConversionResult,
|
||||
@@ -94,7 +94,6 @@ impl PrefixGenerator for TokenPrefix {
|
||||
Self::DownloadJob => "jdown_", // NB: Previously "JGUP:"
|
||||
Self::EmailSenderJob => "email_job_",
|
||||
Self::InferenceJob => "jinf_",
|
||||
Self::Favorite => "fav_",
|
||||
Self::MediaFile => "m_",
|
||||
Self::MediaUpload => "mu_",
|
||||
Self::ModelWeight => "weight_",
|
||||
@@ -102,6 +101,7 @@ impl PrefixGenerator for TokenPrefix {
|
||||
Self::PasswordReset => "pw_reset_",
|
||||
Self::TtsRenderTask => "tts_task_",
|
||||
Self::User => "user_", // NB: Previously "U:"
|
||||
Self::UserBookmark => "ub_",
|
||||
Self::UserSession => "session_",
|
||||
Self::VoiceConversionModel => "vcm_",
|
||||
Self::VoiceConversionResult => "vcr_",
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::prefixes::TokenPrefix;
|
||||
/// A rare instance that is *not* a primary key.
|
||||
/// These are generated as cookies to track users for a better logged out experience and for analytics.
|
||||
/// We use these as indices into several columns (ML result types, uploads, etc.)
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize, Default)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct AnonymousVisitorTrackingToken(pub String);
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// The primary key for "generic" inference jobs.
|
||||
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize, Default, ToSchema)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct InferenceJobToken(String);
|
||||
|
||||
|
||||
@@ -34,4 +34,4 @@ pub mod w2l_templates;
|
||||
pub mod zs_voice_dataset_samples;
|
||||
pub mod zs_voice_datasets;
|
||||
pub mod zs_voices;
|
||||
pub mod favorites;
|
||||
pub mod user_bookmarks;
|
||||
|
||||
@@ -5,8 +5,9 @@ use serde::Serialize;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
use utoipa::ToSchema;
|
||||
/// The primary key for the "model_weights" table.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize,ToSchema)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct ModelWeightToken(pub String);
|
||||
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ use crate::prefixes::TokenPrefix;
|
||||
/// The primary key for Audit Logs.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct FavoriteToken(pub String);
|
||||
pub struct UserBookmarkToken(pub String);
|
||||
|
||||
impl_string_token!(FavoriteToken);
|
||||
impl_crockford_generator!(FavoriteToken, 32usize, TokenPrefix::Favorite, CrockfordLower);
|
||||
impl_string_token!(UserBookmarkToken);
|
||||
impl_crockford_generator!(UserBookmarkToken, 32usize, TokenPrefix::UserBookmark, CrockfordLower);
|
||||
@@ -4,9 +4,9 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
use utoipa::ToSchema;
|
||||
/// The primary key for users.
|
||||
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize, Default,ToSchema)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct UserToken(pub String);
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
/// The primary key for user weight uploads
|
||||
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct WeightUploadToken(pub String);
|
||||
|
||||
impl_string_token!(WeightUploadToken);
|
||||
impl_crockford_generator!(WeightUploadToken, 32usize, TokenPrefix::WeightUpload, CrockfordLower);
|
||||
@@ -18,6 +18,9 @@ path = "src/main.rs"
|
||||
container_common = { path = "../../lib/deprecated/container_common" }
|
||||
easyenv = { path = "../../lib/easyenv" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
# TODO/NB: Commenting out clap4 as it prevents windows builds
|
||||
@@ -28,4 +31,3 @@ log = "0.4.14"
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
@@ -18,6 +18,9 @@ path = "src/main.rs"
|
||||
container_common = { path = "../../lib/deprecated/container_common" }
|
||||
easyenv = { path = "../../lib/easyenv" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
# TODO/NB: Commenting out clap4 as it prevents windows builds
|
||||
@@ -28,4 +31,3 @@ log = "0.4.14"
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
@@ -28,6 +28,9 @@ mysql_queries = { path = "../../lib/mysql_queries" }
|
||||
storyteller_root = { path = "../../lib/storyteller_root" }
|
||||
tokens = { path = "../../_types/tokens" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
log = "0.4.14"
|
||||
clap = "2.34.0" # TODO: This is really out of date, but has conflicts when updated
|
||||
@@ -36,14 +39,9 @@ clap = "2.34.0" # TODO: This is really out of date, but has conflicts when updat
|
||||
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
|
||||
tokio = { version = "1.6.0", features = ["macros"] }
|
||||
|
||||
# MySql Database
|
||||
# "offline" supports typesafe builds without a live database
|
||||
# "rustls" doesn't appear to work with IP addresses, per:
|
||||
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
|
||||
|
||||
elasticsearch = "8.5.0-alpha.1"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -56,7 +56,6 @@ pub async fn main() -> AnyhowResult<()> {
|
||||
seed_voice_conversion(&pool).await?;
|
||||
|
||||
seed_weights(&pool).await?;
|
||||
|
||||
|
||||
seed_tts_tacotron2(&pool, maybe_bucket_clients.as_ref()).await?;
|
||||
|
||||
|
||||
@@ -1,20 +1,357 @@
|
||||
use std::vec;
|
||||
|
||||
use log::info;
|
||||
use sqlx::{MySql, Pool};
|
||||
|
||||
use tokens::tokens::users::UserToken;
|
||||
use sqlx::{ MySql, Pool };
|
||||
use enums::by_table::model_weights::{
|
||||
weights_types::WeightsType,
|
||||
weights_category::WeightsCategory,
|
||||
weights_types::WeightsType,
|
||||
};
|
||||
use errors::{ anyhow, AnyhowResult };
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::{anyhow, AnyhowResult};
|
||||
use mysql_queries::queries::model_weights::create_weight::{create_weight, CreateModelWeightsArgs};
|
||||
use mysql_queries::queries::users::user::get_user_token_by_username::get_user_token_by_username;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::seeding::users::HANASHI_USERNAME;
|
||||
use mysql_queries::queries::model_weights::create_weight::{ create_weight, CreateModelWeightsArgs };
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
use enums::common::visibility::Visibility;
|
||||
|
||||
use mysql_queries::queries::users::user::get_user_token_by_username::get_user_token_by_username;
|
||||
pub async fn seed_weights_for_paging( mysql_pool: &Pool<MySql>,user_token: UserToken) -> AnyhowResult<()> {
|
||||
let sd1_5_markdown_description = r#"
|
||||
# Dragonfruit AI Models Update and Workflow
|
||||
|
||||
## Last Update for Dragonfruit Models
|
||||
- **Note:** This might be the last update for a while, focusing next on a realistic merge (WIP).
|
||||
- **Future Plans:** Possible update to Z.5D v2 after completing the realistic merge.
|
||||
|
||||
## New Models Announcement
|
||||
- **Upcoming Models:** Separate from the Dragonfruit branch, so stay tuned!
|
||||
|
||||
## DragonfruitGT v1 (Z v2)
|
||||
- **Focus:** More fantasy, richer color range, improved landscapes, more masculine men.
|
||||
- **Alternative:** Use DragonfruitOG v2.0 for thicker lines, simpler colors.
|
||||
|
||||
## GT v1.0 (Z v2.0) Features
|
||||
- Improved backgrounds
|
||||
- Deeper contrast and color
|
||||
- Bolder lines and more detail
|
||||
|
||||
### Settings for GT
|
||||
- Steps: 30-50
|
||||
- Clip skip: 2
|
||||
- Upscaler: Euler a / DPM++ 2M SDE Karras
|
||||
- Extensions: Adetailer, VAE: berrysmix
|
||||
|
||||
## Workflow for Images
|
||||
1. **BerryMix VAE:** Ensure correct color.
|
||||
2. **Adetailer Extension:** Improve faces, bodies, and hands. Also available on Civitai and Huggingface.
|
||||
3. **Hires Fix:** Denoising strength 0.3 - 0.35, using upscaler "x_NMKD-Superscale-SP_178000_G".
|
||||
4. **Img2img Transfer:** Use denoising strength 0.3-0.35 with the same prompt and settings. Adjust height after hires.
|
||||
5. **Second Img2img Transfer:** Low denoising strength 0.1-3.0. Use SD upscale script with "RealESRGAN_x4plus_anime_6B" sampler for size increase.
|
||||
|
||||
## DragonfruitZ.5D v1.0
|
||||
- **Style:** 2.5D model, merging DragonfruitZ with realistic elements.
|
||||
- **Features:** Skin color variety, masculine men, landscapes, fantasy, NSFW content, detailed faces.
|
||||
|
||||
### Settings for Z.5D
|
||||
- Steps: 30
|
||||
- Clip skip: 2
|
||||
- Upscaler: Euler a
|
||||
- Extensions: Adetailer, VAE: berrysmix
|
||||
|
||||
## DragonfruitOG v2.0
|
||||
- **Refinement:** Of the original Dragonfruit model.
|
||||
- **Style:** Bold, clean lines and bold colors with decreased detail for simplicity.
|
||||
- **Improvements:** Teeth, skin color variety, landscapes, fantasy elements, NSFW content.
|
||||
|
||||
## DragonfruitZ v1.0
|
||||
- **Alternative Version:** More fantasy and color range, better landscapes, more masculine men.
|
||||
- **Suggestion:** Use Dragonfruit (Unisex) v2 for thicker lines and simpler colors.
|
||||
|
||||
## Dragonfruit OG v1.0
|
||||
- **Focus:** More unisex, suitable for creating male characters.
|
||||
- **Personal Note:** First merge, aimed at 2D, flat, colorful, thick lined styles.
|
||||
|
||||
### Personal Settings
|
||||
- Steps: 20-30
|
||||
- Clip skip: 2
|
||||
- Upscaler: Euler a / DPM++ 2M SDE Karras
|
||||
- Extensions: Adetailer, VAE: berrysmix
|
||||
|
||||
*Thank you for your continued support and feedback!*
|
||||
"#;
|
||||
|
||||
let sd1_5_image_token = "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/be706282-2978-42a0-aaa2-73881aad94e9/width=1024/00049-2287632957-1girl,face,curly%20hair,red%20hair,white%20background,.jpeg";
|
||||
|
||||
let user_token = user_token;
|
||||
|
||||
// create a loop that loops from 1 to 100
|
||||
for i in 1..=100 {
|
||||
// create a new weight
|
||||
|
||||
let weights_category = match i {
|
||||
1..=20 => WeightsCategory::VoiceConversion,
|
||||
21..=40 => WeightsCategory::TextToSpeech,
|
||||
41..=60 => WeightsCategory::ImageGeneration,
|
||||
61..=80 => WeightsCategory::ImageGeneration,
|
||||
81..=100 => WeightsCategory::ImageGeneration,
|
||||
_ => WeightsCategory::ImageGeneration
|
||||
};
|
||||
|
||||
let weights_types = match i {
|
||||
1..=20 => WeightsType::RvcV2,
|
||||
21..=40 => WeightsType::HifiganTacotron2,
|
||||
41..=60 => WeightsType::StableDiffusion15,
|
||||
61..=80 => WeightsType::StableDiffusionXL,
|
||||
81..=100 => WeightsType::LoRA,
|
||||
_ => WeightsType::LoRA
|
||||
};
|
||||
|
||||
let mut model_weight_token;
|
||||
let mut title;
|
||||
let mut description;
|
||||
let mut description_rendered_html;
|
||||
let mut original_filename;
|
||||
let mut original_download_url;
|
||||
let mut thumbnail_token;
|
||||
|
||||
let mut private_bucket_hash:String = "".to_string();
|
||||
let mut private_bucket_prefix;
|
||||
let mut private_bucket_extension;
|
||||
|
||||
let mut cached_user_ratings_total_count;
|
||||
let mut cached_user_ratings_positive_count;
|
||||
let mut cached_user_ratings_negative_count;
|
||||
let mut cached_user_ratings_ratio;
|
||||
let mut version;
|
||||
|
||||
match i {
|
||||
1..=20 => {
|
||||
// voice conversion model
|
||||
let rvc_markdown_description = r#"
|
||||
# RVC v2
|
||||
- **Improved Quality:** The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.
|
||||
- Gawr Gura MOS 4
|
||||
"#;
|
||||
|
||||
model_weight_token = ModelWeightToken(format!("{}", i));
|
||||
title = format!("Gawr Gura: {}", i);
|
||||
description = format!("Description Number {} The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.", i);
|
||||
description_rendered_html = rvc_markdown_description;
|
||||
|
||||
original_filename = format!("gura_gwar{}.safetensors", i);
|
||||
original_download_url = format!("www.google.ca");
|
||||
|
||||
// NOTE TO SELF this will be a join for later on for now they can use this.
|
||||
thumbnail_token = "";
|
||||
|
||||
// private_bucket_hash = format!("bucket_hash{}", i);
|
||||
private_bucket_prefix = format!("_fake");
|
||||
private_bucket_extension = format!("rvcV2");
|
||||
cached_user_ratings_total_count = i;
|
||||
cached_user_ratings_positive_count = i;
|
||||
cached_user_ratings_negative_count = i;
|
||||
cached_user_ratings_ratio = i as u32 / 100;
|
||||
version = i as i32;
|
||||
println!("Seeding RVCv2 model {}", i);
|
||||
},
|
||||
21..=40 =>{
|
||||
// TTS
|
||||
model_weight_token = ModelWeightToken(format!("{}", i));
|
||||
title = format!("dragonfruitGTv1: {}", i);
|
||||
|
||||
description = format!("Description Number {}:", i);
|
||||
|
||||
let tts_markdown_description = r#"
|
||||
# HifiGAN Tacotron2
|
||||
- **Improved Quality:** The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.
|
||||
- Goku MOS 4
|
||||
"#;
|
||||
|
||||
description_rendered_html = tts_markdown_description;
|
||||
|
||||
original_filename = format!("filename{}.txt", i);
|
||||
original_download_url = format!("https://civitai.com/api/download/models/149193?type=Model&format=SafeTensor&size=pruned&fp=fp16");
|
||||
|
||||
// NOTE TO SELF this will be a join for later on for now they can use this.
|
||||
thumbnail_token = "";
|
||||
|
||||
// private_bucket_hash = format!("bucket_hash{}", i);
|
||||
private_bucket_prefix = format!("_fake");
|
||||
private_bucket_extension = format!("tt2");
|
||||
|
||||
cached_user_ratings_total_count = i;
|
||||
cached_user_ratings_positive_count = i;
|
||||
cached_user_ratings_negative_count = i;
|
||||
cached_user_ratings_ratio = i as u32 / 100;
|
||||
version = i as i32;
|
||||
println!("Seeding TT2 model {}", i);
|
||||
},
|
||||
41..=60 => {
|
||||
// SD 1.5
|
||||
model_weight_token = ModelWeightToken(format!("{}", i));
|
||||
title = format!("dragonfruitGTv1: {}", i);
|
||||
|
||||
description = format!("Description Number {}:", i);
|
||||
|
||||
description_rendered_html = sd1_5_markdown_description;
|
||||
|
||||
original_filename = format!("filename{}.txt", i);
|
||||
original_download_url = format!("https://civitai.com/api/download/models/149193?type=Model&format=SafeTensor&size=pruned&fp=fp16");
|
||||
|
||||
// NOTE TO SELF this will be a join for later on for now they can use this.
|
||||
thumbnail_token = ""; //sd1_5_image_token;
|
||||
|
||||
// private_bucket_hash = format!("bucket_hash{}", i);
|
||||
private_bucket_prefix = format!("_fake");
|
||||
private_bucket_extension = format!("sd15");
|
||||
|
||||
cached_user_ratings_total_count = i;
|
||||
cached_user_ratings_positive_count = i;
|
||||
cached_user_ratings_negative_count = i;
|
||||
cached_user_ratings_ratio = i as u32 / 100;
|
||||
version = i as i32;
|
||||
println!("Seeding SD15 model {}", i);
|
||||
},
|
||||
61..=80 => {
|
||||
// SD XL
|
||||
let sdxl_markdown_description = r#"
|
||||
# Special Edition Release Announcement
|
||||
|
||||
## What's New?
|
||||
- **Improved Quality:** The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.
|
||||
|
||||
## Tips for Use
|
||||
1. **Simple Prompts:** Avoid adding words like "detailed, realistic..." or specifying a specific artist. Simply describe what you want to see.
|
||||
2. **CFG Scale:** A range between 3 and 8.5 is effective (recommended: 7).
|
||||
3. **Minimum Steps:** Ensure at least 36 steps for optimal results.
|
||||
4. **Compatibility:**
|
||||
- Works excellently with Hires fix.
|
||||
- Great results with unaestheticXLv31 embedding, although sometimes better without it.
|
||||
5. **Sampling Method:** Either DPM++ 2M SDE Karras or DPM++ 2M Karras.
|
||||
|
||||
Have fun! 😊
|
||||
"#;
|
||||
let sdxl_image_token = "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/be706282-2978-42a0-aaa2-73881aad94e9/width=1024/00049-2287632957-1girl,face,curly%20hair,red%20hair,white%20background,.jpeg";
|
||||
|
||||
model_weight_token = ModelWeightToken(format!("{}", i));
|
||||
title = format!("SDXL_Niji_Special Edition: {}", i);
|
||||
description = format!("Description Number {}:", i);
|
||||
|
||||
// private_bucket_hash = format!("bucket_hash{}", i);
|
||||
private_bucket_prefix = format!("_fake");
|
||||
private_bucket_extension = format!("sdxl");
|
||||
|
||||
description_rendered_html = sdxl_markdown_description;
|
||||
|
||||
original_filename = format!("filename{}.txt", i);
|
||||
original_download_url = format!("https://civitai.com/api/download/models/149193?type=Model&format=SafeTensor&size=pruned&fp=fp16");
|
||||
|
||||
// NOTE TO SELF this will be a join for later on for now they can use this.
|
||||
thumbnail_token = "";
|
||||
|
||||
cached_user_ratings_total_count = i;
|
||||
cached_user_ratings_positive_count = i;
|
||||
cached_user_ratings_negative_count = i;
|
||||
cached_user_ratings_ratio = i as u32 / 100;
|
||||
version = i as i32;
|
||||
println!("Seeding SDXL model {}", i);
|
||||
},
|
||||
81..=100 => {
|
||||
// LoRA
|
||||
let lora_markdown_description = r#"
|
||||
- **Improved Quality:** The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.
|
||||
- LoRA Gawr Gura
|
||||
"#;
|
||||
|
||||
let lora_image_token = "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/123645df-dee2-4239-863a-76a150b09c32/width=1024/00000-2171948503.jpeg";
|
||||
model_weight_token = ModelWeightToken(format!("{}", i));
|
||||
title = format!("Gawr Gura LoRA: {}", i);
|
||||
|
||||
description = format!("Description Number {}:", i);
|
||||
|
||||
description_rendered_html = lora_markdown_description;
|
||||
|
||||
original_filename = format!("filename{}.txt", i);
|
||||
original_download_url = format!("https://civitai.com/api/download/models/149193?type=Model&format=SafeTensor&size=pruned&fp=fp16");
|
||||
|
||||
// NOTE TO SELF this will be a join for later on for now they can use this.
|
||||
thumbnail_token = ""; // lora_image_token;
|
||||
|
||||
// private_bucket_hash = format!("bucket_hash{}", i);
|
||||
private_bucket_prefix = format!("_fake");
|
||||
private_bucket_extension = format!("loRA");
|
||||
|
||||
cached_user_ratings_total_count = i;
|
||||
cached_user_ratings_positive_count = i;
|
||||
cached_user_ratings_negative_count = i;
|
||||
cached_user_ratings_ratio = i as u32 / 100;
|
||||
version = i as i32;
|
||||
println!("Seeding LoRA model {}", i);
|
||||
},
|
||||
_ => {
|
||||
// We went out of range so have more gwar gura
|
||||
let rvc_markdown_description = r#"
|
||||
# RVC v2
|
||||
- **Improved Quality:** The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.
|
||||
- Gawr Gura MOS 4
|
||||
"#;
|
||||
|
||||
model_weight_token = ModelWeightToken(format!("{}", i));
|
||||
title = format!("Gawr Gura: {}", i);
|
||||
description = format!("Description Number {} The special edition offers significantly better quality with fewer issues. It's the model as initially envisioned.", i);
|
||||
description_rendered_html = rvc_markdown_description;
|
||||
|
||||
original_filename = format!("gura_gwar{}.safetensors", i);
|
||||
original_download_url = format!("www.google.ca");
|
||||
|
||||
// NOTE TO SELF this will be a join for later on for now they can use this.
|
||||
thumbnail_token = "";
|
||||
|
||||
// private_bucket_hash = format!("bucket_hash{}", i);
|
||||
private_bucket_prefix = format!("_fake");
|
||||
private_bucket_extension = format!("rvcV2");
|
||||
cached_user_ratings_total_count = i;
|
||||
cached_user_ratings_positive_count = i;
|
||||
cached_user_ratings_negative_count = i;
|
||||
cached_user_ratings_ratio = i as u32 / 100;
|
||||
version = i as i32;
|
||||
|
||||
println!("Out of range");
|
||||
}
|
||||
}
|
||||
|
||||
let args = CreateModelWeightsArgs {
|
||||
token: &model_weight_token, // replace with actual ModelWeightToken
|
||||
weights_type: weights_types, // replace with actual WeightsType
|
||||
weights_category, // replace with actual WeightsCategory
|
||||
title,
|
||||
maybe_thumbnail_token: Some(thumbnail_token.to_string()),
|
||||
description_markdown: description,
|
||||
description_rendered_html: description_rendered_html.to_string(),
|
||||
creator_user_token: Some(&user_token), // replace with actual UserToken
|
||||
creator_ip_address: "192.168.1.1",
|
||||
creator_set_visibility: Visibility::Public,
|
||||
maybe_last_update_user_token: Some(user_token.to_string()),
|
||||
original_download_url: Some(original_download_url),
|
||||
original_filename: Some(original_filename),
|
||||
file_size_bytes: 1024,
|
||||
file_checksum_sha2: "checksum1".to_string(),
|
||||
private_bucket_hash: "bucket_hash1".to_string(),
|
||||
maybe_private_bucket_prefix: Some(private_bucket_prefix),
|
||||
maybe_private_bucket_extension: Some(private_bucket_extension),
|
||||
cached_user_ratings_total_count,
|
||||
cached_user_ratings_positive_count,
|
||||
cached_user_ratings_negative_count,
|
||||
maybe_cached_user_ratings_ratio: Some(cached_user_ratings_ratio as f32),
|
||||
version,
|
||||
mysql_pool: &mysql_pool, // replace with actual MySqlPool
|
||||
};
|
||||
|
||||
create_weight(args).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub async fn seed_weights_for_user_token(
|
||||
mysql_pool: &Pool<MySql>,
|
||||
user_token: UserToken
|
||||
@@ -165,16 +502,9 @@ pub async fn seed_weights_for_user_token(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub async fn seed_weights(mysql_pool: &Pool<MySql>) -> AnyhowResult<()> {
|
||||
info!("Seeding weights...");
|
||||
|
||||
let user_token = match get_user_token_by_username(HANASHI_USERNAME, mysql_pool).await? {
|
||||
None => {
|
||||
return Err(anyhow!("could not find user hanashi"));
|
||||
}
|
||||
Some(token) => token,
|
||||
};
|
||||
|
||||
pub async fn original_seed_weights(mysql_pool: &Pool<MySql>,user_token: UserToken) -> AnyhowResult<()> {
|
||||
let model_weight_token1 = ModelWeightToken("1".to_string());
|
||||
let creator_token1 = UserToken("creatorToken1".to_string());
|
||||
|
||||
@@ -327,9 +657,22 @@ pub async fn seed_weights(mysql_pool: &Pool<MySql>) -> AnyhowResult<()> {
|
||||
create_weight(model_weights_arg).await?;
|
||||
}
|
||||
|
||||
// adds this to HANASHI
|
||||
get_user_token_by_username(HANASHI_USERNAME, mysql_pool).await?;
|
||||
seed_weights_for_user_token(mysql_pool, user_token).await?;
|
||||
Ok(())
|
||||
|
||||
}
|
||||
pub async fn seed_weights(mysql_pool: &Pool<MySql>) -> AnyhowResult<()> {
|
||||
info!("Seeding weights...");
|
||||
|
||||
let user_token = match get_user_token_by_username(HANASHI_USERNAME, mysql_pool).await? {
|
||||
None => {
|
||||
return Err(anyhow!("could not find user hanashi"));
|
||||
}
|
||||
Some(token) => token,
|
||||
};
|
||||
|
||||
//original_seed_weights(mysql_pool,user_token).await?;
|
||||
//seed_weights_for_user_token(mysql_pool, user_token).await?;
|
||||
seed_weights_for_paging(mysql_pool,user_token).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ mimetypes = { path = "../../lib/files/mimetypes" }
|
||||
mysql_queries = { path = "../../lib/mysql_queries" }
|
||||
tokens = { path = "../../_types/tokens" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
clap = "2.34.0" # TODO: This is really out of date, but has conflicts when updated
|
||||
log = "0.4.14"
|
||||
@@ -33,12 +36,7 @@ log = "0.4.14"
|
||||
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
|
||||
tokio = { version = "1.6.0", features = ["macros"] }
|
||||
|
||||
# MySql Database
|
||||
# "offline" supports typesafe builds without a live database
|
||||
# "rustls" doesn't appear to work with IP addresses, per:
|
||||
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -24,6 +24,9 @@ mysql_queries = { path = "../../lib/mysql_queries" }
|
||||
storyteller_root = { path = "../../lib/storyteller_root" }
|
||||
tokens = { path = "../../_types/tokens" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
log = "0.4.14"
|
||||
clap = "2.34.0" # TODO: This is really out of date, but has conflicts when updated
|
||||
@@ -33,10 +36,6 @@ strum = { version = "0.25", features = ["derive"] }
|
||||
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
|
||||
tokio = { version = "1.6.0", features = ["macros"] }
|
||||
|
||||
# MySql Database
|
||||
# "offline" supports typesafe builds without a live database
|
||||
# "rustls" doesn't appear to work with IP addresses, per:
|
||||
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
|
||||
|
||||
elasticsearch = "8.5.0-alpha.1"
|
||||
@@ -45,7 +44,6 @@ elasticsearch = "8.5.0-alpha.1"
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
serde_json = "1.0.108"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -18,12 +18,14 @@ config = { path = "../../lib/deprecated/config" }
|
||||
easyenv = { path = "../../lib/easyenv" }
|
||||
errors = { path = "../../lib/errors" }
|
||||
|
||||
# Workspace hack (faster compile yytimes)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
log = "0.4.20"
|
||||
once_cell = "1.18.0"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.0"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Async Runtime
|
||||
# NB: Not using Tokio here since everything is blocking so far.
|
||||
|
||||
@@ -17,10 +17,12 @@ path = "src/main.rs"
|
||||
errors = { path = "../../lib/errors" }
|
||||
logging = { path = "../../lib/logging" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
clap = { version = "4.4.7", features = ["derive"] }
|
||||
walkdir = "2.4.0"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -18,7 +18,9 @@ path = "src/main.rs"
|
||||
errors = { path = "../../lib/errors" }
|
||||
web_scrapers = { path = "../../lib/web_scrapers" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
clap = "2.34.0" # TODO: This is really out of date, but has conflicts when updated
|
||||
tokio = { version = "1.6.0", features = ["macros"] }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
@@ -17,6 +17,9 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../lib/errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# Actix
|
||||
actix-http = "3.4.0"
|
||||
actix-rt = "2.9.0"
|
||||
@@ -34,7 +37,6 @@ futures-util = "0.3.29"
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_json = "1.0.108"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -17,6 +17,9 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
buckets = { path = "../../../_types/buckets" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
log = "0.4.14"
|
||||
@@ -28,4 +31,3 @@ rust-s3 = { version = "0.33.0" }
|
||||
# Runtime
|
||||
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
|
||||
tokio = { version = "1.6.0", features = ["macros"] }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
@@ -20,7 +20,7 @@ tokens = { path = "../../../_types/tokens" }
|
||||
|
||||
# External
|
||||
bytes = "1.3"
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
log = "0.4.14"
|
||||
once_cell = "1.9.0"
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ path = "src/lib.rs"
|
||||
container_common = { path = "../../deprecated/container_common" }
|
||||
subprocess_common = { path = "../../subprocess_common" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
log = "0.4.14"
|
||||
tempdir = "0.3.7"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ path = "src/lib.rs"
|
||||
container_common = { path = "../../deprecated/container_common" }
|
||||
easyenv = { path = "../../easyenv" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
once_cell = "1.18.0"
|
||||
@@ -31,4 +34,3 @@ twitch_oauth2 = "0.6.0-rc.2"
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
@@ -19,11 +19,13 @@ easyenv = { path = "../easyenv" }
|
||||
errors = { path = "../errors" }
|
||||
server_environment = { path = "../server_environment" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
dotenv = "0.15.0"
|
||||
hostname = "0.3.1"
|
||||
log = "0.4.14"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -17,9 +17,11 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
|
||||
# In-memory caching
|
||||
lru_time_cache = "0.11.11"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
@@ -16,6 +16,9 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Redis Database
|
||||
r2d2_redis = "0.14.0"
|
||||
|
||||
@@ -23,7 +26,6 @@ r2d2_redis = "0.14.0"
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
serde_json = "1.0.108"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -16,7 +16,9 @@ path = "src/lib.rs"
|
||||
[dependencies]
|
||||
# Internal
|
||||
errors = { path = "../errors" }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
# KEEP THIS TO A MINIMUM OR NIL.
|
||||
|
||||
@@ -14,7 +14,10 @@ path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
# (None yet)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
# (None yet)
|
||||
|
||||
@@ -17,11 +17,13 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
hmac = "0.10.0" # jwt signing
|
||||
jwt = "0.13.0"
|
||||
sha2 = "0.9.5" # hmac signing
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -15,8 +15,14 @@ name = "crockford"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
# (None yet)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
rand = "0.8.5"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -13,9 +13,15 @@ name = "datetimes"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
# Internal
|
||||
# (None yet)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
once_cell = "1.18.0"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# (none)
|
||||
@@ -18,7 +18,9 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
easyenv = { path = "../../../lib/easyenv" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
url = "2.4.1"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
@@ -21,10 +21,12 @@ rand = "0.8.5"
|
||||
uuid = { version = "0.8.2", features = ["v4"] }
|
||||
log = "0.4.14"
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Serialization
|
||||
serde = { version = "1.0.125", features = ["derive"] }
|
||||
toml = "0.5.8"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
|
||||
@@ -18,10 +18,13 @@ path = "src/lib.rs"
|
||||
errors = { path = "../../errors" }
|
||||
reusable_types = { path = "../../../_types/reusable_types" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
base64 = "0.21.0"
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
log = "0.4.14"
|
||||
once_cell = "1.18.0"
|
||||
regex = "1.5.4"
|
||||
@@ -39,7 +42,6 @@ language-tags = "0.3.2" # Parsing single tags richly
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
serde_json = "1.0.108"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "2.9.0"
|
||||
|
||||
@@ -16,11 +16,13 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
storyteller_root = { path = "../storyteller_root" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
dotenv = "0.15.0"
|
||||
env_logger = "0.10.1"
|
||||
log = "0.4.14"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -23,10 +23,10 @@ elasticsearch = "8.5.0-alpha.1"
|
||||
log = "0.4.14"
|
||||
|
||||
# Serialization
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.108"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -10,6 +10,12 @@ path = "src/lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
errors = { path = "../errors" }
|
||||
lettre = "0.11.0"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
lettre = "0.11.2"
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ path = "src/lib.rs"
|
||||
# Consider the dependencies here wisely.
|
||||
# Ideally we have almost nothing as a dependency of this crate.
|
||||
anyhow = "1.0.75"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -18,9 +18,11 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
zip = "0.6.6"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -16,11 +16,14 @@ path = "src/lib.rs"
|
||||
[dependencies]
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
log = "0.4.20"
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
# KEEP THIS TO A MINIMUM OR NIL.
|
||||
log = "0.4.20"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -17,12 +17,14 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
bcrypt = "0.8" # password hashes
|
||||
data-encoding = "2.3.2"
|
||||
md-5 = "0.9.1" # DO NOT USE FOR SERIOUS CRYPTO (we use this for gravatar)
|
||||
ring = "0.17.0-alpha.10"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -19,9 +19,11 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
image = "0.24.1"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
testing = { path = "../../testing" }
|
||||
|
||||
@@ -17,6 +17,9 @@ path = "src/lib.rs"
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
log = "0.4.14"
|
||||
|
||||
@@ -26,7 +29,5 @@ log = "0.4.14"
|
||||
# Opus is the browser's default (only) recording codec: https://blog.addpipe.com/audio-constraints-getusermedia/
|
||||
symphonia = { git = "https://github.com/pdeljanov/Symphonia.git", rev = "e1a70095c4409478c1ded499fb8dd4afa540fb90", features = ["aac", "alac", "flac", "isomp4", "mkv", "mp3", "ogg", "opus", "vorbis", "wav"] }
|
||||
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -14,9 +14,12 @@ name = "mimetypes"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
infer = "0.11" # Mimetype detection
|
||||
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -17,9 +17,11 @@ path = "src/lib.rs"
|
||||
# errors = { path = "../../lib/errors" }
|
||||
# (None yet)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
uuid = { version = "0.8.2", features = ["v4"] }
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -22,9 +22,11 @@ container_common = { path = "../deprecated/container_common" }
|
||||
errors = { path = "../errors" }
|
||||
redis_common = { path = "../redis_common" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
log = "0.4.14"
|
||||
r2d2_redis = "0.14.0"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
@@ -14,10 +14,16 @@ name = "logging"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
# (None yet)
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
dotenv = "0.15.0"
|
||||
env_logger = "0.10.1"
|
||||
log = "0.4.20"
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
|
||||
@@ -23,9 +23,12 @@ errors = { path = "../errors" }
|
||||
reusable_types = { path = "../../_types/reusable_types" }
|
||||
tokens = { path = "../../_types/tokens" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.75"
|
||||
chrono = { version = "=0.4.22", features = ["serde"] }
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
dotenv = "0.15.0"
|
||||
log = "0.4.14"
|
||||
|
||||
@@ -39,14 +42,9 @@ serde_derive = "1.0.125"
|
||||
serde_json = "1.0.108"
|
||||
toml = "0.5.8"
|
||||
serial_test = "2.0.0"
|
||||
# MySql Database
|
||||
# "offline" supports typesafe builds without a live database
|
||||
# "rustls" doesn't appear to work with IP addresses, per:
|
||||
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
|
||||
|
||||
tokio = { version = "1.6.0", features = ["full"] }
|
||||
rand = "0.8"
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
|
||||
|
||||
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
use enums::by_table::favorites::favorite_entity_type::FavoriteEntityType;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::tts_models::TtsModelToken;
|
||||
use tokens::tokens::tts_results::TtsResultToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
use tokens::tokens::voice_conversion_models::VoiceConversionModelToken;
|
||||
use tokens::tokens::w2l_results::W2lResultToken;
|
||||
use tokens::tokens::w2l_templates::W2lTemplateToken;
|
||||
use tokens::tokens::zs_voices::ZsVoiceToken;
|
||||
|
||||
pub enum FavoriteEntityToken {
|
||||
User(UserToken),
|
||||
TtsModel(TtsModelToken),
|
||||
TtsResult(TtsResultToken),
|
||||
W2lTemplate(W2lTemplateToken),
|
||||
W2lResult(W2lResultToken),
|
||||
MediaFile(MediaFileToken),
|
||||
VoiceConversionModel(VoiceConversionModelToken),
|
||||
ZsVoice(ZsVoiceToken),
|
||||
}
|
||||
|
||||
impl FavoriteEntityToken {
|
||||
pub fn from_entity_type_and_token(entity_type: FavoriteEntityType, token: &str) -> Self {
|
||||
match entity_type {
|
||||
FavoriteEntityType::User => Self::User(UserToken::new_from_str(token)),
|
||||
FavoriteEntityType::TtsModel => Self::TtsModel(TtsModelToken::new_from_str(token)),
|
||||
FavoriteEntityType::TtsResult => Self::TtsResult(TtsResultToken::new_from_str(token)),
|
||||
FavoriteEntityType::W2lTemplate => Self::W2lTemplate(W2lTemplateToken::new_from_str(token)),
|
||||
FavoriteEntityType::W2lResult => Self::W2lResult(W2lResultToken::new_from_str(token)),
|
||||
FavoriteEntityType::MediaFile => Self::MediaFile(MediaFileToken::new_from_str(token)),
|
||||
FavoriteEntityType::VoiceConversionModel => Self::VoiceConversionModel(VoiceConversionModelToken::new_from_str(token)),
|
||||
FavoriteEntityType::ZsVoice => Self::ZsVoice(ZsVoiceToken::new_from_str(token)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_composite_keys(&self) -> (FavoriteEntityType, &str) {
|
||||
match self {
|
||||
FavoriteEntityToken::User(user_token) => (FavoriteEntityType::User, user_token.as_str()),
|
||||
FavoriteEntityToken::TtsModel(tts_model_token) => (FavoriteEntityType::TtsModel, tts_model_token.as_str()),
|
||||
FavoriteEntityToken::TtsResult(tts_result_token) => (FavoriteEntityType::TtsResult, tts_result_token.as_str()),
|
||||
FavoriteEntityToken::W2lTemplate(w2l_template_token) => (FavoriteEntityType::W2lTemplate, w2l_template_token.as_str()),
|
||||
FavoriteEntityToken::W2lResult(w2l_result_token) => (FavoriteEntityType::W2lResult, w2l_result_token.as_str()),
|
||||
FavoriteEntityToken::MediaFile(media_file_token) => (FavoriteEntityType::MediaFile, media_file_token.as_str()),
|
||||
FavoriteEntityToken::VoiceConversionModel(voice_conversion_model_token) => (FavoriteEntityType::VoiceConversionModel, voice_conversion_model_token.as_str()),
|
||||
FavoriteEntityToken::ZsVoice(zs_voice_token) => (FavoriteEntityType::ZsVoice, zs_voice_token.as_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
pub mod create_favorite;
|
||||
pub mod delete_favorite;
|
||||
pub mod favorite_entity_token;
|
||||
pub mod get_favorite;
|
||||
pub mod list_favorites_for_entity;
|
||||
pub mod list_user_favorites;
|
||||
pub mod list_user_favorites_result;
|
||||
+70
-6
@@ -1,4 +1,5 @@
|
||||
use anyhow::anyhow;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
use sqlx::{MySql, MySqlPool};
|
||||
@@ -14,7 +15,7 @@ use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::helpers::boolean_converters::i8_to_bool;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct GenericInferenceJobStatus {
|
||||
pub job_token: InferenceJobToken,
|
||||
|
||||
@@ -40,7 +41,7 @@ pub struct GenericInferenceJobStatus {
|
||||
|
||||
/// Details about the user's original inference request
|
||||
/// (We may want to present it in the "pending" UI.)
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct RequestDetails {
|
||||
pub inference_category: InferenceCategory,
|
||||
pub maybe_model_type: Option<String>, // TODO: Strongly type
|
||||
@@ -52,7 +53,7 @@ pub struct RequestDetails {
|
||||
}
|
||||
|
||||
/// Details about the generated result
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ResultDetails {
|
||||
pub entity_type: String,
|
||||
pub entity_token: String,
|
||||
@@ -71,7 +72,7 @@ pub struct ResultDetails {
|
||||
|
||||
/// NB: DO NOT EXPOSE TO FRONTEND.
|
||||
/// This is used to gate access to job termination
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct UserDetails {
|
||||
pub maybe_creator_user_token: Option<UserToken>,
|
||||
pub maybe_creator_anonymous_visitor_token: Option<AnonymousVisitorTrackingToken>,
|
||||
@@ -168,6 +169,11 @@ WHERE jobs.token = ?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Some(raw_record_to_public_result(record)))
|
||||
}
|
||||
|
||||
/// Map the internal record type (since we query over several result tables)
|
||||
fn raw_record_to_public_result(record: RawGenericInferenceJobStatus) -> GenericInferenceJobStatus {
|
||||
let maybe_model_title = match record.inference_category {
|
||||
InferenceCategory::LipsyncAnimation => Some("lipsync animation"),
|
||||
InferenceCategory::TextToSpeech => record.maybe_tts_model_title.as_deref(),
|
||||
@@ -213,7 +219,7 @@ WHERE jobs.token = ?
|
||||
})
|
||||
});
|
||||
|
||||
Ok(Some(GenericInferenceJobStatus {
|
||||
GenericInferenceJobStatus {
|
||||
job_token: record.job_token,
|
||||
status: record.status,
|
||||
attempt_count: record.attempt_count,
|
||||
@@ -237,9 +243,10 @@ WHERE jobs.token = ?
|
||||
is_keepalive_required: i8_to_bool(record.is_keepalive_required),
|
||||
created_at: record.created_at,
|
||||
updated_at: record.updated_at,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct RawGenericInferenceJobStatus {
|
||||
pub job_token: InferenceJobToken,
|
||||
|
||||
@@ -281,3 +288,60 @@ struct RawGenericInferenceJobStatus {
|
||||
pub maybe_successfully_completed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use crate::queries::generic_inference::web::get_inference_job_status::{raw_record_to_public_result, RawGenericInferenceJobStatus};
|
||||
|
||||
#[test]
|
||||
fn text_to_speech_as_media_file() {
|
||||
// NB(bt,2023-12-06): After tts migration to media files, these are the results the job system will return
|
||||
let record = RawGenericInferenceJobStatus {
|
||||
inference_category: InferenceCategory::TextToSpeech,
|
||||
maybe_result_entity_type: Some("media_file".to_string()), // NB: Media file record
|
||||
maybe_result_entity_token: Some("m_00af018cy75pxytpb8wbdx9jqgtp0p".to_string()),
|
||||
maybe_media_file_public_bucket_directory_hash: Some("3vb91yq71z5zne56saazn4qntt52yter".to_string()), // NB: Media file
|
||||
maybe_media_file_public_bucket_prefix: Some("fakeyou_".to_string()),
|
||||
maybe_media_file_public_bucket_extension: Some(".wav".to_string()),
|
||||
maybe_tts_public_bucket_path: None, // NB: Not a tts_result!
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let record = raw_record_to_public_result(record);
|
||||
|
||||
assert!(record.maybe_result_details.is_some());
|
||||
|
||||
let result_details = record.maybe_result_details.expect("should have result details");
|
||||
|
||||
assert_eq!(&result_details.entity_type, "media_file");
|
||||
assert_eq!(&result_details.entity_token, "m_00af018cy75pxytpb8wbdx9jqgtp0p");
|
||||
assert_eq!(&result_details.public_bucket_location_or_hash, "3vb91yq71z5zne56saazn4qntt52yter");
|
||||
assert_eq!(result_details.public_bucket_location_is_hash, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_to_speech_as_tts_result() {
|
||||
// NB(bt,2023-12-06): Prior to tts migration to media files, these are the results the job system will return
|
||||
let record = RawGenericInferenceJobStatus {
|
||||
inference_category: InferenceCategory::TextToSpeech,
|
||||
maybe_result_entity_type: Some("text_to_speech".to_string()), // NB: TTS record
|
||||
maybe_result_entity_token: Some("TR:wefhbk4j3yc8d6zwembedbdw4ad4s".to_string()),
|
||||
maybe_tts_public_bucket_path: Some("/tts_inference_output/c/5/8/vocodes_c58aeaef-84df-4478-9e7f-c64280a852e8.wav".to_string()), // NB: tts_result!
|
||||
maybe_media_file_public_bucket_directory_hash: None, // NB: Not a media file!
|
||||
maybe_media_file_public_bucket_prefix: None,
|
||||
maybe_media_file_public_bucket_extension: None,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let record = raw_record_to_public_result(record);
|
||||
|
||||
assert!(record.maybe_result_details.is_some());
|
||||
|
||||
let result_details = record.maybe_result_details.expect("should have result details");
|
||||
|
||||
assert_eq!(&result_details.entity_type, "text_to_speech");
|
||||
assert_eq!(&result_details.entity_token, "TR:wefhbk4j3yc8d6zwembedbdw4ad4s");
|
||||
assert_eq!(&result_details.public_bucket_location_or_hash, "/tts_inference_output/c/5/8/vocodes_c58aeaef-84df-4478-9e7f-c64280a852e8.wav");
|
||||
assert_eq!(result_details.public_bucket_location_is_hash, false);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -81,7 +81,7 @@ WHERE status IN(
|
||||
separated.push_unseparated(") ");
|
||||
|
||||
if let Some(priority) = maybe_priority_or_lower {
|
||||
query_builder.push(format!(" AND priority <= {priority} "));
|
||||
query_builder.push(format!(" AND priority_level <= {priority} "));
|
||||
}
|
||||
|
||||
match target {
|
||||
@@ -136,7 +136,7 @@ mod tests {
|
||||
let statuses = HashSet::from([KillableStatus::Failed]);
|
||||
let builder = query_builder(statuses, KillableTarget::AllJobs, Some(10));
|
||||
let query = cleanup_query(&builder.into_sql());
|
||||
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?) AND priority <= 10".to_string());
|
||||
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?) AND priority_level <= 10".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user