mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 14:24:53 -05:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2929eae094 | ||
|
|
b47f9a522a |
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO uploaded_videos\nSET\n token = ?,\n sha1_checksum = ?,\n filesize_bytes = ?,\n maybe_filename = ?,\n maybe_width = ?,\n maybe_height = ?,\n maybe_resolution = ?,\n maybe_detected_model_family = ?,\n maybe_detected_model_type = ?,\n maybe_report = ?,\n upload_ip_address = ?,\n created_at = NOW()\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 11
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "14e63e59f7d550181126151029bcd17d08278196ba0ee4d32450c2567b1da26e"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nUPDATE uploaded_video_notes\nSET\n maybe_filename = ?,\n maybe_reported_model_type = ?,\n maybe_reported_model_name = ?,\n maybe_website = ?,\n maybe_other_website = ?,\n maybe_comments = ?,\n maybe_email_address = ?,\n can_share_report = ?,\n was_scammed = ?,\n maybe_comment_update_ip_address = ?,\n version = version + 1\nWHERE token = ?\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 11
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4036dfd9d4e9e77e557776468c14b75f49170de1e55a1b9b9e83446a0c356e74"
|
||||
}
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n token as `token: UploadedVideoToken`,\n sha1_checksum,\n filesize_bytes as `filesize_bytes: u32`,\n maybe_width as `maybe_width: u32`,\n maybe_height as `maybe_height: u32`,\n maybe_resolution,\n maybe_detected_model_family as `maybe_detected_model_family: UploadedVideoDetectedModelFamily`,\n maybe_detected_model_type as `maybe_detected_model_type: UploadedVideoDetectedModelType`,\n maybe_report,\n upload_ip_address,\n maybe_updated_ip_address,\n created_at,\n updated_at\nFROM uploaded_videos\nWHERE sha1_checksum = ?\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: UploadedVideoToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "sha1_checksum",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "filesize_bytes: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | UNSIGNED | NO_DEFAULT_VALUE",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "maybe_width: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_height: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_resolution",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 48
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_detected_model_family: UploadedVideoDetectedModelFamily",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "maybe_detected_model_type: UploadedVideoDetectedModelType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "maybe_report",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
"flags": "BLOB | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 67108860
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "upload_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "maybe_updated_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "408c893a0ced805de4c3c6cfdf0c6a4bcc93dd1eaf98382522eae46e72eb3aa5"
|
||||
}
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n token as `token: UploadedVideoToken`,\n sha1_checksum,\n filesize_bytes as `filesize_bytes: u32`,\n maybe_width as `maybe_width: u32`,\n maybe_height as `maybe_height: u32`,\n maybe_resolution,\n maybe_detected_model_family as `maybe_detected_model_family: UploadedVideoDetectedModelFamily`,\n maybe_detected_model_type as `maybe_detected_model_type: UploadedVideoDetectedModelType`,\n maybe_report,\n upload_ip_address,\n maybe_updated_ip_address,\n created_at,\n updated_at\nFROM uploaded_videos\nWHERE token = ?\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: UploadedVideoToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "sha1_checksum",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "filesize_bytes: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | UNSIGNED | NO_DEFAULT_VALUE",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "maybe_width: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_height: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_resolution",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 48
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_detected_model_family: UploadedVideoDetectedModelFamily",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "maybe_detected_model_type: UploadedVideoDetectedModelType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "maybe_report",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
"flags": "BLOB | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 67108860
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "upload_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "maybe_updated_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "73d70c5ee77f5059801d324610a80b3f52da3ddec2e89f63e8f41fc68ff0aaec"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO uploaded_video_notes\nSET\n token = ?,\n uploaded_video_token = ?,\n maybe_filename = ?,\n maybe_reported_model_type = ?,\n maybe_reported_model_name = ?,\n maybe_website = ?,\n maybe_other_website = ?,\n maybe_comments = ?,\n maybe_email_address = ?,\n can_share_report = ?,\n was_scammed = ?,\n comment_create_ip_address = ?,\n created_at = NOW()\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 12
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b1f30a79864351a28a58cae43ee38ff12a8d64d9393b8f27590fe03b0ae3ab05"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nUPDATE uploaded_videos\nSET\n maybe_filename = ?,\n maybe_width = ?,\n maybe_height = ?,\n maybe_resolution = ?,\n maybe_detected_model_family = ?,\n maybe_detected_model_type = ?,\n maybe_report = ?,\n maybe_updated_ip_address = ?,\n version = version + 1\nWHERE token = ?\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 9
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c6bbdc963e0d49ac55973a728d04b371967c20bfb9dd4bd75e4693dc7a114c99"
|
||||
}
|
||||
Generated
-18
@@ -1730,14 +1730,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bucket_client"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"rust-s3",
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bucket_paths"
|
||||
version = "0.0.1"
|
||||
@@ -11004,14 +10996,6 @@ dependencies = [
|
||||
"digest 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1_hash"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"sha1 0.10.6",
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1_smol"
|
||||
version = "1.0.0"
|
||||
@@ -11589,7 +11573,6 @@ dependencies = [
|
||||
"billing_artcraft_component",
|
||||
"billing_component",
|
||||
"bootstrap",
|
||||
"bucket_client",
|
||||
"bucket_paths",
|
||||
"bytes",
|
||||
"chrono",
|
||||
@@ -11661,7 +11644,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"server_environment",
|
||||
"sha1_hash",
|
||||
"shared_env_var_config",
|
||||
"speculoos",
|
||||
"sqlx",
|
||||
|
||||
@@ -10,7 +10,6 @@ members = [
|
||||
"crates/api_clients/artcraft/artcraft_api_keys",
|
||||
"crates/api_clients/artcraft/artcraft_client",
|
||||
"crates/api_clients/artcraft/artcraft_router",
|
||||
"crates/api_clients/bucket_client",
|
||||
"crates/api_clients/cloud_storage",
|
||||
"crates/api_clients/comet_api_client",
|
||||
"crates/api_clients/datadog_client",
|
||||
@@ -88,7 +87,6 @@ members = [
|
||||
"crates/lib/pager",
|
||||
"crates/lib/password",
|
||||
"crates/lib/server_environment",
|
||||
"crates/lib/sha1_hash",
|
||||
"crates/lib/sqlx_mysql_helpers",
|
||||
"crates/lib/storyteller_root",
|
||||
"crates/lib/url_config",
|
||||
@@ -240,7 +238,6 @@ artcraft_api_keys = { path = "crates/api_clients/artcraft/artcraft_api_keys" }
|
||||
artcraft_client = { path = "crates/api_clients/artcraft/artcraft_client" }
|
||||
artcraft_router = { path = "crates/api_clients/artcraft/artcraft_router" }
|
||||
bootstrap = { path = "crates/lib/bootstrap" }
|
||||
bucket_client = { path = "crates/api_clients/bucket_client" }
|
||||
bucket_paths = { path = "crates/schema/buckets/bucket_paths" }
|
||||
build_metadata = { path = "crates/lib/build_metadata" }
|
||||
cloud_storage = { path = "crates/api_clients/cloud_storage" }
|
||||
@@ -285,7 +282,6 @@ openai_sora_client = { path = "crates/api_clients/openai_sora_client" }
|
||||
primitives = { path = "crates/lib/data/primitives" }
|
||||
seedance2pro_client = { path = "crates/api_clients/seedance2pro_client" }
|
||||
server_environment = { path = "crates/lib/server_environment" }
|
||||
sha1_hash = { path = "crates/lib/sha1_hash" }
|
||||
shared_service_components = { path = "crates/lib/shared_service_components" }
|
||||
sqlite_tasks = { path = "crates/schema/database/sqlite_tasks" }
|
||||
subprocess_common = { path = "crates/lib/deprecated/subprocess_common" }
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE IF EXISTS uploaded_videos;
|
||||
@@ -1,62 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE uploaded_videos (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (used internally for lookups and as a foreign key).
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== FILE ==========
|
||||
|
||||
-- SHA-1 checksum of the uploaded bytes (40 hex chars). De-dupes uploads.
|
||||
sha1_checksum VARCHAR(40) NOT NULL,
|
||||
|
||||
-- Size of the uploaded file in bytes.
|
||||
filesize_bytes INT(10) UNSIGNED NOT NULL,
|
||||
|
||||
-- Pixel dimensions, when they could be determined.
|
||||
maybe_width INT(10) UNSIGNED DEFAULT NULL,
|
||||
maybe_height INT(10) UNSIGNED DEFAULT NULL,
|
||||
|
||||
-- Resolution label (e.g. "1080p", "1920x1080"), when known.
|
||||
maybe_resolution VARCHAR(12) DEFAULT NULL,
|
||||
|
||||
-- ========== DETECTION ==========
|
||||
|
||||
-- Detected provenance family (e.g. "seedance", "veo", "sora", "dreamina", "kling").
|
||||
maybe_detected_model_family VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Detected model type / variant (e.g. "full", "fast", "mini").
|
||||
maybe_detected_model_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Free-form report / analysis blob for this upload.
|
||||
maybe_report MEDIUMTEXT DEFAULT NULL,
|
||||
|
||||
-- ========== IP ADDRESSES ==========
|
||||
|
||||
-- IP address that uploaded the video. Wide enough for IPv4/IPv6.
|
||||
upload_ip_address VARCHAR(40) NOT NULL,
|
||||
|
||||
-- IP address that last updated the row. Wide enough for IPv4/IPv6.
|
||||
maybe_updated_ip_address VARCHAR(40) DEFAULT NULL,
|
||||
|
||||
-- ========== VERSION ==========
|
||||
|
||||
-- Optimistic-concurrency "vector clock". Bump by 1 on every update — set in
|
||||
-- the UPDATE statement (MySQL can't auto-increment a plain column via schema).
|
||||
version INT(8) UNSIGNED 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,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (sha1_checksum),
|
||||
KEY index_maybe_detected_model_family (maybe_detected_model_family)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE IF EXISTS uploaded_video_notes;
|
||||
@@ -1,69 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE uploaded_video_notes (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (used internally for lookups and as a foreign key).
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The uploaded video this note is about (FK to uploaded_videos.token).
|
||||
uploaded_video_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== SUBMISSION ==========
|
||||
|
||||
-- Original filename of the submitted clip, as provided by the user.
|
||||
maybe_filename VARCHAR(512) DEFAULT NULL,
|
||||
|
||||
-- The model type the submitter claims this video is.
|
||||
maybe_reported_model_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Free-form custom model name when the submitter's model isn't a known type.
|
||||
maybe_reported_model_name VARCHAR(64) DEFAULT NULL,
|
||||
|
||||
-- The website / platform the video was obtained from.
|
||||
maybe_website VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Free-form website when it isn't a known option.
|
||||
maybe_other_website VARCHAR(128) DEFAULT NULL,
|
||||
|
||||
-- Free-form comments from the submitter.
|
||||
maybe_comments VARCHAR(1024) DEFAULT NULL,
|
||||
|
||||
-- ========== CONTACT & FLAGS ==========
|
||||
|
||||
-- Optional email address for follow-up.
|
||||
maybe_email_address VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Whether the submitter consents to us sharing the report.
|
||||
can_share_report BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether the submitter believes they were scammed.
|
||||
was_scammed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== IP ADDRESSES ==========
|
||||
|
||||
-- IP address that submitted the note. Wide enough for IPv4/IPv6.
|
||||
comment_create_ip_address VARCHAR(40) NOT NULL,
|
||||
|
||||
-- IP address that last updated the note. Wide enough for IPv4/IPv6.
|
||||
maybe_comment_update_ip_address VARCHAR(40) DEFAULT NULL,
|
||||
|
||||
-- ========== VERSION ==========
|
||||
|
||||
-- Optimistic-concurrency "vector clock". Bump by 1 on every update — set in
|
||||
-- the UPDATE statement (MySQL can't auto-increment a plain column via schema).
|
||||
version INT(8) UNSIGNED 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,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY fk_uploaded_video_token (uploaded_video_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE uploaded_videos
|
||||
DROP COLUMN maybe_filename;
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE uploaded_videos
|
||||
ADD COLUMN maybe_filename VARCHAR(512) DEFAULT NULL AFTER filesize_bytes;
|
||||
@@ -1,69 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE uploaded_video_notes (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (used internally for lookups and as a foreign key).
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The uploaded video this note is about (FK to uploaded_videos.token).
|
||||
uploaded_video_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== SUBMISSION ==========
|
||||
|
||||
-- Original filename of the submitted clip, as provided by the user.
|
||||
maybe_filename VARCHAR(512) DEFAULT NULL,
|
||||
|
||||
-- The model type the submitter claims this video is.
|
||||
maybe_reported_model_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Free-form custom model name when the submitter's model isn't a known type.
|
||||
maybe_reported_model_name VARCHAR(64) DEFAULT NULL,
|
||||
|
||||
-- The website / platform the video was obtained from.
|
||||
maybe_website VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Free-form website when it isn't a known option.
|
||||
maybe_other_website VARCHAR(128) DEFAULT NULL,
|
||||
|
||||
-- Free-form comments from the submitter.
|
||||
maybe_comments VARCHAR(1024) DEFAULT NULL,
|
||||
|
||||
-- ========== CONTACT & FLAGS ==========
|
||||
|
||||
-- Optional email address for follow-up.
|
||||
maybe_email_address VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Whether the submitter consents to us sharing the report.
|
||||
can_share_report BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether the submitter believes they were scammed.
|
||||
was_scammed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== IP ADDRESSES ==========
|
||||
|
||||
-- IP address that submitted the note. Wide enough for IPv4/IPv6.
|
||||
comment_create_ip_address VARCHAR(40) NOT NULL,
|
||||
|
||||
-- IP address that last updated the note. Wide enough for IPv4/IPv6.
|
||||
maybe_comment_update_ip_address VARCHAR(40) DEFAULT NULL,
|
||||
|
||||
-- ========== VERSION ==========
|
||||
|
||||
-- Optimistic-concurrency "vector clock". Bump by 1 on every update — set in
|
||||
-- the UPDATE statement (MySQL can't auto-increment a plain column via schema).
|
||||
version INT(8) UNSIGNED 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,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY fk_uploaded_video_token (uploaded_video_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -1,65 +0,0 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE uploaded_videos (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (used internally for lookups and as a foreign key).
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== FILE ==========
|
||||
|
||||
-- SHA-1 checksum of the uploaded bytes (40 hex chars). De-dupes uploads.
|
||||
sha1_checksum VARCHAR(40) NOT NULL,
|
||||
|
||||
-- Size of the uploaded file in bytes.
|
||||
filesize_bytes INT(10) UNSIGNED NOT NULL,
|
||||
|
||||
-- Original filename of the uploaded clip, as provided by the user.
|
||||
maybe_filename VARCHAR(512) DEFAULT NULL,
|
||||
|
||||
-- Pixel dimensions, when they could be determined.
|
||||
maybe_width INT(10) UNSIGNED DEFAULT NULL,
|
||||
maybe_height INT(10) UNSIGNED DEFAULT NULL,
|
||||
|
||||
-- Resolution label (e.g. "1080p", "1920x1080"), when known.
|
||||
maybe_resolution VARCHAR(12) DEFAULT NULL,
|
||||
|
||||
-- ========== DETECTION ==========
|
||||
|
||||
-- Detected provenance family (e.g. "seedance", "veo", "sora", "dreamina", "kling").
|
||||
maybe_detected_model_family VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Detected model type / variant (e.g. "full", "fast", "mini").
|
||||
maybe_detected_model_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Free-form report / analysis blob for this upload.
|
||||
maybe_report MEDIUMTEXT DEFAULT NULL,
|
||||
|
||||
-- ========== IP ADDRESSES ==========
|
||||
|
||||
-- IP address that uploaded the video. Wide enough for IPv4/IPv6.
|
||||
upload_ip_address VARCHAR(40) NOT NULL,
|
||||
|
||||
-- IP address that last updated the row. Wide enough for IPv4/IPv6.
|
||||
maybe_updated_ip_address VARCHAR(40) DEFAULT NULL,
|
||||
|
||||
-- ========== VERSION ==========
|
||||
|
||||
-- Optimistic-concurrency "vector clock". Bump by 1 on every update — set in
|
||||
-- the UPDATE statement (MySQL can't auto-increment a plain column via schema).
|
||||
version INT(8) UNSIGNED 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,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (sha1_checksum),
|
||||
KEY index_maybe_detected_model_family (maybe_detected_model_family)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -1,3 +1 @@
|
||||
pub mod notes;
|
||||
pub mod read_only;
|
||||
pub mod upload;
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
//! Request/response types for `POST /v1/video_info/notes`.
|
||||
//!
|
||||
//! A note is user-submitted context about an uploaded video (what model they
|
||||
//! believe it is, where it came from, free-form comments). Always tied to an
|
||||
//! [`UploadedVideoToken`]; pass a [`UploadVideoNoteToken`] to update an existing
|
||||
//! note instead of creating a new one.
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_model_type::UploadedVideoNoteReportedModelType;
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_website::UploadedVideoNoteReportedWebsite;
|
||||
use tokens::tokens::uploaded_video_notes::UploadVideoNoteToken;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
/// Request body for `POST /v1/video_info/notes`.
|
||||
#[derive(Deserialize, ToSchema, Debug, Clone)]
|
||||
pub struct VideoInfoNoteRequest {
|
||||
/// The uploaded video this note is about. Required.
|
||||
pub uploaded_video_token: UploadedVideoToken,
|
||||
|
||||
/// If present, update this existing note instead of creating a new one.
|
||||
pub maybe_uploaded_video_note_token: Option<UploadVideoNoteToken>,
|
||||
|
||||
/// Original filename of the submitted clip.
|
||||
pub maybe_filename: Option<String>,
|
||||
|
||||
/// The model type the submitter claims this video is (dropdown / enum).
|
||||
pub maybe_reported_model_type: Option<UploadedVideoNoteReportedModelType>,
|
||||
|
||||
/// Free-form custom model name (trimmed; empty becomes absent).
|
||||
pub maybe_reported_model_name: Option<String>,
|
||||
|
||||
/// The website / platform the video came from (dropdown / enum).
|
||||
pub maybe_website: Option<UploadedVideoNoteReportedWebsite>,
|
||||
|
||||
/// Free-form website (trimmed; empty becomes absent).
|
||||
pub maybe_other_website: Option<String>,
|
||||
|
||||
/// Free-form comments (trimmed; empty becomes absent).
|
||||
pub maybe_comments: Option<String>,
|
||||
|
||||
/// Optional contact email (trimmed; empty becomes absent).
|
||||
pub maybe_email_address: Option<String>,
|
||||
|
||||
/// Whether the submitter consents to us sharing the report. Defaults to false.
|
||||
pub can_share_report: Option<bool>,
|
||||
|
||||
/// Whether the submitter believes they were scammed. Defaults to false.
|
||||
pub was_scammed: Option<bool>,
|
||||
}
|
||||
|
||||
/// Response body for `POST /v1/video_info/notes`.
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, Clone)]
|
||||
pub struct VideoInfoNoteResponse {
|
||||
pub success: bool,
|
||||
|
||||
/// The created or updated note's token (e.g. `uvnote_…`).
|
||||
pub uploaded_video_note_token: UploadVideoNoteToken,
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
//! Response type for `POST /v1/video_info/upload`.
|
||||
//!
|
||||
//! Same detected provenance as the read-only endpoint, plus the persisted
|
||||
//! [`UploadedVideoToken`] (used for follow-up requests, e.g. attaching a note).
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
use crate::video_info::read_only::{
|
||||
DreaminaVideoInfo, KlingVideoInfo, SeedanceVideoInfo, SoraVideoInfo, VeoVideoInfo,
|
||||
VideoProvenanceKind,
|
||||
};
|
||||
|
||||
/// Response for `POST /v1/video_info/upload`. Mirrors
|
||||
/// [`crate::video_info::read_only::VideoInfoReadOnlyResponse`] and adds the
|
||||
/// persisted record's token.
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, Clone)]
|
||||
pub struct VideoInfoUploadResponse {
|
||||
pub success: bool,
|
||||
|
||||
/// The persisted `uploaded_videos` record token (e.g. `uvt_…`).
|
||||
pub uploaded_video_token: UploadedVideoToken,
|
||||
|
||||
/// Which provenance family was detected (if any).
|
||||
pub kind: VideoProvenanceKind,
|
||||
|
||||
/// The container `©too` encoder tag, e.g. `"Lavf60.16.100"` or `"Google"`.
|
||||
pub maybe_encoder: Option<String>,
|
||||
|
||||
/// Present when [`kind`](Self::kind) is [`VideoProvenanceKind::Seedance`].
|
||||
pub maybe_seedance: Option<SeedanceVideoInfo>,
|
||||
|
||||
/// Present when [`kind`](Self::kind) is [`VideoProvenanceKind::Veo`].
|
||||
pub maybe_veo: Option<VeoVideoInfo>,
|
||||
|
||||
/// Present when [`kind`](Self::kind) is [`VideoProvenanceKind::Sora`].
|
||||
pub maybe_sora: Option<SoraVideoInfo>,
|
||||
|
||||
/// Present when [`kind`](Self::kind) is [`VideoProvenanceKind::Dreamina`].
|
||||
pub maybe_dreamina: Option<DreaminaVideoInfo>,
|
||||
|
||||
/// Present when [`kind`](Self::kind) is [`VideoProvenanceKind::Kling`].
|
||||
pub maybe_kling: Option<KlingVideoInfo>,
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
[package]
|
||||
name = "bucket_client"
|
||||
edition = "2024"
|
||||
version = "0.0.1"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "bucket_client"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
normal = ["workspace-build-acceleration"]
|
||||
|
||||
[dependencies]
|
||||
# cargo-hakari workspace hack (faster compile times)
|
||||
workspace-build-acceleration.workspace = true
|
||||
|
||||
# External
|
||||
rust-s3.workspace = true
|
||||
@@ -1,66 +0,0 @@
|
||||
use s3::Bucket;
|
||||
|
||||
use crate::bucket_client_error::BucketClientError;
|
||||
use crate::object_name::ObjectName;
|
||||
|
||||
/// Arguments for [`BucketClient::upload_file_bytes`].
|
||||
pub struct UploadFileBytesArgs<'a, S: AsRef<str>> {
|
||||
/// The destination object key (normalized via [`ObjectName`]).
|
||||
pub object_name: S,
|
||||
/// The raw bytes to upload.
|
||||
pub bytes: &'a [u8],
|
||||
/// Optional MIME type. Defaults to `application/octet-stream` when `None`.
|
||||
pub content_type: Option<&'a str>,
|
||||
}
|
||||
|
||||
/// A client for a single S3-compatible bucket. Cheap to clone. Build one with
|
||||
/// [`crate::BucketClientBuilder`].
|
||||
#[derive(Clone)]
|
||||
pub struct BucketClient {
|
||||
bucket: Bucket,
|
||||
}
|
||||
|
||||
impl BucketClient {
|
||||
/// Wrap a fully-configured `Bucket`. Internal — use
|
||||
/// [`crate::BucketClientBuilder`] to construct a client.
|
||||
pub(crate) fn from_bucket(bucket: Bucket) -> Self {
|
||||
Self { bucket }
|
||||
}
|
||||
|
||||
/// The name of the bucket this client targets.
|
||||
pub fn bucket_name(&self) -> &str {
|
||||
self.bucket.name.as_str()
|
||||
}
|
||||
|
||||
/// Upload raw bytes to `object_name`, optionally with an explicit content type.
|
||||
///
|
||||
/// Returns [`BucketClientError::UploadFailed`] if the store responds with a
|
||||
/// non-2xx status, or [`BucketClientError::S3Error`] on a transport/protocol
|
||||
/// error.
|
||||
pub async fn upload_file_bytes<S: AsRef<str>>(
|
||||
&self,
|
||||
args: UploadFileBytesArgs<'_, S>,
|
||||
) -> Result<(), BucketClientError> {
|
||||
let object_name = ObjectName::new(&args.object_name);
|
||||
|
||||
let response = match args.content_type {
|
||||
Some(content_type) => {
|
||||
self
|
||||
.bucket
|
||||
.put_object_with_content_type(object_name.as_str(), args.bytes, content_type)
|
||||
.await?
|
||||
}
|
||||
None => self.bucket.put_object(object_name.as_str(), args.bytes).await?,
|
||||
};
|
||||
|
||||
let status_code = response.status_code();
|
||||
if !(200..300).contains(&status_code) {
|
||||
return Err(BucketClientError::UploadFailed {
|
||||
status_code,
|
||||
message: String::from_utf8_lossy(response.bytes()).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use s3::creds::Credentials;
|
||||
use s3::region::Region;
|
||||
use s3::Bucket;
|
||||
|
||||
use crate::bucket_client::BucketClient;
|
||||
use crate::bucket_client_error::BucketClientError;
|
||||
|
||||
/// Builder for [`BucketClient`].
|
||||
///
|
||||
/// `access_key`, `secret_key`, `region_name`, and `bucket_name` are required;
|
||||
/// `endpoint` and `bucket_request_timeout` are optional.
|
||||
///
|
||||
/// - With an `endpoint` set, the bucket targets a custom S3-compatible host
|
||||
/// (R2, GCS, MinIO, etc.) via `Region::Custom`, and uses path-style addressing
|
||||
/// (subdomain-style for Google Cloud Storage).
|
||||
/// - Without an `endpoint`, the `region_name` is parsed as an AWS region
|
||||
/// (e.g. `"us-east-1"`), which determines the AWS endpoint automatically.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct BucketClientBuilder {
|
||||
access_key: Option<String>,
|
||||
secret_key: Option<String>,
|
||||
region_name: Option<String>,
|
||||
bucket_name: Option<String>,
|
||||
endpoint: Option<String>,
|
||||
bucket_request_timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
impl BucketClientBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn access_key(mut self, access_key: impl Into<String>) -> Self {
|
||||
self.access_key = Some(access_key.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn secret_key(mut self, secret_key: impl Into<String>) -> Self {
|
||||
self.secret_key = Some(secret_key.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn region_name(mut self, region_name: impl Into<String>) -> Self {
|
||||
self.region_name = Some(region_name.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn bucket_name(mut self, bucket_name: impl Into<String>) -> Self {
|
||||
self.bucket_name = Some(bucket_name.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Optional custom S3-compatible endpoint (e.g. an R2/GCS/MinIO URL). When
|
||||
/// unset, an AWS endpoint is derived from `region_name`.
|
||||
pub fn endpoint(mut self, endpoint: impl Into<String>) -> Self {
|
||||
self.endpoint = Some(endpoint.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn bucket_request_timeout(mut self, timeout: Duration) -> Self {
|
||||
self.bucket_request_timeout = Some(timeout);
|
||||
self
|
||||
}
|
||||
|
||||
/// Validate the configuration and construct a [`BucketClient`].
|
||||
pub fn build(self) -> Result<BucketClient, BucketClientError> {
|
||||
let access_key = require(self.access_key, "access_key")?;
|
||||
let secret_key = require(self.secret_key, "secret_key")?;
|
||||
let region_name = require(self.region_name, "region_name")?;
|
||||
let bucket_name = require(self.bucket_name, "bucket_name")?;
|
||||
|
||||
let credentials = Credentials {
|
||||
access_key: Some(access_key),
|
||||
secret_key: Some(secret_key),
|
||||
security_token: None,
|
||||
session_token: None,
|
||||
expiration: None,
|
||||
};
|
||||
|
||||
// A custom endpoint targets an S3-compatible host via `Region::Custom`;
|
||||
// otherwise the region name is parsed as a standard AWS region.
|
||||
let region = match self.endpoint.as_deref() {
|
||||
Some(endpoint) => Region::Custom {
|
||||
region: region_name.clone(),
|
||||
endpoint: endpoint.to_string(),
|
||||
},
|
||||
None => region_name.parse().map_err(|err| {
|
||||
BucketClientError::ClientBuilderSetupError(format!(
|
||||
"invalid region {region_name:?}: {err:?}"
|
||||
))
|
||||
})?,
|
||||
};
|
||||
|
||||
let mut bucket = Bucket::new(&bucket_name, region, credentials)?;
|
||||
bucket.set_request_timeout(self.bucket_request_timeout);
|
||||
|
||||
// Addressing style only matters for custom endpoints: Google Cloud Storage
|
||||
// needs subdomain (virtual-hosted) style; other S3-compatible stores use
|
||||
// path style. AWS uses the crate default (virtual-hosted).
|
||||
if let Some(endpoint) = self.endpoint.as_deref() {
|
||||
if endpoint == "https://storage.googleapis.com" {
|
||||
bucket.set_subdomain_style();
|
||||
} else {
|
||||
bucket.set_path_style();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(BucketClient::from_bucket(*bucket))
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve a required builder field, or report which one was missing.
|
||||
fn require(value: Option<String>, field: &str) -> Result<String, BucketClientError> {
|
||||
value.ok_or_else(|| {
|
||||
BucketClientError::ClientBuilderSetupError(format!("{field} is required"))
|
||||
})
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
/// Errors produced by [`crate::BucketClient`] and [`crate::BucketClientBuilder`].
|
||||
#[derive(Debug)]
|
||||
pub enum BucketClientError {
|
||||
/// An error surfaced by the underlying `rust-s3` client.
|
||||
S3Error(s3::error::S3Error),
|
||||
|
||||
/// A local I/O error (e.g. while reading bytes to upload).
|
||||
IoError(io::Error),
|
||||
|
||||
/// The builder was misconfigured — a required field was missing, or client
|
||||
/// construction failed for a reason we can describe.
|
||||
ClientBuilderSetupError(String),
|
||||
|
||||
/// The object store accepted the request but returned a non-success status.
|
||||
UploadFailed { status_code: u16, message: String },
|
||||
}
|
||||
|
||||
impl fmt::Display for BucketClientError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::S3Error(err) => write!(f, "S3 error: {}", err),
|
||||
Self::IoError(err) => write!(f, "I/O error: {}", err),
|
||||
Self::ClientBuilderSetupError(message) => {
|
||||
write!(f, "bucket client setup error: {}", message)
|
||||
}
|
||||
Self::UploadFailed { status_code, message } => {
|
||||
write!(f, "upload failed (HTTP {}): {}", status_code, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for BucketClientError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
Self::S3Error(err) => Some(err),
|
||||
Self::IoError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<s3::error::S3Error> for BucketClientError {
|
||||
fn from(err: s3::error::S3Error) -> Self {
|
||||
Self::S3Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for BucketClientError {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Self::IoError(err)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
//! bucket_client
|
||||
//!
|
||||
//! A small, ergonomic client for S3-compatible object storage, built on the
|
||||
//! `rust-s3` crate. Construct one with [`BucketClientBuilder`] and upload bytes
|
||||
//! with [`BucketClient::upload_file_bytes`].
|
||||
|
||||
pub mod bucket_client;
|
||||
pub mod bucket_client_builder;
|
||||
pub mod bucket_client_error;
|
||||
pub mod object_name;
|
||||
|
||||
pub use bucket_client::{BucketClient, UploadFileBytesArgs};
|
||||
pub use bucket_client_builder::BucketClientBuilder;
|
||||
pub use bucket_client_error::BucketClientError;
|
||||
pub use object_name::ObjectName;
|
||||
@@ -1,52 +0,0 @@
|
||||
use std::fmt;
|
||||
|
||||
/// A normalized object key for the bucket.
|
||||
///
|
||||
/// Leading slashes are stripped: S3/R2 treat a leading `/` as an empty leading
|
||||
/// path segment, which silently produces surprising keys (e.g. `/foo.mp4`
|
||||
/// becomes an object literally named `/foo.mp4`). Normalizing here keeps stored
|
||||
/// keys consistent regardless of how callers format the name.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ObjectName(String);
|
||||
|
||||
impl ObjectName {
|
||||
/// Build a normalized object name from any string-like value.
|
||||
pub fn new(raw: impl AsRef<str>) -> Self {
|
||||
ObjectName(raw.as_ref().trim_start_matches('/').to_string())
|
||||
}
|
||||
|
||||
/// The normalized key as a string slice.
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ObjectName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ObjectName {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn strips_leading_slashes() {
|
||||
assert_eq!(ObjectName::new("/foo/bar.mp4").as_str(), "foo/bar.mp4");
|
||||
assert_eq!(ObjectName::new("///a").as_str(), "a");
|
||||
assert_eq!(ObjectName::new("already/clean.txt").as_str(), "already/clean.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepts_string_and_str() {
|
||||
assert_eq!(ObjectName::new(String::from("x.bin")).as_str(), "x.bin");
|
||||
assert_eq!(ObjectName::new("x.bin").as_str(), "x.bin");
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -17,7 +17,7 @@ use tokio::io::AsyncReadExt;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LegacyBucketClient {
|
||||
pub struct BucketClient {
|
||||
bucket: Bucket,
|
||||
/// If set, put all files under this root path.
|
||||
optional_bucket_root: Option<String>,
|
||||
@@ -25,21 +25,21 @@ pub struct LegacyBucketClient {
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LegacyBucketClientError {
|
||||
pub enum BucketClientError {
|
||||
ErrorWithCodeAndMessage { code: u16, message: String },
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LegacyBucketClientError {
|
||||
impl std::fmt::Display for BucketClientError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
LegacyBucketClientError::ErrorWithCodeAndMessage { code, message } => write!(f, "Error {}: {}", code, message),
|
||||
BucketClientError::ErrorWithCodeAndMessage { code, message } => write!(f, "Error {}: {}", code, message),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Error for LegacyBucketClientError {}
|
||||
impl Error for BucketClientError {}
|
||||
|
||||
|
||||
impl LegacyBucketClient {
|
||||
impl BucketClient {
|
||||
pub fn bucket_name(&self) -> String {
|
||||
self.bucket.name().to_string()
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
pub mod legacy_bucket_client;
|
||||
pub mod bucket_client;
|
||||
pub mod remote_file_manager;
|
||||
@@ -4,7 +4,7 @@ use tokio::time::Duration;
|
||||
|
||||
use errors::AnyhowResult;
|
||||
|
||||
use crate::legacy_bucket_client::LegacyBucketClient;
|
||||
use crate::bucket_client::BucketClient;
|
||||
|
||||
#[async_trait]
|
||||
#[deprecated(note="this abstraction is too complicated, use another bucket client")]
|
||||
@@ -106,13 +106,13 @@ impl BucketOrchestration {
|
||||
}
|
||||
|
||||
#[deprecated(note="this abstraction is too complicated, use another bucket client")]
|
||||
async fn get_bucket_with_visibility(&self, public: bool) -> AnyhowResult<LegacyBucketClient> {
|
||||
async fn get_bucket_with_visibility(&self, public: bool) -> AnyhowResult<BucketClient> {
|
||||
let bucket_timeout = easyenv::get_env_duration_seconds_or_default(
|
||||
"BUCKET_TIMEOUT_SECONDS", Duration::from_secs(60 * 10));
|
||||
let bucket_client = if public {
|
||||
// use public bucket client
|
||||
info!("Configuring public GCS bucket...");
|
||||
LegacyBucketClient::create(
|
||||
BucketClient::create(
|
||||
&self.access_key,
|
||||
&self.secret_key,
|
||||
&self.region_name,
|
||||
@@ -123,7 +123,7 @@ impl BucketOrchestration {
|
||||
)?
|
||||
} else {
|
||||
info!("Configuring private GCS bucket...");
|
||||
LegacyBucketClient::create(
|
||||
BucketClient::create(
|
||||
&self.access_key,
|
||||
&self.secret_key,
|
||||
&self.region_name,
|
||||
|
||||
+6
-6
@@ -20,7 +20,7 @@ pub struct RemoteCloudFileClient {
|
||||
|
||||
impl RemoteCloudFileClient {
|
||||
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `LegacyBucketClient`")]
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `BucketClient`")]
|
||||
pub async fn get_remote_cloud_file_client() -> AnyhowResult<Self> {
|
||||
let bucket_orchestration = match BucketOrchestration::new_bucket_client_from_existing_env() {
|
||||
Ok(client) => client,
|
||||
@@ -34,7 +34,7 @@ impl RemoteCloudFileClient {
|
||||
})
|
||||
}
|
||||
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `LegacyBucketClient`")]
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `BucketClient`")]
|
||||
pub fn new(bucket_orchestration_client: Box<dyn BucketOrchestrationCore>) -> Self {
|
||||
Self {
|
||||
bucket_orchestration_client
|
||||
@@ -42,7 +42,7 @@ impl RemoteCloudFileClient {
|
||||
}
|
||||
|
||||
// Where the to_system_file_path is let sd_checkpoint_path = work_temp_dir.path().join("sd_checkpoint.safetensors"); path and file name and extension
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `LegacyBucketClient`")]
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `BucketClient`")]
|
||||
pub async fn download_file(&self, remote_cloud_bucket_details:RemoteCloudBucketDetails, to_system_file_path:String) -> AnyhowResult<()> {
|
||||
let file_descriptor = remote_cloud_bucket_details.file_descriptor_from_bucket_details();
|
||||
let file_bucket_directory = FileBucketDirectory::from_existing_bucket_details(remote_cloud_bucket_details);
|
||||
@@ -53,7 +53,7 @@ impl RemoteCloudFileClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `LegacyBucketClient`")]
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `BucketClient`")]
|
||||
pub async fn download_media_file(&self, media_file_path: &MediaFileBucketPath, to_system_file_path: String) -> AnyhowResult<()> {
|
||||
const IS_PUBLIC: bool = true; // NB: Media files are always public
|
||||
let full_remote_cloud_file_path = media_file_path.get_full_object_path_str().to_string();
|
||||
@@ -63,7 +63,7 @@ impl RemoteCloudFileClient {
|
||||
}
|
||||
|
||||
// return error or success with meta data.
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `LegacyBucketClient`")]
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `BucketClient`")]
|
||||
pub async fn upload_file(&self, file_descriptor:Box<dyn FileDescriptor>, from_system_file_path:&str) -> AnyhowResult<FileMetaData> {
|
||||
|
||||
// get file meta data
|
||||
@@ -99,7 +99,7 @@ impl RemoteCloudFileClient {
|
||||
}
|
||||
|
||||
// Retrieve the metadata from the file
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `LegacyBucketClient`")]
|
||||
#[deprecated(note="DO NOT USE THIS AWFUL CLOUD BUCKET CLIENT. These abstractions are complicated. See `BucketClient`")]
|
||||
pub fn get_file_meta_data(system_file_path:&str) -> AnyhowResult<FileMetaData> {
|
||||
let file_size_bytes = file_size(system_file_path.clone())?;
|
||||
let sha256_checksum = sha256_hash_file(system_file_path.clone())?;
|
||||
|
||||
@@ -2,12 +2,12 @@ use std::time::Duration;
|
||||
|
||||
use log::info;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
pub struct BucketClients {
|
||||
pub public: LegacyBucketClient,
|
||||
pub private: LegacyBucketClient,
|
||||
pub public: BucketClient,
|
||||
pub private: BucketClient,
|
||||
}
|
||||
|
||||
pub fn get_bucket_clients() -> AnyhowResult<BucketClients> {
|
||||
@@ -25,7 +25,7 @@ pub fn get_bucket_clients() -> AnyhowResult<BucketClients> {
|
||||
|
||||
info!("Configuring public GCS bucket...");
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
@@ -37,7 +37,7 @@ pub fn get_bucket_clients() -> AnyhowResult<BucketClients> {
|
||||
|
||||
info!("Configuring private GCS bucket...");
|
||||
|
||||
let private_bucket_client = LegacyBucketClient::create(
|
||||
let private_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -2,7 +2,7 @@ use log::info;
|
||||
use sqlx::{MySql, Pool};
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
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;
|
||||
use enums::by_table::zs_voices::encoding_type::ZsVoiceEncodingType;
|
||||
@@ -128,7 +128,7 @@ async fn create_voice_records(
|
||||
Ok((voice_token, dataset_token))
|
||||
}
|
||||
|
||||
async fn seed_file_to_bucket(wav_file: &str, bucket_client: &LegacyBucketClient) -> AnyhowResult<MediaFileBucketPath> {
|
||||
async fn seed_file_to_bucket(wav_file: &str, bucket_client: &BucketClient) -> AnyhowResult<MediaFileBucketPath> {
|
||||
info!("Uploading wav file {} ...", wav_file);
|
||||
|
||||
let public_upload_path = MediaFileBucketPath::generate_new(
|
||||
|
||||
@@ -4,7 +4,7 @@ use log::info;
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
use shared_env_var_config::mysql::env_get_mysql_connection_string_or_default;
|
||||
use enums::by_table::media_files::media_file_type::MediaFileType;
|
||||
@@ -48,7 +48,7 @@ pub async fn main() -> AnyhowResult<()> {
|
||||
|
||||
info!("Configuring GCS bucket...");
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use sqlx::{MySql, Pool};
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
|
||||
pub struct Deps {
|
||||
pub mysql_development : Pool<MySql>,
|
||||
pub mysql_production : Pool<MySql>,
|
||||
|
||||
pub bucket_development_public: LegacyBucketClient,
|
||||
pub bucket_development_private: LegacyBucketClient,
|
||||
pub bucket_development_public: BucketClient,
|
||||
pub bucket_development_private: BucketClient,
|
||||
|
||||
pub bucket_production_public: LegacyBucketClient,
|
||||
pub bucket_production_private: LegacyBucketClient,
|
||||
pub bucket_production_public: BucketClient,
|
||||
pub bucket_production_private: BucketClient,
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use log::info;
|
||||
use sqlx::{MySql, Pool};
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
@@ -68,7 +68,7 @@ async fn get_mysql(env_var_name: &str) -> AnyhowResult<Pool<MySql>> {
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
pub fn get_bucket_client(env_var_suffix: &str) -> AnyhowResult<LegacyBucketClient> {
|
||||
pub fn get_bucket_client(env_var_suffix: &str) -> AnyhowResult<BucketClient> {
|
||||
let env_var_suffix = env_var_suffix.to_uppercase();
|
||||
let access_key = easyenv::get_env_string_required(&format!("ACCESS_KEY_{env_var_suffix}"))?;
|
||||
let secret_key = easyenv::get_env_string_required(&format!("SECRET_KEY_{env_var_suffix}"))?;
|
||||
@@ -84,7 +84,7 @@ pub fn get_bucket_client(env_var_suffix: &str) -> AnyhowResult<LegacyBucketClien
|
||||
|
||||
info!("Configuring GCS bucket {env_var_suffix} ...");
|
||||
|
||||
Ok(LegacyBucketClient::create(
|
||||
Ok(BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -6,7 +6,6 @@ pub (crate) mod artcraft_website;
|
||||
pub (crate) mod development_only;
|
||||
pub (crate) mod fakeyou;
|
||||
pub (crate) mod legacy;
|
||||
pub (crate) mod realseedance;
|
||||
pub (crate) mod storyteller;
|
||||
pub (crate) mod storyteller_board;
|
||||
pub (crate) mod storyteller_render;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
use actix_cors::Cors;
|
||||
use crate::util::netlify_branch_domain_matches::netlify_branch_domain_matches;
|
||||
|
||||
/// CORS for the "Is That Real Seedance?" website (video-info-website).
|
||||
pub fn add_realseedance(cors: Cors, _is_production: bool) -> Cors {
|
||||
cors
|
||||
// Actual domain
|
||||
.allowed_origin("https://realseedance.com")
|
||||
.allowed_origin("https://www.realseedance.com")
|
||||
// Netlify project (bare domain + branch / deploy-preview subdomains)
|
||||
.allowed_origin_fn(|origin, _req_head| {
|
||||
netlify_branch_domain_matches(origin, "real-seedance.netlify.app")
|
||||
})
|
||||
}
|
||||
@@ -9,7 +9,6 @@ use crate::configs::artcraft_website::add_artcraft_website;
|
||||
use crate::configs::development_only::add_development_only;
|
||||
use crate::configs::fakeyou::{add_fakeyou, add_fakeyou_dev_proxy};
|
||||
use crate::configs::legacy::{add_legacy_storyteller_stream, add_legacy_trumped, add_legacy_vocodes, add_power_stream};
|
||||
use crate::configs::realseedance::add_realseedance;
|
||||
use crate::configs::storyteller::{add_storyteller, add_storyteller_dev_proxy};
|
||||
use crate::configs::storyteller_board::add_storyteller_board;
|
||||
use crate::configs::storyteller_render::add_storyteller_render;
|
||||
@@ -53,7 +52,6 @@ fn do_build_cors_config(is_production: bool) -> Cors {
|
||||
cors = add_artcraft_webapp(cors, is_production);
|
||||
cors = add_artcraft_website(cors, is_production);
|
||||
cors = add_artcraft_admin_dashboard(cors, is_production);
|
||||
cors = add_realseedance(cors, is_production);
|
||||
|
||||
// Legacy
|
||||
cors = add_legacy_trumped(cors, is_production);
|
||||
@@ -119,9 +117,6 @@ mod tests {
|
||||
"https://artcraft.ai",
|
||||
"https://www.artcraft.ai",
|
||||
"https://artcraft-dashboard.netlify.app",
|
||||
"https://realseedance.com",
|
||||
"https://www.realseedance.com",
|
||||
"https://real-seedance.netlify.app",
|
||||
];
|
||||
for origin in origins {
|
||||
assert_origin_ok(&production_cors, origin).await;
|
||||
@@ -186,26 +181,6 @@ mod tests {
|
||||
assert_origin_invalid(&development_cors, "https://staging.fakeyou.com").await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_realseedance_production() {
|
||||
let production_cors = build_cors_config(ServerEnvironment::Production);
|
||||
|
||||
// Valid origins
|
||||
assert_origin_ok(&production_cors, "https://realseedance.com").await;
|
||||
assert_origin_ok(&production_cors, "https://www.realseedance.com").await;
|
||||
assert_origin_ok(&production_cors, "https://real-seedance.netlify.app").await;
|
||||
// Netlify deploy-preview / branch subdomain
|
||||
assert_origin_ok(
|
||||
&production_cors,
|
||||
"https://deploy-preview-12--real-seedance.netlify.app",
|
||||
)
|
||||
.await;
|
||||
|
||||
// Invalid origins
|
||||
assert_origin_invalid(&production_cors, "https://realseedance.fake.com").await;
|
||||
assert_origin_invalid(&production_cors, "https://realseedance.netlify.app").await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_storyteller_production() {
|
||||
let production_cors = build_cors_config(ServerEnvironment::Production);
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
[package]
|
||||
name = "sha1_hash"
|
||||
edition = "2024"
|
||||
version = "0.0.1"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "sha1_hash"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
normal = ["workspace-build-acceleration"]
|
||||
|
||||
[dependencies]
|
||||
# Workspace hack (faster compile times)
|
||||
workspace-build-acceleration = { version = "0.1", path = "../../workspace-build-acceleration" }
|
||||
|
||||
# External
|
||||
sha1 = "0.10"
|
||||
@@ -1,17 +0,0 @@
|
||||
use std::fmt;
|
||||
|
||||
/// Errors produced while computing a SHA-1 hash.
|
||||
#[derive(Debug)]
|
||||
pub enum Sha1HashError {
|
||||
/// The SHA-1 digest wasn't the expected 20 bytes. This should be unreachable
|
||||
/// for a well-behaved SHA-1 implementation; it exists as a defensive guard.
|
||||
UnexpectedDigestLength(usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for Sha1HashError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Sha1HashError {}
|
||||
@@ -1,11 +0,0 @@
|
||||
//! sha1_hash
|
||||
//!
|
||||
//! SHA-1 hashing utilities. The primary entry point is
|
||||
//! [`sha1_hash_bytes_as_crockford`], which hashes bytes with SHA-1 and returns
|
||||
//! the 20-byte digest as a lowercase Crockford base32 string (32 chars).
|
||||
|
||||
pub mod error;
|
||||
pub mod sha1_hash_bytes_as_crockford;
|
||||
|
||||
pub use error::Sha1HashError;
|
||||
pub use sha1_hash_bytes_as_crockford::sha1_hash_bytes_as_crockford;
|
||||
@@ -1,74 +0,0 @@
|
||||
use sha1::{Digest, Sha1};
|
||||
|
||||
use crate::error::Sha1HashError;
|
||||
|
||||
/// Lowercase Crockford base32 alphabet (excludes I, L, O, U). Matches the casing
|
||||
/// used by the `tokens` crate's Crockford generators.
|
||||
const CROCKFORD_LOWERCASE: &[u8] = b"0123456789abcdefghjkmnpqrstvwxyz";
|
||||
|
||||
/// The byte length of a SHA-1 digest.
|
||||
const SHA1_DIGEST_LEN: usize = 20;
|
||||
|
||||
/// SHA-1 hash `bytes` and return the 20-byte digest encoded as a lowercase
|
||||
/// Crockford base32 string (32 characters, no padding — 160 bits / 5).
|
||||
pub fn sha1_hash_bytes_as_crockford(bytes: &[u8]) -> Result<String, Sha1HashError> {
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(bytes);
|
||||
let digest = hasher.finalize();
|
||||
|
||||
if digest.len() != SHA1_DIGEST_LEN {
|
||||
return Err(Sha1HashError::UnexpectedDigestLength(digest.len()));
|
||||
}
|
||||
|
||||
Ok(encode_crockford_lower(&digest))
|
||||
}
|
||||
|
||||
/// Encode bytes as lowercase Crockford base32, reading 5 bits at a time.
|
||||
fn encode_crockford_lower(data: &[u8]) -> String {
|
||||
let mut out = String::with_capacity(data.len() * 8 / 5 + 1);
|
||||
let mut buffer: u32 = 0;
|
||||
let mut bits: u32 = 0;
|
||||
for &byte in data {
|
||||
buffer = (buffer << 8) | byte as u32;
|
||||
bits += 8;
|
||||
while bits >= 5 {
|
||||
bits -= 5;
|
||||
let index = ((buffer >> bits) & 0x1f) as usize;
|
||||
out.push(CROCKFORD_LOWERCASE[index] as char);
|
||||
}
|
||||
}
|
||||
if bits > 0 {
|
||||
let index = ((buffer << (5 - bits)) & 0x1f) as usize;
|
||||
out.push(CROCKFORD_LOWERCASE[index] as char);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn empty_input_is_32_crockford_chars() {
|
||||
// SHA-1("") = da39a3ee5e6b4b0d3255bfef95601890afd80709
|
||||
let out = sha1_hash_bytes_as_crockford(&[]).unwrap();
|
||||
assert_eq!(out.len(), 32);
|
||||
assert!(out.bytes().all(|b| CROCKFORD_LOWERCASE.contains(&b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deterministic_and_distinct() {
|
||||
let a = sha1_hash_bytes_as_crockford(b"hello").unwrap();
|
||||
let b = sha1_hash_bytes_as_crockford(b"hello").unwrap();
|
||||
let c = sha1_hash_bytes_as_crockford(b"world").unwrap();
|
||||
assert_eq!(a, b);
|
||||
assert_ne!(a, c);
|
||||
assert_eq!(a.len(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encodes_known_bytes() {
|
||||
// 20 zero bytes → 32 '0' chars.
|
||||
assert_eq!(encode_crockford_lower(&[0u8; 20]), "0".repeat(32));
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,6 @@ pub mod trending_model_analytics;
|
||||
pub mod tts;
|
||||
pub mod twitch;
|
||||
pub mod unsubscribe_reason;
|
||||
pub mod uploaded_video_notes;
|
||||
pub mod uploaded_videos;
|
||||
pub mod user_impersonation_requests;
|
||||
pub mod user_referral_codes;
|
||||
pub mod user_referrals;
|
||||
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_model_type::UploadedVideoNoteReportedModelType;
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_website::UploadedVideoNoteReportedWebsite;
|
||||
use tokens::tokens::uploaded_video_notes::UploadVideoNoteToken;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
pub struct InsertUploadedVideoNoteArgs<'e, 'c, E>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
pub uploaded_video_token: &'e UploadedVideoToken,
|
||||
|
||||
pub maybe_filename: Option<&'e str>,
|
||||
pub maybe_reported_model_type: Option<UploadedVideoNoteReportedModelType>,
|
||||
pub maybe_reported_model_name: Option<&'e str>,
|
||||
pub maybe_website: Option<UploadedVideoNoteReportedWebsite>,
|
||||
pub maybe_other_website: Option<&'e str>,
|
||||
pub maybe_comments: Option<&'e str>,
|
||||
|
||||
pub maybe_email_address: Option<&'e str>,
|
||||
pub can_share_report: bool,
|
||||
pub was_scammed: bool,
|
||||
|
||||
pub comment_create_ip_address: &'e str,
|
||||
|
||||
pub mysql_executor: E,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
/// Insert a new `uploaded_video_notes` record. The `UploadVideoNoteToken` is
|
||||
/// minted here (in the data-access layer, not the handler) and returned.
|
||||
/// `created_at` is set to `NOW()`.
|
||||
pub async fn insert_uploaded_video_note<'e, 'c: 'e, E>(
|
||||
args: InsertUploadedVideoNoteArgs<'e, 'c, E>,
|
||||
) -> Result<UploadVideoNoteToken, sqlx::Error>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
let token = UploadVideoNoteToken::generate();
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO uploaded_video_notes
|
||||
SET
|
||||
token = ?,
|
||||
uploaded_video_token = ?,
|
||||
maybe_filename = ?,
|
||||
maybe_reported_model_type = ?,
|
||||
maybe_reported_model_name = ?,
|
||||
maybe_website = ?,
|
||||
maybe_other_website = ?,
|
||||
maybe_comments = ?,
|
||||
maybe_email_address = ?,
|
||||
can_share_report = ?,
|
||||
was_scammed = ?,
|
||||
comment_create_ip_address = ?,
|
||||
created_at = NOW()
|
||||
"#,
|
||||
token.as_str(),
|
||||
args.uploaded_video_token.as_str(),
|
||||
args.maybe_filename,
|
||||
args.maybe_reported_model_type.map(|model_type| model_type.to_str()),
|
||||
args.maybe_reported_model_name,
|
||||
args.maybe_website.map(|website| website.to_str()),
|
||||
args.maybe_other_website,
|
||||
args.maybe_comments,
|
||||
args.maybe_email_address,
|
||||
args.can_share_report,
|
||||
args.was_scammed,
|
||||
args.comment_create_ip_address,
|
||||
)
|
||||
.execute(args.mysql_executor)
|
||||
.await?;
|
||||
|
||||
Ok(token)
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod insert_uploaded_video_note;
|
||||
pub mod update_uploaded_video_note;
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_model_type::UploadedVideoNoteReportedModelType;
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_website::UploadedVideoNoteReportedWebsite;
|
||||
use tokens::tokens::uploaded_video_notes::UploadVideoNoteToken;
|
||||
|
||||
pub struct UpdateUploadedVideoNoteArgs<'e, 'c, E>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
pub token: &'e UploadVideoNoteToken,
|
||||
|
||||
pub maybe_filename: Option<&'e str>,
|
||||
pub maybe_reported_model_type: Option<UploadedVideoNoteReportedModelType>,
|
||||
pub maybe_reported_model_name: Option<&'e str>,
|
||||
pub maybe_website: Option<UploadedVideoNoteReportedWebsite>,
|
||||
pub maybe_other_website: Option<&'e str>,
|
||||
pub maybe_comments: Option<&'e str>,
|
||||
|
||||
pub maybe_email_address: Option<&'e str>,
|
||||
pub can_share_report: bool,
|
||||
pub was_scammed: bool,
|
||||
|
||||
/// IP address of the request making the update; stamped on `maybe_comment_update_ip_address`.
|
||||
pub maybe_comment_update_ip_address: Option<&'e str>,
|
||||
|
||||
pub mysql_executor: E,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
/// Update the mutable fields of an `uploaded_video_notes` record by `token`. The
|
||||
/// `version` vector clock is incremented by 1, and `updated_at` is refreshed via
|
||||
/// the column's `ON UPDATE` clause. Returns the number of rows affected (0 if no
|
||||
/// row matched).
|
||||
pub async fn update_uploaded_video_note<'e, 'c: 'e, E>(
|
||||
args: UpdateUploadedVideoNoteArgs<'e, 'c, E>,
|
||||
) -> Result<u64, sqlx::Error>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
UPDATE uploaded_video_notes
|
||||
SET
|
||||
maybe_filename = ?,
|
||||
maybe_reported_model_type = ?,
|
||||
maybe_reported_model_name = ?,
|
||||
maybe_website = ?,
|
||||
maybe_other_website = ?,
|
||||
maybe_comments = ?,
|
||||
maybe_email_address = ?,
|
||||
can_share_report = ?,
|
||||
was_scammed = ?,
|
||||
maybe_comment_update_ip_address = ?,
|
||||
version = version + 1
|
||||
WHERE token = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
args.maybe_filename,
|
||||
args.maybe_reported_model_type.map(|model_type| model_type.to_str()),
|
||||
args.maybe_reported_model_name,
|
||||
args.maybe_website.map(|website| website.to_str()),
|
||||
args.maybe_other_website,
|
||||
args.maybe_comments,
|
||||
args.maybe_email_address,
|
||||
args.can_share_report,
|
||||
args.was_scammed,
|
||||
args.maybe_comment_update_ip_address,
|
||||
args.token.as_str(),
|
||||
)
|
||||
.execute(args.mysql_executor)
|
||||
.await?;
|
||||
|
||||
Ok(result.rows_affected())
|
||||
}
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_family::UploadedVideoDetectedModelFamily;
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_type::UploadedVideoDetectedModelType;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
use crate::queries::uploaded_videos::uploaded_video_row::UploadedVideoRow;
|
||||
|
||||
pub struct GetUploadedVideoBySha1ChecksumArgs<'e, 'c, E>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
pub sha1_checksum: &'e str,
|
||||
pub mysql_executor: E,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
/// Look up an `uploaded_videos` record by its `sha1_checksum`. `Ok(None)` if no
|
||||
/// row matches. Useful for de-duplicating re-uploads of the same bytes.
|
||||
pub async fn get_uploaded_video_by_sha1_checksum<'e, 'c: 'e, E>(
|
||||
args: GetUploadedVideoBySha1ChecksumArgs<'e, 'c, E>,
|
||||
) -> Result<Option<UploadedVideoRow>, sqlx::Error>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
SELECT
|
||||
token as `token: UploadedVideoToken`,
|
||||
sha1_checksum,
|
||||
filesize_bytes as `filesize_bytes: u32`,
|
||||
maybe_width as `maybe_width: u32`,
|
||||
maybe_height as `maybe_height: u32`,
|
||||
maybe_resolution,
|
||||
maybe_detected_model_family as `maybe_detected_model_family: UploadedVideoDetectedModelFamily`,
|
||||
maybe_detected_model_type as `maybe_detected_model_type: UploadedVideoDetectedModelType`,
|
||||
maybe_report,
|
||||
upload_ip_address,
|
||||
maybe_updated_ip_address,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM uploaded_videos
|
||||
WHERE sha1_checksum = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
args.sha1_checksum,
|
||||
)
|
||||
.fetch_optional(args.mysql_executor)
|
||||
.await?;
|
||||
|
||||
Ok(result.map(|r| UploadedVideoRow {
|
||||
token: r.token,
|
||||
sha1_checksum: r.sha1_checksum,
|
||||
filesize_bytes: r.filesize_bytes,
|
||||
maybe_width: r.maybe_width,
|
||||
maybe_height: r.maybe_height,
|
||||
maybe_resolution: r.maybe_resolution,
|
||||
maybe_detected_model_family: r.maybe_detected_model_family,
|
||||
maybe_detected_model_type: r.maybe_detected_model_type,
|
||||
maybe_report: r.maybe_report,
|
||||
upload_ip_address: r.upload_ip_address,
|
||||
maybe_updated_ip_address: r.maybe_updated_ip_address,
|
||||
created_at: r.created_at,
|
||||
updated_at: r.updated_at,
|
||||
}))
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_family::UploadedVideoDetectedModelFamily;
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_type::UploadedVideoDetectedModelType;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
use crate::queries::uploaded_videos::uploaded_video_row::UploadedVideoRow;
|
||||
|
||||
pub struct GetUploadedVideoByTokenArgs<'e, 'c, E>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
pub token: &'e UploadedVideoToken,
|
||||
pub mysql_executor: E,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
/// Look up an `uploaded_videos` record by its `token`. `Ok(None)` if no row matches.
|
||||
pub async fn get_uploaded_video_by_token<'e, 'c: 'e, E>(
|
||||
args: GetUploadedVideoByTokenArgs<'e, 'c, E>,
|
||||
) -> Result<Option<UploadedVideoRow>, sqlx::Error>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
SELECT
|
||||
token as `token: UploadedVideoToken`,
|
||||
sha1_checksum,
|
||||
filesize_bytes as `filesize_bytes: u32`,
|
||||
maybe_width as `maybe_width: u32`,
|
||||
maybe_height as `maybe_height: u32`,
|
||||
maybe_resolution,
|
||||
maybe_detected_model_family as `maybe_detected_model_family: UploadedVideoDetectedModelFamily`,
|
||||
maybe_detected_model_type as `maybe_detected_model_type: UploadedVideoDetectedModelType`,
|
||||
maybe_report,
|
||||
upload_ip_address,
|
||||
maybe_updated_ip_address,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM uploaded_videos
|
||||
WHERE token = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
args.token.as_str(),
|
||||
)
|
||||
.fetch_optional(args.mysql_executor)
|
||||
.await?;
|
||||
|
||||
Ok(result.map(|r| UploadedVideoRow {
|
||||
token: r.token,
|
||||
sha1_checksum: r.sha1_checksum,
|
||||
filesize_bytes: r.filesize_bytes,
|
||||
maybe_width: r.maybe_width,
|
||||
maybe_height: r.maybe_height,
|
||||
maybe_resolution: r.maybe_resolution,
|
||||
maybe_detected_model_family: r.maybe_detected_model_family,
|
||||
maybe_detected_model_type: r.maybe_detected_model_type,
|
||||
maybe_report: r.maybe_report,
|
||||
upload_ip_address: r.upload_ip_address,
|
||||
maybe_updated_ip_address: r.maybe_updated_ip_address,
|
||||
created_at: r.created_at,
|
||||
updated_at: r.updated_at,
|
||||
}))
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_family::UploadedVideoDetectedModelFamily;
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_type::UploadedVideoDetectedModelType;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
pub struct InsertUploadedVideoArgs<'e, 'c, E>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
pub sha1_checksum: &'e str,
|
||||
pub filesize_bytes: u32,
|
||||
pub maybe_filename: Option<&'e str>,
|
||||
|
||||
pub maybe_width: Option<u32>,
|
||||
pub maybe_height: Option<u32>,
|
||||
pub maybe_resolution: Option<&'e str>,
|
||||
|
||||
pub maybe_detected_model_family: Option<UploadedVideoDetectedModelFamily>,
|
||||
pub maybe_detected_model_type: Option<UploadedVideoDetectedModelType>,
|
||||
pub maybe_report: Option<&'e str>,
|
||||
|
||||
pub upload_ip_address: &'e str,
|
||||
|
||||
pub mysql_executor: E,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
/// Insert a new `uploaded_videos` record. The `UploadedVideoToken` is minted
|
||||
/// here (in the data-access layer, not the handler) and returned. `created_at`
|
||||
/// is set to `NOW()`.
|
||||
pub async fn insert_uploaded_video<'e, 'c: 'e, E>(
|
||||
args: InsertUploadedVideoArgs<'e, 'c, E>,
|
||||
) -> Result<UploadedVideoToken, sqlx::Error>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
let token = UploadedVideoToken::generate();
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO uploaded_videos
|
||||
SET
|
||||
token = ?,
|
||||
sha1_checksum = ?,
|
||||
filesize_bytes = ?,
|
||||
maybe_filename = ?,
|
||||
maybe_width = ?,
|
||||
maybe_height = ?,
|
||||
maybe_resolution = ?,
|
||||
maybe_detected_model_family = ?,
|
||||
maybe_detected_model_type = ?,
|
||||
maybe_report = ?,
|
||||
upload_ip_address = ?,
|
||||
created_at = NOW()
|
||||
"#,
|
||||
token.as_str(),
|
||||
args.sha1_checksum,
|
||||
args.filesize_bytes,
|
||||
args.maybe_filename,
|
||||
args.maybe_width,
|
||||
args.maybe_height,
|
||||
args.maybe_resolution,
|
||||
args.maybe_detected_model_family.map(|family| family.to_str()),
|
||||
args.maybe_detected_model_type.map(|model_type| model_type.to_str()),
|
||||
args.maybe_report,
|
||||
args.upload_ip_address,
|
||||
)
|
||||
.execute(args.mysql_executor)
|
||||
.await?;
|
||||
|
||||
Ok(token)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
pub mod get_uploaded_video_by_sha1_checksum;
|
||||
pub mod get_uploaded_video_by_token;
|
||||
pub mod insert_uploaded_video;
|
||||
pub mod update_uploaded_video;
|
||||
pub mod uploaded_video_row;
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_family::UploadedVideoDetectedModelFamily;
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_type::UploadedVideoDetectedModelType;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
pub struct UpdateUploadedVideoArgs<'e, 'c, E>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
pub token: &'e UploadedVideoToken,
|
||||
|
||||
pub maybe_filename: Option<&'e str>,
|
||||
|
||||
pub maybe_width: Option<u32>,
|
||||
pub maybe_height: Option<u32>,
|
||||
pub maybe_resolution: Option<&'e str>,
|
||||
|
||||
pub maybe_detected_model_family: Option<UploadedVideoDetectedModelFamily>,
|
||||
pub maybe_detected_model_type: Option<UploadedVideoDetectedModelType>,
|
||||
pub maybe_report: Option<&'e str>,
|
||||
|
||||
/// IP address of the request making the update; stamped on `maybe_updated_ip_address`.
|
||||
pub maybe_updated_ip_address: Option<&'e str>,
|
||||
|
||||
pub mysql_executor: E,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
/// Update the mutable fields of an `uploaded_videos` record by `token`
|
||||
/// (dimensions, detection, report, updater IP). The `version` vector clock is
|
||||
/// incremented by 1, and `updated_at` is refreshed via the column's `ON UPDATE`
|
||||
/// clause. Returns the number of rows affected (0 if no row matched).
|
||||
pub async fn update_uploaded_video<'e, 'c: 'e, E>(
|
||||
args: UpdateUploadedVideoArgs<'e, 'c, E>,
|
||||
) -> Result<u64, sqlx::Error>
|
||||
where
|
||||
E: 'e + Executor<'c, Database = MySql>,
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
UPDATE uploaded_videos
|
||||
SET
|
||||
maybe_filename = ?,
|
||||
maybe_width = ?,
|
||||
maybe_height = ?,
|
||||
maybe_resolution = ?,
|
||||
maybe_detected_model_family = ?,
|
||||
maybe_detected_model_type = ?,
|
||||
maybe_report = ?,
|
||||
maybe_updated_ip_address = ?,
|
||||
version = version + 1
|
||||
WHERE token = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
args.maybe_filename,
|
||||
args.maybe_width,
|
||||
args.maybe_height,
|
||||
args.maybe_resolution,
|
||||
args.maybe_detected_model_family.map(|family| family.to_str()),
|
||||
args.maybe_detected_model_type.map(|model_type| model_type.to_str()),
|
||||
args.maybe_report,
|
||||
args.maybe_updated_ip_address,
|
||||
args.token.as_str(),
|
||||
)
|
||||
.execute(args.mysql_executor)
|
||||
.await?;
|
||||
|
||||
Ok(result.rows_affected())
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_family::UploadedVideoDetectedModelFamily;
|
||||
use enums::by_table::uploaded_videos::uploaded_video_detected_model_type::UploadedVideoDetectedModelType;
|
||||
use tokens::tokens::uploaded_videos::UploadedVideoToken;
|
||||
|
||||
/// A materialized `uploaded_videos` row (minus the internal `id`).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UploadedVideoRow {
|
||||
pub token: UploadedVideoToken,
|
||||
|
||||
pub sha1_checksum: String,
|
||||
pub filesize_bytes: u32,
|
||||
|
||||
pub maybe_width: Option<u32>,
|
||||
pub maybe_height: Option<u32>,
|
||||
pub maybe_resolution: Option<String>,
|
||||
|
||||
pub maybe_detected_model_family: Option<UploadedVideoDetectedModelFamily>,
|
||||
pub maybe_detected_model_type: Option<UploadedVideoDetectedModelType>,
|
||||
pub maybe_report: Option<String>,
|
||||
|
||||
pub upload_ip_address: String,
|
||||
pub maybe_updated_ip_address: Option<String>,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -21,8 +21,6 @@ pub mod staff_audit_logs;
|
||||
pub mod tag_uses;
|
||||
pub mod trending_model_analytics;
|
||||
pub mod tts_models;
|
||||
pub mod uploaded_video_notes;
|
||||
pub mod uploaded_videos;
|
||||
pub mod usages;
|
||||
pub mod user_bookmarks;
|
||||
pub mod user_ratings;
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod uploaded_video_note_reported_model_type;
|
||||
pub mod uploaded_video_note_reported_website;
|
||||
-253
@@ -1,253 +0,0 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `uploaded_video_notes` table in a `VARCHAR(32)` field.
|
||||
///
|
||||
/// The model the note's submitter claims the video is. The variant set mirrors
|
||||
/// [`crate::common::generation::common_video_model::CommonVideoModel`].
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
pub enum UploadedVideoNoteReportedModelType {
|
||||
#[serde(rename = "grok_video")]
|
||||
GrokVideo,
|
||||
#[serde(rename = "grok_imagine_video")]
|
||||
GrokImagineVideo,
|
||||
#[serde(rename = "grok_imagine_video_1p5")]
|
||||
GrokImagineVideo1p5,
|
||||
#[serde(rename = "kling_1p6_pro")]
|
||||
Kling16Pro,
|
||||
#[serde(rename = "kling_2p1_pro")]
|
||||
Kling21Pro,
|
||||
#[serde(rename = "kling_2p1_master")]
|
||||
Kling21Master,
|
||||
#[serde(rename = "kling_2p5_turbo_pro")]
|
||||
Kling2p5TurboPro,
|
||||
#[serde(rename = "kling_2p6_pro")]
|
||||
Kling2p6Pro,
|
||||
#[serde(rename = "kling_3p0_standard")]
|
||||
Kling3p0Standard,
|
||||
#[serde(rename = "kling_3p0_pro")]
|
||||
Kling3p0Pro,
|
||||
#[serde(rename = "happy_horse_1p0")]
|
||||
HappyHorse1p0,
|
||||
#[serde(rename = "seedance_1p0_lite")]
|
||||
Seedance10Lite,
|
||||
#[serde(rename = "seedance_1p5_pro")]
|
||||
Seedance1p5Pro,
|
||||
// `preview_model` is a retired alias that collapses onto Seedance 2.0.
|
||||
#[serde(rename = "seedance_2p0", alias = "preview_model")]
|
||||
Seedance2p0,
|
||||
// `preview_model_fast` is a retired alias that collapses onto Seedance 2.0 Fast.
|
||||
#[serde(rename = "seedance_2p0_fast", alias = "preview_model_fast")]
|
||||
Seedance2p0Fast,
|
||||
#[serde(rename = "seedance_2p0_bp")]
|
||||
Seedance2p0BytePlus,
|
||||
#[serde(rename = "seedance_2p0_bp_fast")]
|
||||
Seedance2p0BytePlusFast,
|
||||
#[serde(rename = "seedance_2p0_u")]
|
||||
Seedance2p0Ultra,
|
||||
#[serde(rename = "seedance_2p0_u_fast")]
|
||||
Seedance2p0UltraFast,
|
||||
#[serde(rename = "seedance_2p0_bpu")]
|
||||
Seedance2p0BytePlusUltra,
|
||||
#[serde(rename = "seedance_2p0_bpu_fast")]
|
||||
Seedance2p0BytePlusUltraFast,
|
||||
#[serde(rename = "sora_2")]
|
||||
Sora2,
|
||||
#[serde(rename = "sora_2_pro")]
|
||||
Sora2Pro,
|
||||
#[serde(rename = "veo_2")]
|
||||
Veo2,
|
||||
#[serde(rename = "veo_3")]
|
||||
Veo3,
|
||||
#[serde(rename = "veo_3_fast")]
|
||||
Veo3Fast,
|
||||
#[serde(rename = "veo_3p1")]
|
||||
Veo3p1,
|
||||
#[serde(rename = "veo_3p1_fast")]
|
||||
Veo3p1Fast,
|
||||
}
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(UploadedVideoNoteReportedModelType);
|
||||
impl_mysql_enum_coders!(UploadedVideoNoteReportedModelType);
|
||||
impl_mysql_from_row!(UploadedVideoNoteReportedModelType);
|
||||
|
||||
impl UploadedVideoNoteReportedModelType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::GrokVideo => "grok_video",
|
||||
Self::GrokImagineVideo => "grok_imagine_video",
|
||||
Self::GrokImagineVideo1p5 => "grok_imagine_video_1p5",
|
||||
Self::Kling16Pro => "kling_1p6_pro",
|
||||
Self::Kling21Pro => "kling_2p1_pro",
|
||||
Self::Kling21Master => "kling_2p1_master",
|
||||
Self::Kling2p5TurboPro => "kling_2p5_turbo_pro",
|
||||
Self::Kling2p6Pro => "kling_2p6_pro",
|
||||
Self::Kling3p0Standard => "kling_3p0_standard",
|
||||
Self::Kling3p0Pro => "kling_3p0_pro",
|
||||
Self::HappyHorse1p0 => "happy_horse_1p0",
|
||||
Self::Seedance10Lite => "seedance_1p0_lite",
|
||||
Self::Seedance1p5Pro => "seedance_1p5_pro",
|
||||
Self::Seedance2p0 => "seedance_2p0",
|
||||
Self::Seedance2p0Fast => "seedance_2p0_fast",
|
||||
Self::Seedance2p0BytePlus => "seedance_2p0_bp",
|
||||
Self::Seedance2p0BytePlusFast => "seedance_2p0_bp_fast",
|
||||
Self::Seedance2p0Ultra => "seedance_2p0_u",
|
||||
Self::Seedance2p0UltraFast => "seedance_2p0_u_fast",
|
||||
Self::Seedance2p0BytePlusUltra => "seedance_2p0_bpu",
|
||||
Self::Seedance2p0BytePlusUltraFast => "seedance_2p0_bpu_fast",
|
||||
Self::Sora2 => "sora_2",
|
||||
Self::Sora2Pro => "sora_2_pro",
|
||||
Self::Veo2 => "veo_2",
|
||||
Self::Veo3 => "veo_3",
|
||||
Self::Veo3Fast => "veo_3_fast",
|
||||
Self::Veo3p1 => "veo_3p1",
|
||||
Self::Veo3p1Fast => "veo_3p1_fast",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"grok_video" => Ok(Self::GrokVideo),
|
||||
"grok_imagine_video" => Ok(Self::GrokImagineVideo),
|
||||
"grok_imagine_video_1p5" => Ok(Self::GrokImagineVideo1p5),
|
||||
"kling_1p6_pro" => Ok(Self::Kling16Pro),
|
||||
"kling_2p1_pro" => Ok(Self::Kling21Pro),
|
||||
"kling_2p1_master" => Ok(Self::Kling21Master),
|
||||
"kling_2p5_turbo_pro" => Ok(Self::Kling2p5TurboPro),
|
||||
"kling_2p6_pro" => Ok(Self::Kling2p6Pro),
|
||||
"kling_3p0_standard" => Ok(Self::Kling3p0Standard),
|
||||
"kling_3p0_pro" => Ok(Self::Kling3p0Pro),
|
||||
"happy_horse_1p0" => Ok(Self::HappyHorse1p0),
|
||||
"seedance_1p0_lite" => Ok(Self::Seedance10Lite),
|
||||
"seedance_1p5_pro" => Ok(Self::Seedance1p5Pro),
|
||||
"seedance_2p0" => Ok(Self::Seedance2p0),
|
||||
"seedance_2p0_fast" => Ok(Self::Seedance2p0Fast),
|
||||
"seedance_2p0_bp" => Ok(Self::Seedance2p0BytePlus),
|
||||
"seedance_2p0_bp_fast" => Ok(Self::Seedance2p0BytePlusFast),
|
||||
"seedance_2p0_u" => Ok(Self::Seedance2p0Ultra),
|
||||
"seedance_2p0_u_fast" => Ok(Self::Seedance2p0UltraFast),
|
||||
"seedance_2p0_bpu" => Ok(Self::Seedance2p0BytePlusUltra),
|
||||
"seedance_2p0_bpu_fast" => Ok(Self::Seedance2p0BytePlusUltraFast),
|
||||
"sora_2" => Ok(Self::Sora2),
|
||||
"sora_2_pro" => Ok(Self::Sora2Pro),
|
||||
"veo_2" => Ok(Self::Veo2),
|
||||
"veo_3" => Ok(Self::Veo3),
|
||||
"veo_3_fast" => Ok(Self::Veo3Fast),
|
||||
"veo_3p1" => Ok(Self::Veo3p1),
|
||||
"veo_3p1_fast" => Ok(Self::Veo3p1Fast),
|
||||
// Retired values: collapse onto the Seedance 2.0 equivalents.
|
||||
"preview_model" => Ok(Self::Seedance2p0),
|
||||
"preview_model_fast" => Ok(Self::Seedance2p0Fast),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
BTreeSet::from([
|
||||
Self::GrokVideo,
|
||||
Self::GrokImagineVideo,
|
||||
Self::GrokImagineVideo1p5,
|
||||
Self::Kling16Pro,
|
||||
Self::Kling21Pro,
|
||||
Self::Kling21Master,
|
||||
Self::Kling2p5TurboPro,
|
||||
Self::Kling2p6Pro,
|
||||
Self::Kling3p0Standard,
|
||||
Self::Kling3p0Pro,
|
||||
Self::HappyHorse1p0,
|
||||
Self::Seedance10Lite,
|
||||
Self::Seedance1p5Pro,
|
||||
Self::Seedance2p0,
|
||||
Self::Seedance2p0Fast,
|
||||
Self::Seedance2p0BytePlus,
|
||||
Self::Seedance2p0BytePlusFast,
|
||||
Self::Seedance2p0Ultra,
|
||||
Self::Seedance2p0UltraFast,
|
||||
Self::Seedance2p0BytePlusUltra,
|
||||
Self::Seedance2p0BytePlusUltraFast,
|
||||
Self::Sora2,
|
||||
Self::Sora2Pro,
|
||||
Self::Veo2,
|
||||
Self::Veo3,
|
||||
Self::Veo3Fast,
|
||||
Self::Veo3p1,
|
||||
Self::Veo3p1Fast,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in UploadedVideoNoteReportedModelType::all_variants() {
|
||||
assert_eq!(variant, UploadedVideoNoteReportedModelType::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, UploadedVideoNoteReportedModelType::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, UploadedVideoNoteReportedModelType::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
assert!(UploadedVideoNoteReportedModelType::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_round_trip() {
|
||||
for variant in UploadedVideoNoteReportedModelType::all_variants() {
|
||||
let json = serde_json::to_string(&variant).unwrap();
|
||||
let deserialized: UploadedVideoNoteReportedModelType = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(variant, deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
/// The MySQL string (to_str) and the JSON string (serde) must stay aligned.
|
||||
#[test]
|
||||
fn to_str_matches_serde() {
|
||||
for variant in UploadedVideoNoteReportedModelType::all_variants() {
|
||||
let json = serde_json::to_string(&variant).unwrap();
|
||||
assert_eq!(json, format!("\"{}\"", variant.to_str()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variant_count() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(UploadedVideoNoteReportedModelType::all_variants().len(), UploadedVideoNoteReportedModelType::iter().len());
|
||||
assert_eq!(UploadedVideoNoteReportedModelType::COUNT, 28);
|
||||
}
|
||||
|
||||
/// Retired `preview_model*` values must still decode, collapsing onto Seedance 2.0.
|
||||
#[test]
|
||||
fn legacy_preview_values_map_to_seedance() {
|
||||
assert_eq!(
|
||||
UploadedVideoNoteReportedModelType::from_str("preview_model").unwrap(),
|
||||
UploadedVideoNoteReportedModelType::Seedance2p0
|
||||
);
|
||||
assert_eq!(
|
||||
UploadedVideoNoteReportedModelType::from_str("preview_model_fast").unwrap(),
|
||||
UploadedVideoNoteReportedModelType::Seedance2p0Fast
|
||||
);
|
||||
let decoded: UploadedVideoNoteReportedModelType =
|
||||
serde_json::from_str("\"preview_model\"").unwrap();
|
||||
assert_eq!(decoded, UploadedVideoNoteReportedModelType::Seedance2p0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialized_length_ok_for_database() {
|
||||
const MAX_LENGTH: usize = 32;
|
||||
for variant in UploadedVideoNoteReportedModelType::all_variants() {
|
||||
let serialized = variant.to_str();
|
||||
assert!(!serialized.is_empty(), "variant {:?} is too short", variant);
|
||||
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `uploaded_video_notes` table in a `VARCHAR(32)` field.
|
||||
///
|
||||
/// The website / platform the note's submitter says the video came from.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum UploadedVideoNoteReportedWebsite {
|
||||
Runway,
|
||||
Higgsfield,
|
||||
Krea,
|
||||
OpenArt,
|
||||
Artcraft,
|
||||
Magnific,
|
||||
FreePik,
|
||||
}
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(UploadedVideoNoteReportedWebsite);
|
||||
impl_mysql_enum_coders!(UploadedVideoNoteReportedWebsite);
|
||||
impl_mysql_from_row!(UploadedVideoNoteReportedWebsite);
|
||||
|
||||
impl UploadedVideoNoteReportedWebsite {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Runway => "runway",
|
||||
Self::Higgsfield => "higgsfield",
|
||||
Self::Krea => "krea",
|
||||
Self::OpenArt => "open_art",
|
||||
Self::Artcraft => "artcraft",
|
||||
Self::Magnific => "magnific",
|
||||
Self::FreePik => "free_pik",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"runway" => Ok(Self::Runway),
|
||||
"higgsfield" => Ok(Self::Higgsfield),
|
||||
"krea" => Ok(Self::Krea),
|
||||
"open_art" => Ok(Self::OpenArt),
|
||||
"artcraft" => Ok(Self::Artcraft),
|
||||
"magnific" => Ok(Self::Magnific),
|
||||
"free_pik" => Ok(Self::FreePik),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
BTreeSet::from([
|
||||
Self::Runway,
|
||||
Self::Higgsfield,
|
||||
Self::Krea,
|
||||
Self::OpenArt,
|
||||
Self::Artcraft,
|
||||
Self::Magnific,
|
||||
Self::FreePik,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::Runway, "runway");
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::Higgsfield, "higgsfield");
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::Krea, "krea");
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::OpenArt, "open_art");
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::Artcraft, "artcraft");
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::Magnific, "magnific");
|
||||
assert_serialization(UploadedVideoNoteReportedWebsite::FreePik, "free_pik");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in UploadedVideoNoteReportedWebsite::all_variants() {
|
||||
assert_eq!(variant, UploadedVideoNoteReportedWebsite::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, UploadedVideoNoteReportedWebsite::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, UploadedVideoNoteReportedWebsite::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
assert!(UploadedVideoNoteReportedWebsite::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_str_matches_serde() {
|
||||
for variant in UploadedVideoNoteReportedWebsite::all_variants() {
|
||||
let json = serde_json::to_string(&variant).unwrap();
|
||||
assert_eq!(json, format!("\"{}\"", variant.to_str()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variant_count() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(UploadedVideoNoteReportedWebsite::all_variants().len(), UploadedVideoNoteReportedWebsite::iter().len());
|
||||
assert_eq!(UploadedVideoNoteReportedWebsite::COUNT, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialized_length_ok_for_database() {
|
||||
const MAX_LENGTH: usize = 32;
|
||||
for variant in UploadedVideoNoteReportedWebsite::all_variants() {
|
||||
let serialized = variant.to_str();
|
||||
assert!(!serialized.is_empty(), "variant {:?} is too short", variant);
|
||||
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod uploaded_video_detected_model_family;
|
||||
pub mod uploaded_video_detected_model_type;
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `uploaded_videos` table in a `VARCHAR(32)` field.
|
||||
///
|
||||
/// The detected provenance family of an uploaded video.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum UploadedVideoDetectedModelFamily {
|
||||
Seedance,
|
||||
Veo,
|
||||
Sora,
|
||||
Kling,
|
||||
Grok,
|
||||
HappyHorse,
|
||||
}
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(UploadedVideoDetectedModelFamily);
|
||||
impl_mysql_enum_coders!(UploadedVideoDetectedModelFamily);
|
||||
impl_mysql_from_row!(UploadedVideoDetectedModelFamily);
|
||||
|
||||
impl UploadedVideoDetectedModelFamily {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Seedance => "seedance",
|
||||
Self::Veo => "veo",
|
||||
Self::Sora => "sora",
|
||||
Self::Kling => "kling",
|
||||
Self::Grok => "grok",
|
||||
Self::HappyHorse => "happy_horse",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"seedance" => Ok(Self::Seedance),
|
||||
"veo" => Ok(Self::Veo),
|
||||
"sora" => Ok(Self::Sora),
|
||||
"kling" => Ok(Self::Kling),
|
||||
"grok" => Ok(Self::Grok),
|
||||
"happy_horse" => Ok(Self::HappyHorse),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
BTreeSet::from([
|
||||
Self::Seedance,
|
||||
Self::Veo,
|
||||
Self::Sora,
|
||||
Self::Kling,
|
||||
Self::Grok,
|
||||
Self::HappyHorse,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(UploadedVideoDetectedModelFamily::Seedance, "seedance");
|
||||
assert_serialization(UploadedVideoDetectedModelFamily::Veo, "veo");
|
||||
assert_serialization(UploadedVideoDetectedModelFamily::Sora, "sora");
|
||||
assert_serialization(UploadedVideoDetectedModelFamily::Kling, "kling");
|
||||
assert_serialization(UploadedVideoDetectedModelFamily::Grok, "grok");
|
||||
assert_serialization(UploadedVideoDetectedModelFamily::HappyHorse, "happy_horse");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in UploadedVideoDetectedModelFamily::all_variants() {
|
||||
assert_eq!(variant, UploadedVideoDetectedModelFamily::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, UploadedVideoDetectedModelFamily::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, UploadedVideoDetectedModelFamily::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
assert!(UploadedVideoDetectedModelFamily::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_str_matches_serde() {
|
||||
for variant in UploadedVideoDetectedModelFamily::all_variants() {
|
||||
let json = serde_json::to_string(&variant).unwrap();
|
||||
assert_eq!(json, format!("\"{}\"", variant.to_str()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variant_count() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(UploadedVideoDetectedModelFamily::all_variants().len(), UploadedVideoDetectedModelFamily::iter().len());
|
||||
assert_eq!(UploadedVideoDetectedModelFamily::COUNT, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialized_length_ok_for_database() {
|
||||
const MAX_LENGTH: usize = 32;
|
||||
for variant in UploadedVideoDetectedModelFamily::all_variants() {
|
||||
let serialized = variant.to_str();
|
||||
assert!(!serialized.is_empty(), "variant {:?} is too short", variant);
|
||||
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
-253
@@ -1,253 +0,0 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `uploaded_videos` table in a `VARCHAR(32)` field.
|
||||
///
|
||||
/// The detected model / variant of an uploaded video. The variant set mirrors
|
||||
/// [`crate::common::generation::common_video_model::CommonVideoModel`].
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
pub enum UploadedVideoDetectedModelType {
|
||||
#[serde(rename = "grok_video")]
|
||||
GrokVideo,
|
||||
#[serde(rename = "grok_imagine_video")]
|
||||
GrokImagineVideo,
|
||||
#[serde(rename = "grok_imagine_video_1p5")]
|
||||
GrokImagineVideo1p5,
|
||||
#[serde(rename = "kling_1p6_pro")]
|
||||
Kling16Pro,
|
||||
#[serde(rename = "kling_2p1_pro")]
|
||||
Kling21Pro,
|
||||
#[serde(rename = "kling_2p1_master")]
|
||||
Kling21Master,
|
||||
#[serde(rename = "kling_2p5_turbo_pro")]
|
||||
Kling2p5TurboPro,
|
||||
#[serde(rename = "kling_2p6_pro")]
|
||||
Kling2p6Pro,
|
||||
#[serde(rename = "kling_3p0_standard")]
|
||||
Kling3p0Standard,
|
||||
#[serde(rename = "kling_3p0_pro")]
|
||||
Kling3p0Pro,
|
||||
#[serde(rename = "happy_horse_1p0")]
|
||||
HappyHorse1p0,
|
||||
#[serde(rename = "seedance_1p0_lite")]
|
||||
Seedance10Lite,
|
||||
#[serde(rename = "seedance_1p5_pro")]
|
||||
Seedance1p5Pro,
|
||||
// `preview_model` is a retired alias that collapses onto Seedance 2.0.
|
||||
#[serde(rename = "seedance_2p0", alias = "preview_model")]
|
||||
Seedance2p0,
|
||||
// `preview_model_fast` is a retired alias that collapses onto Seedance 2.0 Fast.
|
||||
#[serde(rename = "seedance_2p0_fast", alias = "preview_model_fast")]
|
||||
Seedance2p0Fast,
|
||||
#[serde(rename = "seedance_2p0_bp")]
|
||||
Seedance2p0BytePlus,
|
||||
#[serde(rename = "seedance_2p0_bp_fast")]
|
||||
Seedance2p0BytePlusFast,
|
||||
#[serde(rename = "seedance_2p0_u")]
|
||||
Seedance2p0Ultra,
|
||||
#[serde(rename = "seedance_2p0_u_fast")]
|
||||
Seedance2p0UltraFast,
|
||||
#[serde(rename = "seedance_2p0_bpu")]
|
||||
Seedance2p0BytePlusUltra,
|
||||
#[serde(rename = "seedance_2p0_bpu_fast")]
|
||||
Seedance2p0BytePlusUltraFast,
|
||||
#[serde(rename = "sora_2")]
|
||||
Sora2,
|
||||
#[serde(rename = "sora_2_pro")]
|
||||
Sora2Pro,
|
||||
#[serde(rename = "veo_2")]
|
||||
Veo2,
|
||||
#[serde(rename = "veo_3")]
|
||||
Veo3,
|
||||
#[serde(rename = "veo_3_fast")]
|
||||
Veo3Fast,
|
||||
#[serde(rename = "veo_3p1")]
|
||||
Veo3p1,
|
||||
#[serde(rename = "veo_3p1_fast")]
|
||||
Veo3p1Fast,
|
||||
}
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(UploadedVideoDetectedModelType);
|
||||
impl_mysql_enum_coders!(UploadedVideoDetectedModelType);
|
||||
impl_mysql_from_row!(UploadedVideoDetectedModelType);
|
||||
|
||||
impl UploadedVideoDetectedModelType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::GrokVideo => "grok_video",
|
||||
Self::GrokImagineVideo => "grok_imagine_video",
|
||||
Self::GrokImagineVideo1p5 => "grok_imagine_video_1p5",
|
||||
Self::Kling16Pro => "kling_1p6_pro",
|
||||
Self::Kling21Pro => "kling_2p1_pro",
|
||||
Self::Kling21Master => "kling_2p1_master",
|
||||
Self::Kling2p5TurboPro => "kling_2p5_turbo_pro",
|
||||
Self::Kling2p6Pro => "kling_2p6_pro",
|
||||
Self::Kling3p0Standard => "kling_3p0_standard",
|
||||
Self::Kling3p0Pro => "kling_3p0_pro",
|
||||
Self::HappyHorse1p0 => "happy_horse_1p0",
|
||||
Self::Seedance10Lite => "seedance_1p0_lite",
|
||||
Self::Seedance1p5Pro => "seedance_1p5_pro",
|
||||
Self::Seedance2p0 => "seedance_2p0",
|
||||
Self::Seedance2p0Fast => "seedance_2p0_fast",
|
||||
Self::Seedance2p0BytePlus => "seedance_2p0_bp",
|
||||
Self::Seedance2p0BytePlusFast => "seedance_2p0_bp_fast",
|
||||
Self::Seedance2p0Ultra => "seedance_2p0_u",
|
||||
Self::Seedance2p0UltraFast => "seedance_2p0_u_fast",
|
||||
Self::Seedance2p0BytePlusUltra => "seedance_2p0_bpu",
|
||||
Self::Seedance2p0BytePlusUltraFast => "seedance_2p0_bpu_fast",
|
||||
Self::Sora2 => "sora_2",
|
||||
Self::Sora2Pro => "sora_2_pro",
|
||||
Self::Veo2 => "veo_2",
|
||||
Self::Veo3 => "veo_3",
|
||||
Self::Veo3Fast => "veo_3_fast",
|
||||
Self::Veo3p1 => "veo_3p1",
|
||||
Self::Veo3p1Fast => "veo_3p1_fast",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"grok_video" => Ok(Self::GrokVideo),
|
||||
"grok_imagine_video" => Ok(Self::GrokImagineVideo),
|
||||
"grok_imagine_video_1p5" => Ok(Self::GrokImagineVideo1p5),
|
||||
"kling_1p6_pro" => Ok(Self::Kling16Pro),
|
||||
"kling_2p1_pro" => Ok(Self::Kling21Pro),
|
||||
"kling_2p1_master" => Ok(Self::Kling21Master),
|
||||
"kling_2p5_turbo_pro" => Ok(Self::Kling2p5TurboPro),
|
||||
"kling_2p6_pro" => Ok(Self::Kling2p6Pro),
|
||||
"kling_3p0_standard" => Ok(Self::Kling3p0Standard),
|
||||
"kling_3p0_pro" => Ok(Self::Kling3p0Pro),
|
||||
"happy_horse_1p0" => Ok(Self::HappyHorse1p0),
|
||||
"seedance_1p0_lite" => Ok(Self::Seedance10Lite),
|
||||
"seedance_1p5_pro" => Ok(Self::Seedance1p5Pro),
|
||||
"seedance_2p0" => Ok(Self::Seedance2p0),
|
||||
"seedance_2p0_fast" => Ok(Self::Seedance2p0Fast),
|
||||
"seedance_2p0_bp" => Ok(Self::Seedance2p0BytePlus),
|
||||
"seedance_2p0_bp_fast" => Ok(Self::Seedance2p0BytePlusFast),
|
||||
"seedance_2p0_u" => Ok(Self::Seedance2p0Ultra),
|
||||
"seedance_2p0_u_fast" => Ok(Self::Seedance2p0UltraFast),
|
||||
"seedance_2p0_bpu" => Ok(Self::Seedance2p0BytePlusUltra),
|
||||
"seedance_2p0_bpu_fast" => Ok(Self::Seedance2p0BytePlusUltraFast),
|
||||
"sora_2" => Ok(Self::Sora2),
|
||||
"sora_2_pro" => Ok(Self::Sora2Pro),
|
||||
"veo_2" => Ok(Self::Veo2),
|
||||
"veo_3" => Ok(Self::Veo3),
|
||||
"veo_3_fast" => Ok(Self::Veo3Fast),
|
||||
"veo_3p1" => Ok(Self::Veo3p1),
|
||||
"veo_3p1_fast" => Ok(Self::Veo3p1Fast),
|
||||
// Retired values: collapse onto the Seedance 2.0 equivalents.
|
||||
"preview_model" => Ok(Self::Seedance2p0),
|
||||
"preview_model_fast" => Ok(Self::Seedance2p0Fast),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
BTreeSet::from([
|
||||
Self::GrokVideo,
|
||||
Self::GrokImagineVideo,
|
||||
Self::GrokImagineVideo1p5,
|
||||
Self::Kling16Pro,
|
||||
Self::Kling21Pro,
|
||||
Self::Kling21Master,
|
||||
Self::Kling2p5TurboPro,
|
||||
Self::Kling2p6Pro,
|
||||
Self::Kling3p0Standard,
|
||||
Self::Kling3p0Pro,
|
||||
Self::HappyHorse1p0,
|
||||
Self::Seedance10Lite,
|
||||
Self::Seedance1p5Pro,
|
||||
Self::Seedance2p0,
|
||||
Self::Seedance2p0Fast,
|
||||
Self::Seedance2p0BytePlus,
|
||||
Self::Seedance2p0BytePlusFast,
|
||||
Self::Seedance2p0Ultra,
|
||||
Self::Seedance2p0UltraFast,
|
||||
Self::Seedance2p0BytePlusUltra,
|
||||
Self::Seedance2p0BytePlusUltraFast,
|
||||
Self::Sora2,
|
||||
Self::Sora2Pro,
|
||||
Self::Veo2,
|
||||
Self::Veo3,
|
||||
Self::Veo3Fast,
|
||||
Self::Veo3p1,
|
||||
Self::Veo3p1Fast,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in UploadedVideoDetectedModelType::all_variants() {
|
||||
assert_eq!(variant, UploadedVideoDetectedModelType::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, UploadedVideoDetectedModelType::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, UploadedVideoDetectedModelType::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
assert!(UploadedVideoDetectedModelType::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_round_trip() {
|
||||
for variant in UploadedVideoDetectedModelType::all_variants() {
|
||||
let json = serde_json::to_string(&variant).unwrap();
|
||||
let deserialized: UploadedVideoDetectedModelType = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(variant, deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
/// The MySQL string (to_str) and the JSON string (serde) must stay aligned.
|
||||
#[test]
|
||||
fn to_str_matches_serde() {
|
||||
for variant in UploadedVideoDetectedModelType::all_variants() {
|
||||
let json = serde_json::to_string(&variant).unwrap();
|
||||
assert_eq!(json, format!("\"{}\"", variant.to_str()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variant_count() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(UploadedVideoDetectedModelType::all_variants().len(), UploadedVideoDetectedModelType::iter().len());
|
||||
assert_eq!(UploadedVideoDetectedModelType::COUNT, 28);
|
||||
}
|
||||
|
||||
/// Retired `preview_model*` values must still decode, collapsing onto Seedance 2.0.
|
||||
#[test]
|
||||
fn legacy_preview_values_map_to_seedance() {
|
||||
assert_eq!(
|
||||
UploadedVideoDetectedModelType::from_str("preview_model").unwrap(),
|
||||
UploadedVideoDetectedModelType::Seedance2p0
|
||||
);
|
||||
assert_eq!(
|
||||
UploadedVideoDetectedModelType::from_str("preview_model_fast").unwrap(),
|
||||
UploadedVideoDetectedModelType::Seedance2p0Fast
|
||||
);
|
||||
let decoded: UploadedVideoDetectedModelType =
|
||||
serde_json::from_str("\"preview_model\"").unwrap();
|
||||
assert_eq!(decoded, UploadedVideoDetectedModelType::Seedance2p0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialized_length_ok_for_database() {
|
||||
const MAX_LENGTH: usize = 32;
|
||||
for variant in UploadedVideoDetectedModelType::all_variants() {
|
||||
let serialized = variant.to_str();
|
||||
assert!(!serialized.is_empty(), "variant {:?} is too short", variant);
|
||||
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,8 +46,6 @@ pub(crate) enum TokenPrefix {
|
||||
StaffAuditLog,
|
||||
Tag,
|
||||
TtsRenderTask, // NB: aichatbot / sqlite
|
||||
UploadedVideo,
|
||||
UploadedVideoNote,
|
||||
User,
|
||||
UserImpersonationRequest,
|
||||
UserBookmark,
|
||||
@@ -138,8 +136,6 @@ impl PrefixGenerator for TokenPrefix {
|
||||
Self::StaffAuditLog => "stfaud_",
|
||||
Self::Tag => "tag_",
|
||||
Self::TtsRenderTask => "tts_task_",
|
||||
Self::UploadedVideo => "uvt_",
|
||||
Self::UploadedVideoNote => "uvnote_",
|
||||
Self::User => "user_", // NB: Previously "U:"
|
||||
Self::UserImpersonationRequest => "uimpr_",
|
||||
Self::UserBookmark => "ub_",
|
||||
|
||||
@@ -31,8 +31,6 @@ pub mod tts_results;
|
||||
pub mod twitch_event_rule;
|
||||
pub mod twitch_oauth_tokens_grouping;
|
||||
pub mod twitch_oauth_tokens_internal;
|
||||
pub mod uploaded_video_notes;
|
||||
pub mod uploaded_videos;
|
||||
pub mod user_bookmarks;
|
||||
pub mod user_impersonation_requests;
|
||||
pub mod user_referral_codes;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
/// The primary key for uploaded_video_notes.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[cfg_attr(feature = "database", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "database", sqlx(transparent))]
|
||||
pub struct UploadVideoNoteToken(pub String);
|
||||
|
||||
impl_string_token!(UploadVideoNoteToken);
|
||||
impl_mysql_token_from_row!(UploadVideoNoteToken);
|
||||
impl_crockford_generator!(UploadVideoNoteToken, 32usize, TokenPrefix::UploadedVideoNote, CrockfordLower);
|
||||
@@ -1,17 +0,0 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
/// The primary key for uploaded_videos.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[cfg_attr(feature = "database", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "database", sqlx(transparent))]
|
||||
pub struct UploadedVideoToken(pub String);
|
||||
|
||||
impl_string_token!(UploadedVideoToken);
|
||||
impl_mysql_token_from_row!(UploadedVideoToken);
|
||||
impl_crockford_generator!(UploadedVideoToken, 32usize, TokenPrefix::UploadedVideo, CrockfordLower);
|
||||
@@ -5,7 +5,7 @@ use r2d2_redis::RedisConnectionManager;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
use bootstrap::bootstrap::ContainerEnvironment;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use google_drive_downloader::google_drive_download_command::GoogleDriveDownloadCommand;
|
||||
use mysql_queries::common_inputs::container_environment_arg::ContainerEnvironmentArg;
|
||||
@@ -33,8 +33,8 @@ pub struct JobState {
|
||||
|
||||
pub redis_pool: r2d2::Pool<RedisConnectionManager>,
|
||||
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub private_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
pub private_bucket_client: BucketClient,
|
||||
|
||||
pub firehose_publisher: FirehosePublisher,
|
||||
pub badge_granter: BadgeGranter,
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ use anyhow::anyhow;
|
||||
use log::info;
|
||||
use tempdir::TempDir;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use errors::AnyhowResult;
|
||||
use filesys::create_dir_all_if_missing::create_dir_all_if_missing;
|
||||
use filesys::file_exists::file_exists;
|
||||
@@ -38,7 +38,7 @@ impl PretrainedHubertModel {
|
||||
|
||||
pub async fn download_if_not_on_filesystem(
|
||||
&self,
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
temp_dir: &TempDir,
|
||||
) -> AnyhowResult<()> {
|
||||
if file_exists(&self.filesystem_path) {
|
||||
|
||||
@@ -28,7 +28,7 @@ use sqlx::mysql::MySqlPoolOptions;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use config::common_env::CommonEnv;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
@@ -96,7 +96,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
let bucket_timeout = easyenv::get_env_duration_seconds_or_default("BUCKET_TIMEOUT_SECONDS",
|
||||
Duration::from_secs(60 * 5));
|
||||
|
||||
let private_bucket_client = LegacyBucketClient::create(
|
||||
let private_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
@@ -106,7 +106,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Some(bucket_timeout),
|
||||
)?;
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ use log::{debug, error, info, warn};
|
||||
use tempdir::TempDir;
|
||||
use bucket_paths::legacy::typified_paths::public::weight_files::bucket_directory::WeightFileBucketDirectory;
|
||||
use bucket_paths::legacy::typified_paths::public::weight_files::bucket_file_path::WeightFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use filesys::rename_across_devices::{rename_across_devices, RenameError};
|
||||
use filesys::file_deletion::safe_delete_directory::safe_delete_directory;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
@@ -18,7 +18,7 @@ pub async fn download_package(
|
||||
model_weight_token: ModelWeightToken,
|
||||
weights_file_bucket_directory: &WeightFileBucketDirectory,
|
||||
download_directory: &Path,
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
scoped_tempdir_creator: &ScopedTempDirCreator,
|
||||
force_download: bool,
|
||||
) -> Result<(), ProcessSingleJobError> {
|
||||
@@ -69,7 +69,7 @@ pub async fn do_download_package(
|
||||
model_weight_token: ModelWeightToken,
|
||||
weights_file_bucket_directory: &WeightFileBucketDirectory,
|
||||
download_directory: &Path,
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
temp_dir: &TempDir,
|
||||
force_download: bool,
|
||||
entry: GptSovitsPackageFileType,
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ use zip::ZipArchive;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::weight_files::bucket_directory::WeightFileBucketDirectory;
|
||||
use bucket_paths::legacy::typified_paths::public::weight_files::bucket_file_path::WeightFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use filesys::path_to_string::path_to_string;
|
||||
use hashing::sha256::sha256_hash_bytes::sha256_hash_bytes;
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::job::job_types::gpt_sovits::upload_model::get_gptsovits_zip_entries::
|
||||
|
||||
pub async fn extract_and_upload_gpt_sovits_package_files(
|
||||
zip_container_file_bytes: &[u8],
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
weights_file_bucket_directory: &WeightFileBucketDirectory,
|
||||
) -> Result<GptSovitsPackageDetails, GptSovitsPackageError> {
|
||||
let cursor = Cursor::new(zip_container_file_bytes);
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ use tempdir::TempDir;
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_uploads::bucket_file_path::MediaUploadOriginalFilePath;
|
||||
use bucket_paths::legacy::typified_paths::public::voice_conversion_results::bucket_file_path::VoiceConversionResultOriginalFilePath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
|
||||
use mysql_queries::payloads::generic_inference_args::inner_payloads::lipsync_payload::LipsyncAnimationAudioSource;
|
||||
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
|
||||
@@ -28,7 +28,7 @@ pub struct AudioFile {
|
||||
|
||||
pub struct DownloadAudioFileArgs<'a> {
|
||||
pub audio_source: &'a LipsyncAnimationAudioSource,
|
||||
pub public_bucket_client: &'a LegacyBucketClient,
|
||||
pub public_bucket_client: &'a BucketClient,
|
||||
pub job_progress_reporter: &'a mut Box<dyn JobProgressReporter>,
|
||||
pub job: &'a AvailableInferenceJob,
|
||||
pub temp_dir_creator: &'a ScopedTempDirCreator,
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ use tempdir::TempDir;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_uploads::bucket_file_path::MediaUploadOriginalFilePath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
|
||||
use mysql_queries::payloads::generic_inference_args::inner_payloads::lipsync_payload::LipsyncAnimationImageSource;
|
||||
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
|
||||
@@ -26,7 +26,7 @@ pub struct ImageFile {
|
||||
|
||||
pub struct DownloadImageFileArgs<'a> {
|
||||
pub image_source: &'a LipsyncAnimationImageSource,
|
||||
pub public_bucket_client: &'a LegacyBucketClient,
|
||||
pub public_bucket_client: &'a BucketClient,
|
||||
pub job_progress_reporter: &'a mut Box<dyn JobProgressReporter>,
|
||||
pub job: &'a AvailableInferenceJob,
|
||||
pub temp_dir_creator: &'a ScopedTempDirCreator,
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ use tempdir::TempDir;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_uploads::bucket_file_path::MediaUploadOriginalFilePath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
|
||||
use mysql_queries::payloads::generic_inference_args::inner_payloads::mocap_payload::MocapVideoSource;
|
||||
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
|
||||
@@ -27,7 +27,7 @@ pub struct VideoFile {
|
||||
// TODO: Replace with remote cloud client
|
||||
pub async fn download_video_file(
|
||||
video_source: &MocapVideoSource,
|
||||
public_bucket_client: &LegacyBucketClient,
|
||||
public_bucket_client: &BucketClient,
|
||||
job_progress_reporter: &mut Box<dyn JobProgressReporter>,
|
||||
job: &AvailableInferenceJob,
|
||||
temp_dir_creator: &ScopedTempDirCreator,
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ use log::{error, info, warn};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_directory::{ModelCategory, ModelType};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_file_path::ZeroShotVoiceEmbeddingBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use enums::by_table::generic_inference_jobs::inference_result_type::InferenceResultType;
|
||||
use enums::by_table::zs_voices::encoding_type::ZsVoiceEncodingType;
|
||||
@@ -295,7 +295,7 @@ pub struct AudioFile {
|
||||
pub async fn download_audio_from_hash(
|
||||
bucket_hash: &str,
|
||||
name: &str,
|
||||
private_bucket_client: &LegacyBucketClient,
|
||||
private_bucket_client: &BucketClient,
|
||||
path: &PathBuf
|
||||
) -> Result<AudioFile, ProcessSingleJobError> {
|
||||
let unifer = BucketPathUnifier::default_paths();
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ use log::{error, info, warn};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_directory::{ModelCategory, ModelType};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_file_path::ZeroShotVoiceEmbeddingBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use enums::by_table::generic_inference_jobs::inference_result_type::InferenceResultType;
|
||||
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
|
||||
@@ -244,7 +244,7 @@ pub struct VoiceFile {
|
||||
pub async fn download_voice_embedding_from_hash(
|
||||
bucket_hash: &str,
|
||||
name: &str,
|
||||
private_bucket_client: &LegacyBucketClient,
|
||||
private_bucket_client: &BucketClient,
|
||||
path: &PathBuf
|
||||
) -> Result<VoiceFile, ProcessSingleJobError> {
|
||||
let unifer = BucketPathUnifier::default_paths();
|
||||
@@ -271,7 +271,7 @@ pub async fn download_voice_embedding_from_hash(
|
||||
|
||||
pub async fn download_voice_embedding(
|
||||
voice: &ZsVoice,
|
||||
private_bucket_client: &LegacyBucketClient,
|
||||
private_bucket_client: &BucketClient,
|
||||
download_path: &PathBuf,
|
||||
) -> Result<VoiceFile, ProcessSingleJobError> {
|
||||
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ use log::{error, info, warn};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_directory::{ModelCategory, ModelType};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_file_path::ZeroShotVoiceEmbeddingBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use enums::by_table::generic_inference_jobs::inference_result_type::InferenceResultType;
|
||||
use enums::by_table::zs_voices::encoding_type::ZsVoiceEncodingType;
|
||||
@@ -316,7 +316,7 @@ pub struct AudioFile {
|
||||
pub async fn download_audio_from_hash(
|
||||
bucket_hash: &str,
|
||||
name: &str,
|
||||
private_bucket_client: &LegacyBucketClient,
|
||||
private_bucket_client: &BucketClient,
|
||||
path: &PathBuf
|
||||
) -> Result<AudioFile, ProcessSingleJobError> {
|
||||
let unifer = BucketPathUnifier::default_paths();
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ use log::{error, info, warn};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_directory::{ModelCategory, ModelType};
|
||||
use bucket_paths::legacy::typified_paths::private::zs_voices::bucket_file_path::ZeroShotVoiceEmbeddingBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use enums::by_table::generic_inference_jobs::inference_result_type::InferenceResultType;
|
||||
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
|
||||
@@ -260,7 +260,7 @@ pub struct VoiceFile {
|
||||
pub async fn download_voice_embedding_from_hash(
|
||||
bucket_hash: &str,
|
||||
name: &str,
|
||||
private_bucket_client: &LegacyBucketClient,
|
||||
private_bucket_client: &BucketClient,
|
||||
path: &PathBuf
|
||||
) -> Result<VoiceFile, ProcessSingleJobError> {
|
||||
let unifer = BucketPathUnifier::default_paths();
|
||||
@@ -287,7 +287,7 @@ pub async fn download_voice_embedding_from_hash(
|
||||
|
||||
pub async fn download_voice_embedding(
|
||||
voice: &ZsVoice,
|
||||
private_bucket_client: &LegacyBucketClient,
|
||||
private_bucket_client: &BucketClient,
|
||||
download_path: &PathBuf,
|
||||
) -> Result<VoiceFile, ProcessSingleJobError> {
|
||||
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ use std::path::PathBuf;
|
||||
use anyhow::anyhow;
|
||||
use log::{error, info};
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use filesys::create_dir_all_if_missing::create_dir_all_if_missing;
|
||||
use filesys::file_exists::file_exists;
|
||||
use filesys::rename_across_devices::rename_across_devices;
|
||||
@@ -41,7 +41,7 @@ impl PretrainedHubertModel {
|
||||
|
||||
pub async fn download_if_not_on_filesystem(
|
||||
&self,
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
scoped_tempdir_creator: &ScopedTempDirCreator,
|
||||
) -> Result<(), ProcessSingleJobError> {
|
||||
if file_exists(&self.filesystem_path) {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ use anyhow::anyhow;
|
||||
use tempdir::TempDir;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
|
||||
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
|
||||
use mysql_queries::queries::model_weights::get::get_weight::RetrievedModelWeight;
|
||||
@@ -19,7 +19,7 @@ pub struct ModelFile {
|
||||
// TODO replace this with remote cloud file manager.
|
||||
pub async fn download_model_file(
|
||||
model_record: &Option<RetrievedModelWeight>,
|
||||
public_bucket_client: &LegacyBucketClient,
|
||||
public_bucket_client: &BucketClient,
|
||||
job_progress_reporter: &mut Box<dyn JobProgressReporter>,
|
||||
job: &AvailableInferenceJob,
|
||||
temp_dir_creator: &ScopedTempDirCreator,
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ use tempdir::TempDir;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use bucket_paths::legacy::typified_paths::public::media_uploads::bucket_file_path::MediaUploadOriginalFilePath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
|
||||
use mysql_queries::payloads::generic_inference_args::inner_payloads::videofilter_payload::VideofilterVideoSource;
|
||||
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
|
||||
@@ -26,7 +26,7 @@ pub struct VideoFile {
|
||||
// TODO replace this with remote cloud file manager.
|
||||
pub async fn download_video_file(
|
||||
video_source: &VideofilterVideoSource,
|
||||
public_bucket_client: &LegacyBucketClient,
|
||||
public_bucket_client: &BucketClient,
|
||||
job_progress_reporter: &mut Box<dyn JobProgressReporter>,
|
||||
job: &AvailableInferenceJob,
|
||||
temp_dir_creator: &ScopedTempDirCreator,
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use filesys::file_read_bytes::file_read_bytes;
|
||||
use log::{debug, warn};
|
||||
use std::path::PathBuf;
|
||||
@@ -20,12 +20,12 @@ pub enum BucketUploadMessage {
|
||||
UploadFrame {
|
||||
disk_path: PathBuf,
|
||||
bucket_path: MediaFileBucketPath,
|
||||
bucket_client: LegacyBucketClient,
|
||||
bucket_client: BucketClient,
|
||||
result: oneshot::Sender<BucketUploadResult>
|
||||
},
|
||||
UploadMultipleFrames {
|
||||
requests: Vec<BucketUploadRequest>,
|
||||
bucket_client: LegacyBucketClient,
|
||||
bucket_client: BucketClient,
|
||||
result: oneshot::Sender<Vec<(PathBuf, BucketUploadResult)>>,
|
||||
},
|
||||
}
|
||||
@@ -39,7 +39,7 @@ struct BucketUploadActor {
|
||||
rx: mpsc::Receiver<BucketUploadMessage>,
|
||||
}
|
||||
|
||||
fn handle_single_frame_upload(disk_path: PathBuf, bucket_path: MediaFileBucketPath, bucket_client: LegacyBucketClient) -> (PathBuf,BucketUploadResult) {
|
||||
fn handle_single_frame_upload(disk_path: PathBuf, bucket_path: MediaFileBucketPath, bucket_client: BucketClient) -> (PathBuf,BucketUploadResult) {
|
||||
let disk_path2 = disk_path.clone();
|
||||
let handle = tokio::runtime::Handle::current();
|
||||
let attempt = handle.block_on(
|
||||
@@ -139,7 +139,7 @@ impl BucketUploadActorHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn upload_frame(&self, disk_path: PathBuf, bucket_path: MediaFileBucketPath, bucket_client: LegacyBucketClient) -> () {
|
||||
pub async fn upload_frame(&self, disk_path: PathBuf, bucket_path: MediaFileBucketPath, bucket_client: BucketClient) -> () {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let message = BucketUploadMessage::UploadFrame {
|
||||
disk_path,
|
||||
@@ -151,7 +151,7 @@ impl BucketUploadActorHandle {
|
||||
let _ = rx.await;
|
||||
}
|
||||
|
||||
pub async fn upload_multiple_frames(&self, requests: Vec<BucketUploadRequest>, bucket_client: LegacyBucketClient) -> Vec<(PathBuf,BucketUploadResult)> {
|
||||
pub async fn upload_multiple_frames(&self, requests: Vec<BucketUploadRequest>, bucket_client: BucketClient) -> Vec<(PathBuf,BucketUploadResult)> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let message = BucketUploadMessage::UploadMultipleFrames {
|
||||
requests,
|
||||
|
||||
+8
-8
@@ -14,7 +14,7 @@ use crate::job::job_types::workflow::video_style_transfer::util::preview_process
|
||||
use crate::job::job_types::workflow::video_style_transfer::util::preview_processor::dir_walker::{DirWalker, PathBatch};
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_directory::MediaFileBucketDirectory;
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use crockford::crockford_entropy_lower;
|
||||
use redis_schema::keys::inference_job::style_transfer_progress_key::StyleTransferProgressKey;
|
||||
use redis_schema::payloads::inference_job::style_transfer_progress_state::{InferenceProgressDetailsResponse, InferenceStageDetails};
|
||||
@@ -306,7 +306,7 @@ impl StageDirectoryState {
|
||||
}
|
||||
|
||||
|
||||
async fn upload_frame_from_disk(&self, bucket_client: &LegacyBucketClient, frame_number: u32, disk_path: PathBuf) -> PreviewFrameUpdate {
|
||||
async fn upload_frame_from_disk(&self, bucket_client: &BucketClient, frame_number: u32, disk_path: PathBuf) -> PreviewFrameUpdate {
|
||||
let local_file_extension = match disk_path.extension().and_then(|s| s.to_str()) {
|
||||
Some(e) => {
|
||||
if ALLOWED_TYPES_FRAMES.contains(e) {
|
||||
@@ -355,7 +355,7 @@ impl StageDirectoryState {
|
||||
}
|
||||
}
|
||||
|
||||
async fn upload_frame_from_disk_with_retry(&self, bucket_client: &LegacyBucketClient, frame_number: u32, disk_path: PathBuf) -> PreviewFrameUpdate {
|
||||
async fn upload_frame_from_disk_with_retry(&self, bucket_client: &BucketClient, frame_number: u32, disk_path: PathBuf) -> PreviewFrameUpdate {
|
||||
let mut retries = 0;
|
||||
loop {
|
||||
if retries > 3 {
|
||||
@@ -385,7 +385,7 @@ impl StageDirectoryState {
|
||||
}
|
||||
|
||||
|
||||
async fn upload_multiple_frames_from_disk(&self, bucket_client: &LegacyBucketClient, frames: Vec<(u32, PathBuf)>) -> Vec<PreviewFrameUpdate> {
|
||||
async fn upload_multiple_frames_from_disk(&self, bucket_client: &BucketClient, frames: Vec<(u32, PathBuf)>) -> Vec<PreviewFrameUpdate> {
|
||||
let mut bucket_upload_requests = Vec::with_capacity(frames.len());
|
||||
let mut updates = Vec::with_capacity(frames.len());
|
||||
|
||||
@@ -635,7 +635,7 @@ impl PreviewProcessor {
|
||||
let _r: String = redis.set_ex(key.to_string(), serde_json::to_string(&status).unwrap(), expire_at).unwrap();
|
||||
}
|
||||
|
||||
pub async fn start_processing(&mut self, bucket_client: &LegacyBucketClient) -> () {
|
||||
pub async fn start_processing(&mut self, bucket_client: &BucketClient) -> () {
|
||||
let (frames_tx, mut frames_rx) = mpsc::channel(100);
|
||||
let walker = DirWalker::new_with_batch_size(self.base_directory.clone(), frames_tx.clone(), 30);
|
||||
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(5));
|
||||
@@ -693,7 +693,7 @@ impl PreviewProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn process_upload(&mut self, bucket_client: &LegacyBucketClient, disk_path: PathBuf) -> () {
|
||||
pub async fn process_upload(&mut self, bucket_client: &BucketClient, disk_path: PathBuf) -> () {
|
||||
if !self.is_disk_path_valid(&disk_path) {
|
||||
log::warn!("Invalid disk path: {:?}", disk_path);
|
||||
return;
|
||||
@@ -707,7 +707,7 @@ impl PreviewProcessor {
|
||||
};
|
||||
}
|
||||
|
||||
async fn process_batch_upload(&mut self, bucket_client: &LegacyBucketClient, disk_paths: PathBatch) -> () {
|
||||
async fn process_batch_upload(&mut self, bucket_client: &BucketClient, disk_paths: PathBatch) -> () {
|
||||
let mut paths_by_stage: HashMap<PreviewStage, Vec<(u32, PathBuf)>> = HashMap::new();
|
||||
for disk_path in disk_paths.get_paths() {
|
||||
if !self.is_disk_path_valid(&disk_path) {
|
||||
@@ -749,7 +749,7 @@ impl PreviewProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
async fn upload_frame_from_disk(&self, stage: PreviewStage, frame_number: u32, bucket_client: &LegacyBucketClient, disk_path: PathBuf) -> PreviewFrameUploadResult {
|
||||
async fn upload_frame_from_disk(&self, stage: PreviewStage, frame_number: u32, bucket_client: &BucketClient, disk_path: PathBuf) -> PreviewFrameUploadResult {
|
||||
let stage_state = self.stages.get(&stage).unwrap();
|
||||
if stage_state.state == PreviewStageState::UploadComplete {
|
||||
log::debug!("Skipped re-uploading frame: {:?}", disk_path);
|
||||
|
||||
@@ -28,7 +28,7 @@ use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use config::common_env::CommonEnv;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
@@ -117,7 +117,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
let bucket_timeout = easyenv::get_env_duration_seconds_or_default("BUCKET_TIMEOUT_SECONDS",
|
||||
Duration::from_secs(60 * 5));
|
||||
|
||||
let private_bucket_client = LegacyBucketClient::create(
|
||||
let private_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
@@ -127,7 +127,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Some(bucket_timeout),
|
||||
)?;
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
@@ -137,7 +137,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Some(bucket_timeout),
|
||||
)?;
|
||||
|
||||
let auto_gc_bucket_client = LegacyBucketClient::create(
|
||||
let auto_gc_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -10,7 +10,7 @@ use r2d2_redis::RedisConnectionManager;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
use bootstrap::bootstrap::ContainerEnvironment;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporterBuilder;
|
||||
@@ -135,9 +135,9 @@ pub struct DatabaseDependencies {
|
||||
}
|
||||
|
||||
pub struct BucketDependencies {
|
||||
pub private_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub auto_gc_bucket_client: LegacyBucketClient,
|
||||
pub private_bucket_client: BucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
pub auto_gc_bucket_client: BucketClient,
|
||||
pub bucket_path_unifier: BucketPathUnifier,
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ use std::path::Path;
|
||||
|
||||
use log::{error, info, warn};
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use filesys::file_size::file_size;
|
||||
use filesys::rename_across_devices::{rename_across_devices, RenameError};
|
||||
use filesys::file_deletion::safe_delete_directory::safe_delete_directory;
|
||||
@@ -19,7 +19,7 @@ pub struct MaybeDownloadArgs<'a> {
|
||||
pub name_or_description_of_file: &'a str,
|
||||
pub final_filesystem_file_path: &'a Path,
|
||||
pub bucket_object_path: &'a Path,
|
||||
pub bucket_client: &'a LegacyBucketClient,
|
||||
pub bucket_client: &'a BucketClient,
|
||||
pub job_progress_reporter: &'a mut Box<dyn JobProgressReporter>,
|
||||
pub job_progress_update_description: &'a str,
|
||||
pub job_id: i64,
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ use anyhow::anyhow;
|
||||
use async_trait::async_trait;
|
||||
use log::{error, info};
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use filesys::create_dir_all_if_missing::create_dir_all_if_missing;
|
||||
use filesys::file_exists::file_exists;
|
||||
use filesys::rename_across_devices::{rename_across_devices, RenameError};
|
||||
@@ -29,7 +29,7 @@ pub trait ModelDownloader {
|
||||
|
||||
async fn download_if_not_on_filesystem(
|
||||
&self,
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
scoped_tempdir_creator: &ScopedTempDirCreator,
|
||||
) -> Result<(), ProcessSingleJobError> {
|
||||
let filesystem_path = self.get_filesystem_path();
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use log::{error, info, warn};
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::weight_files::bucket_file_path::WeightFileBucketPath;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use errors::AnyhowResult;
|
||||
use filesys::file_size::file_size;
|
||||
use filesys::rename_across_devices::{rename_across_devices, RenameError};
|
||||
@@ -26,7 +26,7 @@ pub struct ModelWeightsCacheDirectory {
|
||||
pub scoped_tempdir_creator: ScopedTempDirCreator,
|
||||
|
||||
/// A client to download from the public bucket.
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
/// NB: Sometimes the downloader incompletely downloads files. Typically, this is a zero file
|
||||
/// size, but the Rust system may report a non-zero (but small) number of bytes. This should
|
||||
@@ -49,7 +49,7 @@ impl ModelWeightsCacheDirectory {
|
||||
/// Configure and try to create the directory if it doesn't exist.
|
||||
pub fn setup_from_env_and_deps(
|
||||
scoped_temp_dir_creator: &ScopedTempDirCreator,
|
||||
public_bucket_client: &LegacyBucketClient,
|
||||
public_bucket_client: &BucketClient,
|
||||
) -> AnyhowResult<Self> {
|
||||
let directory = easyenv::get_env_pathbuf_or_default(
|
||||
"MODEL_WEIGHTS_CACHE_DIR",
|
||||
|
||||
@@ -28,7 +28,7 @@ use sqlx::mysql::MySqlPoolOptions;
|
||||
use sqlx::MySqlPool;
|
||||
use tempdir::TempDir;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use config::bad_urls::is_bad_tts_model_download_url;
|
||||
use config::common_env::CommonEnv;
|
||||
@@ -74,7 +74,7 @@ struct Downloader {
|
||||
|
||||
pub redis_pool: r2d2::Pool<RedisConnectionManager>,
|
||||
|
||||
pub bucket_client: LegacyBucketClient,
|
||||
pub bucket_client: BucketClient,
|
||||
pub firehose_publisher: FirehosePublisher,
|
||||
pub badge_granter: BadgeGranter,
|
||||
pub google_drive_downloader: GoogleDriveDownloadCommand,
|
||||
@@ -128,7 +128,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
let bucket_timeout = easyenv::get_env_duration_seconds_or_default("BUCKET_TIMEOUT_SECONDS",
|
||||
Duration::from_secs(60 * 5));
|
||||
|
||||
let bucket_client = LegacyBucketClient::create(
|
||||
let bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ use std::path::Path;
|
||||
|
||||
use log::{info, warn};
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
|
||||
|
||||
use crate::{ProcessSingleJobError, ScopedTempDirCreator};
|
||||
@@ -13,7 +13,7 @@ pub async fn maybe_download_file_from_bucket(
|
||||
name_or_description_of_file: &str,
|
||||
file_path: &Path,
|
||||
bucket_object_path: &Path,
|
||||
bucket_client: &LegacyBucketClient,
|
||||
bucket_client: &BucketClient,
|
||||
job_progress_reporter: &mut Box<dyn JobProgressReporter>,
|
||||
job_progress_update_description: &str,
|
||||
job_id: i64,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::path::PathBuf;
|
||||
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporterBuilder;
|
||||
use jobs_common::job_stats::JobStats;
|
||||
@@ -25,8 +25,8 @@ pub struct JobArgs {
|
||||
|
||||
pub job_progress_reporter: Box<dyn JobProgressReporterBuilder>,
|
||||
|
||||
pub private_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub private_bucket_client: BucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
pub firehose_publisher: FirehosePublisher,
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use r2d2_redis::RedisConnectionManager;
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use bucket_paths::legacy::old_bespoke_paths::bucket_path_unifier::BucketPathUnifier;
|
||||
use collections::multiple_random_from_vec::multiple_random_from_vec;
|
||||
use config::common_env::CommonEnv;
|
||||
@@ -126,7 +126,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
let bucket_timeout = easyenv::get_env_duration_seconds_or_default("BUCKET_TIMEOUT_SECONDS",
|
||||
Duration::from_secs(60 * 5));
|
||||
|
||||
let private_bucket_client = LegacyBucketClient::create(
|
||||
let private_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
@@ -136,7 +136,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Some(bucket_timeout),
|
||||
)?;
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use gmicloud_client::creds::gmicloud_api_key::GmiCloudApiKey;
|
||||
use jobs_common::job_stats::JobStats;
|
||||
@@ -10,7 +10,7 @@ pub struct JobDependencies {
|
||||
pub mysql_pool: MySqlPool,
|
||||
|
||||
/// Public GCS/S3 bucket for storing generated videos.
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
/// API key for GmiCloud.
|
||||
pub gmicloud_api_key: GmiCloudApiKey,
|
||||
|
||||
@@ -16,7 +16,7 @@ use log::{info, warn};
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
use errors::AnyhowResult;
|
||||
@@ -88,7 +88,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Duration::from_secs(60 * 5),
|
||||
);
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use grok_api_client::creds::grok_api_key::GrokApiKey;
|
||||
use jobs_common::job_stats::JobStats;
|
||||
@@ -14,7 +14,7 @@ pub struct JobDependencies {
|
||||
pub mysql_pool: MySqlPool,
|
||||
|
||||
/// Public GCS/S3 bucket for storing generated videos.
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
/// API key for xAI's Imagine API.
|
||||
pub grok_api_key: GrokApiKey,
|
||||
|
||||
@@ -18,7 +18,7 @@ use sqlx::mysql::MySqlPoolOptions;
|
||||
use tokio::sync::Notify;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use errors::AnyhowResult;
|
||||
use grok_api_client::creds::grok_api_key::GrokApiKey;
|
||||
@@ -89,7 +89,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Duration::from_secs(60 * 5),
|
||||
);
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::kinovi_version::KinoviVersion;
|
||||
use chrono::Duration;
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use jobs_common::job_stats::JobStats;
|
||||
use pager::client::pager::Pager;
|
||||
@@ -16,7 +16,7 @@ pub struct JobDependencies {
|
||||
pub mysql_pool: MySqlPool,
|
||||
|
||||
/// Public GCS/S3 bucket for storing generated videos.
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
/// Session credentials for polling seedance2-pro.com.
|
||||
pub seedance2pro_session: Seedance2ProSession,
|
||||
|
||||
@@ -18,7 +18,7 @@ use sqlx::mysql::MySqlPoolOptions;
|
||||
use tokio::sync::Notify;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
use errors::AnyhowResult;
|
||||
@@ -93,7 +93,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Duration::from_secs(60 * 5),
|
||||
);
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use jobs_common::job_stats::JobStats;
|
||||
use pager::client::pager::Pager;
|
||||
@@ -17,7 +17,7 @@ pub struct JobDependencies {
|
||||
pub mysql_pool: MySqlPool,
|
||||
|
||||
/// Public GCS/S3 bucket for downloading source videos and uploading generated thumbnails.
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
pub server_environment: ServerEnvironment,
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ use log::{info, warn};
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
use errors::AnyhowResult;
|
||||
@@ -85,7 +85,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Duration::from_secs(60 * 5),
|
||||
);
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use jobs_common::job_stats::JobStats;
|
||||
use server_environment::ServerEnvironment;
|
||||
@@ -9,7 +9,7 @@ pub struct JobDependencies {
|
||||
pub mysql_pool: MySqlPool,
|
||||
|
||||
/// Public GCS/S3 bucket for storing generated splats.
|
||||
pub public_bucket_client: LegacyBucketClient,
|
||||
pub public_bucket_client: BucketClient,
|
||||
|
||||
/// API credentials for World Labs.
|
||||
pub worldlabs_creds: WorldLabsApiCreds,
|
||||
|
||||
@@ -16,7 +16,7 @@ use log::{info, warn};
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use bootstrap::bootstrap::{bootstrap, BootstrapArgs};
|
||||
use cloud_storage::legacy_bucket_client::LegacyBucketClient;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
use shared_env_var_config::logging::DEFAULT_RUST_LOG;
|
||||
use errors::AnyhowResult;
|
||||
@@ -85,7 +85,7 @@ async fn main() -> AnyhowResult<()> {
|
||||
Duration::from_secs(60 * 5),
|
||||
);
|
||||
|
||||
let public_bucket_client = LegacyBucketClient::create(
|
||||
let public_bucket_client = BucketClient::create(
|
||||
&access_key,
|
||||
&secret_key,
|
||||
®ion_name,
|
||||
|
||||
@@ -38,10 +38,8 @@ actix_helpers.workspace = true
|
||||
artcraft_api_defs.workspace = true
|
||||
artcraft_api_keys.workspace = true
|
||||
artcraft_router.workspace = true
|
||||
sha1_hash.workspace = true
|
||||
video_info.workspace = true
|
||||
bootstrap.workspace = true
|
||||
bucket_client.workspace = true
|
||||
bucket_paths.workspace = true
|
||||
cloud_storage.workspace = true
|
||||
collections.workspace = true
|
||||
|
||||
@@ -365,13 +365,7 @@ use artcraft_api_defs::user_referral_codes::delete_referral_code::*;
|
||||
use artcraft_api_defs::user_referral_codes::list_referral_codes::*;
|
||||
use artcraft_api_defs::web_referrals::log_web_referral::*;
|
||||
use artcraft_api_defs::video_info::read_only::*;
|
||||
use artcraft_api_defs::video_info::upload::*;
|
||||
use artcraft_api_defs::video_info::notes::*;
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_model_type::UploadedVideoNoteReportedModelType;
|
||||
use enums::by_table::uploaded_video_notes::uploaded_video_note_reported_website::UploadedVideoNoteReportedWebsite;
|
||||
use crate::http_server::endpoints::video_info::video_info_read_info_handler::*;
|
||||
use crate::http_server::endpoints::video_info::video_info_upload_handler::*;
|
||||
use crate::http_server::endpoints::video_info::video_info_notes_handler::*;
|
||||
use crate::http_server::endpoints::web_referrals::log_web_referral_handler::*;
|
||||
use crate::http_server::endpoints::image_studio::update_gpt_image_job_status_handler::*;
|
||||
use crate::http_server::endpoints::voice_conversion::enqueue_seed_vc_inference_handler::*;
|
||||
@@ -626,8 +620,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
crate::http_server::endpoints::subscriptions::get_session_subscription_handler::get_session_subscription_handler,
|
||||
// Web Referrals
|
||||
crate::http_server::endpoints::video_info::video_info_read_info_handler::video_info_read_info_handler,
|
||||
crate::http_server::endpoints::video_info::video_info_upload_handler::video_info_upload_handler,
|
||||
crate::http_server::endpoints::video_info::video_info_notes_handler::video_info_notes_handler,
|
||||
crate::http_server::endpoints::web_referrals::log_web_referral_handler::log_web_referral_handler,
|
||||
// User Referral Codes
|
||||
crate::http_server::endpoints::user_referral_codes::create_referral_code_handler::create_referral_code_handler,
|
||||
@@ -1263,12 +1255,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
// Video info (provenance detection)
|
||||
VideoInfoReadOnlyForm,
|
||||
VideoInfoReadOnlyResponse,
|
||||
VideoInfoUploadForm,
|
||||
VideoInfoUploadResponse,
|
||||
VideoInfoNoteRequest,
|
||||
VideoInfoNoteResponse,
|
||||
UploadedVideoNoteReportedModelType,
|
||||
UploadedVideoNoteReportedWebsite,
|
||||
VideoProvenanceKind,
|
||||
SeedanceVideoInfo,
|
||||
VeoVideoInfo,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user