Compare commits

..
Author SHA1 Message Date
saltacc 25b90c07ce add model downloading 2023-12-18 15:49:55 -08:00
saltacc 2f971dda60 add model downloading 2023-12-13 21:17:44 -08:00
saltacc b30c352d79 pass tests 2023-12-13 16:29:45 -08:00
saltacc cb2d36401c merge rerender a video 2023-12-13 16:12:30 -08:00
Brandon Thomas 7dea4c64fa Merge pull request #208 from storytold/brandon-more-rate-limiter-fixes
more rate limiter fixes
2023-12-13 17:04:14 -05:00
Brandon Thomas 9ab8e52211 more rate limiter fixes 2023-12-13 16:58:37 -05:00
Brandon Thomas 81dd377599 clean up and test rate limiter choice code 2023-12-13 15:27:34 -05:00
Brandon Thomas e641f26d21 Merge pull request #207 from storytold/brandon-ai-streamer-support
Rate limiter support for AI streamers
2023-12-13 13:35:51 -05:00
Brandon Thomas 3766758cfb Rate limiter support for AI streamers 2023-12-13 13:33:48 -05:00
Brandon Thomas 196be25fb5 voice takedown requests 2023-12-13 11:04:13 -05:00
salt 57e2f70707 WORKING! 2023-12-12 23:07:27 -08:00
salt 292b831d16 update tests 2023-12-12 17:36:53 -08:00
salt d51ee67d4c complete failure 2023-12-12 17:35:36 -08:00
Brandon Thomas e375c8090c fix IDE handling (code compiled and tested, but IDE unhappy) 2023-12-12 19:21:42 -05:00
Brandon Thomas e5a85c7528 fix failing doctest 2023-12-12 18:56:02 -05:00
salt 14432cce83 fix errors 2023-12-12 15:12:34 -08:00
salt 43030402ca update 2023-12-12 14:50:50 -08:00
salt 2d59c5c573 initial commit 2023-12-12 13:47:12 -08:00
Brandon Thomas 18309385b4 Merge pull request #204 from storytold/brandon-nix-newrelic
Kill newrelic. This is painful to keep upgrading
2023-12-12 11:58:33 -05:00
Brandon Thomas f9ff9b8c9f Kill newrelic. This is painful to keep upgrading
Keeping the vendor directory because we may introduce later. We've
already done some upkeep.
2023-12-12 11:57:42 -05:00
Brandon Thomas d22d64fac7 Merge pull request #195 from storytold/fix_warnings
Fix some warnings
2023-12-12 03:44:46 -05:00
Brandon Thomas 08d8e5279e Merge pull request #201 from storytold/dependabot/cargo/version-sync-0.9.5
Bump version-sync from 0.8.1 to 0.9.5
2023-12-12 03:43:43 -05:00
dependabot[bot] d9fe4e56a0 Bump version-sync from 0.8.1 to 0.9.5
Bumps [version-sync](https://github.com/mgeisler/version-sync) from 0.8.1 to 0.9.5.
- [Release notes](https://github.com/mgeisler/version-sync/releases)
- [Commits](https://github.com/mgeisler/version-sync/compare/0.8.1...0.9.5)

---
updated-dependencies:
- dependency-name: version-sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-12 08:00:32 +00:00
Brandon Thomas dcf6451693 Merge pull request #199 from storytold/dependabot/cargo/hyper-tls-0.6.0
Bump hyper-tls from 0.5.0 to 0.6.0
2023-12-12 02:57:31 -05:00
Brandon Thomas dbe3d5e977 Merge pull request #200 from storytold/dependabot/cargo/tokio-1.34.0
Bump tokio from 0.1.22 to 1.34.0
2023-12-12 02:56:41 -05:00
Brandon Thomas 07750fa122 refactor bucket modules 2023-12-12 02:55:23 -05:00
Brandon Thomas 795eb7a141 spacing nit 2023-12-12 02:15:06 -05:00
Brandon Thomas d49b01930e Merge pull request #198 from storytold/dec-07-mithoo-bookmarks
Rename favorites -> user_bookmarks, add new table
2023-12-11 23:36:22 -05:00
Brandon Thomas 052e4bfbd8 Merge pull request #203 from storytold/brandon-seed-media-files-2
seed video files + fix idempotency
2023-12-11 22:11:00 -05:00
Brandon Thomas 30d6bca9b2 seed video files + fix idempotency 2023-12-11 21:53:31 -05:00
Brandon Thomas 94d62736ad Merge pull request #202 from storytold/brandon-seed-media-files
Seed media files
2023-12-11 21:07:08 -05:00
Brandon Thomas 1cde23c080 Seed media files 2023-12-11 20:52:20 -05:00
dependabot[bot] d3be9a3a6b Bump tokio from 0.1.22 to 1.34.0
Bumps [tokio](https://github.com/tokio-rs/tokio) from 0.1.22 to 1.34.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-0.1.22...tokio-1.34.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 22:09:11 +00:00
dependabot[bot] c09adc3729 Bump hyper-tls from 0.5.0 to 0.6.0
Bumps [hyper-tls](https://github.com/hyperium/hyper-tls) from 0.5.0 to 0.6.0.
- [Commits](https://github.com/hyperium/hyper-tls/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: hyper-tls
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 22:08:50 +00:00
Michael Chung e78cdf85e3 Upload weights front end side done,
need to write the download code then run inference depending on the model.
2023-12-11 14:40:14 -05:00
kasisnu 5971d95a80 Rename favorites -> user_bookmarks, add new table 2023-12-11 21:08:33 +05:30
Brandon Thomas 602de6d736 env vars 2023-12-08 05:15:13 -05:00
Brandon Thomas de8eb05db6 inference-job - sadtalker to work with image media files 2023-12-08 04:45:28 -05:00
Brandon Thomas 996f8ce05b inference-job : sad talker to use audio media files 2023-12-08 04:38:46 -05:00
Brandon Thomas b4afec5c26 rename endpoint (internally) 2023-12-08 04:21:16 -05:00
Brandon Thomas ab1f81036f update my-workspace-hack 2023-12-08 04:00:42 -05:00
Brandon Thomas 4a806e7d67 codegen db 2023-12-08 02:16:50 -05:00
Brandon Thomas c811296bdc temporarily disable test 2023-12-08 02:04:34 -05:00
Brandon Thomas 6033289a36 fix most tests and lints 2023-12-08 01:36:39 -05:00
Brandon Thomas 90ec14b8d0 vendored needs to refer to workplace-hack 2023-12-08 01:27:10 -05:00
Brandon Thomas e18b86a55a everything needs to refer to workplace-hack 2023-12-08 01:25:49 -05:00
salt d39962491f fix some warnings (mostly unnecessary mut) 2023-12-07 18:36:51 -08:00
ArEnSc 6c320dd329 Merge pull request #180 from storytold/feature/weights_endpoints
Feature/weights endpoints WIP
2023-12-07 20:15:55 -05:00
Michael Chung fd95aaff8c Merge branch 'feature/weights_endpoints' of https://github.com/storytold/storyteller-rust into feature/weights_endpoints 2023-12-07 20:02:02 -05:00
Michael Chung 8afd10c864 minor fixes to spelling 2023-12-07 17:52:21 -05:00
ArEnSc 0e62fe9d08 Merge branch 'master' into feature/weights_endpoints 2023-12-07 00:35:53 -05:00
Michael Chung dda2e0840d Updated docs and weights_types 2023-12-07 00:25:57 -05:00
Michael Chung b26276cfda done now for code 2023-12-06 23:36:20 -05:00
Brandon Thomas eedbc346fe Merge pull request #194 from storytold/brandon-tts-as-media-file
Save TTS results as media files
2023-12-06 23:33:51 -05:00
Brandon Thomas 7976f68fd0 Save TTS results as media files 2023-12-06 23:31:47 -05:00
Michael Chung f327dfcdbb Builds and docs work 2023-12-06 23:27:34 -05:00
Michael Chung f4176bf84a Alright should fix the generation now... 2023-12-06 21:31:37 -05:00
Michael Chung 43b6808f23 Ok fixed docs and avaoilable weights endpoint 2023-12-06 20:05:23 -05:00
Michael Chung 330f24413d added missing file 2023-12-06 19:54:21 -05:00
Michael Chung af6370eea1 Issue with the api doc not sure. 2023-12-06 19:53:52 -05:00
Michael Chung 3a4ca7b548 weights doc complete. 2023-12-06 16:14:08 -05:00
Michael Chung f7d5ad496c Update docs 2023-12-06 14:01:31 -05:00
Brandon Thomas 8a6678c7f5 move workspace-hack under crates/ 2023-12-06 02:12:57 -05:00
Michael Chung f76928d001 Delete weight documentation added 2023-12-06 01:28:54 -05:00
Michael Chung 32cfb10323 added weights list documentation 2023-12-06 00:55:28 -05:00
Brandon Thomas d9b1c8c36b Merge pull request #192 from storytold/brandon-upgrade-chrono-vendored-limitation
upgrade chrono with vendored limitation
2023-12-05 21:54:36 -05:00
Brandon Thomas fc122cb996 upgrade chrono with vendored limitation 2023-12-05 21:54:06 -05:00
Michael Chung 08d3c389b9 Merge branch 'master' into feature/weights_endpoints 2023-12-05 21:48:14 -05:00
Michael Chung 1a3b02b5d2 Adding docs 2023-12-05 21:46:53 -05:00
Brandon Thomas e0e85fed5f Merge pull request #191 from storytold/brandon-vendor-limitation
vendor `limitation` crate
2023-12-05 20:58:27 -05:00
Brandon Thomas 092745166e vendor limitation crate
The limitation crate is four years old, stuck at 0.1.1. It looks unlikey
to be updated by the maintainer.

Upgrades to chrono and other libraries have broken limitation, so we're
likely now on the hook for maintaining this.
2023-12-05 20:56:22 -05:00
Michael Chung 024b4d769c Merge branch 'master' into feature/weights_endpoints 2023-12-05 20:41:44 -05:00
Brandon Thomas ea859bfc1e Merge pull request #190 from storytold/brandon-revert-chrono-upgrade
Revert "Bump chrono from 0.4.22 to 0.4.31"
2023-12-05 20:40:37 -05:00
Brandon Thomas 92e0b1e9f4 Revert "Bump chrono from 0.4.22 to 0.4.31"
This reverts commit 4856ac28aa.
2023-12-05 20:40:09 -05:00
ArEnSc d52d3f993a Merge pull request #189 from storytold/feature/api-spec
Feature/api spec
2023-12-05 20:27:57 -05:00
Brandon Thomas 514f80b884 Merge pull request #184 from storytold/dependabot/cargo/rustix-0.38.26
Bump rustix from 0.38.25 to 0.38.26
2023-12-05 19:22:24 -05:00
Brandon Thomas 74c548c02f Merge pull request #182 from storytold/dependabot/cargo/chrono-0.4.31
Bump chrono from 0.4.22 to 0.4.31
2023-12-05 19:21:53 -05:00
Brandon Thomas 5fe09a182f Merge pull request #185 from storytold/dependabot/cargo/lettre-0.11.2
Bump lettre from 0.11.1 to 0.11.2
2023-12-05 19:21:40 -05:00
dependabot[bot] 4856ac28aa Bump chrono from 0.4.22 to 0.4.31
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.22 to 0.4.31.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.22...v0.4.31)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 00:19:36 +00:00
Brandon Thomas 404853e129 cleanup misleading old comment 2023-12-05 19:16:55 -05:00
Brandon Thomas 300ac56ab7 Merge pull request #188 from storytold/brandon-media-files-global-list-fixed
global list of media files
2023-12-05 19:11:20 -05:00
Brandon Thomas e32f8094e5 global list of media files 2023-12-05 19:09:42 -05:00
Brandon Thomas 642e17a77d Merge pull request #187 from storytold/brandon-fix-sqlx-query-builder
Fix QueryBuilder with respect to column names and type juggling
2023-12-05 18:31:13 -05:00
Brandon Thomas 36f3003576 Fix QueryBuilder with respect to column names and type juggling 2023-12-05 18:30:26 -05:00
Michael Chung 4993410740 Built needs a simple endpoint query test 2023-12-05 14:54:32 -05:00
Michael Chung f99b5a92b8 Added weights paging to michael's spec missing the fields. 2023-12-05 13:44:50 -05:00
Brandon Thomas b9f604dd18 reusable pagination types 2023-12-04 23:11:41 -05:00
Michael Chung 130e0daa08 paging works correctly. 2023-12-04 22:49:33 -05:00
Brandon Thomas e6f5ecb980 Merge pull request #186 from storytold/brandon-list-media-files-for-user
list media files for user
2023-12-04 22:02:53 -05:00
Brandon Thomas 2e3ff8a730 list media files for user 2023-12-04 21:59:39 -05:00
Michael Chung cda690773f Merge branch 'master' into feature/weights_endpoints 2023-12-04 18:26:24 -05:00
Michael Chung 91d0a1da8f Tests pass again 2023-12-04 18:21:43 -05:00
Michael Chung 8c7b100150 Adding new seed then have to switch tests back. 2023-12-04 18:06:11 -05:00
dependabot[bot] ac13be2900 Bump lettre from 0.11.1 to 0.11.2
Bumps [lettre](https://github.com/lettre/lettre) from 0.11.1 to 0.11.2.
- [Release notes](https://github.com/lettre/lettre/releases)
- [Changelog](https://github.com/lettre/lettre/blob/master/CHANGELOG.md)
- [Commits](https://github.com/lettre/lettre/compare/v0.11.1...v0.11.2)

---
updated-dependencies:
- dependency-name: lettre
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 22:30:26 +00:00
dependabot[bot] b55435d992 Bump rustix from 0.38.25 to 0.38.26
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.25 to 0.38.26.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.25...v0.38.26)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 22:30:06 +00:00
Michael Chung ae5eea53fe Something wrong with the query parameters not passing off the limits etc 2023-12-04 03:57:40 -05:00
Michael Chung 241f648baf Add type filtering in there and category filtering 2023-12-04 03:38:51 -05:00
Michael Chung e4756a4f2c Added more data seeding to the database for the model_weights table. 2023-12-04 01:52:14 -05:00
Michael Chung 9c8ee8dbbb Ok list_weights_by_user works properly now. 2023-12-03 22:55:56 -05:00
Michael Chung 8072d13596 Fixed Delete and Updates for Weights 2023-12-03 01:35:04 -05:00
Michael Chung 1d937ab981 Initial weights_endpoints need testing right now. 2023-12-01 15:22:32 -05:00
Michael Chung 496ccd68f1 Working on uploads gonna be testing the endpoints soon.
Need a ui for the upload page to understand how to write it but it's similar to prior art just need to check that out.
2023-11-30 23:05:02 -05:00
Michael Chung 72fdd75568 added upload weights / create weight endpoint
original file for the weights
weights file type for safetensors or checkpoint
Gotta add one more thing for record creation
2023-11-30 17:33:25 -05:00
Michael Chung fba7d2a1eb needs some tests for users and query builds with pagination 2023-11-30 00:48:54 -05:00
Michael Chung 347fe685cd List list_availible_weights needs testing but is written. 2023-11-29 23:11:47 -05:00
Michael Chung 32331f9890 compiles working on list queries 2023-11-29 21:46:42 -05:00
Michael Chung 65d6f178bc WIP - weights endpoints need to be tested
Update weights endpoints had to be fixed.
should be ready to unit test the 3 endpoints before using the list weights
2023-11-29 17:07:18 -05:00
Michael Chung d9d166e500 Run routes using open api spec 2023-11-28 17:27:32 -05:00
285 changed files with 9359 additions and 1782 deletions
+2 -1
View File
@@ -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.
@@ -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"
}
@@ -1,12 +0,0 @@
{
"db_name": "MySQL",
"query": "\nINSERT INTO media_files\nSET\n token = ?,\n\n origin_category = ?,\n origin_product_category = ?,\n\n media_type = ?,\n maybe_mime_type = ?,\n file_size_bytes = ?,\n checksum_sha2 = ?,\n\n public_bucket_directory_hash = ?,\n maybe_public_bucket_prefix = ?,\n maybe_public_bucket_extension = ?,\n\n maybe_creator_user_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 13
},
"nullable": []
},
"hash": "030e26fa7977555cdd04864d9b95c07196ab520cd8c63d30689b6021fa4b4ec1"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nINSERT INTO media_files\nSET\n token = ?,\n\n origin_category = ?,\n origin_product_category = ?,\n\n media_type = ?,\n maybe_mime_type = ?,\n file_size_bytes = ?,\n checksum_sha2 = ?,\n\n maybe_origin_filename = ?,\n\n public_bucket_directory_hash = ?,\n maybe_public_bucket_prefix = ?,\n maybe_public_bucket_extension = ?,\n\n maybe_creator_user_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 14
},
"nullable": []
},
"hash": "8f8b81d54aeabb31a200de98ba3106ac6bea906979c89355f805abb9650a7588"
}
@@ -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"
}
@@ -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"
}
@@ -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
+196 -82
View File
@@ -468,6 +468,12 @@ dependencies = [
"tokio",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -521,7 +527,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -531,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -805,7 +811,7 @@ dependencies = [
"serde_json",
"sqlx",
"tokio",
"toml",
"toml 0.5.11",
"url_config",
]
@@ -1037,18 +1043,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.22"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-integer",
"num-traits",
"serde",
"time 0.1.45",
"wasm-bindgen",
"winapi 0.3.9",
"windows-targets 0.48.5",
]
[[package]]
@@ -1273,7 +1278,7 @@ dependencies = [
"rand 0.8.5",
"serde",
"tempfile",
"toml",
"toml 0.5.11",
"uuid 0.8.2",
]
@@ -2172,7 +2177,8 @@ dependencies = [
"sqlx-core",
"sqlx-mysql",
"strum",
"toml",
"toml 0.5.11",
"utoipa",
]
[[package]]
@@ -2196,12 +2202,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@@ -2220,7 +2226,7 @@ checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
dependencies = [
"cfg-if 1.0.0",
"home",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -2714,7 +2720,7 @@ version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
dependencies = [
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -2907,16 +2913,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.5.0"
@@ -3020,12 +3016,13 @@ dependencies = [
"log",
"media",
"memory_caching",
"mime",
"mimetypes",
"my-workspace-hack",
"mysql_queries",
"newrelic-telemetry",
"once_cell",
"r2d2_redis",
"rand 0.8.5",
"redis_common",
"serde",
"serde_derive",
@@ -3034,6 +3031,7 @@ dependencies = [
"subprocess",
"subprocess_common",
"tempdir",
"time 0.3.30",
"tokens",
"tokio",
"tts_common",
@@ -3080,7 +3078,7 @@ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi 0.3.3",
"rustix",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -3216,9 +3214,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "lettre"
version = "0.11.1"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a466bc111374ccf4d90877dba636924a2185e67e5be4b35d32043199365097b2"
checksum = "a48c2e9831b370bc2d7233c2620298c45f3a158ed6b4b8d7416b2ada5a268fd8"
dependencies = [
"base64 0.21.5",
"chumsky",
@@ -3228,7 +3226,7 @@ dependencies = [
"futures-util",
"hostname",
"httpdate",
"idna 0.4.0",
"idna",
"mime",
"native-tls",
"nom",
@@ -3294,13 +3292,14 @@ dependencies = [
[[package]]
name = "limitation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e415413963930f7050f21994bfd336dc75ef8b5b3b142e99c55b72b61f726d5"
dependencies = [
"chrono",
"futures 0.1.31",
"my-workspace-hack",
"redis 0.13.0",
"time 0.1.45",
"tokio",
"version-sync",
]
[[package]]
@@ -3601,7 +3600,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -3686,11 +3685,11 @@ dependencies = [
"generic-array",
"getrandom 0.1.16",
"getrandom 0.2.11",
"hashbrown 0.12.3",
"hashbrown 0.14.2",
"heck",
"hmac 0.12.1",
"hyper",
"indexmap",
"lazy_static",
"libc",
"log",
@@ -3737,7 +3736,8 @@ dependencies = [
"url",
"void",
"winapi 0.3.9",
"windows-sys",
"windows-sys 0.48.0",
"zip",
]
[[package]]
@@ -3765,7 +3765,7 @@ dependencies = [
"sqlx",
"tokens",
"tokio",
"toml",
"toml 0.5.11",
]
[[package]]
@@ -3819,25 +3819,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "newrelic-telemetry"
version = "0.1.0"
dependencies = [
"anyhow",
"env_logger",
"flate2",
"futures 0.3.29",
"hyper",
"hyper-tls",
"log",
"my-workspace-hack",
"rand 0.8.5",
"serde",
"serde_json",
"tokio",
"uuid 0.8.2",
]
[[package]]
name = "nix"
version = "0.26.4"
@@ -4132,7 +4113,7 @@ dependencies = [
"libc",
"redox_syscall 0.4.1",
"smallvec 1.11.2",
"windows-targets",
"windows-targets 0.48.5",
]
[[package]]
@@ -4837,7 +4818,7 @@ dependencies = [
"serde",
"serde_derive",
"sqlx",
"toml",
"toml 0.5.11",
]
[[package]]
@@ -4866,7 +4847,7 @@ dependencies = [
"libc",
"spin 0.9.8",
"untrusted 0.9.0",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -5011,15 +4992,15 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.25"
version = "0.38.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a"
dependencies = [
"bitflags 2.4.1",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@@ -5121,7 +5102,7 @@ version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
dependencies = [
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -5333,6 +5314,15 @@ dependencies = [
"syn 2.0.39",
]
[[package]]
name = "serde_spanned"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@@ -5583,7 +5573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -5915,6 +5905,7 @@ dependencies = [
"hex",
"hmac 0.10.1",
"hostname",
"http",
"http_server_common",
"hyper",
"infer 0.5.0",
@@ -5956,7 +5947,7 @@ dependencies = [
"time 0.3.30",
"tokens",
"tokio",
"toml",
"toml 0.5.11",
"tts_common",
"twitch_common",
"twitch_oauth2",
@@ -6302,7 +6293,7 @@ dependencies = [
"fastrand 2.0.1",
"redox_syscall 0.4.1",
"rustix",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -6457,7 +6448,7 @@ dependencies = [
"sqlx",
"sqlx-core",
"strum",
"toml",
"toml 0.5.11",
"utoipa",
]
@@ -6477,7 +6468,7 @@ dependencies = [
"signal-hook-registry",
"socket2 0.5.5",
"tokio-macros",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@@ -6656,6 +6647,40 @@ dependencies = [
"serde",
]
[[package]]
name = "toml"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
name = "tower-service"
version = "0.3.2"
@@ -6754,7 +6779,6 @@ dependencies = [
"memory_caching",
"my-workspace-hack",
"mysql_queries",
"newrelic-telemetry",
"r2d2_redis",
"serde",
"serde_derive",
@@ -6845,7 +6869,7 @@ dependencies = [
"tokens",
"tokio",
"tokio-tungstenite",
"toml",
"toml 0.5.11",
"tts_common",
"twitch_api2",
"twitch_common",
@@ -7007,7 +7031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna 0.5.0",
"idna",
"percent-encoding",
"serde",
]
@@ -7081,7 +7105,7 @@ dependencies = [
"strum_macros",
"time 0.3.30",
"tokens",
"toml",
"toml 0.5.11",
"user_input_common",
]
@@ -7165,6 +7189,21 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version-sync"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "835169da0173ea373ddf5987632aac1f918967fbbe58195e304342282efa6089"
dependencies = [
"proc-macro2",
"pulldown-cmark",
"regex",
"semver 1.0.20",
"syn 2.0.39",
"toml 0.7.8",
"url",
]
[[package]]
name = "version_check"
version = "0.9.4"
@@ -7464,7 +7503,7 @@ dependencies = [
"sqlx",
"time 0.3.30",
"tokio",
"toml",
"toml 0.5.11",
"twitch_api2",
"twitch_common",
"twitch_oauth2",
@@ -7532,7 +7571,7 @@ version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
"windows-targets",
"windows-targets 0.48.5",
]
[[package]]
@@ -7541,7 +7580,16 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
]
[[package]]
@@ -7550,13 +7598,28 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
]
[[package]]
@@ -7565,42 +7628,93 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "winnow"
version = "0.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
version = "0.50.0"
@@ -7608,7 +7722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
"cfg-if 1.0.0",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
+5 -3
View File
@@ -86,8 +86,10 @@ members = [
"crates/service/plugins/users",
# Vendored code
"crates/vendor/newrelic-telemetry-sdk-rust",
"crates/vendor/limitation",
# NB(bt,2023-12-12): Newrelic keeps breaking with upgrades. Kill for now.
#"crates/vendor/newrelic-telemetry-sdk-rust",
# Vendored code
"my-workspace-hack",
# cargo-hakari workspace hack (compilation speedup hack)
"crates/my-workspace-hack",
]
+30
View File
@@ -344,6 +344,36 @@ where token IN (
'vcm_zmxv2k1q9jd8'
);
update voice_conversion_models
set
mod_deleted_at = NOW(),
maybe_mod_comments = 'takedown request'
where token IN (
'vcm_3mzcjkf78x7m',
'vcm_7k2t1wnyqxsc',
'vcm_w2edpe6q2nya',
'vcm_vz9cg294xa29',
'vcm_0z1ys58589k7',
'vcm_4x8a30h1r26z',
'vcm_0vf9prxsww60',
'vcm_yxbadkvqhg16',
'vcm_p0ezrc6wvzak',
'vcm_6r5pbtexyvtp',
'vcm_pb0ewrf7ych5',
'vcm_7frb2xk0cxk3',
'vcm_x129c9s2af06',
'vcm_e0snndfd59b6',
'vcm_nb8zb0djqwqw',
'vcm_2erz5hbh8tpf',
'vcm_e9wn2ccqe3bk',
'vcm_f8jbxdbjgcjb',
'vcm_x02h7z3jqxb0',
'vcm_xy97xcgnk9y6',
'vcm_a47wtfbsjrfc',
'vcm_kygenhbg5mgj',
'vcm_s8gndv19yt7p'
);
@@ -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;
+3 -1
View File
@@ -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 -1
View File
@@ -1 +1,2 @@
pub mod private_path;
pub mod private_path;
pub mod zs_voices;
@@ -1,6 +1,6 @@
use crockford::crockford_entropy_lower;
use crate::private::private_path::PrivatePath;
use crate::private::private_path::PrivatePath;
use crate::util::hashed_directory_path_long_string::hashed_directory_path_long_string;
// TODO: Generate these from a macro.
@@ -79,7 +79,7 @@ impl ZeroShotVoiceEmbeddingBucketDirectory {
#[cfg(test)]
mod tests {
use crate::public::zs_voices::directory::{ModelCategory, ModelType, ZeroShotVoiceEmbeddingBucketDirectory};
use crate::private::zs_voices::bucket_directory::{ModelCategory, ModelType, ZeroShotVoiceEmbeddingBucketDirectory};
#[test]
pub fn generate_new_entropy() {
@@ -3,11 +3,10 @@ use std::path::PathBuf;
use crockford::crockford_entropy_lower;
use crate::private::private_path::PrivatePath;
use crate::public::zs_voices::directory::{ModelCategory, ModelType, ZeroShotVoiceEmbeddingBucketDirectory};
use crate::private::zs_voices::bucket_directory::{ModelCategory, ModelType, ZeroShotVoiceEmbeddingBucketDirectory};
// TODO: Generate these from a macro.
/// The original user upload file.
/// It may have derivative files (down samples, crops, etc.) that live alongside it.
#[derive(Clone)]
@@ -74,11 +73,9 @@ impl ZeroShotVoiceEmbeddingBucketPath {
mod tests {
use std::path::PathBuf;
use crate::public::media_files::original_file::MediaFileBucketPath;
mod with_prefix_and_extension {
use crate::public::zs_voices::directory::ModelCategory;
use crate::public::zs_voices::file::{ModelType, ZeroShotVoiceEmbeddingBucketPath};
use crate::private::zs_voices::bucket_directory::ModelCategory;
use crate::private::zs_voices::bucket_file_path::{ModelType, ZeroShotVoiceEmbeddingBucketPath};
#[test]
pub fn generate_new_entropy() {
@@ -97,8 +94,8 @@ mod tests {
}
mod without_prefix_and_extension {
use crate::public::zs_voices::directory::ModelCategory;
use crate::public::zs_voices::file::{ModelType, ZeroShotVoiceEmbeddingBucketPath};
use crate::private::zs_voices::bucket_directory::ModelCategory;
use crate::private::zs_voices::bucket_file_path::{ModelType, ZeroShotVoiceEmbeddingBucketPath};
use super::*;
@@ -135,7 +132,7 @@ mod tests {
#[test]
pub fn get_object_hash() {
let hash = "abcdefghijk";
let file = MediaFileBucketPath::from_object_hash(hash, None, None);
let file = ZeroShotVoiceEmbeddingBucketPath::from_object_hash(hash, ModelCategory::Tts, ModelType::VallEx, 1);
assert_eq!(file.get_object_hash(), hash);
}
}
@@ -0,0 +1,2 @@
pub mod bucket_directory;
pub mod bucket_file_path;
@@ -4,7 +4,6 @@ use crate::public::public_path::PublicPath;
use crate::util::hashed_directory_path_long_string::hashed_directory_path_long_string;
// TODO: Generate these from a macro.
// TODO: Use a central path registry for quick reference
const MEDIA_FILE_DIRECTORY: &str = "/media";
@@ -47,7 +46,7 @@ impl MediaFileBucketDirectory {
#[cfg(test)]
mod tests {
use crate::public::media_files::directory::MediaFileBucketDirectory;
use crate::public::media_files::bucket_directory::MediaFileBucketDirectory;
#[test]
pub fn generate_new_entropy() {
@@ -2,7 +2,7 @@ use std::path::PathBuf;
use crockford::crockford_entropy_lower;
use crate::public::media_files::directory::MediaFileBucketDirectory;
use crate::public::media_files::bucket_directory::MediaFileBucketDirectory;
use crate::public::public_path::PublicPath;
const ORIGINAL_FILE_BASENAME : &str = "file.bin";
@@ -79,7 +79,7 @@ impl MediaFileBucketPath {
mod tests {
use std::path::PathBuf;
use crate::public::media_files::original_file::MediaFileBucketPath;
use crate::public::media_files::bucket_file_path::MediaFileBucketPath;
mod with_prefix_and_extension {
use super::*;
@@ -1,2 +1,2 @@
pub mod directory;
pub mod original_file;
pub mod bucket_directory;
pub mod bucket_file_path;
@@ -47,7 +47,7 @@ impl MediaUploadDirectory {
#[cfg(test)]
mod tests {
use crate::public::media_uploads::directory::MediaUploadDirectory;
use crate::public::media_uploads::bucket_directory::MediaUploadDirectory;
#[test]
pub fn generate_new_entropy() {
@@ -2,7 +2,7 @@ use std::path::PathBuf;
use crockford::crockford_entropy_lower;
use crate::public::media_uploads::directory::MediaUploadDirectory;
use crate::public::media_uploads::bucket_directory::MediaUploadDirectory;
use crate::public::public_path::PublicPath;
const ORIGINAL_FILE_BASENAME : &str = "original_upload.bin";
@@ -61,7 +61,7 @@ impl MediaUploadOriginalFilePath {
mod tests {
use std::path::PathBuf;
use crate::public::media_uploads::original_file::MediaUploadOriginalFilePath;
use crate::public::media_uploads::bucket_file_path::MediaUploadOriginalFilePath;
#[test]
pub fn generate_new_entropy() {
@@ -1,2 +1,2 @@
pub mod directory;
pub mod original_file;
pub mod bucket_directory;
pub mod bucket_file_path;
+1 -1
View File
@@ -2,4 +2,4 @@ pub mod media_files;
pub mod media_uploads;
pub mod public_path;
pub mod voice_conversion_results;
pub mod zs_voices;
pub mod weight_uploads;
@@ -40,7 +40,7 @@ impl VoiceConversionResultDirectory {
#[cfg(test)]
mod tests {
use crate::public::voice_conversion_results::directory::VoiceConversionResultDirectory;
use crate::public::voice_conversion_results::bucket_directory::VoiceConversionResultDirectory;
#[test]
pub fn get_directory_path_str() {
@@ -3,7 +3,7 @@ use std::path::PathBuf;
use crockford::crockford_entropy_lower;
use crate::public::public_path::PublicPath;
use crate::public::voice_conversion_results::directory::VoiceConversionResultDirectory;
use crate::public::voice_conversion_results::bucket_directory::VoiceConversionResultDirectory;
const ORIGINAL_FILE_PREFIX : &str = "fakeyou_";
const ORIGINAL_FILE_SUFFIX : &str = ".wav";
@@ -65,7 +65,7 @@ impl VoiceConversionResultOriginalFilePath {
mod tests {
use std::path::PathBuf;
use crate::public::voice_conversion_results::original_file::VoiceConversionResultOriginalFilePath;
use crate::public::voice_conversion_results::bucket_file_path::VoiceConversionResultOriginalFilePath;
#[test]
pub fn generate_new_entropy() {
@@ -1,2 +1,2 @@
pub mod directory;
pub mod original_file;
pub mod bucket_directory;
pub mod bucket_file_path;
@@ -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::bucket_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,100 @@
use std::path::PathBuf;
use crockford::crockford_entropy_lower;
use crate::public::public_path::PublicPath;
use crate::public::weight_uploads::bucket_directory::WeightUploadDirectory;
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::bucket_file_path::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);
}
}
@@ -0,0 +1,2 @@
pub mod bucket_directory;
pub mod bucket_file_path;
@@ -1,2 +0,0 @@
pub mod directory;
pub mod file;
+7 -5
View File
@@ -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")]
@@ -24,6 +25,9 @@ pub enum InferenceCategory {
#[serde(rename = "voice_conversion")]
VoiceConversion,
#[serde(rename = "video_filter")]
VideoFilter,
}
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
@@ -37,6 +41,7 @@ impl InferenceCategory {
Self::LipsyncAnimation => "lipsync_animation",
Self::TextToSpeech => "text_to_speech",
Self::VoiceConversion => "voice_conversion",
Self::VideoFilter => "video_filter",
}
}
@@ -45,6 +50,7 @@ impl InferenceCategory {
"lipsync_animation" => Ok(Self::LipsyncAnimation),
"text_to_speech" => Ok(Self::TextToSpeech),
"voice_conversion" => Ok(Self::VoiceConversion),
"video_filter" => Ok(Self::VideoFilter),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -56,6 +62,7 @@ impl InferenceCategory {
Self::LipsyncAnimation,
Self::TextToSpeech,
Self::VoiceConversion,
Self::VideoFilter,
])
}
}
@@ -70,6 +77,7 @@ mod tests {
assert_serialization(InferenceCategory::LipsyncAnimation, "lipsync_animation");
assert_serialization(InferenceCategory::TextToSpeech, "text_to_speech");
assert_serialization(InferenceCategory::VoiceConversion, "voice_conversion");
assert_serialization(InferenceCategory::VideoFilter, "video_filter");
}
#[test]
@@ -77,6 +85,7 @@ mod tests {
assert_eq!(InferenceCategory::LipsyncAnimation.to_str(), "lipsync_animation");
assert_eq!(InferenceCategory::TextToSpeech.to_str(), "text_to_speech");
assert_eq!(InferenceCategory::VoiceConversion.to_str(), "voice_conversion");
assert_eq!(InferenceCategory::VideoFilter.to_str(), "video_filter");
}
#[test]
@@ -84,16 +93,18 @@ mod tests {
assert_eq!(InferenceCategory::from_str("lipsync_animation").unwrap(), InferenceCategory::LipsyncAnimation);
assert_eq!(InferenceCategory::from_str("text_to_speech").unwrap(), InferenceCategory::TextToSpeech);
assert_eq!(InferenceCategory::from_str("voice_conversion").unwrap(), InferenceCategory::VoiceConversion);
assert_eq!(InferenceCategory::from_str("video_filter").unwrap(), InferenceCategory::VideoFilter);
}
#[test]
fn all_variants() {
// Static check
let mut variants = InferenceCategory::all_variants();
assert_eq!(variants.len(), 3);
assert_eq!(variants.len(), 4);
assert_eq!(variants.pop_first(), Some(InferenceCategory::LipsyncAnimation));
assert_eq!(variants.pop_first(), Some(InferenceCategory::TextToSpeech));
assert_eq!(variants.pop_first(), Some(InferenceCategory::VoiceConversion));
assert_eq!(variants.pop_first(), Some(InferenceCategory::VideoFilter));
assert_eq!(variants.pop_first(), None);
// Generated check
@@ -31,6 +31,8 @@ pub enum InferenceModelType {
Vits,
#[serde(rename = "vall_e_x")]
VallEX,
#[serde(rename = "rerender_a_video")]
RerenderAVideo,
}
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
@@ -46,7 +48,8 @@ impl InferenceModelType {
Self::SoVitsSvc => "so_vits_svc",
Self::Tacotron2 => "tacotron2",
Self::Vits => "vits",
Self::VallEX => "vall_e_x"
Self::VallEX => "vall_e_x",
Self::RerenderAVideo => "rerender_a_video",
}
}
@@ -58,6 +61,7 @@ impl InferenceModelType {
"tacotron2" => Ok(Self::Tacotron2),
"vits" => Ok(Self::Vits),
"vall_e_x" => Ok(Self::VallEX),
"rerender_a_video" => Ok(Self::RerenderAVideo),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -71,7 +75,8 @@ impl InferenceModelType {
InferenceModelType::SoVitsSvc,
InferenceModelType::Tacotron2,
InferenceModelType::Vits,
InferenceModelType::VallEX
InferenceModelType::VallEX,
InferenceModelType::RerenderAVideo
])
}
}
@@ -89,6 +94,7 @@ mod tests {
assert_serialization(InferenceModelType::Tacotron2, "tacotron2");
assert_serialization(InferenceModelType::Vits, "vits");
assert_serialization(InferenceModelType::VallEX, "vall_e_x");
assert_serialization(InferenceModelType::RerenderAVideo, "rerender_a_video");
}
#[test]
@@ -99,6 +105,7 @@ mod tests {
assert_eq!(InferenceModelType::Tacotron2.to_str(), "tacotron2");
assert_eq!(InferenceModelType::Vits.to_str(), "vits");
assert_eq!(InferenceModelType::VallEX.to_str(), "vall_e_x");
assert_eq!(InferenceModelType::RerenderAVideo.to_str(), "rerender_a_video");
}
#[test]
@@ -109,19 +116,21 @@ mod tests {
assert_eq!(InferenceModelType::from_str("tacotron2").unwrap(), InferenceModelType::Tacotron2);
assert_eq!(InferenceModelType::from_str("vits").unwrap(), InferenceModelType::Vits);
assert_eq!(InferenceModelType::from_str("vall_e_x").unwrap(), InferenceModelType::VallEX);
assert_eq!(InferenceModelType::from_str("rerender_a_video").unwrap(), InferenceModelType::RerenderAVideo);
}
#[test]
fn all_variants() {
// Static check
let mut variants = InferenceModelType::all_variants();
assert_eq!(variants.len(), 6);
assert_eq!(variants.len(), 7);
assert_eq!(variants.pop_first(), Some(InferenceModelType::RvcV2));
assert_eq!(variants.pop_first(), Some(InferenceModelType::SadTalker));
assert_eq!(variants.pop_first(), Some(InferenceModelType::SoVitsSvc));
assert_eq!(variants.pop_first(), Some(InferenceModelType::Tacotron2));
assert_eq!(variants.pop_first(), Some(InferenceModelType::Vits));
assert_eq!(variants.pop_first(), Some(InferenceModelType::VallEX));
assert_eq!(variants.pop_first(), Some(InferenceModelType::RerenderAVideo));
assert_eq!(variants.pop_first(), None);
// Generated check
@@ -21,6 +21,15 @@ pub enum IdCategory {
#[serde(rename = "lipsync_animation")]
LipsyncAnimationResult,
// Results from video filters
#[serde(rename = "video_filter")]
VideoFilterResult,
/// 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,10 +61,12 @@ 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",
Self::ZeroShotTtsResult => "zs_tts_result",
Self::VideoFilterResult => "video_filter",
Self::ModelWeights => "model_weights",
}
}
@@ -64,10 +75,12 @@ 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),
"zs_tts_result" => Ok(Self::ZeroShotTtsResult),
"video_filter" => Ok(Self::VideoFilterResult),
"model_weights" => Ok(Self::ModelWeights),
_ => Err(format!("invalid value: {:?}", value)),
}
@@ -79,6 +92,8 @@ impl IdCategory {
BTreeSet::from([
Self::MediaFile,
Self::LipsyncAnimationResult,
Self::VideoFilterResult,
Self::TtsResult,
Self::VoiceConversionResult,
Self::ZeroShotTtsResult,
Self::ZeroShotVoiceDataset,
@@ -100,6 +115,8 @@ mod tests {
fn test_serialization() {
assert_serialization(IdCategory::MediaFile, "media_file");
assert_serialization(IdCategory::LipsyncAnimationResult, "lipsync_animation");
assert_serialization(IdCategory::VideoFilterResult, "video_filter");
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 +128,8 @@ mod tests {
fn to_str() {
assert_eq!(IdCategory::MediaFile.to_str(), "media_file");
assert_eq!(IdCategory::LipsyncAnimationResult.to_str(), "lipsync_animation");
assert_eq!(IdCategory::VideoFilterResult.to_str(), "video_filter");
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 +141,8 @@ 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("video_filter").unwrap(), IdCategory::VideoFilterResult);
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 +154,11 @@ mod tests {
fn all_variants() {
// Static check
let mut variants = IdCategory::all_variants();
assert_eq!(variants.len(), 7);
assert_eq!(variants.len(), 9);
assert_eq!(variants.pop_first(), Some(IdCategory::MediaFile));
assert_eq!(variants.pop_first(), Some(IdCategory::LipsyncAnimationResult));
assert_eq!(variants.pop_first(), Some(IdCategory::VideoFilterResult));
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,13 +24,21 @@ 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,
#[serde(rename = "rerender")]
Rerender,
}
// 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,7 +47,9 @@ impl MediaFileOriginModelType {
Self::RvcV2 => "rvc_v2",
Self::SadTalker => "sad_talker",
Self::SoVitsSvc => "so_vits_svc",
Self::VallEX => "vall_e_x"
Self::Tacotron2 => "tacotron2",
Self::VallEX => "vall_e_x",
Self::Rerender => "rerender",
}
}
@@ -48,7 +58,9 @@ 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),
"rerender" => Ok(Self::Rerender),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -60,7 +72,9 @@ impl MediaFileOriginModelType {
Self::RvcV2,
Self::SadTalker,
Self::SoVitsSvc,
Self::VallEX
Self::Tacotron2,
Self::VallEX,
Self::Rerender,
])
}
}
@@ -83,7 +97,9 @@ 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");
assert_eq!(MediaFileOriginModelType::Rerender.to_str(), "rerender");
}
#[test]
@@ -91,18 +107,22 @@ 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_eq!(MediaFileOriginModelType::from_str("rerender").unwrap(), MediaFileOriginModelType::Rerender);
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(), 6);
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(), Some(MediaFileOriginModelType::Rerender));
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.)
@@ -34,29 +38,38 @@ pub enum MediaFileOriginProductCategory {
/// Media files created by (or uploaded for) the Zero Shot voice product.
#[serde(rename = "zs_voice")]
ZeroShotVoice,
// Media files for video filters
#[serde(rename = "video_filter")]
VideoFilter,
}
// 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",
Self::VideoFilter => "video_filter",
}
}
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),
"video_filter" => Ok(Self::VideoFilter),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -66,6 +79,8 @@ impl MediaFileOriginProductCategory {
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
BTreeSet::from([
Self::FaceAnimator,
Self::TextToSpeech,
Self::VideoFilter,
Self::Unknown,
Self::VoiceConversion,
Self::ZeroShotVoice,
@@ -84,35 +99,43 @@ 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");
assert_serialization(MediaFileOriginProductCategory::VideoFilter, "video_filter")
}
#[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");
assert_eq!(MediaFileOriginProductCategory::VideoFilter.to_str(), "video_filter");
}
#[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);
assert_eq!(MediaFileOriginProductCategory::from_str("video_filter").unwrap(), MediaFileOriginProductCategory::VideoFilter);
}
#[test]
fn all_variants() {
let mut variants = MediaFileOriginProductCategory::all_variants();
assert_eq!(variants.len(), 4);
assert_eq!(variants.len(), 6);
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));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VideoFilter));
assert_eq!(variants.pop_first(), None);
}
}
@@ -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());
}
}
+1 -1
View File
@@ -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");
+4 -2
View File
@@ -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:
+1
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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>;
}
+4 -2
View File
@@ -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
+8 -6
View File
@@ -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,15 +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 = ["actix_extras"] }
utoipa = { version = "4", features = ["chrono","actix_extras"] }
[dev-dependencies]
+2 -2
View File
@@ -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);
@@ -7,7 +7,7 @@ use crate::prefixes::TokenPrefix;
use utoipa::ToSchema;
/// The primary key for "generic" inference jobs.
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize,ToSchema)]
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize, Default, ToSchema)]
#[sqlx(transparent)]
pub struct InferenceJobToken(String);
+1 -1
View File
@@ -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);
@@ -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);
+2 -2
View File
@@ -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);
+3 -1
View File
@@ -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" }
+3 -1
View File
@@ -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" }
+4 -6
View File
@@ -28,22 +28,20 @@ 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
# Runtime
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
tokio = { version = "1.6.0", features = ["macros"] }
tokio = { version = "1.34.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
+2 -1
View File
@@ -8,6 +8,7 @@ use errors::AnyhowResult;
use crate::bucket_clients::get_bucket_clients;
use crate::cli_args::parse_cli_args;
use crate::seeding::model_weights::seed_weights;
use crate::seeding::seed_media_files::seed_media_files;
use crate::seeding::tts_tacotron2::seed_tts_tacotron2;
use crate::seeding::users::seed_user_accounts;
use crate::seeding::voice_conversion::seed_voice_conversion;
@@ -52,11 +53,11 @@ pub async fn main() -> AnyhowResult<()> {
}
seed_user_accounts(&pool).await?;
seed_media_files(&pool, maybe_bucket_clients.as_ref()).await?;
seed_zero_shot_tts(&pool, maybe_bucket_clients.as_ref()).await?;
seed_voice_conversion(&pool).await?;
seed_weights(&pool).await?;
seed_tts_tacotron2(&pool, maybe_bucket_clients.as_ref()).await?;
@@ -1,5 +1,6 @@
pub mod model_weights;
pub mod seed_media_files;
pub mod tts_tacotron2;
pub mod users;
pub mod voice_conversion;
pub mod zero_shot_tts;
pub mod model_weights;
pub mod zero_shot_tts;
@@ -1,20 +1,355 @@
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";
// 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 +500,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 +655,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(())
}
@@ -0,0 +1,224 @@
use std::path::Path;
use log::{info, warn};
use sqlx::{MySql, Pool};
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use filesys::file_read_bytes::file_read_bytes;
use filesys::file_size::file_size;
use filesys::path_to_string::path_to_string;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use mimetypes::mimetype_for_bytes::get_mimetype_for_bytes;
use mimetypes::mimetype_for_file::get_mimetype_for_file;
use mysql_queries::queries::media_files::get_media_file::get_media_file;
use mysql_queries::queries::media_files::insert_media_file_from_cli_tool::{insert_media_file_from_cli_tool, InsertArgs};
use storyteller_root::get_seed_tool_data_root;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::users::UserToken;
use crate::bucket_clients::BucketClients;
use crate::seeding::users::HANASHI_USER_TOKEN;
pub async fn seed_media_files(mysql_pool: &Pool<MySql>, maybe_bucket_clients: Option<&BucketClients>) -> AnyhowResult<()> {
info!("Seeding media files...");
// NB: This is idempotent and will only install the media files once.
// Delete the records if you want to re-seed.
let media_files = [
// Audio
(HANASHI_USER_TOKEN, "m_21jxt406aattq2cna1xtgf5m4mjyyr", MediaFileType::Audio, "media/audio/voice-samples/biden.wav"),
(HANASHI_USER_TOKEN, "m_cxzabpxf88h10rshqraksxbqmhs41h", MediaFileType::Audio, "media/audio/voice-samples/brandon1.wav"),
(HANASHI_USER_TOKEN, "m_sq2vhrrmmbr079afk21543aa2jg53g", MediaFileType::Audio, "media/audio/voice-samples/brandon2.wav"),
(HANASHI_USER_TOKEN, "m_s61a8g3jnddr3xdg3gctsjxxk9jwja", MediaFileType::Audio, "media/audio/voice-samples/elon.wav"),
(HANASHI_USER_TOKEN, "m_e59fh75g76pvebx4qe4r4aymd93q30", MediaFileType::Audio, "media/audio/voice-samples/goku.wav"),
(HANASHI_USER_TOKEN, "m_ttq0ym8ht4v0z87zqz27fhadp0743c", MediaFileType::Audio, "media/audio/voice-samples/hillary.wav"),
(HANASHI_USER_TOKEN, "m_300bv6f141hv553fjf287p5gb76k37", MediaFileType::Audio, "media/audio/voice-samples/mario_impersonator.wav"),
(HANASHI_USER_TOKEN, "m_rd1ey2jem8a37r3vna2h9mht6zevs5", MediaFileType::Audio, "media/audio/voice-samples/rick.wav"),
(HANASHI_USER_TOKEN, "m_8n5epqfvs2vh60khap0s3ezem4epkc", MediaFileType::Audio, "media/audio/voice-samples/trump.wav"),
(HANASHI_USER_TOKEN, "m_g6dpwcpq51e6kvmpbbkdvgxfan9k1k", MediaFileType::Audio, "media/audio/voice-samples/trump_tts.wav"),
// Images
(HANASHI_USER_TOKEN, "m_cn5t6ywm9k1ge9qzzxst5krc5tm08m", MediaFileType::Image, "media/image/face-animator-inputs/bill.jpg"),
(HANASHI_USER_TOKEN, "m_nf9xebrr8hd1bxkfy7src5k8nv2dzy", MediaFileType::Image, "media/image/face-animator-inputs/elon.jpg"),
(HANASHI_USER_TOKEN, "m_t17zh2r3ahs485b8m7c9q502cs6jqh", MediaFileType::Image, "media/image/face-animator-inputs/ernest.jpg"),
(HANASHI_USER_TOKEN, "m_vms09sby8tyw742y2s66a4w8f0w278", MediaFileType::Image, "media/image/face-animator-inputs/link.jpg"),
(HANASHI_USER_TOKEN, "m_s1z9krfzrscy92jgq3sxhpx1n4vxvc", MediaFileType::Image, "media/image/face-animator-inputs/ripley.jpg"),
(HANASHI_USER_TOKEN, "m_we7mnzbd76g4yn19dm6m53er0pjvew", MediaFileType::Image, "media/image/face-animator-inputs/san.png"),
(HANASHI_USER_TOKEN, "m_wahwz92nxxfg0x42dw9fdrhwq30yk0", MediaFileType::Image, "media/image/face-animator-inputs/zelda.jpg"),
// Video
(HANASHI_USER_TOKEN, "m_gedarcfdkxx3zv8zz2wmwsnc1r8jbp", MediaFileType::Video, "media/video/storyteller-studio-renders/girl-rotating-room.mp4"),
(HANASHI_USER_TOKEN, "m_3s74yyd4jwrjdp17yx1694n29jv5gr", MediaFileType::Video, "media/video/storyteller-studio-renders/hanashi-run.mp4"),
(HANASHI_USER_TOKEN, "m_p6d64gm1wawz25bmdahfded3366b9f", MediaFileType::Video, "media/video/storyteller-studio-renders/mocap-kiss.mp4"),
(HANASHI_USER_TOKEN, "m_szp2c77z6je965k44vc22xn9432a88", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-mocap-girl.mp4"),
(HANASHI_USER_TOKEN, "m_mdwspz81zymw9hvmb1d3jm830t25xe", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-mocap-m.mp4"),
(HANASHI_USER_TOKEN, "m_prcs6xkm8phs5y4a2dfwemwjy6n6z3", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-girl.mp4"),
(HANASHI_USER_TOKEN, "m_5j889dzw08vn9pbrscx1sncff43ekp", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-jww.mp4"),
(HANASHI_USER_TOKEN, "m_fwm2w6wbssez274ayz6x8ta0h1a9qp", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-pascal.mp4"),
(HANASHI_USER_TOKEN, "m_yqqkrt2srep6a35xg78114jn9epwg1", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-pop.mp4"),
(HANASHI_USER_TOKEN, "m_m4r043kez14pm6vaamsecpz8fafh7g", MediaFileType::Video, "media/video/video-style-transfer/man-explaining.mp4"),
(HANASHI_USER_TOKEN, "m_81gq3hygqvrahg6ncxbtcpjap4f9nv", MediaFileType::Video, "media/video/video-style-transfer/woman-gradient-background.mp4"),
(HANASHI_USER_TOKEN, "m_dp9ykj3yasjx69g2fx2bpd26wwjz0f", MediaFileType::Video, "media/video/video-style-transfer/woman-red-hair.mp4"),
];
let seed_tool_data_root = get_seed_tool_data_root();
for (user_token, media_file_token, media_file_type, subdirectory_path) in media_files {
let user_token = UserToken::new_from_str(user_token);
let media_file_token = MediaFileToken::new_from_str(media_file_token);
let mut media_file_path = seed_tool_data_root.clone();
media_file_path.push(subdirectory_path);
let result = seed_model(
&mysql_pool,
&media_file_token,
&user_token,
media_file_type,
&media_file_path,
maybe_bucket_clients,
).await;
match result {
Ok(_) => info!("Seeded {:?}", media_file_path),
Err(err) => warn!(r#"
Could not seed media file {} , {:?} : {:?}
(No worries: if there's a duplicate key error, we probably already
seeded the media file on a previous invocation!)
"#, media_file_token, subdirectory_path, err),
}
}
Ok(())
}
async fn seed_model(
mysql_pool: &Pool<MySql>,
media_file_token: &MediaFileToken,
user_token: &UserToken,
media_file_type: MediaFileType,
media_file_path: &Path,
maybe_bucket_clients: Option<&BucketClients>,
) -> AnyhowResult<()> {
info!("Seeding Media file {:?} ...", media_file_path);
let mut bucket_hash = "NOT_UPLOADED_BY_SEED_TOOL".to_string();
let mut maybe_bucket_prefix = None;
let mut maybe_bucket_extension = None;
if media_file_exists(mysql_pool, media_file_token).await? {
info!("Media file already seeded: {:?}", media_file_token);
return Ok(())
}
if let Some(bucket_clients) = maybe_bucket_clients {
let bucket_details = seed_file_to_bucket(media_file_path, bucket_clients).await?;
bucket_hash = bucket_details.bucket_hash;
maybe_bucket_prefix = bucket_details.maybe_bucket_prefix;
maybe_bucket_extension = bucket_details.maybe_bucket_extension;
}
let maybe_mime_type = get_mimetype_for_file(media_file_path)?;
let file_size_bytes = file_size(media_file_path)?;
let sha256_checksum = sha256_hash_file(media_file_path)?;
let maybe_filename = media_file_path
.file_name()
.map(|name| name.to_str())
.flatten();
insert_media_file_from_cli_tool(InsertArgs {
pool: &mysql_pool,
maybe_use_apriori_media_token: Some(media_file_token),
media_file_type,
maybe_mime_type,
file_size_bytes,
sha256_checksum: &sha256_checksum,
maybe_origin_filename: maybe_filename,
maybe_creator_user_token: Some(user_token),
creator_set_visibility: Visibility::Public,
public_bucket_directory_hash: &bucket_hash,
maybe_public_bucket_prefix: maybe_bucket_prefix.as_deref(),
maybe_public_bucket_extension: maybe_bucket_extension.as_deref(),
}).await?;
Ok(())
}
async fn media_file_exists(
mysql_pool: &Pool<MySql>,
media_file_token: &MediaFileToken,
) -> AnyhowResult<bool> {
const CAN_SEE_DELETED : bool = true;
let maybe_file = get_media_file(
&media_file_token,
CAN_SEE_DELETED,
mysql_pool
).await?;
Ok(maybe_file.is_some())
}
struct BucketDetails {
bucket_hash: String,
maybe_bucket_prefix: Option<String>,
maybe_bucket_extension: Option<String>,
}
async fn seed_file_to_bucket(
media_file_path: &Path,
bucket_clients: &BucketClients,
) -> AnyhowResult<BucketDetails> {
info!("Uploading media file {:?} ...", media_file_path);
let maybe_bucket_prefix = Some("fakeyou_");
let maybe_bucket_extension = media_file_path
.extension()
.map(|extension| extension.to_str())
.flatten();
let bucket_location = MediaFileBucketPath::generate_new(maybe_bucket_prefix, maybe_bucket_extension);
let bucket_path = path_to_string(bucket_location.to_full_object_pathbuf());
info!("Reading media file: {:?}", media_file_path);
let bytes = file_read_bytes(media_file_path)?;
let mimetype = get_mimetype_for_bytes(&bytes).unwrap_or("application/octet-stream");
info!("Uploading media file to bucket path: {:?}", bucket_path);
let _r = bucket_clients.public.upload_file_with_content_type(
&bucket_path,
bytes.as_ref(),
mimetype
).await?;
Ok(BucketDetails {
bucket_hash: bucket_location.get_object_hash().to_string(),
maybe_bucket_prefix: maybe_bucket_prefix.map(|s| s.to_string()),
maybe_bucket_extension: maybe_bucket_extension.map(|s| s.to_string()),
})
}
// Temporary "test" to generate random tokens.
// #[cfg(test)]
// mod tests {
// use tokens::tokens::media_files::MediaFileToken;
//
// #[test]
// fn test() {
// // Print some randomly sampled tokens
// for _i in 0..50 {
// let token = MediaFileToken::generate();
// println!("Token: {}", token);
// }
// // Deliberately fail the test to get the output
// assert_eq!(1, 2);
// }
// }
@@ -1,7 +1,7 @@
use log::info;
use sqlx::{MySql, Pool};
use buckets::public::media_files::original_file::MediaFileBucketPath;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use cloud_storage::bucket_client::BucketClient;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_uploads::media_upload_type::MediaUploadType;
+4 -6
View File
@@ -25,20 +25,18 @@ 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"
# Runtime
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
tokio = { version = "1.6.0", features = ["macros"] }
tokio = { version = "1.34.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
+3 -1
View File
@@ -3,7 +3,7 @@ use std::time::Duration;
use log::info;
use sqlx::mysql::MySqlPoolOptions;
use buckets::public::media_files::original_file::MediaFileBucketPath;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use cloud_storage::bucket_client::BucketClient;
use config::shared_constants::{DEFAULT_MYSQL_CONNECTION_STRING, DEFAULT_RUST_LOG};
use enums::by_table::media_files::media_file_type::MediaFileType;
@@ -119,10 +119,12 @@ pub async fn main() -> AnyhowResult<()> {
let (media_file_token, _id) = insert_media_file_from_cli_tool(InsertArgs {
pool: &pool,
maybe_use_apriori_media_token: None,
media_file_type,
maybe_mime_type,
file_size_bytes: 0, // TODO
sha256_checksum: "", // TODO
maybe_origin_filename: None,
maybe_creator_user_token: None,
creator_set_visibility,
public_bucket_directory_hash: public_upload_path.get_object_hash(),
+4 -6
View File
@@ -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
@@ -31,12 +34,8 @@ strum = { version = "0.25", features = ["derive"] }
# Runtime
# NB: We switched to Tokio from `async-std` for broader ecosystem support.
tokio = { version = "1.6.0", features = ["macros"] }
tokio = { version = "1.34.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
+3 -1
View File
@@ -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.
+3 -1
View File
@@ -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
+4 -2
View File
@@ -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" }
tokio = { version = "1.34.0", features = ["macros"] }
+3 -1
View File
@@ -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"
@@ -27,5 +30,4 @@ 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" }
tokio = { version = "1.34.0", features = ["macros"] }
@@ -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" }
+3 -1
View File
@@ -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
+3 -1
View File
@@ -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" }
+3 -1
View File
@@ -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
+3 -1
View File
@@ -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.
+4 -1
View File
@@ -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)
+3 -1
View File
@@ -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
+7 -1
View File
@@ -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
+8 -2
View File
@@ -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)
+3 -1
View File
@@ -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" }

Some files were not shown because too many files have changed in this diff Show More