mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-23 01:59:31 -04:00
Compare commits
51
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6633412140 | ||
|
|
f6dfd02cfc | ||
|
|
5d05309d95 | ||
|
|
56e43f9f1d | ||
|
|
66a805c53f | ||
|
|
a5c5161939 | ||
|
|
f0fd411640 | ||
|
|
a2d81ddf0c | ||
|
|
676eb12d56 | ||
|
|
bab9cf76f0 | ||
|
|
9633a0ba85 | ||
|
|
7d14c3c01c | ||
|
|
8477991327 | ||
|
|
5e5aa01ce7 | ||
|
|
ca21b69610 | ||
|
|
41348dd585 | ||
|
|
f6c630cc49 | ||
|
|
2b3be7c172 | ||
|
|
677ed59005 | ||
|
|
4849b4d6bb | ||
|
|
dbda51bd29 | ||
|
|
9d9ec36341 | ||
|
|
0163504aad | ||
|
|
5093361f2c | ||
|
|
b59909c1aa | ||
|
|
9d8eedc77a | ||
|
|
0e7ebd3914 | ||
|
|
d508bf55e2 | ||
|
|
cac0c0b188 | ||
|
|
f837f79404 | ||
|
|
b632d79833 | ||
|
|
d909d55e6f | ||
|
|
1847533e8a | ||
|
|
95894a87b9 | ||
|
|
3ad642f150 | ||
|
|
3fb683185a | ||
|
|
36780e5669 | ||
|
|
77614e06d9 | ||
|
|
4c1d1007a2 | ||
|
|
9740121012 | ||
|
|
27d6794d22 | ||
|
|
4aa91af67e | ||
|
|
ddc33ce600 | ||
|
|
c017fbc25a | ||
|
|
7557e586ba | ||
|
|
2286d663ac | ||
|
|
4181e24f7f | ||
|
|
d4911f226b | ||
|
|
93db726c19 | ||
|
|
dac64fb38c | ||
|
|
60009f98ac |
+168
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n token as `token: tokens::tokens::user_subscriptions::UserSubscriptionToken`,\n user_token as `user_token: tokens::tokens::users::UserToken`,\n subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n subscription_product_slug,\n maybe_stripe_customer_id,\n maybe_stripe_product_id,\n maybe_stripe_subscription_id,\n maybe_stripe_subscription_status,\n maybe_stripe_invoice_is_paid,\n subscription_start_at,\n subscription_expires_at,\n current_billing_period_end_at,\n maybe_cancel_at,\n maybe_canceled_at\n\nFROM user_subscriptions\n\nWHERE\n user_token = ?\n AND subscription_namespace = ?\n AND maybe_stripe_customer_id IS NOT NULL\n AND maybe_stripe_subscription_id IS NOT NULL\n AND maybe_stripe_subscription_status IS NOT NULL\n AND maybe_stripe_subscription_status NOT IN ('canceled', 'incomplete_expired')\n AND subscription_expires_at > CURRENT_TIMESTAMP\n ORDER BY id ASC\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::user_subscriptions::UserSubscriptionToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "subscription_namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "subscription_product_slug",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_stripe_customer_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_stripe_product_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_stripe_subscription_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "maybe_stripe_subscription_status",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "maybe_stripe_invoice_is_paid",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "subscription_start_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "subscription_expires_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "current_billing_period_end_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "maybe_cancel_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"name": "maybe_canceled_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "1e08676857e999a58d3c85474c2a2acec38a413e53ca4207aade690e0bfffe25"
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n token as `token: tokens::tokens::wallets::WalletToken`,\n wallet_namespace as `namespace: enums::common::payments_namespace::PaymentsNamespace`,\n owner_user_token as `owner_user_token: tokens::tokens::users::UserToken`,\n banked_credits,\n monthly_credits\nFROM wallets\nWHERE token = ?\nLIMIT 1\nFOR UPDATE\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::wallets::WalletToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "owner_user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "banked_credits",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "monthly_credits",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "2be78dc9fada8cda24df59ee9911118aa6f40247b10c6a76e07cfa74fd7f1412"
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n SELECT\n token as `token: tokens::tokens::wallets::WalletToken`\n FROM wallets\n WHERE owner_user_token = ?\n AND wallet_namespace = ?\n ORDER BY id ASC\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::wallets::WalletToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "2c98facb81a43364997db5558ad0f12300230691b09ce96d49e530f8361c237f"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n UPDATE wallets\n SET\n monthly_credits = ?,\n version = version + 1\n WHERE token = ?\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "47b14121f41b98b0dc92772e9f58a3f4a3821b11ebb10b768595d7635e472dbb"
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n token as `token: tokens::tokens::user_subscriptions::UserSubscriptionToken`,\n user_token as `user_token: tokens::tokens::users::UserToken`,\n subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n subscription_product_slug,\n maybe_stripe_subscription_status,\n maybe_stripe_customer_id,\n maybe_stripe_product_id,\n maybe_stripe_subscription_id\n\nFROM user_subscriptions\n\nWHERE\n user_token = ?\n AND subscription_namespace = ?\n AND maybe_stripe_customer_id IS NOT NULL\n AND maybe_stripe_subscription_id IS NOT NULL\n AND maybe_stripe_subscription_status IS NOT NULL\n AND maybe_stripe_subscription_status NOT IN ('canceled', 'incomplete_expired')\n AND subscription_expires_at > CURRENT_TIMESTAMP\n ORDER BY id ASC\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::user_subscriptions::UserSubscriptionToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "subscription_namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "subscription_product_slug",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_stripe_subscription_status",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_stripe_customer_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_stripe_product_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "maybe_stripe_subscription_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "4bfa96682bd1e7576c26c89e3d1a17162193f7df3c1530122ca8e715afc5f385"
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n token as `token: tokens::tokens::user_subscriptions::UserSubscriptionToken`,\n user_token as `user_token: tokens::tokens::users::UserToken`,\n subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n subscription_product_slug,\n maybe_stripe_subscription_status,\n maybe_stripe_customer_id,\n maybe_stripe_product_id,\n maybe_stripe_subscription_id\n\nFROM user_subscriptions\n\nWHERE\n user_token = ?\n AND subscription_namespace = ?\n AND maybe_stripe_customer_id IS NOT NULL\n AND maybe_stripe_subscription_id IS NOT NULL\n AND maybe_stripe_subscription_status IS NOT NULL\n ORDER BY id ASC\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::user_subscriptions::UserSubscriptionToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "subscription_namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "subscription_product_slug",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_stripe_subscription_status",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_stripe_customer_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_stripe_product_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "maybe_stripe_subscription_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "4c2a71386362fb54f38bd6633f8aebe75e0bd8edf1b1b8773c6298c1f6018332"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO wallets\nSET\n token = ?,\n wallet_namespace = ?,\n\n owner_user_token = ?,\n \n banked_credits = 0,\n monthly_credits = 0\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 3
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4f5100a2cfb465964e77eaacb1ae394daae94de20c56a0966a8222dc9bea63c6"
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n user_token,\n subscription_namespace,\n subscription_product_slug,\n subscription_expires_at\n\nFROM user_subscriptions\n\nWHERE\n user_token = ?\n AND subscription_expires_at > CURRENT_TIMESTAMP\n ORDER BY id ASC\n ",
|
||||
"query": "\nSELECT\n user_token,\n subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n subscription_product_slug,\n subscription_expires_at\n\nFROM user_subscriptions\n\nWHERE\n user_token = ?\n AND subscription_expires_at > CURRENT_TIMESTAMP\n ORDER BY id ASC\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "subscription_namespace",
|
||||
"name": "subscription_namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
@@ -54,5 +54,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "46e1cb058bffbea5a5d3ffa5dd904416d6f34ccefdb394030f19cc762b507d68"
|
||||
"hash": "680d60fcda0f6fdf269f3525a3fe582db847e56ca7380c0ff5696cbd6efb7db3"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO user_stripe_customer_links\nSET\n user_token = ?,\n payments_namespace = ?,\n stripe_customer_id = ?\n\nON DUPLICATE KEY UPDATE\n updated_at = CURRENT_TIMESTAMP\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 3
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6df1b3d2cd145fa3199898fe53565eef28a74206093f4fc6585aad6cc2e9ae71"
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n user_token as `user_token: tokens::tokens::users::UserToken`,\n payments_namespace as `payments_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n stripe_customer_id\n\nFROM user_stripe_customer_links\n\nWHERE\n user_token = ?\n AND payments_namespace = ?\n ORDER BY id ASC\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "payments_namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "stripe_customer_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "771ebd8c236cc3bfeee2df7168c05f639b666e5d67a46593332ce02a0316b4f9"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO user_subscriptions\nSET\n token = ?,\n\n maybe_stripe_invoice_is_paid = ?,\n\n user_token = ?,\n subscription_namespace = ?,\n subscription_product_slug = ?,\n\n maybe_stripe_subscription_id = ?,\n maybe_stripe_customer_id = ?,\n\n maybe_stripe_product_id = ?,\n maybe_stripe_price_id = ?,\n\n maybe_stripe_recurring_interval = ?,\n maybe_stripe_subscription_status = ?,\n maybe_stripe_is_production = ?,\n \n maybe_stripe_billing_cycle_anchor = ?,\n\n subscription_start_at = ?,\n current_billing_period_start_at = ?,\n current_billing_period_end_at = ?,\n subscription_expires_at = ?,\n maybe_cancel_at = ?,\n maybe_canceled_at = ?,\n\n version = version + 1\n\nON DUPLICATE KEY UPDATE\n maybe_stripe_invoice_is_paid = ?,\n\n subscription_namespace = ?,\n subscription_product_slug= ?,\n\n maybe_stripe_product_id = ?,\n maybe_stripe_price_id = ?,\n\n maybe_stripe_recurring_interval = ?,\n maybe_stripe_subscription_status = ?,\n \n maybe_stripe_billing_cycle_anchor = ?,\n\n current_billing_period_start_at = ?,\n current_billing_period_end_at = ?,\n subscription_expires_at = ?,\n maybe_cancel_at = ?,\n maybe_canceled_at = ?,\n\n version = version + 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 32
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "871163ef30d2f6767f836a05f46d2ce7fb4733583eedddbf07732ebb5c1f1b53"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO user_subscriptions\nSET\n token = ?,\n user_token = ?,\n subscription_namespace = ?,\n subscription_product_slug = ?,\n\n maybe_stripe_subscription_id = ?,\n maybe_stripe_customer_id = ?,\n\n maybe_stripe_product_id = ?,\n maybe_stripe_price_id = ?,\n\n maybe_stripe_recurring_interval = ?,\n maybe_stripe_subscription_status = ?,\n maybe_stripe_is_production = ?,\n\n subscription_start_at = ?,\n current_billing_period_start_at = ?,\n current_billing_period_end_at = ?,\n subscription_expires_at = ?,\n maybe_cancel_at = ?,\n maybe_canceled_at = ?,\n\n version = version + 1\n\nON DUPLICATE KEY UPDATE\n subscription_namespace = ?,\n subscription_product_slug= ?,\n\n maybe_stripe_product_id = ?,\n maybe_stripe_price_id = ?,\n\n maybe_stripe_recurring_interval = ?,\n maybe_stripe_subscription_status = ?,\n\n current_billing_period_start_at = ?,\n current_billing_period_end_at = ?,\n subscription_expires_at = ?,\n maybe_cancel_at = ?,\n maybe_canceled_at = ?,\n\n version = version + 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 28
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8d267a609157e6459393ffa32ea83996dcf135c52ee8a930d5be628802d97371"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO wallet_ledger_entries\nSET\n token = ?,\n wallet_token = ?,\n entry_type = ?,\n maybe_entity_ref = ?,\n credits_delta = ?,\n banked_credits_before = ?,\n banked_credits_after = ?,\n monthly_credits_before = ?,\n monthly_credits_after = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 9
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9d26917668d4f0ecd2492a94a7775e4561fc5d8b33194274a7715b9853ecea00"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO user_subscriptions\nSET\n token = ?,\n user_token = ?,\n subscription_namespace = ?,\n subscription_product_slug = ?,\n\n maybe_stripe_subscription_id = ?,\n maybe_stripe_customer_id = ?,\n\n maybe_stripe_product_id = ?,\n maybe_stripe_price_id = ?,\n\n maybe_stripe_recurring_interval = ?,\n maybe_stripe_subscription_status = ?,\n maybe_stripe_is_production = ?,\n \n maybe_stripe_billing_cycle_anchor = ?,\n\n subscription_start_at = ?,\n current_billing_period_start_at = ?,\n current_billing_period_end_at = ?,\n subscription_expires_at = ?,\n maybe_cancel_at = ?,\n maybe_canceled_at = ?,\n\n version = version + 1\n\nON DUPLICATE KEY UPDATE\n subscription_namespace = ?,\n subscription_product_slug= ?,\n\n maybe_stripe_product_id = ?,\n maybe_stripe_price_id = ?,\n\n maybe_stripe_recurring_interval = ?,\n maybe_stripe_subscription_status = ?,\n \n maybe_stripe_billing_cycle_anchor = ?,\n\n current_billing_period_start_at = ?,\n current_billing_period_end_at = ?,\n subscription_expires_at = ?,\n maybe_cancel_at = ?,\n maybe_canceled_at = ?,\n\n version = version + 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 30
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a28d6de7424b269e64e97692a4c67a12fcfb789a3e5a512a103a78dea60e75ce"
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n SELECT\n token as `token: tokens::tokens::wallets::WalletToken`,\n wallet_namespace as `namespace: enums::common::payments_namespace::PaymentsNamespace`,\n banked_credits,\n monthly_credits\n FROM wallets\n WHERE owner_user_token = ?\n AND wallet_namespace = ?\n ORDER BY id ASC\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::wallets::WalletToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "namespace: enums::common::payments_namespace::PaymentsNamespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "banked_credits",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "monthly_credits",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ac8e3bc9f4e0722ec2f805dbb52b8e43ec8f7a1aa923b9f8f5f6c0770a315ee6"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n UPDATE wallets\n SET\n banked_credits = ?,\n version = version + 1\n WHERE token = ?\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b721e3fda6d80df5041c918b1a127236c802ed18ccc961cc6ac96d156bf085da"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n UPDATE wallets\n SET\n banked_credits = ?,\n monthly_credits = ?,\n version = version + 1\n WHERE token = ?\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 3
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c7f20753f9704d5ff3358586240ecc8a505990f4634ba3af9de6c99c22aa7368"
|
||||
}
|
||||
Generated
+258
-3
@@ -926,11 +926,155 @@ dependencies = [
|
||||
"serde_qs 0.10.1",
|
||||
"sha2 0.10.8",
|
||||
"smart-default 0.6.0",
|
||||
"smol_str",
|
||||
"smol_str 0.1.24",
|
||||
"thiserror 1.0.63",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe"
|
||||
version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cecbddf002ad7a13d2041eadf1b234cb3f57653ffdd901a01bc3f1c65aa77440"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"hmac 0.12.1",
|
||||
"http-types",
|
||||
"hyper 0.14.28",
|
||||
"hyper-tls 0.5.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_qs 0.10.1",
|
||||
"sha2 0.10.8",
|
||||
"smart-default 0.6.0",
|
||||
"smol_str 0.1.24",
|
||||
"thiserror 1.0.63",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92140fa7152f9dcde7554cb1da37c7ae93b0c724db5214c754c55a9765afbe8"
|
||||
dependencies = [
|
||||
"async-stripe-client-core",
|
||||
"async-stripe-shared",
|
||||
"bytes 1.10.1",
|
||||
"http-body-util",
|
||||
"hyper 1.6.0",
|
||||
"hyper-tls 0.6.0",
|
||||
"hyper-util",
|
||||
"miniserde",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-billing"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33c4cd0ac61e0dcb39da4f3c04b049c0d8a3a98868ca976e18ff56ecac1b6e08"
|
||||
dependencies = [
|
||||
"async-stripe-client-core",
|
||||
"async-stripe-shared",
|
||||
"async-stripe-types",
|
||||
"miniserde",
|
||||
"serde",
|
||||
"smol_str 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-checkout"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b115740c799730d4caac099d48be4908d2d99611d56a874d2d3555b5d4306a97"
|
||||
dependencies = [
|
||||
"async-stripe-client-core",
|
||||
"async-stripe-shared",
|
||||
"async-stripe-types",
|
||||
"miniserde",
|
||||
"serde",
|
||||
"smol_str 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-client-core"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb1f6b6693946e650a9361feb319389a1408534ec1b618cd9239f1e2e20b8668"
|
||||
dependencies = [
|
||||
"async-stripe-shared",
|
||||
"async-stripe-types",
|
||||
"bytes 1.10.1",
|
||||
"futures-util",
|
||||
"miniserde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_qs 0.13.0",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-core"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81d0445a38170bcc3e4adf52fd80c94b70b02dc73a102afcd0bc9d6051eada18"
|
||||
dependencies = [
|
||||
"async-stripe-client-core",
|
||||
"async-stripe-shared",
|
||||
"async-stripe-types",
|
||||
"miniserde",
|
||||
"serde",
|
||||
"smol_str 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-shared"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b4328e5c0deeacd7cd5a95286d4f5dce045791b30be87583dd706c2342236c3"
|
||||
dependencies = [
|
||||
"async-stripe-types",
|
||||
"miniserde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smol_str 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-types"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985b4f00fd57ce9cbd015c6410d05dfbe5d2bf90513e20b417e70b6f022e3f88"
|
||||
dependencies = [
|
||||
"miniserde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smol_str 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stripe-webhook"
|
||||
version = "1.0.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75f8382af92463fa8e0b86e825d7d08eecbcd8715c197f1a66173fcc18e35774"
|
||||
dependencies = [
|
||||
"async-stripe-shared",
|
||||
"async-stripe-types",
|
||||
"chrono",
|
||||
"hex",
|
||||
"hmac 0.12.1",
|
||||
"miniserde",
|
||||
"serde",
|
||||
"sha2 0.10.8",
|
||||
"thiserror 1.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.7.1"
|
||||
@@ -1201,6 +1345,41 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "billing_artcraft_component"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"artcraft_api_defs",
|
||||
"async-stripe 1.0.0-alpha.2",
|
||||
"async-stripe-billing",
|
||||
"async-stripe-checkout",
|
||||
"async-stripe-core",
|
||||
"async-stripe-shared",
|
||||
"async-stripe-types",
|
||||
"async-stripe-webhook",
|
||||
"chrono",
|
||||
"component_traits",
|
||||
"enums",
|
||||
"errors",
|
||||
"http_server_common",
|
||||
"log",
|
||||
"mockall",
|
||||
"mysql_queries",
|
||||
"once_cell",
|
||||
"reusable_types",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tokens",
|
||||
"tokio",
|
||||
"user_traits_component",
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "billing_component"
|
||||
version = "0.0.1"
|
||||
@@ -1208,9 +1387,11 @@ dependencies = [
|
||||
"actix-http",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"async-stripe",
|
||||
"async-stripe 0.26.0",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"component_traits",
|
||||
"enums",
|
||||
"errors",
|
||||
"http_server_common",
|
||||
"log",
|
||||
@@ -2089,6 +2270,34 @@ dependencies = [
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "component_traits"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"artcraft_api_defs",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"enums",
|
||||
"errors",
|
||||
"http_server_common",
|
||||
"log",
|
||||
"mockall",
|
||||
"mysql_queries",
|
||||
"once_cell",
|
||||
"reusable_types",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tokens",
|
||||
"tokio",
|
||||
"user_traits_component",
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "composite_identifiers"
|
||||
version = "0.0.1"
|
||||
@@ -6398,6 +6607,17 @@ dependencies = [
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mini-internal"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6c74ab4f1a0c0ab045260ee4727b23c00cc17e5eff5095262d08eef8c3c8d49"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minidom"
|
||||
version = "0.16.0"
|
||||
@@ -6413,6 +6633,17 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniserde"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08ec68bf2ad170a53a6efa92c3df7187968d6e475fe7a935725868154074ca0f"
|
||||
dependencies = [
|
||||
"itoa 1.0.11",
|
||||
"mini-internal",
|
||||
"ryu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.2"
|
||||
@@ -9528,6 +9759,17 @@ dependencies = [
|
||||
"thiserror 1.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_qs"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
"thiserror 1.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.19"
|
||||
@@ -9904,6 +10146,16 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smol_str"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.10"
|
||||
@@ -10292,9 +10544,11 @@ dependencies = [
|
||||
"actix_helpers",
|
||||
"anyhow",
|
||||
"artcraft_api_defs",
|
||||
"async-stripe",
|
||||
"async-stripe 0.26.0",
|
||||
"async-stripe 0.41.0",
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"billing_artcraft_component",
|
||||
"billing_component",
|
||||
"bootstrap",
|
||||
"bucket_paths",
|
||||
@@ -10302,6 +10556,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"cloud_storage",
|
||||
"collections",
|
||||
"component_traits",
|
||||
"composite_identifiers",
|
||||
"config",
|
||||
"cookies",
|
||||
|
||||
+37
-32
@@ -6,6 +6,7 @@ resolver = "2"
|
||||
members = [
|
||||
# API clients for external services
|
||||
# These might be custom implementations or wrappers over other client libraries.
|
||||
"crates/api_clients/artcraft_api_defs", # TODO: api_clients/{artcraft}/{api_defs,client}
|
||||
"crates/api_clients/cloud_storage",
|
||||
"crates/api_clients/fal_client",
|
||||
"crates/api_clients/google_drive_common",
|
||||
@@ -97,7 +98,6 @@ members = [
|
||||
#"crates/schema/database/sqlite_queries",
|
||||
|
||||
# Schema (public): common strongly-typed tokens, ids, payloads, etc.
|
||||
"crates/schema/public/api/artcraft_api_defs",
|
||||
"crates/schema/public/composite_identifiers",
|
||||
"crates/schema/public/enums",
|
||||
"crates/schema/public/enums_public",
|
||||
@@ -119,6 +119,8 @@ members = [
|
||||
|
||||
# Service Plugins: complete subsystems that can be plugged into services (users, billing, etc.)
|
||||
"crates/service/plugins/billing",
|
||||
"crates/service/plugins/billing_artcraft",
|
||||
"crates/service/plugins/component_traits",
|
||||
"crates/service/plugins/inference_workloads",
|
||||
"crates/service/plugins/user_traits_component",
|
||||
|
||||
@@ -176,6 +178,40 @@ publish = false
|
||||
#
|
||||
workspace-build-acceleration = { path = "crates/workspace-build-acceleration" }
|
||||
|
||||
# Internal libs
|
||||
# Setting paths here ensures we don't need to do so in every crate's Cargo.toml
|
||||
# It makes refactoring much easier.
|
||||
artcraft_api_defs = { path = "crates/api_clients/artcraft_api_defs" }
|
||||
build_metadata = { path = "crates/lib/build_metadata" }
|
||||
cloud_storage = { path = "crates/api_clients/cloud_storage" }
|
||||
cloudflare_errors = { path = "crates/lib/cloudflare_errors" }
|
||||
component_traits = { path = "crates/service/plugins/component_traits" }
|
||||
cookie_store = { path = "crates/lib/cookie_store" }
|
||||
crockford = { path = "crates/lib/data/crockford" }
|
||||
enums = { path = "crates/schema/public/enums" }
|
||||
enums_public = { path = "crates/schema/public/enums_public" }
|
||||
errors = { path = "crates/lib/errors" }
|
||||
fal_client = { path = "crates/api_clients/fal_client" }
|
||||
file_to_base64_url = { path = "crates/lib/files/file_to_base64_url" }
|
||||
filesys = { path = "crates/lib/files/filesys" }
|
||||
idempotency = { path = "crates/lib/idempotency" }
|
||||
images = { path = "crates/lib/files/images" }
|
||||
jwt_light = { path = "crates/lib/jwt_light" }
|
||||
memory_caching = { path = "crates/lib/caching/memory_caching" }
|
||||
memory_store = { path = "crates/lib/caching/memory_store" }
|
||||
midjourney_client = { path = "crates/api_clients/midjourney_client" }
|
||||
mimetypes = { path = "crates/lib/files/mimetypes" }
|
||||
openai_sora_client = { path = "crates/api_clients/openai_sora_client" }
|
||||
primitives = { path = "crates/lib/data/primitives" }
|
||||
shared_service_components = { path = "crates/lib/shared_service_components" }
|
||||
sqlite_tasks = { path = "crates/schema/database/sqlite_tasks" }
|
||||
storyteller_client = { path = "crates/api_clients/storyteller_client" }
|
||||
subprocess_common = { path = "crates/lib/subprocess_common" }
|
||||
test_data = { path = "crates/lib/test_data" }
|
||||
testing = { path = "crates/lib/testing" }
|
||||
tokens = { path = "crates/schema/public/tokens" }
|
||||
web_base64 = { path = "crates/lib/data/web_base64" }
|
||||
|
||||
# External libs
|
||||
# Centrally pinned versions so that we can uniformly upgrade/downgrade versions across the workspace
|
||||
# If a crate needs to use an older/newer version, the dependency should be managed in that crate's own Cargo.toml
|
||||
@@ -219,34 +255,3 @@ thiserror = "2.0.12"
|
||||
tokio = { version = "1.45.1", features = ["macros"] }
|
||||
toml = "0.8.22"
|
||||
url = { version = "2.5.4", features = ["serde"] }
|
||||
|
||||
# Internal libs
|
||||
artcraft_api_defs = { path = "crates/schema/public/api/artcraft_api_defs" }
|
||||
build_metadata = { path = "crates/lib/build_metadata" }
|
||||
cloud_storage = { path = "crates/api_clients/cloud_storage" }
|
||||
cloudflare_errors = { path = "crates/lib/cloudflare_errors" }
|
||||
cookie_store = { path = "crates/lib/cookie_store" }
|
||||
crockford = { path = "crates/lib/data/crockford" }
|
||||
enums = { path = "crates/schema/public/enums" }
|
||||
enums_public = { path = "crates/schema/public/enums_public" }
|
||||
errors = { path = "crates/lib/errors" }
|
||||
fal_client = { path = "crates/api_clients/fal_client" }
|
||||
file_to_base64_url = { path = "crates/lib/files/file_to_base64_url" }
|
||||
filesys = { path = "crates/lib/files/filesys" }
|
||||
idempotency = { path = "crates/lib/idempotency" }
|
||||
images = { path = "crates/lib/files/images" }
|
||||
jwt_light = { path = "crates/lib/jwt_light" }
|
||||
memory_caching = { path = "crates/lib/caching/memory_caching" }
|
||||
memory_store = { path = "crates/lib/caching/memory_store" }
|
||||
midjourney_client = { path = "crates/api_clients/midjourney_client" }
|
||||
mimetypes = { path = "crates/lib/files/mimetypes" }
|
||||
openai_sora_client = { path = "crates/api_clients/openai_sora_client" }
|
||||
primitives = { path = "crates/lib/data/primitives" }
|
||||
shared_service_components = { path = "crates/lib/shared_service_components" }
|
||||
sqlite_tasks = { path = "crates/schema/database/sqlite_tasks" }
|
||||
storyteller_client = { path = "crates/api_clients/storyteller_client" }
|
||||
subprocess_common = { path = "crates/lib/subprocess_common" }
|
||||
test_data = { path = "crates/lib/test_data" }
|
||||
testing = { path = "crates/lib/testing" }
|
||||
tokens = { path = "crates/schema/public/tokens" }
|
||||
web_base64 = { path = "crates/lib/data/web_base64" }
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE user_subscriptions DROP COLUMN maybe_stripe_invoice_is_paid;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE user_subscriptions
|
||||
ADD COLUMN maybe_stripe_invoice_is_paid BOOLEAN DEFAULT NULL
|
||||
AFTER maybe_stripe_subscription_status;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE wallets;
|
||||
@@ -0,0 +1,66 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE wallets (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- If we host multiple sites with distinct categories, this will enable us to
|
||||
-- segregate wallets. This is effectively a wallet namespace.
|
||||
-- NB: Uses the `PaymentsNamespace` enum, which is also shared with subscriptions.
|
||||
wallet_namespace VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Who owns the wallet
|
||||
-- In the future, we might allow other users to use the same wallet,
|
||||
-- but the wallet would still have an owner.
|
||||
-- For now, we'll keep this 1:1 with users, but we may want 1:n in the future.
|
||||
owner_user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The durable credits bucket.
|
||||
-- This bucket is persistent and is refilled by user credit purchases.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
banked_credits INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- The monthly credits bucket.
|
||||
-- This bucket is ephemeral and is refilled monthly.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
monthly_credits INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Whether the stripe subscription is active.
|
||||
-- subscription_is_active BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether the stripe subscription is paid.
|
||||
-- If the subscription is not paid, we should not allow usage of monthly credits.
|
||||
-- subscription_is_paid BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== RECORD TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- ========== PAYMENTS AND SUBSCRIPTIONS TIMESTAMPS ==========
|
||||
|
||||
-- When the user last purchased banked (durable) credits.
|
||||
-- banked_credits_last_purchased_at TIMESTAMP DEFAULT NULL,
|
||||
|
||||
-- When we last refilled the monthly bucket.
|
||||
-- This has to do with subscription logic.
|
||||
-- monthly_wallet_refilled_at TIMESTAMP DEFAULT NULL,
|
||||
|
||||
-- ========== INDICES ==========
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (wallet_namespace, owner_user_token), -- For now
|
||||
INDEX idx_wallet_namespace (wallet_namespace),
|
||||
INDEX idx_owner_user_token (owner_user_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE wallet_ledger_entries;
|
||||
@@ -0,0 +1,52 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE wallet_ledger_entries (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Which wallet this entry corresponds to.
|
||||
wallet_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The type of ledger entry this is.
|
||||
entry_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- A record we can look up to attribute the credit or deduction against
|
||||
-- This could be an internal entity token (prompt_token, job token) or an
|
||||
-- external token (stripe event_id, stripe invoice.id, etc.)
|
||||
-- Length is VARCHAR(255) to accommodate Stripe IDs.
|
||||
maybe_entity_ref VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Signed integer that shows the delta of credits for this event.
|
||||
-- This combines impacts to both banked_credits and monthly_credits.
|
||||
-- This is less authoritative than the before/after fields, but is useful
|
||||
credits_delta INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of banked credits before the event.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
banked_credits_before INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of banked credits after the event.
|
||||
banked_credits_after INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of monthly credits before the event.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
monthly_credits_before INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of monthly credits after the event.
|
||||
monthly_credits_after INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== RECORD TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- ========== INDICES ==========
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY index_wallet_token (wallet_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE user_subscriptions DROP COLUMN maybe_stripe_billing_cycle_anchor;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE user_subscriptions
|
||||
ADD COLUMN maybe_stripe_billing_cycle_anchor TIMESTAMP DEFAULT NULL
|
||||
AFTER maybe_stripe_invoice_is_paid;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE stripe_webhook_event_logs DROP COLUMN maybe_internal_entity_token;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE stripe_webhook_event_logs
|
||||
ADD COLUMN maybe_internal_entity_token VARCHAR(32) DEFAULT NULL
|
||||
AFTER maybe_user_token;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE user_stripe_customer_links;
|
||||
@@ -0,0 +1,36 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- 1:1 links between a user and a stripe customer (per payments namespace)
|
||||
-- We can hard delete records if we have to.
|
||||
-- If users need a new stripe customer ID, we need to hard delete the existing record.
|
||||
CREATE TABLE user_stripe_customer_links (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Composite primary key
|
||||
user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Composite primary key
|
||||
-- If we host multiple sites with distinct categories, this will enable us to
|
||||
-- segregate accounts.
|
||||
-- NB: Uses the `PaymentsNamespace` enum, which is also shared with subscriptions.
|
||||
payments_namespace VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Unique key. (We can loosen to `stripe_customer_id, wallet_namespace` later if
|
||||
-- we want to share billing.)
|
||||
stripe_customer_id VARCHAR(255) NOT NULL,
|
||||
|
||||
-- ========== RECORD 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 (user_token, payments_namespace),
|
||||
-- UNIQUE KEY (stripe_customer_id, payments_namespace)
|
||||
UNIQUE KEY (stripe_customer_id)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,66 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE stripe_webhook_event_logs (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- ========== STRIPE DATA ==========
|
||||
|
||||
-- You can safely assume object IDs we generate will never exceed 255 characters,
|
||||
-- but you should be able to handle IDs of up to that length. If for example you’re using MySQL,
|
||||
-- you should store IDs in a VARCHAR(255) COLLATE utf8_bin column (the COLLATE configuration ensures
|
||||
-- case-sensitivity in lookups).
|
||||
-- https://stackoverflow.com/a/61809494
|
||||
stripe_event_id VARCHAR(255) NOT NULL,
|
||||
|
||||
-- The type of webhook event
|
||||
stripe_event_type VARCHAR(255) NOT NULL,
|
||||
|
||||
-- The id of the entity that was the subject of the event.
|
||||
-- We don't always extract this.
|
||||
maybe_stripe_event_entity_id VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- The id of the entity that was the subject of the event.
|
||||
-- We don't always extract this.
|
||||
maybe_stripe_customer_id VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Whether this is in production or test mode in Stripe.
|
||||
-- This is controlled by which API keys are used.
|
||||
-- "livemode"=true in production.
|
||||
stripe_is_production BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== INTERNAL SYSTEM METADATA ==========
|
||||
|
||||
-- Whether we handled the event with any sort of action
|
||||
action_was_taken BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether we should ignore any future retries by Stripe replaying the event.
|
||||
-- This helps us treat events with idempotency.
|
||||
should_ignore_retry BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Some event types may attach a user token
|
||||
maybe_user_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- An internal optional entity token this resolves to.
|
||||
-- eg. `wallets.token` or `user_subscriptions.token`.
|
||||
maybe_internal_entity_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- When the event was created on Stripe's end
|
||||
stripe_event_created_at TIMESTAMP NOT NULL,
|
||||
|
||||
-- ========== INDICES ==========
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (stripe_event_id),
|
||||
KEY index_stripe_event_type (stripe_event_type),
|
||||
KEY index_maybe_stripe_event_entity_id (maybe_stripe_event_entity_id),
|
||||
KEY index_maybe_stripe_customer_id (maybe_stripe_customer_id),
|
||||
KEY fk_maybe_user_token (maybe_user_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,36 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- 1:1 links between a user and a stripe customer (per payments namespace)
|
||||
-- We can hard delete records if we have to.
|
||||
-- If users need a new stripe customer ID, we need to hard delete the existing record.
|
||||
CREATE TABLE user_stripe_customer_links (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Composite primary key
|
||||
user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Composite primary key
|
||||
-- If we host multiple sites with distinct categories, this will enable us to
|
||||
-- segregate accounts.
|
||||
-- NB: Uses the `PaymentsNamespace` enum, which is also shared with subscriptions.
|
||||
payments_namespace VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Unique key. (We can loosen to `stripe_customer_id, wallet_namespace` later if
|
||||
-- we want to share billing.)
|
||||
stripe_customer_id VARCHAR(255) NOT NULL,
|
||||
|
||||
-- ========== RECORD 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 (user_token, payments_namespace),
|
||||
-- UNIQUE KEY (stripe_customer_id, payments_namespace)
|
||||
UNIQUE KEY (stripe_customer_id)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -53,6 +53,18 @@ CREATE TABLE user_subscriptions (
|
||||
-- Subscription object status enum as string
|
||||
maybe_stripe_subscription_status VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Primarily managed by the `invoice.paid` and `invoice.payment_failed` webhooks.
|
||||
-- NB: Not applicable to FakeYou subscriptions!
|
||||
maybe_stripe_invoice_is_paid BOOLEAN DEFAULT NULL,
|
||||
|
||||
-- Which day of the month, or month of the year, etc. to anchor the subscription to.
|
||||
-- See docs on the subscription object.
|
||||
-- Stripe:
|
||||
-- "The reference point that aligns future billing cycle dates. It sets the day
|
||||
-- of week for week intervals, the day of month for month and year intervals, and
|
||||
-- the month of year for year intervals. The timestamp is in UTC format."
|
||||
maybe_stripe_billing_cycle_anchor TIMESTAMP DEFAULT NULL,
|
||||
|
||||
maybe_stripe_is_production BOOLEAN DEFAULT NULL,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
@@ -64,6 +76,8 @@ CREATE TABLE user_subscriptions (
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- NB(bt, 2025-09-16): I don't think we write to the soft deleted_at field for user_subscriptions.
|
||||
deleted_at TIMESTAMP DEFAULT NULL,
|
||||
|
||||
-- ========== SUBSCRIPTION TIMESTAMPS ==========
|
||||
@@ -72,7 +86,10 @@ CREATE TABLE user_subscriptions (
|
||||
-- This may predate the Stripe object `created` timestamp due to backdating.
|
||||
subscription_start_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- We'll use this to determine if the subscription is active.
|
||||
-- Our synthetic "expire" date. Moved forward for active subscriptions,
|
||||
-- backdated for canceled subscriptions.
|
||||
--
|
||||
-- TODO: We'll (maybe?) use this to determine if the subscription is active.
|
||||
--
|
||||
-- Always compare against MySQL's clock rather than the app's clock so that we
|
||||
-- don't get weird clock skew behaviors across multiple requests.
|
||||
@@ -82,8 +99,12 @@ CREATE TABLE user_subscriptions (
|
||||
subscription_expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Billing periods.
|
||||
-- Maybe useful for debugging.
|
||||
-- Stripe API: subscription.items[0].data.current_period_start
|
||||
current_billing_period_start_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Stripe API: subscription.items[0].data.current_period_end
|
||||
-- current_period_end is when the subscription renews (or cancels, if the
|
||||
-- subscription is set to cancel).
|
||||
current_billing_period_end_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Subscription cancellation (future and past)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE wallet_ledger_entries (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Which wallet this entry corresponds to.
|
||||
wallet_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The type of ledger entry this is.
|
||||
entry_type VARCHAR(16) NOT NULL,
|
||||
|
||||
-- A record we can look up to attribute the credit or deduction against
|
||||
-- This could be an internal entity token (prompt_token, job token) or an
|
||||
-- external token (stripe event_id, stripe invoice.id, etc.)
|
||||
-- Length is VARCHAR(255) to accommodate Stripe IDs.
|
||||
maybe_entity_ref VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Signed integer that shows the delta of credits for this event.
|
||||
-- This combines impacts to both banked_credits and monthly_credits.
|
||||
-- This is less authoritative than the before/after fields, but is useful
|
||||
credits_delta INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of banked credits before the event.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
banked_credits_before INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of banked credits after the event.
|
||||
banked_credits_after INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of monthly credits before the event.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
monthly_credits_before INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Balance of monthly credits after the event.
|
||||
monthly_credits_after INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== RECORD TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- ========== INDICES ==========
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY index_wallet_token (wallet_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,66 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE wallets (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- If we host multiple sites with distinct categories, this will enable us to
|
||||
-- segregate wallets. This is effectively a wallet namespace.
|
||||
-- NB: Uses the `PaymentsNamespace` enum, which is also shared with subscriptions.
|
||||
wallet_namespace VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Who owns the wallet
|
||||
-- In the future, we might allow other users to use the same wallet,
|
||||
-- but the wallet would still have an owner.
|
||||
-- For now, we'll keep this 1:1 with users, but we may want 1:n in the future.
|
||||
owner_user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The durable credits bucket.
|
||||
-- This bucket is persistent and is refilled by user credit purchases.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
banked_credits INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- The monthly credits bucket.
|
||||
-- This bucket is ephemeral and is refilled monthly.
|
||||
-- Max value unsigned: 4,294,967,295 (U32)
|
||||
monthly_credits INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- Whether the stripe subscription is active.
|
||||
-- subscription_is_active BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether the stripe subscription is paid.
|
||||
-- If the subscription is not paid, we should not allow usage of monthly credits.
|
||||
-- subscription_is_paid BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== RECORD TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- ========== PAYMENTS AND SUBSCRIPTIONS TIMESTAMPS ==========
|
||||
|
||||
-- When the user last purchased banked (durable) credits.
|
||||
-- banked_credits_last_purchased_at TIMESTAMP DEFAULT NULL,
|
||||
|
||||
-- When we last refilled the monthly bucket.
|
||||
-- This has to do with subscription logic.
|
||||
-- monthly_wallet_refilled_at TIMESTAMP DEFAULT NULL,
|
||||
|
||||
-- ========== INDICES ==========
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (wallet_namespace, owner_user_token), -- For now
|
||||
INDEX idx_wallet_namespace (wallet_namespace),
|
||||
INDEX idx_owner_user_token (owner_user_token)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,20 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GetSessionCreditsResponse {
|
||||
pub success: bool,
|
||||
|
||||
/// Any free credits the user might have
|
||||
/// We might support daily free credits.
|
||||
pub free_credits: u64,
|
||||
|
||||
/// Any monthly refilling credits the user might have
|
||||
pub monthly_credits: u64,
|
||||
|
||||
/// Any banked credits the user might have.
|
||||
pub banked_credits: u64,
|
||||
|
||||
/// All the credit amounts added together.
|
||||
pub sum_total_credits: u64,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod get_session_credits;
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const GEMINI_25_FLASH_EDIT_IMAGE_PATH: &str = "/v1/generate/image/edit/gemini_25_flash";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct Gemini25FlashEditImageRequest {
|
||||
/// Idempotency token to prevent duplicate requests.
|
||||
pub uuid_idempotency_token: String,
|
||||
|
||||
/// Text prompt to generate the image from.
|
||||
pub prompt: Option<String>,
|
||||
|
||||
// TODO: OneOf for image_urls or image_media_tokens
|
||||
/// Image media tokens to include in the editing context.
|
||||
pub image_media_tokens: Option<Vec<MediaFileToken>>,
|
||||
|
||||
/// Number of images to generate. Default is one.
|
||||
pub num_images: Option<Gemini25FlashEditImageNumImages>,
|
||||
|
||||
/// Quality of the image to generate. Default is High.
|
||||
pub image_quality: Option<Gemini25FlashEditImageImageQuality>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Gemini25FlashEditImageNumImages {
|
||||
One, // Default
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Gemini25FlashEditImageImageQuality {
|
||||
Auto,
|
||||
Low,
|
||||
Medium,
|
||||
High, // Default
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct Gemini25FlashEditImageResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
pub mod flux_pro_kontext_max_edit_image;
|
||||
pub mod gpt_image_1_edit_image;
|
||||
pub mod gemini_25_flash_edit_image;
|
||||
pub mod qwen_edit_image;
|
||||
pub mod seededit_3_edit_image;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const QWEN_EDIT_IMAGE_PATH: &str = "/v1/generate/image/edit/qwen";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct QwenEditImageRequest {
|
||||
/// Idempotency token to prevent duplicate requests.
|
||||
pub uuid_idempotency_token: String,
|
||||
|
||||
/// The image we're editing.
|
||||
pub image_media_token: MediaFileToken,
|
||||
|
||||
/// Text prompt to generate the image from.
|
||||
pub prompt: Option<String>,
|
||||
|
||||
/// Text prompt to generate the image from.
|
||||
pub negative_prompt: Option<String>,
|
||||
|
||||
/// Acceleration level for image generation.
|
||||
/// Options: 'none', 'regular'. Higher acceleration increases speed.
|
||||
/// 'regular' balances speed and quality. Default value: "none"
|
||||
pub acceleration: Option<QwenEditImageAcceleration>,
|
||||
|
||||
/// Number of images to generate. Default is one.
|
||||
pub num_images: Option<QwenEditImageNumImages>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub enum QwenEditImageAcceleration {
|
||||
None,
|
||||
Regular,
|
||||
High,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum QwenEditImageNumImages {
|
||||
One, // Default
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct QwenEditImageResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const SEEDEDIT_3_EDIT_IMAGE_PATH: &str = "/v1/generate/image/edit/seededit_3";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct SeedEdit3EditImageRequest {
|
||||
/// Idempotency token to prevent duplicate requests.
|
||||
pub uuid_idempotency_token: String,
|
||||
|
||||
/// The image we're editing.
|
||||
pub image_media_token: MediaFileToken,
|
||||
|
||||
/// Text prompt to generate the image from.
|
||||
pub prompt: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct SeedEdit3EditImageResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const GENERATE_SEEDANCE_1_0_PRO_IMAGE_TO_VIDEO_URL_PATH: &str = "/v1/generate/video/seedance_1.0_pro_image_to_video";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GenerateSeedance10ProImageToVideoRequest {
|
||||
/// Idempotency token to prevent duplicate requests.
|
||||
pub uuid_idempotency_token: String,
|
||||
|
||||
/// Source of the image file to convert to video.
|
||||
/// It must be an image.
|
||||
pub media_file_token: Option<MediaFileToken>,
|
||||
|
||||
/// Optional text prompt.
|
||||
pub prompt: Option<String>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
pub resolution: Option<GenerateSeedance10ProResolution>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
pub duration: Option<GenerateSeedance10ProDuration>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateSeedance10ProResolution {
|
||||
FourEightyP,
|
||||
SevenTwentyP,
|
||||
TenEightyP,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateSeedance10ProDuration {
|
||||
ThreeSeconds,
|
||||
FourSeconds,
|
||||
FiveSeconds,
|
||||
SixSeconds,
|
||||
SevenSeconds,
|
||||
EightSeconds,
|
||||
NineSeconds,
|
||||
TenSeconds,
|
||||
ElevenSeconds,
|
||||
TwelveSeconds,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GenerateSeedance10ProImageToVideoResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const GENERATE_VEO_3_FAST_IMAGE_TO_VIDEO_URL_PATH: &str = "/v1/generate/video/veo_3_fast_image_to_video";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GenerateVeo3FastImageToVideoRequest {
|
||||
/// Idempotency token to prevent duplicate requests.
|
||||
pub uuid_idempotency_token: String,
|
||||
|
||||
/// Source of the image file to convert to video.
|
||||
/// It must be an image.
|
||||
pub media_file_token: Option<MediaFileToken>,
|
||||
|
||||
/// Optional text prompt.
|
||||
pub prompt: Option<String>,
|
||||
|
||||
/// Optional: resolution of the generated video.
|
||||
pub resolution: Option<GenerateVeo3FastResolution>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
pub duration: Option<GenerateVeo3FastDuration>,
|
||||
|
||||
/// Optional: Generate an audio track along with the video
|
||||
pub generate_audio: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateVeo3FastResolution {
|
||||
SevenTwentyP, // 720p
|
||||
TenEightyP, // 1080p
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateVeo3FastDuration {
|
||||
EightSeconds,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GenerateVeo3FastImageToVideoResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const GENERATE_VEO_3_IMAGE_TO_VIDEO_URL_PATH: &str = "/v1/generate/video/veo_3_image_to_video";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GenerateVeo3ImageToVideoRequest {
|
||||
/// Idempotency token to prevent duplicate requests.
|
||||
pub uuid_idempotency_token: String,
|
||||
|
||||
/// Source of the image file to convert to video.
|
||||
/// It must be an image.
|
||||
pub media_file_token: Option<MediaFileToken>,
|
||||
|
||||
/// Optional text prompt.
|
||||
pub prompt: Option<String>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
pub aspect_ratio: Option<GenerateVeo3AspectRatio>,
|
||||
|
||||
/// Optional: resolution of the generated video.
|
||||
pub resolution: Option<GenerateVeo3Resolution>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
pub duration: Option<GenerateVeo3Duration>,
|
||||
|
||||
/// Optional: Generate an audio track along with the video
|
||||
pub generate_audio: Option<bool>,
|
||||
|
||||
// /// Optional.
|
||||
// pub enhance_prompt: Option<bool>,
|
||||
// /// Optional. Whether to automatically attempt to fix prompts that fail
|
||||
// /// content policy or other validation checks by rewriting them
|
||||
// /// Default value: true
|
||||
// pub auto_fix: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateVeo3AspectRatio {
|
||||
WideSixteenNine, // 16:9
|
||||
TallNineSixteen, // 9:16
|
||||
Square, // 1:1
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateVeo3Resolution {
|
||||
SevenTwentyP, // 720p
|
||||
TenEightyP, // 1080p
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GenerateVeo3Duration {
|
||||
EightSeconds,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GenerateVeo3ImageToVideoResponse {
|
||||
pub success: bool,
|
||||
pub inference_job_token: InferenceJobToken,
|
||||
}
|
||||
+4
-1
@@ -2,4 +2,7 @@ pub mod generate_kling_1_6_pro_image_to_video;
|
||||
pub mod generate_kling_2_1_master_image_to_video;
|
||||
pub mod generate_kling_2_1_pro_image_to_video;
|
||||
pub mod generate_seedance_1_0_lite_image_to_video;
|
||||
pub mod generate_veo_2_image_to_video;
|
||||
pub mod generate_seedance_1_0_pro_image_to_video;
|
||||
pub mod generate_veo_2_image_to_video;
|
||||
pub mod generate_veo_3_fast_image_to_video;
|
||||
pub mod generate_veo_3_image_to_video;
|
||||
@@ -0,0 +1,8 @@
|
||||
pub mod common;
|
||||
pub mod credits;
|
||||
pub mod generate;
|
||||
pub mod jobs;
|
||||
pub mod media_file;
|
||||
pub mod prompts;
|
||||
pub mod stripe_artcraft;
|
||||
pub mod subscriptions;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
use enums::common::artcraft_credits_pack_slug::ArtcraftCreditsPackSlug;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const CREATE_CREDITS_PACK_CHECKOUT_URL_PATH: &str = "/v1/stripe_artcraft/checkout/credits_pack";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCreateCreditsPackCheckoutRequest {
|
||||
pub credits_pack: Option<ArtcraftCreditsPackSlug>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCreateCreditsPackCheckoutResponse {
|
||||
pub success: bool,
|
||||
pub stripe_checkout_redirect_url: String,
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
use enums::common::artcraft_subscription_slug::ArtcraftSubscriptionSlug;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const CREATE_SUBSCRIPTION_CHECKOUT_URL_PATH: &str = "/v1/stripe_artcraft/checkout/subscription";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCreateSubscriptionCheckoutRequest {
|
||||
/// The (non-Stripe) internal identifier for the product or subscription.
|
||||
/// This will be translated into a Stripe identifier.
|
||||
pub plan: Option<ArtcraftSubscriptionSlug>,
|
||||
|
||||
pub cadence: Option<PlanBillingCadence>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, Copy, Clone)]
|
||||
pub enum PlanBillingCadence {
|
||||
#[serde(rename = "monthly")]
|
||||
Monthly,
|
||||
|
||||
#[serde(rename = "yearly")]
|
||||
Yearly,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCreateSubscriptionCheckoutResponse {
|
||||
pub success: bool,
|
||||
pub stripe_checkout_redirect_url: String,
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const CUSTOMER_PORTAL_CANCEL_PLAN_URL_PATH: &str = "/v1/stripe_artcraft/portal/cancel_plan";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalCancelPlanRequest {
|
||||
// TODO: Not sure if this is needed
|
||||
pub portal_config_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalCancelPlanResponse {
|
||||
pub success: bool,
|
||||
pub stripe_portal_url: String,
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const CUSTOMER_PORTAL_MANAGE_PLAN_URL_PATH: &str = "/v1/stripe_artcraft/portal/manage_plan";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalManagePlanRequest {
|
||||
// TODO: Not sure if this is needed
|
||||
pub portal_config_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalManagePlanResponse {
|
||||
pub success: bool,
|
||||
pub stripe_portal_url: String,
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
use enums::common::artcraft_subscription_slug::ArtcraftSubscriptionSlug;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const CUSTOMER_PORTAL_SWITCH_PLAN_URL_PATH: &str = "/v1/stripe_artcraft/portal/switch_plan";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalSwitchPlanRequest {
|
||||
// TODO: Not sure if this is needed
|
||||
pub portal_config_id: Option<String>,
|
||||
|
||||
/// REQUIRED
|
||||
/// The plan we're switching to.
|
||||
pub plan: Option<ArtcraftSubscriptionSlug>,
|
||||
|
||||
/// REQUIRED
|
||||
/// The cadence for the plan billing.
|
||||
pub cadence: Option<PlanBillingCadenceConfirmation>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, Copy, Clone)]
|
||||
pub enum PlanBillingCadenceConfirmation {
|
||||
#[serde(rename = "monthly")]
|
||||
Monthly,
|
||||
|
||||
#[serde(rename = "yearly")]
|
||||
Yearly,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalSwitchPlanResponse {
|
||||
pub success: bool,
|
||||
pub stripe_portal_url: String,
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const CUSTOMER_PORTAL_UPDATE_PAYMENT_METHOD_URL_PATH: &str = "/v1/stripe_artcraft/portal/update_payment_method";
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalUpdatePaymentMethodRequest {
|
||||
// TODO: Not sure if this is needed
|
||||
pub portal_config_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct StripeArtcraftCustomerPortalUpdatePaymentMethodResponse {
|
||||
pub success: bool,
|
||||
pub stripe_portal_url: String,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
pub mod create_credits_pack_checkout;
|
||||
pub mod create_subscription_checkout;
|
||||
pub mod customer_portal_cancel_plan;
|
||||
pub mod customer_portal_manage_plan;
|
||||
pub mod customer_portal_switch_plan;
|
||||
pub mod customer_portal_update_payment_method;
|
||||
@@ -0,0 +1,37 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::user_subscriptions::UserSubscriptionToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
// TODO: Maybe make "artcraft_subscription" or "fakeyou_subscription" with strongly typed slugs?
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct GetSessionSubscriptionResponse {
|
||||
pub success: bool,
|
||||
|
||||
/// Information about the user's subscription, if any.
|
||||
pub active_subscription: Option<SubscriptionInfo>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct SubscriptionInfo {
|
||||
/// Unique token for the subscription.
|
||||
pub subscription_token: UserSubscriptionToken,
|
||||
|
||||
/// Namespace for the subscription.
|
||||
pub namespace: PaymentsNamespace,
|
||||
|
||||
/// Local key for the subscription.
|
||||
pub product_slug: String,
|
||||
|
||||
/// If the subscription is currently active, this is the next billing date.
|
||||
pub next_bill_at: Option<DateTime<Utc>>,
|
||||
|
||||
/// If the subscription is set to cancel, this is the end date of the subscription.
|
||||
pub subscription_end_at: Option<DateTime<Utc>>,
|
||||
|
||||
///// When the current billing period ends (either
|
||||
///// auto-renew/rebill date or auto-cancel/cancellation date).
|
||||
//pub current_billing_period_end_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod get_session_subscription;
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::gemini_25_flash_image::edit::gemini_25_flash_image_edit;
|
||||
use fal::prelude::fal_ai::gemini_25_flash_image::edit::Gemini25FlashImageEditInput;
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
|
||||
pub struct Gemini25FlashEditArgs<'a, R: IntoUrl> {
|
||||
// Request required
|
||||
pub prompt: &'a str,
|
||||
pub image_urls: Vec<String>,
|
||||
pub num_images: Gemini25FlashEditNumImages,
|
||||
|
||||
// Fulfillment
|
||||
pub webhook_url: R,
|
||||
pub api_key: &'a FalApiKey,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Gemini25FlashEditNumImages {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gemini_25_flash_edit_webhook<R: IntoUrl>(
|
||||
args: Gemini25FlashEditArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
let num_images = match args.num_images {
|
||||
Gemini25FlashEditNumImages::One => 1,
|
||||
Gemini25FlashEditNumImages::Two => 2,
|
||||
Gemini25FlashEditNumImages::Three => 3,
|
||||
Gemini25FlashEditNumImages::Four => 4,
|
||||
};
|
||||
|
||||
let request = Gemini25FlashImageEditInput {
|
||||
prompt: args.prompt.to_string(),
|
||||
image_urls: args.image_urls,
|
||||
// Constants
|
||||
num_images: Some(num_images),
|
||||
output_format: Some("png".to_string()),
|
||||
};
|
||||
|
||||
let result = gemini_25_flash_image_edit(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue_webhook(args.webhook_url)
|
||||
.await;
|
||||
|
||||
result.map_err(|err| classify_fal_error(err))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::webhook::image::edit::enqueue_gemini_25_flash_edit_webhook::{enqueue_gemini_25_flash_edit_webhook, Gemini25FlashEditArgs, Gemini25FlashEditNumImages};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_data::web::image_urls::{GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test() -> AnyhowResult<()> {
|
||||
// XXX: Don't commit secrets!
|
||||
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
|
||||
|
||||
let api_key = FalApiKey::from_str(&secret);
|
||||
|
||||
let args = Gemini25FlashEditArgs {
|
||||
image_urls: vec![
|
||||
GHOST_IMAGE_URL.to_string(),
|
||||
TREX_SKELETON_IMAGE_URL.to_string(),
|
||||
],
|
||||
num_images: Gemini25FlashEditNumImages::Two,
|
||||
prompt: "add the ghost to the image of the t-rex skeleton, make it look spooky but friendly",
|
||||
api_key: &api_key,
|
||||
webhook_url: "https://example.com/webhook",
|
||||
};
|
||||
|
||||
let result = enqueue_gemini_25_flash_edit_webhook(args).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -21,7 +21,7 @@ pub struct GptEditImageByokArgs<'a, V: IntoUrl> {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum GptEditImageSize{
|
||||
pub enum GptEditImageSize {
|
||||
Auto,
|
||||
Square,
|
||||
Horizontal,
|
||||
@@ -92,7 +92,7 @@ pub async fn enqueue_gpt_image_1_edit_image_webhook<V: IntoUrl>(
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use crate::requests::webhook::image::enqueue_gpt_image_1_edit_image_webhook::{enqueue_gpt_image_1_edit_image_webhook, GptEditImageByokArgs, GptEditImageNumImages, GptEditImageQuality, GptEditImageSize};
|
||||
use crate::requests::webhook::image::edit::enqueue_gpt_image_1_edit_image_webhook::{enqueue_gpt_image_1_edit_image_webhook, GptEditImageByokArgs, GptEditImageNumImages, GptEditImageQuality, GptEditImageSize};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_data::web::image_urls::{ERNEST_SCARED_STUPID_IMAGE_URL, GHOST_IMAGE_URL, GRASSY_HILL_TRANSPARENT_IMAGE_URL};
|
||||
+9
@@ -14,6 +14,13 @@ pub struct QwenImageEditArgs<'a, U: IntoUrl, R: IntoUrl> {
|
||||
pub num_images: Option<QwenImageEditNumImages>,
|
||||
pub image_size: Option<QwenImageEditSize>,
|
||||
|
||||
pub negative_prompt: Option<String>,
|
||||
|
||||
/// Acceleration level for image generation.
|
||||
/// Options: 'none', 'regular'. Higher acceleration increases speed.
|
||||
/// 'regular' balances speed and quality. Default value: "none"
|
||||
pub acceleration: Option<String>,
|
||||
|
||||
// Fulfillment
|
||||
pub webhook_url: R,
|
||||
pub api_key: &'a FalApiKey,
|
||||
@@ -109,6 +116,8 @@ mod tests {
|
||||
prompt: "put christmas lights on the tree, add snow to the mountains",
|
||||
num_images: Some(QwenImageEditNumImages::One),
|
||||
image_size: None,
|
||||
negative_prompt: None,
|
||||
acceleration: None,
|
||||
api_key: &api_key,
|
||||
webhook_url: "https://example.com/webhook",
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod enqueue_flux_pro_kontext_max_edit_webhook;
|
||||
pub mod enqueue_gemini_25_flash_edit_webhook;
|
||||
pub mod enqueue_gpt_image_1_edit_image_webhook;
|
||||
pub mod enqueue_qwen_image_edit_webhook;
|
||||
pub mod enqueue_seededit_v3_edit_webhook;
|
||||
@@ -3,7 +3,6 @@ pub mod enqueue_flux_1_dev_text_to_image_webhook;
|
||||
pub mod enqueue_flux_1_schnell_text_to_image_webhook;
|
||||
pub mod enqueue_flux_pro_11_text_to_image_webhook;
|
||||
pub mod enqueue_flux_pro_11_ultra_text_to_image_webhook;
|
||||
pub mod enqueue_gpt_image_1_edit_image_webhook;
|
||||
pub mod enqueue_gpt_image_1_text_to_image_webhook;
|
||||
pub mod infill;
|
||||
pub mod remove_background_rembg_webhook;
|
||||
|
||||
+2
@@ -57,6 +57,8 @@ pub async fn enqueue_seedance_1_lite_image_to_video_webhook<U: IntoUrl, T: IntoU
|
||||
// TODO: Add these later
|
||||
camera_fixed: None,
|
||||
seed: -1,
|
||||
// Static
|
||||
enable_safety_checker: Some(false),
|
||||
};
|
||||
|
||||
let result = image_to_video(request)
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::bytedance::seedance::v1::pro::image_to_video::{seedance_v1_pro_image_to_video, SeedanceImageToVideoProRequest};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
|
||||
pub struct Seedance1ProArgs<'a, U: IntoUrl, V: IntoUrl> {
|
||||
pub image_url: U,
|
||||
pub webhook_url: V,
|
||||
pub prompt: &'a str,
|
||||
pub api_key: &'a FalApiKey,
|
||||
pub camera_fixed: bool,
|
||||
pub duration: Seedance1ProDuration,
|
||||
pub resolution: Seedance1ProResolution,
|
||||
pub seed: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Seedance1ProDuration {
|
||||
ThreeSeconds,
|
||||
FourSeconds,
|
||||
FiveSeconds,
|
||||
SixSeconds,
|
||||
SevenSeconds,
|
||||
EightSeconds,
|
||||
NineSeconds,
|
||||
TenSeconds,
|
||||
ElevenSeconds,
|
||||
TwelveSeconds,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Seedance1ProResolution {
|
||||
FourEightyP, // 480p
|
||||
SevenTwentyP, // 720p
|
||||
TenEightyP, // 1080p
|
||||
}
|
||||
|
||||
pub async fn enqueue_seedance_1_pro_image_to_video_webhook<U: IntoUrl, V: IntoUrl>(
|
||||
args: Seedance1ProArgs<'_, U, V>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
let duration = match args.duration {
|
||||
Seedance1ProDuration::ThreeSeconds => Some("3".to_string()),
|
||||
Seedance1ProDuration::FourSeconds => Some("4".to_string()),
|
||||
Seedance1ProDuration::FiveSeconds => Some("5".to_string()),
|
||||
Seedance1ProDuration::SixSeconds => Some("6".to_string()),
|
||||
Seedance1ProDuration::SevenSeconds => Some("7".to_string()),
|
||||
Seedance1ProDuration::EightSeconds => Some("8".to_string()),
|
||||
Seedance1ProDuration::NineSeconds => Some("9".to_string()),
|
||||
Seedance1ProDuration::TenSeconds => Some("10".to_string()),
|
||||
Seedance1ProDuration::ElevenSeconds => Some("11".to_string()),
|
||||
Seedance1ProDuration::TwelveSeconds => Some("12".to_string()),
|
||||
};
|
||||
|
||||
let resolution = match args.resolution {
|
||||
Seedance1ProResolution::FourEightyP => Some("480p".to_string()),
|
||||
Seedance1ProResolution::SevenTwentyP => Some("720p".to_string()),
|
||||
Seedance1ProResolution::TenEightyP => Some("1080p".to_string()),
|
||||
};
|
||||
|
||||
let image_url = args.image_url.as_str().to_string();
|
||||
|
||||
let request = SeedanceImageToVideoProRequest {
|
||||
image_url,
|
||||
prompt: args.prompt.to_string(),
|
||||
duration,
|
||||
resolution,
|
||||
// TODO: Add these later
|
||||
camera_fixed: None,
|
||||
// Static
|
||||
enable_safety_checker: Some(false),
|
||||
};
|
||||
|
||||
let result = seedance_v1_pro_image_to_video(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue_webhook(args.webhook_url)
|
||||
.await;
|
||||
|
||||
result.map_err(|err| classify_fal_error(err))
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::webhook::video::enqueue_seedance_1_pro_image_to_video_webhook::{enqueue_seedance_1_pro_image_to_video_webhook, Seedance1ProArgs, Seedance1ProDuration, Seedance1ProResolution};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_data::web::image_urls::TALL_MOCHI_WITH_GLASSES_IMAGE_URL;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test() -> AnyhowResult<()> {
|
||||
// XXX: Don't commit secrets!
|
||||
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
|
||||
|
||||
let api_key = FalApiKey::from_str(&secret);
|
||||
|
||||
let args = Seedance1ProArgs {
|
||||
image_url: TALL_MOCHI_WITH_GLASSES_IMAGE_URL,
|
||||
prompt: "shiba in glasses runs to the lake and stands by the shore",
|
||||
api_key: &api_key,
|
||||
camera_fixed: false,
|
||||
duration: Seedance1ProDuration::FiveSeconds,
|
||||
resolution: Seedance1ProResolution::SevenTwentyP,
|
||||
seed: None,
|
||||
webhook_url: "https://example.com/webhook",
|
||||
};
|
||||
|
||||
let result = enqueue_seedance_1_pro_image_to_video_webhook(args).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+25
-9
@@ -6,12 +6,13 @@ use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
|
||||
pub struct Veo3Args<'a, U: IntoUrl, V: IntoUrl> {
|
||||
pub prompt: &'a str,
|
||||
pub image_url: U,
|
||||
pub prompt: &'a str,
|
||||
pub duration: Veo3Duration,
|
||||
pub api_key: &'a FalApiKey,
|
||||
pub aspect_ratio: Veo3AspectRatio,
|
||||
pub resolution: Veo3Resolution,
|
||||
pub generate_audio: bool,
|
||||
pub api_key: &'a FalApiKey,
|
||||
pub webhook_url: V,
|
||||
}
|
||||
|
||||
@@ -21,6 +22,14 @@ pub enum Veo3Duration {
|
||||
EightSeconds,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Veo3AspectRatio {
|
||||
Default,
|
||||
WideSixteenNine,
|
||||
TallNineSixteen,
|
||||
Square,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Veo3Resolution {
|
||||
Default,
|
||||
@@ -35,6 +44,13 @@ pub async fn enqueue_veo_3_image_to_video_webhook<U: IntoUrl, V: IntoUrl>(
|
||||
Veo3Duration::Default => None,
|
||||
Veo3Duration::EightSeconds => Some("8s".to_string()),
|
||||
};
|
||||
|
||||
let aspect_ratio = match args.aspect_ratio {
|
||||
Veo3AspectRatio::Default => None,
|
||||
Veo3AspectRatio::WideSixteenNine => Some("16:9".to_string()),
|
||||
Veo3AspectRatio::TallNineSixteen => Some("9:16".to_string()),
|
||||
Veo3AspectRatio::Square => Some("1:1".to_string()),
|
||||
};
|
||||
|
||||
let resolution= match args.resolution {
|
||||
Veo3Resolution::Default => None,
|
||||
@@ -47,6 +63,7 @@ pub async fn enqueue_veo_3_image_to_video_webhook<U: IntoUrl, V: IntoUrl>(
|
||||
let request = ImageToVideoInput {
|
||||
image_url,
|
||||
prompt: args.prompt.to_string(),
|
||||
aspect_ratio,
|
||||
resolution,
|
||||
duration,
|
||||
generate_audio: Some(args.generate_audio),
|
||||
@@ -64,28 +81,27 @@ pub async fn enqueue_veo_3_image_to_video_webhook<U: IntoUrl, V: IntoUrl>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::webhook::video::enqueue_veo_3_image_to_video_webhook::{enqueue_veo_3_image_to_video_webhook, Veo3Args, Veo3Duration, Veo3Resolution};
|
||||
use crate::requests::webhook::video::enqueue_veo_3_image_to_video_webhook::{enqueue_veo_3_image_to_video_webhook, Veo3Args, Veo3AspectRatio, Veo3Duration, Veo3Resolution};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_data::web::image_urls::JUNO_AT_LAKE_IMAGE_URL;
|
||||
use test_data::web::image_urls::{JUNO_AT_LAKE_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test() -> AnyhowResult<()> {
|
||||
let image_url = JUNO_AT_LAKE_IMAGE_URL;
|
||||
|
||||
// XXX: Don't commit secrets!
|
||||
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
|
||||
|
||||
let api_key = FalApiKey::from_str(&secret);
|
||||
|
||||
let args = Veo3Args {
|
||||
image_url: image_url,
|
||||
prompt: "corgi at the lake. the corgi barks. camera pulls back to show a wider shot of the lake as the corgi jumps into the water. there are sounds of barking and splashing. cinematic, 8k, ultra wide shot",
|
||||
image_url: TREX_SKELETON_IMAGE_URL,
|
||||
prompt: "the t-rex skeleton starts walking towards the camera and roars",
|
||||
api_key: &api_key,
|
||||
duration: Veo3Duration::EightSeconds,
|
||||
generate_audio: true,
|
||||
aspect_ratio: Veo3AspectRatio::WideSixteenNine,
|
||||
resolution: Veo3Resolution::TenEightyP,
|
||||
generate_audio: true,
|
||||
webhook_url: "https://example.com/webhook",
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user