diff --git a/Cargo.toml b/Cargo.toml index 24304ccc1d..79f721fcf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,9 +72,6 @@ members = [ #"crates/lib/api_clients/fakeyou_client", #"crates/lib/sqlite_queries", - # Programs: Desktop apps - #"crates/programs/aichatbot-sidecar", - # Services: API servers, jobs, workers, etc. "crates/service/job/analytics_job", "crates/service/job/download_job", diff --git a/_sql/migrations_todo/2022-03-14-035745_twitch_event_match_logs/down.sql b/_sql/migrations_todo/2022-03-14-035745_twitch_event_match_logs/down.sql deleted file mode 100644 index ff2b203e89..0000000000 --- a/_sql/migrations_todo/2022-03-14-035745_twitch_event_match_logs/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE twitch_event_match_logs; diff --git a/_sql/migrations_todo/2022-03-14-035745_twitch_event_match_logs/up.sql b/_sql/migrations_todo/2022-03-14-035745_twitch_event_match_logs/up.sql deleted file mode 100644 index 25e4fee799..0000000000 --- a/_sql/migrations_todo/2022-03-14-035745_twitch_event_match_logs/up.sql +++ /dev/null @@ -1,23 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - --- Log any event matching (bits, channel points, etc.) -CREATE TABLE twitch_event_match_logs( - -- Not used for anything except replication. - id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, - - token VARCHAR(32) NOT NULL, - - -- Type of event, eg. - event_type VARCHAR(32) NOT NULL, - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted_at TIMESTAMP DEFAULT NULL, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; diff --git a/_sql/migrations_todo/2022-08-23-140455_credits/down.sql b/_sql/migrations_todo/2022-08-23-140455_credits/down.sql deleted file mode 100644 index 283831e5e7..0000000000 --- a/_sql/migrations_todo/2022-08-23-140455_credits/down.sql +++ /dev/null @@ -1,9 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE paypal_payment_events; -DROP TABLE stripe_payment_events; -DROP TABLE credit_spend_events; -DROP TABLE credit_refill_events; -DROP TABLE credit_balances; diff --git a/_sql/migrations_todo/2022-08-23-140455_credits/up.sql b/_sql/migrations_todo/2022-08-23-140455_credits/up.sql deleted file mode 100644 index 80a4389fc3..0000000000 --- a/_sql/migrations_todo/2022-08-23-140455_credits/up.sql +++ /dev/null @@ -1,253 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - --- Current credit balances -CREATE TABLE credit_balances ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- The type of credit - -- Each credit type is its own logical "bucket" that cannot be mixed with the other types. - -- eg. "image_generation" - -- We'll have a composite unique key on this, so there can only be one balance per user per type. - credit_type VARCHAR(32) NOT NULL, - - -- Foreign key to user - -- We'll have a composite unique key on this, so there can only be one balance per user per type. - user_token VARCHAR(32) NOT NULL, - - -- ========== BALANCE INFO ========== - - -- The credit balance - -- (for the user within this credit_type bucket) - -- Maximum value signed: 4,294,967,295 - balance INT UNSIGNED NOT NULL DEFAULT 0, - - -- ========== VECTOR CLOCK ========== - - -- Vector clock incremented on update - version INT UNSIGNED NOT NULL DEFAULT 0, - - -- ========== TIMESTAMPS ========== - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - last_refilled_at TIMESTAMP DEFAULT NULL, - last_spent_at TIMESTAMP DEFAULT NULL, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (credit_type, user_token), - KEY index_credit_type (credit_type), - KEY fk_user_token (user_token) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - - --- Record of credit refill (eg. purchase) events, some of which may be free --- At time of record creation, these are considered "already processed" and reflected in the "user_balances" table. --- For all intents and purposes, this is just a historical ledger of changes to active balance. -CREATE TABLE credit_refill_events ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" - token VARCHAR(32) NOT NULL, - - -- The type of credit - -- Each credit type is its own logical "bucket" that cannot be mixed with the other types. - -- eg. "image_generation" - credit_type VARCHAR(32) NOT NULL, - - -- Foreign key to user (not unique!) - user_token VARCHAR(32) NOT NULL, - - -- ========== REFILL INFO ========== - - -- If we filled the balance for free, this will be set to true. - -- These may be rewards for users, subscriptions that refill buckets, etc. - is_free_event BOOL NOT NULL DEFAULT false, - - -- Added funds - -- Maximum value signed: 4,294,967,295 - amount_added INT UNSIGNED NOT NULL DEFAULT 0, - - -- What the balance should be after the funds are added - -- This is not the source of truth and is only used for debugging. - balance_after_added INT UNSIGNED NOT NULL DEFAULT 0, - - -- Where the balance increase came from. - -- eg. "stripe", "paypal", "coinbase", "free", etc. - funds_source VARCHAR(32) NOT NULL, - - -- ========== ABUSE TRACKING ========== - - -- For abuse tracking. - -- Wide enough for IPv4/6 - maybe_creator_ip_address VARCHAR(40) DEFAULT NULL, - - -- ========== TIMESTAMPS ========== - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token), - KEY index_credit_type_and_user_token (credit_type, user_token), - KEY index_credit_type (credit_type), - KEY fk_user_token (user_token) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - - --- Record of credit use events (some of which may be zero-credit "free" uses) --- At time of record creation, these are considered "already processed" and reflected in the "user_balances" table. --- For all intents and purposes, this is just a historical ledger of changes to active balance. -CREATE TABLE credit_spend_events ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" - token VARCHAR(32) NOT NULL, - - -- The type of credit. - -- Each credit type is its own logical "bucket" that cannot be mixed with the other types. - -- eg. "image_generation" - credit_type VARCHAR(32) NOT NULL, - - -- Foreign key to user (not unique!) - user_token VARCHAR(32) NOT NULL, - - -- ========== SPEND INFO ========== - - -- If we processed the transaction for free, this will be set to true. - -- These may be rewards for users, subscriptions that refill, etc. - is_free_event BOOL NOT NULL DEFAULT false, - - -- Subtracted funds - -- Maximum value signed: 4,294,967,295 - amount_subtracted INT UNSIGNED NOT NULL DEFAULT 0, - - -- What the balance should be after the funds are subtracted - -- This is not the source of truth and is only used for debugging. - balance_after_subtracted INT UNSIGNED NOT NULL DEFAULT 0, - - -- Where the funds were spent. Typically 1:1 with "credit_type". - -- eg. "stable_diffusion", "voice_commission", etc. - spent_on VARCHAR(32) NOT NULL, - - -- If we can link it to whatever was purchased, do so. - -- If it was a job run, it's set here. - maybe_spent_on_job_token VARCHAR(32) DEFAULT NULL, - - -- If we can link it to whatever was purchased, do so. - -- We may not have the entity token if the workload was async, but we can update this record later. - maybe_spent_on_entity_token VARCHAR(32) DEFAULT NULL, - - -- ========== ABUSE TRACKING ========== - - -- For abuse tracking. - -- Wide enough for IPv4/6 - maybe_creator_ip_address VARCHAR(40) DEFAULT NULL, - - -- ========== TIMESTAMPS ========== - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token), - KEY index_credit_type_and_user_token (credit_type, user_token), - KEY index_credit_type (credit_type), - KEY fk_user_token (user_token), - KEY fk_maybe_spent_on_job_token (maybe_spent_on_job_token), - KEY fk_maybe_spent_on_entity_token (maybe_spent_on_entity_token) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - - --- Stripe payments -CREATE TABLE stripe_payment_events ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" - token VARCHAR(32) NOT NULL, - - -- Foreign key to user (not unique!) - user_token VARCHAR(32) NOT NULL, - - -- ========== PAYMENT INFO ========== - - -- Potentially an internal event token (eg. if this goes to a balance, not a subscription) - maybe_balance_refill_event_token VARCHAR(32) NOT NULL, - - -- The stripe payment ID - maybe_payment_id VARCHAR(64) NOT NULL, - - -- The stripe customer ID - maybe_customer_id VARCHAR(64) NOT NULL, - - -- ========== ABUSE TRACKING ========== - - -- For abuse tracking. - -- Wide enough for IPv4/6 - maybe_creator_ip_address VARCHAR(40) DEFAULT NULL, - - -- ========== TIMESTAMPS ========== - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token), - KEY fk_user_token (user_token), - KEY fk_maybe_balance_refill_event_token (maybe_balance_refill_event_token) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - --- Paypal payments -CREATE TABLE paypal_payment_events ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" - token VARCHAR(32) NOT NULL, - - -- Foreign key to user (not unique!) - user_token VARCHAR(32) NOT NULL, - - -- ========== PAYMENT INFO ========== - - -- Potentially an internal event token (eg. if this goes to a balance, not a subscription) - maybe_balance_refill_event_token VARCHAR(32) NOT NULL, - - -- The paypal payment ID - maybe_payment_id VARCHAR(64) NOT NULL, - - -- The paypal customer ID - maybe_customer_id VARCHAR(64) NOT NULL, - - -- ========== ABUSE TRACKING ========== - - -- For abuse tracking. - -- Wide enough for IPv4/6 - maybe_creator_ip_address VARCHAR(40) DEFAULT NULL, - - -- ========== TIMESTAMPS ========== - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token), - KEY fk_user_token (user_token), - KEY fk_maybe_balance_refill_event_token (maybe_balance_refill_event_token) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; diff --git a/_sql/migrations_todo/2022-08-23-140535_generic_workloads/down.sql b/_sql/migrations_todo/2022-08-23-140535_generic_workloads/down.sql deleted file mode 100644 index 4125aef7b1..0000000000 --- a/_sql/migrations_todo/2022-08-23-140535_generic_workloads/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE generic_workloads; diff --git a/_sql/migrations_todo/2022-08-23-140535_generic_workloads/up.sql b/_sql/migrations_todo/2022-08-23-140535_generic_workloads/up.sql deleted file mode 100644 index b34fb831bc..0000000000 --- a/_sql/migrations_todo/2022-08-23-140535_generic_workloads/up.sql +++ /dev/null @@ -1,108 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -CREATE TABLE generic_workloads ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" (PUBLIC) - -- This is so the in-progress results can be looked up by the UI. - token VARCHAR(32) NOT NULL, - - -- Idempotency token - -- This is so the frontend client doesn't submit duplicate jobs. - uuid_idempotency_token VARCHAR(36) NOT NULL, - - -- ========== SUCCESS CASE ========== - - -- If the job completes successfully, this is the result token. - -- This is only populated on a successful result. - on_success_finished_entity_token VARCHAR(32) DEFAULT NULL, - - -- The type of the object will vary based on the type of the workload, - -- and we may include heuristics that auto-detect types in the future - on_success_finished_entity_type VARCHAR(32) DEFAULT NULL, - - -- ========== WORKLOAD DETAILS ========== - - -- A "well defined" type of workload - -- The first workload type will be "image_generation_request" - workload_type VARCHAR(32) NOT NULL, - - -- JSON serialized details about the workload - -- The schema varies and is controlled by the "workload_type" - -- TEXT – 64KB (65,535 characters); TEXT also requires 2 bytes overhead. - workload_details TEXT, - - -- ========== CREATOR DETAILS AND PREFERENCES ========== - - -- Foreign key to user - maybe_creator_user_token VARCHAR(32) DEFAULT NULL, - - -- Based on a cookie sent by the frontend. - -- We'll save this even if the user is logged in. - maybe_creator_anonymous_visitor_token VARCHAR(32) DEFAULT NULL, - - -- For abuse tracking. - -- Wide enough for IPv4/6 - creator_ip_address VARCHAR(40) NOT NULL, - - -- The creator can set a desired visibility for their data. - -- This does not always apply to every workload type. - -- Additionally, some workload types may require moderator approval prior - -- to being publicly listed, and this field has no bearing on that. - -- NB: DO NOT CHANGE THE ORDER OF THE ENUM VALUES DURING SCHEMA MIGRATIONS. - creator_set_visibility ENUM( - 'public', - 'hidden', - 'private' - ) NOT NULL DEFAULT 'public', - - -- ========== JOB SYSTEM DETAILS ========== - - -- Jobs begin as "pending", then transition to other states. - -- - -- * Pending = job is ready to go - -- * Started = job is running - -- * Complete_Success = job is done (success) - -- * Complete_Failure = job is done (failure) - -- * Attempt_Failed = job failed but may retry. - -- * Dead = job failed permanently. - -- - -- Pending -> Started -> Complete_Success - -- |-> Complete_Failure - -- \-> Attempt_Failed -> Started -> { Complete, Failed, Dead } - status ENUM( - 'pending', - 'started', - 'complete_success', - 'complete_failure', - 'attempt_failed', - 'dead') NOT NULL DEFAULT 'pending', - - -- We can track this against a "max_attempt_count" - attempt_count INT(3) NOT NULL DEFAULT 0, - - -- If there is a failure, tell the user why. - failure_reason VARCHAR(512) DEFAULT NULL, - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- Failed jobs will set a next attempt time. - -- Subsequent tries can increase the timeout. - -- Failures because of permissions require human intervention => [retry_at=null]. - -- Failures because of invalid files are dead => [status=dead]. - retry_at TIMESTAMP NULL, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token), - UNIQUE KEY (uuid_idempotency_token), - KEY index_on_workload_type (workload_type), - KEY fk_maybe_creator_user_token (maybe_creator_user_token), - KEY index_status (status), - KEY index_creator_ip_address (creator_ip_address) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; diff --git a/_sql/migrations_todo/2022-08-23-140631_generated_images/down.sql b/_sql/migrations_todo/2022-08-23-140631_generated_images/down.sql deleted file mode 100644 index 3c2304d721..0000000000 --- a/_sql/migrations_todo/2022-08-23-140631_generated_images/down.sql +++ /dev/null @@ -1,7 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE generated_images; -DROP TABLE generated_image_batches; -DROP TABLE generated_image_request_logs; diff --git a/_sql/migrations_todo/2022-08-23-140631_generated_images/up.sql b/_sql/migrations_todo/2022-08-23-140631_generated_images/up.sql deleted file mode 100644 index 74d883ec53..0000000000 --- a/_sql/migrations_todo/2022-08-23-140631_generated_images/up.sql +++ /dev/null @@ -1,111 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - --- Sometimes we'll block image generation requests. --- This is a log of *everything* that gets sent to us so that we can track abuse --- of the system and identify bad actors. -CREATE TABLE generated_image_request_logs( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" (PUBLIC) - -- This is so the in-progress results can be looked up by the UI. - token VARCHAR(32) NOT NULL, - - -- ========== REQUEST DETAILS ========== - - -- The text prompt - text_prompt VARCHAR(512) DEFAULT NULL, - - -- If the request consumed credits - request_was_paid BOOL NOT NULL DEFAULT false, - - -- If we determined the request was NSFW - request_was_nsfw BOOL NOT NULL DEFAULT false, - - -- If we determined we should block the request upfront - request_was_blocked BOOL NOT NULL DEFAULT false, - - -- ========== CREATOR DETAILS ========== - - -- Foreign key to user - -- If no user is logged in, this is null. - maybe_creator_user_token VARCHAR(32) DEFAULT NULL, - - -- Based on a cookie sent by the frontend. - -- We'll save this even if the user is logged in. - maybe_creator_anonymous_visitor_token VARCHAR(32) DEFAULT NULL, - - -- For abuse tracking. - -- Wide enough for IPv4/6 - creator_ip_address VARCHAR(40) NOT NULL, - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - --- Each image generation request will produce multiple images. --- This is the parent record for multiple images. -CREATE TABLE generated_image_batches ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" (PUBLIC) - -- This is so the in-progress results can be looked up by the UI. - token VARCHAR(32) NOT NULL, - - -- ========== CREATOR DETAILS ========== - - -- Foreign key to user - -- If no user is logged in, this is null. - maybe_creator_user_token VARCHAR(32) DEFAULT NULL, - - -- Based on a cookie sent by the frontend. - -- We'll save this even if the user is logged in. - maybe_creator_anonymous_visitor_token VARCHAR(32) DEFAULT NULL, - - -- For abuse tracking. - -- Wide enough for IPv4/6 - creator_ip_address VARCHAR(40) NOT NULL, - - -- (THIS MIGHT NOT BE USED) - -- NB: DO NOT SORT! - -- THIS MUST MATCH THE RESPECTIVE JOBS TABLE. - creator_set_visibility ENUM( - 'public', - 'hidden', - 'private' - ) NOT NULL DEFAULT 'public', - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - --- This is the child record for single images within a generated batch -CREATE TABLE generated_images ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" (PUBLIC) - -- This is so the in-progress results can be looked up by the UI. - token VARCHAR(32) NOT NULL, - - -- Reference to the batch this image belongs to. - batch_token VARCHAR(32) NOT NULL, - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; diff --git a/_sql/migrations_todo/2023-03-16-121816_voice_survey_answers/down.sql b/_sql/migrations_todo/2023-03-16-121816_voice_survey_answers/down.sql deleted file mode 100644 index 167231c6d0..0000000000 --- a/_sql/migrations_todo/2023-03-16-121816_voice_survey_answers/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE voice_survey_answers; diff --git a/_sql/migrations_todo/2023-03-16-121816_voice_survey_answers/up.sql b/_sql/migrations_todo/2023-03-16-121816_voice_survey_answers/up.sql deleted file mode 100644 index 8d3faf6ad3..0000000000 --- a/_sql/migrations_todo/2023-03-16-121816_voice_survey_answers/up.sql +++ /dev/null @@ -1,53 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - --- Voice survey answers -CREATE TABLE voice_survey_answers ( - -- Not used for anything except replication. - id BIGINT(20) NOT NULL AUTO_INCREMENT, - - -- Effective "primary key" (PUBLIC) - token VARCHAR(32) NOT NULL, - - -- Idempotency token from client - -- This is so the frontend client doesn't submit duplicate items. - uuid_idempotency_token VARCHAR(36) NOT NULL, - - -- User making the comment - maybe_user_token VARCHAR(32) DEFAULT NULL, - - -- The voice that is being requested - voice_name VARCHAR(128) NOT NULL, - - -- If the person would pay for FakeYou premium - would_pay BOOLEAN NOT NULL DEFAULT FALSE, - - -- How much the user would hypothetically pay per month - would_pay_amount DOUBLE DEFAULT NULL, - - -- For abuse tracking. - -- Wide enough for IPv4/6 - creator_ip_address VARCHAR(40) NOT NULL, - - -- ========== VECTOR CLOCK ========== - - -- Incremented with every update. - version INT NOT NULL DEFAULT 0, - - -- ========== TIMESTAMPS ========== - - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - -- INDICES -- - PRIMARY KEY (id), - UNIQUE KEY (token), - UNIQUE KEY (uuid_idempotency_token), - KEY index_maybe_user_token (maybe_user_token), - KEY index_voice_name (voice_name), - KEY index_would_pay (would_pay), - KEY index_would_pay_amount (would_pay_amount), - KEY index_created_at (created_at) - -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; diff --git a/assets/fonts/FiraSans-Bold.ttf b/assets/fonts/FiraSans-Bold.ttf deleted file mode 100644 index e3593fb0f3..0000000000 Binary files a/assets/fonts/FiraSans-Bold.ttf and /dev/null differ diff --git a/assets/fonts/FiraSans-Light.ttf b/assets/fonts/FiraSans-Light.ttf deleted file mode 100644 index 663d1de502..0000000000 Binary files a/assets/fonts/FiraSans-Light.ttf and /dev/null differ diff --git a/assets/fonts/FiraSans-OFL.txt b/assets/fonts/FiraSans-OFL.txt deleted file mode 100644 index 53aea66cac..0000000000 --- a/assets/fonts/FiraSans-OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/fonts/FiraSans-Regular.ttf b/assets/fonts/FiraSans-Regular.ttf deleted file mode 100644 index 6f80647494..0000000000 Binary files a/assets/fonts/FiraSans-Regular.ttf and /dev/null differ diff --git a/assets/seed/alice.wav b/assets/seed/alice.wav deleted file mode 100644 index 3389f24c51..0000000000 Binary files a/assets/seed/alice.wav and /dev/null differ diff --git a/assets/seed/biden.wav b/assets/seed/biden.wav deleted file mode 100644 index e3f3b1a9e9..0000000000 Binary files a/assets/seed/biden.wav and /dev/null differ diff --git a/assets/seed/goku.wav b/assets/seed/goku.wav deleted file mode 100644 index e0b35227af..0000000000 Binary files a/assets/seed/goku.wav and /dev/null differ diff --git a/assets/seed/hilary.wav b/assets/seed/hilary.wav deleted file mode 100644 index 096dcbaa52..0000000000 Binary files a/assets/seed/hilary.wav and /dev/null differ diff --git a/assets/seed/obama.wav b/assets/seed/obama.wav deleted file mode 100644 index 07f1651b76..0000000000 Binary files a/assets/seed/obama.wav and /dev/null differ diff --git a/assets/seed/trump.wav b/assets/seed/trump.wav deleted file mode 100644 index 3b43c4d1e5..0000000000 Binary files a/assets/seed/trump.wav and /dev/null differ diff --git a/assets/seed/trump_problem.wav b/assets/seed/trump_problem.wav deleted file mode 100644 index 3b43c4d1e5..0000000000 Binary files a/assets/seed/trump_problem.wav and /dev/null differ diff --git a/assets/seed/vocodes2.wav b/assets/seed/vocodes2.wav deleted file mode 100644 index f7acca5213..0000000000 Binary files a/assets/seed/vocodes2.wav and /dev/null differ diff --git a/crates/programs/aichatbot-sidecar/.env b/crates/programs/aichatbot-sidecar/.env deleted file mode 100644 index a435c0ccf1..0000000000 --- a/crates/programs/aichatbot-sidecar/.env +++ /dev/null @@ -1,3 +0,0 @@ -# This is only set to run database migrations on Windows -DATABASE_URL=sqlite://../../../runtime_data/database.db - diff --git a/crates/programs/aichatbot-sidecar/Cargo.toml b/crates/programs/aichatbot-sidecar/Cargo.toml deleted file mode 100644 index 6eea1f30e4..0000000000 --- a/crates/programs/aichatbot-sidecar/Cargo.toml +++ /dev/null @@ -1,76 +0,0 @@ -[package] -name = "aichatbot-sidecar" -publish = false -edition = "2021" -version = "0.0.1" -authors = [ - "Brandon Thomas ", - "Brandon Thomas ", -] - -[[bin]] -name = "aichatbot-sidecar" -path = "src/main.rs" - -[dependencies] - -# Internal -actix_helpers = { path = "../../lib/actix_helpers" } -concurrency = { path = "../../lib/concurrency" } -easyenv = { path = "../../lib/easyenv" } -enums = { path = "../../_types/enums" } -errors = { path = "../../lib/errors" } -fakeyou_client = { path = "../../lib/api_clients/fakeyou_client" } -filesys = { path = "../../lib/files/filesys" } -hashing = { path = "../../lib/files/hashing" } -http_server_common = { path = "../../lib/deprecated/http_server_common" } -idempotency = { path = "../../lib/idempotency" } -media = { path = "../../lib/files/media" } -sqlite_queries = { path = "../../lib/sqlite_queries" } -tokens = { path = "../../_types/tokens" } -web_scrapers = { path = "../../lib/web_scrapers" } - -# External -base64 = "0.21.0" -chrono = { version = "0.4.22", features = ["serde"] } -clap = "2.34.0" # TODO: This is really out of date, but has conflicts when updated -dotenv = "0.15.0" -log = "0.4.14" -once_cell = "1.9.0" -path-absolutize = "3.0.14" # Absolute paths have not stabilized in Rust yet -rand = "0.8.3" -regex = "1.5.4" -strum = { version = "0.24", features = ["derive"] } # Fancy enum iteration, etc. - -sqlx = { version = "0.7.2", features = [ "sqlite", "runtime-tokio-native-tls", "chrono" ] } - -# Async Runtime -tokio = { version = "1.6.0", features = ["macros"] } - -# Content downloads -reqwest = { version = "0.11", features = ["json"] } # HTTP Client -rss = "2.0.2" - -# Webserver -actix-cors = "0.6.0-beta.3" -actix-files= "0.6.0-beta.8" -actix-http = "3.0.0-beta.11" -actix-multipart = "0.4.0-beta.7" -actix-rt = "2.4.0" -actix-service = "2.0.1" -actix-utils = "3.0.0" -actix-web = "4.0.0-beta.10" -actix-web-actors = "4.0.0-beta.7" - -# Serialization -serde = "1.0.125" -serde_derive = "1.0.125" -serde_json = "1.0.64" -serde_yaml = "0.9.1" - -# Gui (Egui) -eframe = "0.20.1" -egui = "0.20.1" - -# API integrations -async-openai = "0.6.0" diff --git a/crates/programs/aichatbot-sidecar/README.md b/crates/programs/aichatbot-sidecar/README.md deleted file mode 100644 index 75ba5021af..0000000000 --- a/crates/programs/aichatbot-sidecar/README.md +++ /dev/null @@ -1,54 +0,0 @@ -aichatbot-sidecar (Sidecar companion to AiChatBot) -================= - -This is the first app that doesn't run as a part of our SoA API architecture. (Though it is written such that we -could port it.) This app is responsible for generating all the content that goes into our streaming AI-powered TV -programs. - -### Installation on Windows - -The application uses sqlite, which is tricky to install on Windows. - -1. Put together an sqlite build directory containing the sources and dll file. One is checked in under this monorepo - in `./windows/sqlite` at the time of this writing, though that may change in the future. - - -2. Add environment variables for the sqlite build directory (see https://github.com/diesel-rs/diesel/issues/487) - - * PATH (append the sqlite build directory to the end) - * SQLITE3_LIB_DIR (a new environment variable; set it to the sqllite build path) - - -3. Build the `sqlite3.lib` file with the following: - - ``` - lib /def:sqlite3.def /out:sqlite3.lib /MACHINE:amd64 - ``` - - This must be done in "Developer Command Prompt for VS 2022" (or similar), not `cmd` or `PowerShell`. - - -4. Run the diesel_cli tool build - ``` - cargo install diesel_cli --no-default-features --features sqlite - ``` - - If it still complains about the `sqlite3.lib` file not being found, be sure to double check that `echo %PATH%` shows - the updated PATH from the steps above. - - -### Installation on Linux - -The egui/eframe libraries require the installation of a metric ton of dependencies, so have at it: - -``` -sudo apt-get install \ - cmake \ - libfontconfig1-dev \ - libspeechd-dev \ - libssl-dev \ - libxcb-render0-dev \ - libxcb-shape0-dev \ - libxcb-xfixes0-dev \ - libxkbcommon-dev -``` \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/.gitkeep b/crates/programs/aichatbot-sidecar/_sql/migrations/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-05-064307_web_scraping_targets/down.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-05-064307_web_scraping_targets/down.sql deleted file mode 100644 index 3b89303c90..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-05-064307_web_scraping_targets/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE web_scraping_targets; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-05-064307_web_scraping_targets/up.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-05-064307_web_scraping_targets/up.sql deleted file mode 100644 index 76c4b662b2..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-05-064307_web_scraping_targets/up.sql +++ /dev/null @@ -1,43 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - --- NB: These tables are designed for sqlite, not MySQL! - -CREATE TABLE web_scraping_targets ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - - -- Canonical URLs help us avoid aliases of the same content. - -- We'll need to figure this out for each site. - canonical_url TEXT NOT NULL UNIQUE, - - -- Effectively an enum-like: CnnArticle, SlashdotArticle, HackerNewsThread, etc. - web_content_type TEXT NOT NULL, - - -- Optional title of the target, which might help downstream. - maybe_title TEXT, - - -- A full image will only be set at this stage if the RSS feed or HTML specifies one. - -- This can be useful downstream during the actual scraping. - maybe_article_full_image_url TEXT, - - -- A thumbnail will only be set at this stage if the RSS feed or HTML specifies one. - -- This can be useful downstream during the actual scraping. - maybe_article_thumbnail_image_url TEXT, - - -- If we skip the target (a priori or after scraping), this is why. - -- Enum-like value, eg. "predominantly_video", "empty", "filtered_topic", "nobody_cares", etc. - maybe_skip_reason TEXT, - - -- Scraping status: "new", "failed", "permanently_failed", "success", "skipped" - scraping_status TEXT DEFAULT "new" NOT NULL, - scrape_attempts INT DEFAULT 0 NOT NULL, - - created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - -- fetched_at DATETIME DEFAULT NULL, - - version INT DEFAULT 0 NOT NULL -); - -CREATE INDEX index_scraping_status ON web_scraping_targets(scraping_status); diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-10-073239_tts_render_tasks/down.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-10-073239_tts_render_tasks/down.sql deleted file mode 100644 index e24ccc6a2d..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-10-073239_tts_render_tasks/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE tts_render_tasks; diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-10-073239_tts_render_tasks/up.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-10-073239_tts_render_tasks/up.sql deleted file mode 100644 index c98701ebea..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-10-073239_tts_render_tasks/up.sql +++ /dev/null @@ -1,67 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - --- NB: These tables are designed for sqlite, not MySQL! - -CREATE TABLE tts_render_tasks ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - - -- Effective primary key. - -- Follows a single TTS audio through the phases of rendering - token TEXT NOT NULL UNIQUE, - - -- Composite primary key for what this TTS render job belongs to (eg. news story) - story_type TEXT NOT NULL, - story_token TEXT NOT NULL, - - -- For each "sequence" of audio, this is the order. - -- This is 1-indexed - sequence_order INTEGER NOT NULL, - - -- The total number of audio files in the entire speech. - sequence_length INTEGER NOT NULL, - - -- If the source came from somewhere, this is it - -- maybe_canonical_url TEXT NOT NULL UNIQUE, - - -- The name of the service used to generate TTS. - -- I expect this will be FakeYou for a long time, but perhaps that will one day change. - -- Enum-like value, eg. "fakeyou". - tts_service TEXT NOT NULL, - - -- The identifier of the voice. For FakeYou, this is the tts_token. - tts_voice_identifier TEXT NOT NULL, - - -- Original text of the TTS result - full_text TEXT NOT NULL, - - -- For pending audio results, this is the job token to check back later. - maybe_inference_job_token TEXT, - - -- For finished audio results, the token of the result. - maybe_result_token TEXT, - - -- For finished audio results, the URL to the result. - maybe_result_url TEXT, - - -- For audio results that get downloaded, they live on the filesystem here - -- This is relative to the runtime data directory. - maybe_result_relative_filesystem_location TEXT, - - -- When the file is downloaded, the duration in milliseconds. - maybe_audio_duration_millis INTEGER, - - -- TTS render status: "new", "processing", "failed", "permanently_failed", "success", "skipped" - tts_render_status TEXT DEFAULT "new" NOT NULL, - tts_render_attempts INT DEFAULT 0 NOT NULL, - - created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - -- fetched_at DATETIME DEFAULT NULL, - - version INT DEFAULT 0 NOT NULL -); - -CREATE INDEX index_tts_render_status ON tts_render_tasks(tts_render_status); -CREATE INDEX index_tts_render_foreign_key ON tts_render_tasks(story_type, story_token); diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010705_news_story_productions/down.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010705_news_story_productions/down.sql deleted file mode 100644 index 88faceca0a..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010705_news_story_productions/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE news_story_productions; diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010705_news_story_productions/up.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010705_news_story_productions/up.sql deleted file mode 100644 index 3e439f0037..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010705_news_story_productions/up.sql +++ /dev/null @@ -1,80 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -CREATE TABLE news_story_productions ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - - -- Entropic token that follows a single news story through the phases of production - -- This isn't a primary key that belongs to this table alone: it tracks several 1:1 and 1:n entities. - news_story_token TEXT NOT NULL UNIQUE, - - -- The original URL for the news item - original_news_canonical_url TEXT NOT NULL UNIQUE, - - -- Effectively an enum-like: CnnArticle, SlashdotArticle, HackerNewsThread, etc. - web_content_type TEXT NOT NULL, - - -- Original article title (not LLM renditioned) - original_news_title TEXT NOT NULL, - - -- LLM renditioned news title, short. Under 60 characters. - maybe_summary_news_title TEXT, - - -- Comma-separated categories for the story. Generated by LLM. - maybe_categorization TEXT, - - -- If we skip the production at any stage (after scraping, after rendition, etc.), for a non-failure - -- reason, this is why. - -- Enum-like value, eg. "predominantly_video", "empty", "world_leader", "nobody_cares", "advertisement", etc. - maybe_skip_reason TEXT, - - -- The overall status of the news story. - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - overall_production_status TEXT DEFAULT "not_ready" NOT NULL, - - -- Renditioning the audio with LLM/GPT - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - llm_rendition_status TEXT DEFAULT "not_ready" NOT NULL, - - -- Number of LLM/GPT rendition attempts that have been made - llm_rendition_attempts INT DEFAULT 0 NOT NULL, - - -- Summarizing the title with LLM/GPT - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - llm_title_summary_status TEXT DEFAULT "not_ready" NOT NULL, - - -- Number of LLM/GPT title summary attempts that have been made - llm_title_summary_attempts INT DEFAULT 0 NOT NULL, - - -- Classifying the categories with LLM/GPT - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - llm_categorization_status TEXT DEFAULT "not_ready" NOT NULL, - - -- Number of LLM/GPT category summary attempts that have been made - llm_categorization_attempts INT DEFAULT 0 NOT NULL, - - -- TTS for the audio with FakeYou - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - audio_generation_status TEXT DEFAULT "not_ready" NOT NULL, - - -- Generating headline images - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - image_generation_status TEXT DEFAULT "not_ready" NOT NULL, - - -- Number of image generation attempts that have been made - image_generation_attempts INT DEFAULT 0 NOT NULL, - - -- Generating extra media (images, etc.) - -- "not_ready", "ready_waiting", "processing", "retryably_failed", "permanently_failed", "skipped", "done" - -- media_generation_status TEXT DEFAULT "not_ready" NOT NULL, - - created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - - version INT DEFAULT 0 NOT NULL -); - -CREATE INDEX index_overall_production_status ON news_story_productions(overall_production_status); -CREATE INDEX index_llm_rendition_status ON news_story_productions(llm_rendition_status); -CREATE INDEX index_audio_generation_status ON news_story_productions(audio_generation_status); diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010711_news_stories/down.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010711_news_stories/down.sql deleted file mode 100644 index 44c99a7891..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010711_news_stories/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE news_stories; diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010711_news_stories/up.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010711_news_stories/up.sql deleted file mode 100644 index ae2f88475e..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-010711_news_stories/up.sql +++ /dev/null @@ -1,48 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -CREATE TABLE news_stories ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - - -- Entropic token that follows a single news story through the phases of production - -- This isn't a primary key that belongs to this table alone: it tracks several 1:1 and 1:n entities. - news_story_token TEXT NOT NULL UNIQUE, - - -- The original URL for the news item - original_news_canonical_url TEXT NOT NULL UNIQUE, - - -- Effectively an enum-like: CnnArticle, SlashdotArticle, HackerNewsThread, etc. - web_content_type TEXT NOT NULL, - - -- Original article title (not LLM renditioned) - original_news_title TEXT NOT NULL, - - -- LLM renditioned news title, short. Under 60 characters. - summary_news_title TEXT NOT NULL, - - -- Comma-separated categories for the story. Generated by LLM. - llm_categorization TEXT NOT NULL, - - -- Total number of discrete audio files for this story - audio_file_count INTEGER NOT NULL, - - -- Total amount of time in the audio files. - -- NB: This is seconds, not millis! - audio_total_duration_seconds INTEGER NOT NULL, - - -- When the story should stop being scheduled. - replayable_until DATETIME NOT NULL, - - -- A kill switch for news stories. - is_playable BOOLEAN NOT NULL DEFAULT FALSE, - - created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - -- fetched_at DATETIME DEFAULT NULL, - - version INT DEFAULT 0 NOT NULL -); - -CREATE INDEX index_replayable_until ON news_stories(replayable_until); -CREATE INDEX index_is_playable ON news_stories(is_playable); diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-015956_news_story_schedule_histories/down.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-015956_news_story_schedule_histories/down.sql deleted file mode 100644 index 9660a8fefb..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-015956_news_story_schedule_histories/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -DROP TABLE news_story_schedule_histories; diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-015956_news_story_schedule_histories/up.sql b/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-015956_news_story_schedule_histories/up.sql deleted file mode 100644 index 8828a9136c..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations/2023-02-11-015956_news_story_schedule_histories/up.sql +++ /dev/null @@ -1,16 +0,0 @@ --- noinspection SqlDialectInspectionForFile --- noinspection SqlNoDataSourceInspectionForFile --- noinspection SqlResolveForFile - -CREATE TABLE news_story_schedule_histories ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - - -- We can have many entries for the same news story. - news_story_token TEXT NOT NULL, - - -- Records when the story was played. - played_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL -); - -CREATE INDEX index_news_story_token ON news_story_schedule_histories(news_story_token); -CREATE INDEX played_at ON news_story_schedule_histories(played_at); diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations_todo/2023-02-05-064527_content_schedules/down.sql b/crates/programs/aichatbot-sidecar/_sql/migrations_todo/2023-02-05-064527_content_schedules/down.sql deleted file mode 100644 index 291a97c5ce..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations_todo/2023-02-05-064527_content_schedules/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/_sql/migrations_todo/2023-02-05-064527_content_schedules/up.sql b/crates/programs/aichatbot-sidecar/_sql/migrations_todo/2023-02-05-064527_content_schedules/up.sql deleted file mode 100644 index 33cf74b578..0000000000 --- a/crates/programs/aichatbot-sidecar/_sql/migrations_todo/2023-02-05-064527_content_schedules/up.sql +++ /dev/null @@ -1 +0,0 @@ --- Your SQL goes here \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/diesel.toml b/crates/programs/aichatbot-sidecar/diesel.toml deleted file mode 100644 index 81fdbd615a..0000000000 --- a/crates/programs/aichatbot-sidecar/diesel.toml +++ /dev/null @@ -1,13 +0,0 @@ -# For documentation on how to configure this file, -# see diesel.rs/guides/configuring-diesel-cli - -[print_schema] -file = "_ignored_schema.rs" - -# I want to sort this directory first for easier reference -# Not released yet, but added here: -# https://github.com/diesel-rs/diesel/pull/2179 -# You'll need to install the a non-released diesel CLI -# (See storyteller READMEs/docs on how to install) -[migrations_directory] -dir = "_sql/migrations" diff --git a/crates/programs/aichatbot-sidecar/src/configs/fakeyou_voice_option.rs b/crates/programs/aichatbot-sidecar/src/configs/fakeyou_voice_option.rs deleted file mode 100644 index d807e110c3..0000000000 --- a/crates/programs/aichatbot-sidecar/src/configs/fakeyou_voice_option.rs +++ /dev/null @@ -1,54 +0,0 @@ -use strum::EnumIter; -use strum::IntoEnumIterator; -use tokens::tokens::tts_models::TtsModelToken; - -/// Static configurations for usable voices. -/// These will be well-known character voices, test voices, etc. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -#[derive(EnumIter)] -pub enum FakeYouVoiceOption { - AndersonCooper, - HanashiV3, - HanashiV2, - // NB: Hanashi v1 has strokes. - HanashiV1, - // NB: John Madden is fantastic. - JohnMadden, -} - -impl Default for FakeYouVoiceOption { - fn default() -> Self { - Self::AndersonCooper - } -} - -impl FakeYouVoiceOption { - - pub fn variant_name(&self) -> &'static str { - match self { - FakeYouVoiceOption::AndersonCooper => "Anderson Cooper", - FakeYouVoiceOption::HanashiV3 => "Hanashi (v3)", - FakeYouVoiceOption::HanashiV2 => "Hanashi (v2)", - FakeYouVoiceOption::HanashiV1 => "Hanashi (v1)", - FakeYouVoiceOption::JohnMadden => "John Madden", - } - } - - pub fn tts_model_token_str(&self) -> &'static str { - match self { - FakeYouVoiceOption::AndersonCooper => "TM:5mk6h46emvhk", - FakeYouVoiceOption::HanashiV3 => "TM:5hc38cg7cdtm", - FakeYouVoiceOption::HanashiV2 => "TM:zcd4qzrwacq0", - FakeYouVoiceOption::HanashiV1 => "TM:npxv6rgtddmv", - FakeYouVoiceOption::JohnMadden => "TM:30ha2t6bxfn4", - } - } - - pub fn tts_model_token(&self) -> TtsModelToken { - TtsModelToken::new_from_str(self.tts_model_token_str()) - } - - pub fn iterate() -> FakeYouVoiceOptionIter { - Self::iter() - } -} diff --git a/crates/programs/aichatbot-sidecar/src/configs/level_option.rs b/crates/programs/aichatbot-sidecar/src/configs/level_option.rs deleted file mode 100644 index 1ed892e0b7..0000000000 --- a/crates/programs/aichatbot-sidecar/src/configs/level_option.rs +++ /dev/null @@ -1,51 +0,0 @@ -use strum::EnumIter; -use strum::IntoEnumIterator; - -/// Static configurations for which levels the Unreal Engine program can present. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -#[derive(EnumIter)] -pub enum LevelOption { - BlankBlue, - BlankRed, - FakeCnn, - FantasyStorytelling, - CartoonNewsStation, - VirtualMusician, - AiUpscaledDeepFake, -} - -impl Default for LevelOption { - fn default() -> Self { - Self::FakeCnn - } -} - -impl LevelOption { - pub fn variant_name(&self) -> &'static str { - match self { - Self::BlankBlue => "Blank (Blue)", - Self::BlankRed => "Blank (Red)", - Self::FakeCnn => "Fake CNN", - Self::FantasyStorytelling => "Fantasy Storytelling", - Self::CartoonNewsStation => "Cartoon News Station", - Self::VirtualMusician => "Virtual Musician", - Self::AiUpscaledDeepFake => "AI Upscaled Deep Fake (Unreal -> DeepFaceLive)", - } - } - - pub fn tts_model_token_str(&self) -> &'static str { - match self { - Self::BlankBlue => "blank_blue", - Self::BlankRed => "blank_red", - Self::FakeCnn => "fake_cnn", - Self::CartoonNewsStation => "cartoon_news_station", - Self::FantasyStorytelling => "fantasy_storytelling", - Self::VirtualMusician => "virtual_musician", - Self::AiUpscaledDeepFake => "ai_upscaled_deep_fake", - } - } - - pub fn iterate() -> LevelOptionIter { - Self::iter() - } -} diff --git a/crates/programs/aichatbot-sidecar/src/configs/mod.rs b/crates/programs/aichatbot-sidecar/src/configs/mod.rs deleted file mode 100644 index ffeddd8ce3..0000000000 --- a/crates/programs/aichatbot-sidecar/src/configs/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod fakeyou_voice_option; -pub mod level_option; diff --git a/crates/programs/aichatbot-sidecar/src/gpt_prompts/categorization_gpt_prompt.rs b/crates/programs/aichatbot-sidecar/src/gpt_prompts/categorization_gpt_prompt.rs deleted file mode 100644 index 690bd57124..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gpt_prompts/categorization_gpt_prompt.rs +++ /dev/null @@ -1,23 +0,0 @@ - -pub struct CategorizationGptPrompt { - // TODO: Add other details (title, etc.) - paragraphs: Vec, -} - -impl CategorizationGptPrompt { - - pub fn new(paragraphs: &Vec) -> Self { - Self { - paragraphs: paragraphs.clone(), - } - } - - pub fn make_prompt(&self) -> String { - // TODO: This will need a lot of work and experimentation. - let start = "Come up with a comma separated list of keywords or concepts for this news article:\n\n-----\n\n"; - - let end = "\n\n-----\n\nThese keywords will classify the key points of the article. List the top five words and no more"; - - format!("{}{}{}", start, &self.paragraphs.join("\n\n"), end) - } -} diff --git a/crates/programs/aichatbot-sidecar/src/gpt_prompts/concise_title_gpt_prompt.rs b/crates/programs/aichatbot-sidecar/src/gpt_prompts/concise_title_gpt_prompt.rs deleted file mode 100644 index 84e9480c06..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gpt_prompts/concise_title_gpt_prompt.rs +++ /dev/null @@ -1,24 +0,0 @@ - -pub struct ConciseTitleGptPrompt { - title: String, - paragraphs: Vec, -} - -impl ConciseTitleGptPrompt { - - pub fn new(title: &str, paragraphs: &Vec) -> Self { - Self { - title: title.to_string(), - paragraphs: paragraphs.clone(), - } - } - - pub fn make_prompt(&self) -> String { - // TODO: This will need a lot of work and experimentation. - let start = "The following is a news article:\n\n-----\n\n"; - - let end = "\n\n-----\n\nSummarize a headline news title for the article that is under 50 characters. The title must be 50 characters or less"; - - format!("{}{}\n\n{}{}", start, &self.title, &self.paragraphs.join("\n\n"), end) - } -} diff --git a/crates/programs/aichatbot-sidecar/src/gpt_prompts/mod.rs b/crates/programs/aichatbot-sidecar/src/gpt_prompts/mod.rs deleted file mode 100644 index 4e546ef12b..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gpt_prompts/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod categorization_gpt_prompt; -pub mod concise_title_gpt_prompt; -pub mod news_article_prompt; diff --git a/crates/programs/aichatbot-sidecar/src/gpt_prompts/news_article_prompt.rs b/crates/programs/aichatbot-sidecar/src/gpt_prompts/news_article_prompt.rs deleted file mode 100644 index cd2ec80cd4..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gpt_prompts/news_article_prompt.rs +++ /dev/null @@ -1,25 +0,0 @@ - -// TODO: We'll add more types of prompt templates in the future. - -pub struct NewsArticlePrompt { - // TODO: Add other details (title, etc.) - paragraphs: Vec, -} - -impl NewsArticlePrompt { - - pub fn new(paragraphs: &Vec) -> Self { - Self { - paragraphs: paragraphs.clone(), - } - } - - // TODO: This will need a lot of work and experimentation. - pub fn make_prompt(&self) -> String { - let start = "The following is a news article:\n\n"; - - let end = "\n\nPlease reword the above article as if you were a newscaster presenting the news. Spell out any abbreviations and numbers"; - - format!("{}{}{}", start, &self.paragraphs.join("\n\n"), end) - } -} diff --git a/crates/programs/aichatbot-sidecar/src/gui/gui.rs b/crates/programs/aichatbot-sidecar/src/gui/gui.rs deleted file mode 100644 index 01158b1d09..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gui/gui.rs +++ /dev/null @@ -1,134 +0,0 @@ -use std::sync::Arc; - -use eframe::egui; -use log::{error, info}; - -use crate::configs::fakeyou_voice_option::FakeYouVoiceOption; -use crate::configs::level_option::LevelOption; -use crate::shared_state::app_control_state::AppControlState; - -/// Initial state for the GUI -pub struct AppGuiArgs { - /// Where the program saves its database - pub save_directory: String, - - /// Shared state with the HTTP server and workers. - pub control_state: Arc, -} - -pub struct AppGui { - // NB: This is not the authoritative set of state. - // These will be copied into the shared server state. - filename: String, - default_directory: String, - - is_unreal_paused : bool, - is_scraping_paused: bool, - is_openai_paused: bool, - is_fakeyou_paused: bool, - - current_level: LevelOption, // NB: Just a copy for the UI, not the authoritative copy - fakeyou_voice: FakeYouVoiceOption, // NB: Just a copy for the UI, not the authoritative copy - - /// Shared state with the HTTP server and workers. - control_state: Arc, -} - -impl AppGui { - pub fn new(args: AppGuiArgs) -> Self { - Self { - filename: "".to_string(), - default_directory: args.save_directory, - is_unreal_paused: false, - is_scraping_paused: false, - is_openai_paused: false, - is_fakeyou_paused: false, - current_level: LevelOption::default(), - fakeyou_voice: FakeYouVoiceOption::default(), - control_state: args.control_state, - } - } -} - -impl eframe::App for AppGui { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - //if let Err(e) = self.control_state.set_is_paused(self.is_paused) { - // error!("Couldn't set paused state: {:?}", e); - //} - - self.control_state.set_is_unreal_paused(self.is_unreal_paused); - self.control_state.set_is_scraping_paused(self.is_scraping_paused); - self.control_state.set_is_openai_paused(self.is_openai_paused); - self.control_state.set_is_fakeyou_paused(self.is_fakeyou_paused); - - let _r = self.control_state.set_level(self.current_level); // NB: Ignore lock errors. - let _r = self.control_state.set_fakeyou_voice(self.fakeyou_voice); // NB: Ignore lock errors. - - egui::CentralPanel::default().show(ctx, |ui| { - //ui.heading("AiChatBot Sidecar"); - //ui.horizontal(|ui| { - // let name_label = ui.label("Filename: "); - // ui.text_edit_singleline(&mut self.filename) - // .labelled_by(name_label.id); - //}); - //ui.horizontal(|ui| { - // let name_label = ui.label("Default directory: "); - // ui.text_edit_singleline(&mut self.default_directory) - // .labelled_by(name_label.id); - //}); - - //ui.horizontal(|ui| { - // let name_label = ui.label("Is Paused?: "); - // ui.checkbox(&mut self.is_paused, "Is Paused?") - // .labelled_by(name_label.id); - //}); - - ui.add_space(10.0); - ui.heading("Unreal Level"); - ui.add_space(7.0); - - egui::ComboBox::from_label("Control for what programming is generated and played.") - .selected_text(format!("{:?}", self.current_level)) - .show_ui(ui, |ui| { - for option in LevelOption::iterate() { - ui.selectable_value(&mut self.current_level, option, option.variant_name()); - } - }); - - ui.add_space(10.0); - ui.heading("Sidecar Pause Controls"); - ui.add_space(7.0); - - ui.horizontal(|ui| { - ui.checkbox(&mut self.is_scraping_paused, "Web Scraping"); - }); - ui.horizontal(|ui| { - ui.checkbox(&mut self.is_openai_paused, "OpenAI API"); - }); - ui.horizontal(|ui| { - ui.checkbox(&mut self.is_fakeyou_paused, "FakeYou API"); - }); - - ui.add_space(20.0); - ui.heading("Unreal Pause Controls"); - ui.add_space(7.0); - ui.horizontal(|ui| { - ui.checkbox(&mut self.is_unreal_paused, "TODO: This does not work yet."); - }); - - ui.add_space(20.0); - ui.heading("FakeYou Voice"); - ui.add_space(7.0); - - egui::ComboBox::from_label("Note: once a story is generated, it will not be re-voiced!") - .selected_text(format!("{:?}", self.fakeyou_voice)) - .show_ui(ui, |ui| { - for option in FakeYouVoiceOption::iterate() { - ui.selectable_value(&mut self.fakeyou_voice, option, option.variant_name()); - } - }); - - ui.add_space(30.0); - }); - } -} diff --git a/crates/programs/aichatbot-sidecar/src/gui/launch_gui.rs b/crates/programs/aichatbot-sidecar/src/gui/launch_gui.rs deleted file mode 100644 index 5b407f03a5..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gui/launch_gui.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::sync::Arc; - -use eframe::egui; -use errors::AnyhowResult; - -use crate::gui::gui::{AppGui, AppGuiArgs}; -use crate::shared_state::app_control_state::AppControlState; -use crate::startup_args::StartupArgs; - -pub fn launch_gui(startup_args: StartupArgs, control_state: Arc) -> AnyhowResult<()> { - // Log to stdout (if you run with `RUST_LOG=debug`). - //tracing_subscriber::fmt::init(); - - // TODO: Is there a way for the program to determine size by itself? Default::default() yields a bad size too. - let width = 440.0; - let height = 400.0; - - let options = eframe::NativeOptions { - initial_window_size: Some(egui::vec2(width, height)), - ..Default::default() - }; - - let app_state = AppGui::new(AppGuiArgs { - save_directory: startup_args.save_directory, - control_state, - }); - - let result = eframe::run_native( - "AiChatBot Sidecar", - options, - Box::new(|_cc| Box::new(app_state)), - ); - - Ok(()) -} \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/gui/mod.rs b/crates/programs/aichatbot-sidecar/src/gui/mod.rs deleted file mode 100644 index 536f4bcab1..0000000000 --- a/crates/programs/aichatbot-sidecar/src/gui/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod gui; -pub mod launch_gui; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/main.rs b/crates/programs/aichatbot-sidecar/src/main.rs deleted file mode 100644 index 609c2147b3..0000000000 --- a/crates/programs/aichatbot-sidecar/src/main.rs +++ /dev/null @@ -1,211 +0,0 @@ -// NB: The following windows directive is cargo-culted from: -// https://github.com/emilk/egui/blob/master/examples/hello_world/src/main.rs -#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release - -#[macro_use] extern crate serde_derive; - -use actix_web::{HttpResponse, HttpServer, web}; -use async_openai::Client; -use clap::{App, Arg}; -use enums::common::sqlite::web_content_type::WebContentType; -use errors::AnyhowResult; -use fakeyou_client::credentials::FakeYouCredentials; -use fakeyou_client::fakeyou_api_client::FakeYouApiClient; -use log::info; -use sqlite_queries::queries::by_table::web_scraping_targets::insert_web_scraping_target::{Args, insert_web_scraping_target}; -use sqlx::sqlite::SqlitePoolOptions; -use tokio::runtime::{Builder, Runtime}; -use web_scrapers::sites::cnn::cnn_article_scraper::cnn_article_scraper; -use web_scrapers::sites::techcrunch::techcrunch_article_scraper::techcrunch_article_scraper; -use workers::news_stories::phase_4::news_story_audio_final_verification::main_loop::news_story_audio_final_verification_main_loop; -use workers::news_stories::phase_5::news_story_post_production_finalization::main_loop::news_story_post_production_finalization_main_loop; - -use crate::gui::launch_gui::launch_gui; -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::app_control_state::AppControlState; -use crate::shared_state::job_state::JobState; -use crate::startup_args::get_startup_args; -use crate::web_server::launch_web_server::{launch_web_server, LaunchWebServerArgs}; -use crate::workers::audio::fakeyou_audio_create::main_loop::fakeyou_audio_create_main_loop; -use crate::workers::audio::fakeyou_audio_download::main_loop::fakeyou_audio_download_main_loop; -use crate::workers::news_stories::phase_1::news_story_greenlighting::main_loop::news_story_greenlighting_main_loop; -use crate::workers::news_stories::phase_2::news_story_image_generation::main_loop::news_story_image_generation_main_loop; -use crate::workers::news_stories::phase_2::news_story_llm_category_summary::main_loop::news_story_llm_category_summary_main_loop; -use crate::workers::news_stories::phase_2::news_story_llm_rendition::main_loop::news_story_llm_rendition_main_loop; -use crate::workers::news_stories::phase_2::news_story_llm_title_summary::main_loop::news_story_llm_title_summary_main_loop; -use crate::workers::news_stories::phase_3::news_story_audio_preprocessing::main_loop::news_story_audio_preprocessing_main_loop; -use crate::workers::web::web_content_scraping::main_loop::web_content_scraping_main_loop; -use crate::workers::web::web_content_scraping::single_target::ingest_url_scrape_and_save::ingest_url_scrape_and_save; -use crate::workers::web::web_index_ingestion::main_loop::web_index_ingestion_main_loop; - -pub mod configs; -pub mod gpt_prompts; -pub mod gui; -pub mod persistence; -pub mod shared_state; -pub mod startup_args; -pub mod test; -pub mod web_server; -pub mod workers; - -pub const LOG_LEVEL: &str = concat!( - "info,", - "actix_web=info,", - "symphonia_core=warn,", // Symphonia is spammy af. - "sqlx::query=warn,", // SQLX logs all queries as "info", which is super spammy - "hyper::proto::h1::io=warn,", - "http_server_common::request::get_request_ip=info," // Debug spams Rust logs -); - -//#[tokio::main] -//pub async fn main() -> AnyhowResult<()> { -// test::test().await -//} - -#[actix_web::main] -pub async fn main() -> AnyhowResult<()> { - easyenv::init_all_with_default_logging(Some(LOG_LEVEL)); - - // NB: Do not check this secrets-containing dotenv file into VCS. - // This file should only contain *development* secrets, never production. - let _ = dotenv::from_filename(".env-aichatbot-secrets").ok(); - - let startup_args = get_startup_args()?; - - // TODO: Fix this mess of Arc wrapping other Arc ! - let app_control_state_inner = AppControlState::new(); - let app_control_state = Arc::new(app_control_state_inner.clone()); - - let openai_client = Client::new() - .with_api_key(startup_args.openai_secret_key.clone()) - //.with_backoff(backoff::ExponentialBackoff) - ; - - let openai_client = Arc::new(openai_client); - - let fakeyou_credentials = FakeYouCredentials::from_session_cookie_payload( - &startup_args.fakeyou_session_cookie_payload); - - let fakeyou_client = - Arc::new(FakeYouApiClient::make_production_client_from_credentials(fakeyou_credentials)?); - - let save_directory = SaveDirectory::new(&startup_args.save_directory); - - let database_url = easyenv::get_env_string_required("DATABASE_URL")?; - - let pool = SqlitePoolOptions::new() - .max_connections(16) - .connect(&database_url).await?; - - let pool2 = pool.clone(); // NB: Clone-safe. - - let job_state = Arc::new(JobState { - openai_client: openai_client.clone(), - fakeyou_client: fakeyou_client.clone(), - save_directory: save_directory.clone(), - sqlite_pool: pool, - app_control_state: app_control_state_inner.clone(), - }); - - info!("Starting worker threads and web server..."); - - let app_control_state2 = app_control_state.clone(); - let openai_client2 = openai_client.clone(); - - // NB: both egui and imgui (which we aren't using) complain about launching on a non-main thread. - // They even complain that this is impossible on Windows (and our program aims to be multiplatform) - // Thus, we launch everything else into its own thread. - thread::spawn(move || { - let tokio_runtime = Builder::new_multi_thread() - .worker_threads(16) - .thread_name("tokio-worker") - .thread_stack_size(3 * 1024 * 1024) - .enable_time() - .enable_io() - .build() - .unwrap(); - - let job_state2 = job_state.clone(); - let job_state3 = job_state.clone(); - let job_state4 = job_state.clone(); - let job_state5 = job_state.clone(); - let job_state6 = job_state.clone(); - let job_state7 = job_state.clone(); - let job_state8 = job_state.clone(); - let job_state9 = job_state.clone(); - let job_state10 = job_state.clone(); - let job_state11 = job_state.clone(); - let job_state12 = job_state.clone(); - let job_state13 = job_state.clone(); - - tokio_runtime.spawn(async { - let _r = web_index_ingestion_main_loop(job_state2).await; - }); - - tokio_runtime.spawn(async { - let _r = web_content_scraping_main_loop(job_state3).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_greenlighting_main_loop(job_state4).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_llm_rendition_main_loop(job_state5).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_llm_title_summary_main_loop(job_state12).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_llm_category_summary_main_loop(job_state13).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_audio_preprocessing_main_loop(job_state6).await; - }); - - tokio_runtime.spawn(async { - let _r = fakeyou_audio_create_main_loop(job_state7).await; - }); - - tokio_runtime.spawn(async { - let _r = fakeyou_audio_download_main_loop(job_state8).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_audio_final_verification_main_loop(job_state9).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_post_production_finalization_main_loop(job_state10).await; - }); - - tokio_runtime.spawn(async { - let _r = news_story_image_generation_main_loop(job_state11).await; - }); - - // TODO: Final scheduling thread - //tokio_runtime.spawn(async { - // // TODO... - //}); - - let server_future = launch_web_server(LaunchWebServerArgs { - app_control_state: app_control_state2, - openai_client: openai_client2, - save_directory, - sqlite_pool: pool2.clone(), - }); - - let runtime = actix_web::rt::System::new(); - - runtime.block_on(server_future) - }); - - info!("Starting GUI ..."); - - let _r = launch_gui(startup_args.clone(), app_control_state.clone()); - - Ok(()) -} diff --git a/crates/programs/aichatbot-sidecar/src/persistence/hashed_directory_path.rs b/crates/programs/aichatbot-sidecar/src/persistence/hashed_directory_path.rs deleted file mode 100644 index f6e7cadd68..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/hashed_directory_path.rs +++ /dev/null @@ -1,10 +0,0 @@ - -// NB: this is copied from crates/_types/buckets/src/util/hashed_directory_path_short_string.rs -pub fn hashed_directory_path(file_hash: &str) -> String { - match file_hash.len() { - 0 | 1 => "".to_string(), - 2 => format!("{}/", &file_hash[0..1]), - 3 => format!("{}/{}/", &file_hash[0..1], &file_hash[1..2]), - _ => format!("{}/{}/{}/", &file_hash[0..1], &file_hash[1..2], &file_hash[2..3]), - } -} diff --git a/crates/programs/aichatbot-sidecar/src/persistence/image_generation_debug_data.rs b/crates/programs/aichatbot-sidecar/src/persistence/image_generation_debug_data.rs deleted file mode 100644 index 23db5957de..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/image_generation_debug_data.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::path::Path; - -use errors::AnyhowResult; - -/// For serializing Image Generation responses for debugging -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ImageGenerationDebugData { - /// Prompt used to generate the image - pub image_generation_prompt: String, - - /// We might have created a prompt to generate a prompt. - pub maybe_preconditioning_prompt: Option, -} - -impl ImageGenerationDebugData { - - //pub fn try_from_yaml_file>(filename: P) -> AnyhowResult { - // let file = std::fs::File::open(filename)?; - // let object = serde_yaml::from_reader(file)?; - // Ok(object) - //} - - pub fn write_to_yaml_file>(&self, filename: P) -> AnyhowResult<()> { - let mut file = std::fs::File::create(filename)?; - serde_yaml::to_writer(file, &self)?; - Ok(()) - } -} diff --git a/crates/programs/aichatbot-sidecar/src/persistence/load_scraped_result.rs b/crates/programs/aichatbot-sidecar/src/persistence/load_scraped_result.rs deleted file mode 100644 index 7631ee7a8d..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/load_scraped_result.rs +++ /dev/null @@ -1,11 +0,0 @@ -use errors::AnyhowResult; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; - -use crate::persistence::save_directory::SaveDirectory; - -pub async fn load_scraped_result(url: &str, save_directory: &SaveDirectory) -> AnyhowResult { - let scrape_yaml_filename = save_directory.scrape_summary_file_for_webpage_url(url)?; - let mut file = std::fs::File::open(&scrape_yaml_filename)?; - let scraping_result : ScrapedWebArticle = serde_yaml::from_reader(file)?; - Ok(scraping_result) -} diff --git a/crates/programs/aichatbot-sidecar/src/persistence/mod.rs b/crates/programs/aichatbot-sidecar/src/persistence/mod.rs deleted file mode 100644 index 2a02553536..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod hashed_directory_path; -pub mod image_generation_debug_data; -pub mod load_scraped_result; -pub mod rendition_data; -pub mod save_directory; -pub mod speakable_monologue; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/persistence/rendition_data.rs b/crates/programs/aichatbot-sidecar/src/persistence/rendition_data.rs deleted file mode 100644 index 7cca5109b3..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/rendition_data.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::path::Path; - -use errors::AnyhowResult; - -/// For serializing OpenAI GPT requests. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RenditionData { - /// Location the article came from - pub original_content_url: String, - - /// The prompt we sent to OpenAI - pub original_prompt: String, - - /// Response from OpenAI - pub response: String, -} - -impl RenditionData { - - pub fn try_from_yaml_file>(filename: P) -> AnyhowResult { - let file = std::fs::File::open(filename)?; - let object = serde_yaml::from_reader(file)?; - Ok(object) - } - - pub fn write_to_yaml_file>(&self, filename: P) -> AnyhowResult<()> { - let mut file = std::fs::File::create(filename)?; - serde_yaml::to_writer(file, &self)?; - Ok(()) - } -} diff --git a/crates/programs/aichatbot-sidecar/src/persistence/save_directory.rs b/crates/programs/aichatbot-sidecar/src/persistence/save_directory.rs deleted file mode 100644 index c74dde2b09..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/save_directory.rs +++ /dev/null @@ -1,89 +0,0 @@ -use std::path::{Path, PathBuf}; - -use errors::{anyhow, AnyhowResult}; -use hashing::sha256::sha256_hash_string::sha256_hash_string; -use log::info; -use path_absolutize::Absolutize; -use tokens::tokens::news_stories::NewsStoryToken; - -use crate::persistence::hashed_directory_path::hashed_directory_path; - -#[derive(Clone)] -pub struct SaveDirectory { - directory: PathBuf, -} - -impl SaveDirectory { - - pub fn new>(directory: P) -> Self { - Self { - directory: directory.as_ref().to_path_buf() - } - } - - // TODO: Move web pages for news under "news_stories/{hashed_url_path}/" - pub fn directory_for_webpage_url(&self, url: &str) -> AnyhowResult { - let url_hash = sha256_hash_string(url)?; - let directory_path= hashed_directory_path(&url_hash); - - let directory = self.directory.clone() - .join("webpages/") - .join(directory_path) - .join(url_hash); - - Ok(directory) - } - - // TODO: Move web pages for news under "news_stories/{hashed_url_path}/audio/" - // This requires associating the job with the URL. - pub fn directory_for_audio(&self, news_story_token: &NewsStoryToken) -> AnyhowResult { - let entropy_part = news_story_token.entropy_suffix(); - let directory_path= hashed_directory_path(&entropy_part); - - let directory = self.directory.clone() - .join("audio/") - .join(directory_path) - .join(news_story_token.as_str()); - - Ok(directory) - } - - pub fn html_file_for_webpage_url(&self, url: &str) -> AnyhowResult { - Ok(self.directory_for_webpage_url(url)?.join("webpage.html")) - } - - pub fn scrape_summary_file_for_webpage_url(&self, url: &str) -> AnyhowResult { - Ok(self.directory_for_webpage_url(url)?.join("scrape_summary.yaml")) - } - - pub fn rendition_file_for_webpage_url(&self, url: &str) -> AnyhowResult { - Ok(self.directory_for_webpage_url(url)?.join("gpt_rendition.yaml")) - } - - pub fn speakable_monologue_file_for_webpage_url(&self, url: &str) -> AnyhowResult { - Ok(self.directory_for_webpage_url(url)?.join("speakable_monologue.yaml")) - } - - pub fn generated_headline_image_for_webpage_url(&self, url: &str) -> AnyhowResult { - Ok(self.directory_for_webpage_url(url)?.join("generated_headline_image.png")) - } - - pub fn image_generation_prompt_debug_file_webpage_url(&self, url: &str) -> AnyhowResult { - Ok(self.directory_for_webpage_url(url)?.join("image_generation_prompts.yaml")) - } - - pub fn audio_wav_file_for_news_story(&self, news_story_token: &NewsStoryToken, sequence_order: i64) -> AnyhowResult { - let filename = format!("{}.wav", sequence_order); - Ok(self.directory_for_audio(news_story_token)?.join(filename)) - } - - /// This is just the first directory structure, which is sequential audio files. - /// We'll be using a database and well-formed filesystem layout later. - pub fn get_audio_files_dir_v1(&self) -> PathBuf { - let result = self.directory.join("audio_files"); - let result = result.absolutize() - .map(|file| file.to_path_buf()) - .unwrap_or(result); - result - } -} diff --git a/crates/programs/aichatbot-sidecar/src/persistence/speakable_monologue.rs b/crates/programs/aichatbot-sidecar/src/persistence/speakable_monologue.rs deleted file mode 100644 index 6e7b285073..0000000000 --- a/crates/programs/aichatbot-sidecar/src/persistence/speakable_monologue.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::path::Path; - -use errors::AnyhowResult; - -/// For handing off to FakeYou for audio generation -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SpeakableMonologue { - /// Paragraphs to speak - pub paragraphs: Vec, -} - -impl SpeakableMonologue { - - pub fn try_from_yaml_file>(filename: P) -> AnyhowResult { - let file = std::fs::File::open(filename)?; - let object = serde_yaml::from_reader(file)?; - Ok(object) - } - - pub fn write_to_yaml_file>(&self, filename: P) -> AnyhowResult<()> { - let mut file = std::fs::File::create(filename)?; - serde_yaml::to_writer(file, &self)?; - Ok(()) - } -} diff --git a/crates/programs/aichatbot-sidecar/src/shared_state/app_control_state.rs b/crates/programs/aichatbot-sidecar/src/shared_state/app_control_state.rs deleted file mode 100644 index 2fe1482bfb..0000000000 --- a/crates/programs/aichatbot-sidecar/src/shared_state/app_control_state.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::sync::{Arc, RwLock}; - -use concurrency::relaxed_atomic_bool::RelaxedAtomicBool; -use errors::{anyhow, AnyhowResult}; - -use crate::configs::fakeyou_voice_option::FakeYouVoiceOption; -use crate::configs::level_option::LevelOption; - -/// User-controlled parameters that determine how the app behaves at runtime. -#[derive(Clone)] -pub struct AppControlState { - /// Whether the playback should be paused - /// Unreal Engine will get this over HTTP and know whether to no-op. - is_paused: Arc>, - - /// Whether unreal should pause playback. - is_unreal_paused: RelaxedAtomicBool, - - /// Whether the web scraping should be paused. - is_scraping_paused: RelaxedAtomicBool, - - /// Whether calls to OpenAI should be paused. - is_openai_paused: RelaxedAtomicBool, - - /// Whether calls to FakeYou should be paused. - is_fakeyou_paused: RelaxedAtomicBool, - - /// Which level to present. - current_level: Arc>, - - /// Option of which voice to use for TTS. - fakeyou_voice: Arc>, -} - -impl AppControlState { - - pub fn new() -> Self { - AppControlState { - is_paused: Arc::new(RwLock::new(false)), - is_unreal_paused: RelaxedAtomicBool::new(false), - is_scraping_paused: RelaxedAtomicBool::new(false), - is_openai_paused: RelaxedAtomicBool::new(false), - is_fakeyou_paused: RelaxedAtomicBool::new(false), - current_level: Arc::new(RwLock::new(LevelOption::default())), - fakeyou_voice: Arc::new(RwLock::new(FakeYouVoiceOption::default())), - } - } - - pub fn is_paused(&self) -> AnyhowResult { - match self.is_paused.read() { - Ok(value) => Ok(*value), - Err(err) => Err(anyhow!("lock error: {:?}", err)), - } - } - - pub fn set_is_paused(&self, new_value: bool) -> AnyhowResult<()> { - match self.is_paused.write() { - Ok(mut value) => { - *value = new_value; - Ok(()) - }, - Err(err) => Err(anyhow!("lock error: {:?}", err)), - } - } - - pub fn is_unreal_paused(&self) -> bool { - self.is_unreal_paused.get() - } - - pub fn set_is_unreal_paused(&self, new_value: bool) { - self.is_unreal_paused.set(new_value) - } - - pub fn is_scraping_paused(&self) -> bool { - self.is_scraping_paused.get() - } - - pub fn set_is_scraping_paused(&self, new_value: bool) { - self.is_scraping_paused.set(new_value) - } - - pub fn is_openai_paused(&self) -> bool { - self.is_openai_paused.get() - } - - pub fn set_is_openai_paused(&self, new_value: bool) { - self.is_openai_paused.set(new_value) - } - - pub fn is_fakeyou_paused(&self) -> bool { - self.is_fakeyou_paused.get() - } - - pub fn set_is_fakeyou_paused(&self, new_value: bool) { - self.is_fakeyou_paused.set(new_value) - } - - pub fn get_level(&self) -> AnyhowResult { - match self.current_level.read() { - Ok(value) => Ok(*value), - Err(err) => Err(anyhow!("lock error: {:?}", err)), - } - } - - pub fn set_level(&self, new_value: LevelOption) -> AnyhowResult<()> { - match self.current_level.write() { - Ok(mut value) => { - *value = new_value; - Ok(()) - }, - Err(err) => Err(anyhow!("lock error: {:?}", err)), - } - } - - pub fn fakeyou_voice(&self) -> AnyhowResult { - match self.fakeyou_voice.read() { - Ok(value) => Ok(*value), - Err(err) => Err(anyhow!("lock error: {:?}", err)), - } - } - - pub fn set_fakeyou_voice(&self, new_value: FakeYouVoiceOption) -> AnyhowResult<()> { - match self.fakeyou_voice.write() { - Ok(mut value) => { - *value = new_value; - Ok(()) - }, - Err(err) => Err(anyhow!("lock error: {:?}", err)), - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/shared_state/job_state.rs b/crates/programs/aichatbot-sidecar/src/shared_state/job_state.rs deleted file mode 100644 index ac630c2f13..0000000000 --- a/crates/programs/aichatbot-sidecar/src/shared_state/job_state.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::sync::Arc; - -use async_openai::Client; -use fakeyou_client::fakeyou_api_client::FakeYouApiClient; -use sqlx::{Pool, Sqlite}; - -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::app_control_state::AppControlState; - -#[derive(Clone)] -pub struct JobState { - pub openai_client: Arc, - pub fakeyou_client: Arc, - - pub save_directory: SaveDirectory, - pub sqlite_pool: Pool, - - pub app_control_state: AppControlState, -} - diff --git a/crates/programs/aichatbot-sidecar/src/shared_state/mod.rs b/crates/programs/aichatbot-sidecar/src/shared_state/mod.rs deleted file mode 100644 index 9e1bf81972..0000000000 --- a/crates/programs/aichatbot-sidecar/src/shared_state/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod app_control_state; -pub mod job_state; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/startup_args.rs b/crates/programs/aichatbot-sidecar/src/startup_args.rs deleted file mode 100644 index 5ccf31ee22..0000000000 --- a/crates/programs/aichatbot-sidecar/src/startup_args.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::path::PathBuf; - -use clap::{App, Arg, ArgMatches}; -use errors::{anyhow, AnyhowResult}; -use log::info; -use path_absolutize::Absolutize; - -const DEFAULT_SAVE_DIRECTORY : &str = "runtime_data"; - -#[derive(Clone, Default)] -pub struct StartupArgs { - /// Where the program stores its state and database - pub save_directory: String, - - pub openai_secret_key: String, - pub fakeyou_api_token: String, - pub fakeyou_session_cookie_payload: String, -} - -/// Read in environment and CLI args and output the consolidated startup state -pub fn get_startup_args() -> AnyhowResult { - let matches = App::new("aichatbot-sidecar") - .arg(Arg::with_name("file") - .short("d") - .long("directory") - .value_name("DIRECTORY") - .help("The save directory") - .takes_value(true) - .required(false)) - .get_matches(); - - let openai_secret_key = easyenv::get_env_string_required("OPENAI_SECRET_KEY")?; - - let fakeyou_api_token = easyenv::get_env_string_required("FAKEYOU_API_TOKEN")?; - - let fakeyou_session_cookie_payload = easyenv::get_env_string_required("FAKEYOU_SESSION_COOKIE_PAYLOAD")?; - - let save_directory = get_save_directory(&matches)?; - - Ok(StartupArgs { - save_directory, - openai_secret_key, - fakeyou_api_token, - fakeyou_session_cookie_payload, - }) -} - - -fn get_save_directory(matches: &ArgMatches) -> AnyhowResult { - let mut maybe_save_directory = matches.value_of("directory") - .map(|val| val.trim().to_string()) - .map(|val| PathBuf::from(val)); - - info!("SA dir(1): {:?}", maybe_save_directory); - - if maybe_save_directory.is_none() { - // Use the current directory - maybe_save_directory = std::env::current_dir() - .ok() - .map(|pathbuf| pathbuf.join(DEFAULT_SAVE_DIRECTORY)); - //.map(|pathbuf| std::fs::canonicalize(pathbuf).ok()) - //.flatten(); - - info!("SA dir(2): {:?}", maybe_save_directory); - } - - let save_directory = maybe_save_directory - .unwrap_or_else(|| PathBuf::from(DEFAULT_SAVE_DIRECTORY)); - - info!("SA dir(3): {:?}", save_directory); - - let save_directory = save_directory - .absolutize() - .ok() - .map(|inner| inner.to_path_buf()) - .map(|pathbuf| pathbuf.to_str().map(|s| s.to_string())) - .flatten() - .ok_or(anyhow!("could not construct path"))?; - - info!("SA dir(4): {:?}", save_directory); - - Ok(save_directory) -} diff --git a/crates/programs/aichatbot-sidecar/src/test.rs b/crates/programs/aichatbot-sidecar/src/test.rs deleted file mode 100644 index 914458a0a2..0000000000 --- a/crates/programs/aichatbot-sidecar/src/test.rs +++ /dev/null @@ -1,83 +0,0 @@ -//! -//! This is for testing new functionality quickly without running the whole program. -//! - -use async_openai::Client; -use async_openai::types::{CreateImageRequest, ImageSize, ResponseFormat}; -use enums::common::sqlite::web_content_type::WebContentType; -use errors::AnyhowResult; -use sqlx::sqlite::SqlitePoolOptions; - -use crate::persistence::save_directory::SaveDirectory; -use crate::startup_args::get_startup_args; -use crate::workers::web::web_content_scraping::single_target::ingest_url_scrape_and_save::ingest_url_scrape_and_save; - -pub async fn test() -> AnyhowResult<()> { - let database_url = easyenv::get_env_string_required("DATABASE_URL")?; - let pool = SqlitePoolOptions::new() - .max_connections(5) - .connect(&database_url).await?; - - let _ = dotenv::from_filename(".env-aichatbot-secrets").ok(); - let startup_args = get_startup_args()?; - let save_directory = SaveDirectory::new(&startup_args.save_directory); - - //let url = "https://techcrunch.com/2023/02/04/elon-musk-says-twitter-will-provide-a-free-write-only-api-to-bots-providing-good-content/"; - let url = "https://www.cnn.com/2023/02/04/business/automakers-problems-catching-up-with-tesla/index.html"; - ingest_url_scrape_and_save(url, WebContentType::CnnArticle, &save_directory).await?; - - let openai_client = Client::new() - .with_api_key(startup_args.openai_secret_key.clone()); - - let create_request = CreateImageRequest { - n: Some(1), - //prompt: "A news headline image; headline: After nearly one year of war, how Ukraine defied the odds — and may still defeat Russia".to_string(), - //prompt: "A news headline image; headline: 'Heartbreaking': Visitor accidentally shatters Jeff Koons 'balloon dog' sculpture at Art Wynwood".to_string(), - //prompt: "A news headline image; headline: Mayorkas goes on the offensive as GOP scrutiny builds, says it’s up to Congress to fix immigration system ".to_string(), - //prompt: "Brave or lucky? See the moment a dog took on a hammerhead shark".to_string(), - //prompt: "Headline: Jimmy Carter to begin receiving home hospice care".to_string(), - //prompt: "Nine children hurt, shooting; Tragic, frightful, chaotic, violent, frightening.".to_string(), - //prompt: "9 kids hurt in Georgia; Disturbing, tragic, frightening, violent, chaotic; Art Style/Director: Wes Anderson/Surrealist.; remove text; no text; no English text".to_string(), - //prompt: "Summary: 9 kids hurt in Georgia; Adjectives: Disturbing, tragic, frightening, violent, chaotic; Art Style/Director: Wes Anderson/Surrealist.".to_string(), - //prompt: "Reviving cheetahs in India. Adventurous, ambitious, necessary, daring, wild. Wes Anderson, Runnings fields with cheetahs racing around in the distance, trees swaying in the wind, and the sun setting in the background.".to_string(), - prompt: "Closure found after WWII; moving, emotional, joyous, triumphant, proud. -Art style: Impressionism. -Setting: A coastal beach with a few people looking out to sea, with a large American flag waving in the background. Objects: a few boats in the distant, a lighthouse, and some driftwood on the shore. A photo or painting of this might be a peaceful beachscape with vibrant colors of the sky, sea, and flag.".to_string(), - //prompt: "LGBTQ love, vibrant, colorful, playful, revolutionary. Art style: Bollywood musicals. Setting: A city street in the evening, lit up with vibrant neon signs and bustling crowds. There are couples in traditional Indian clothing, dancing and singing around colorful street vendors selling snacks and trinkets.".to_string(), - //prompt: "Kinkade painting of Releasing twelve manatees: miraculous, astounding, incredible, remarkable, amazing. Setting: A peaceful beach, with gentle sand and a clear blue sky. Objects: A crowd of people lined up along the shore, a boat full of manatees, and the vibrant colors of the ocean.".to_string(), - //prompt: "Photo of Releasing twelve manatees: miraculous, astounding, incredible, remarkable, amazing. Art style: Tim Burton.".to_string(), - size: Some(ImageSize::S1024x1024), - response_format: Some(ResponseFormat::Url), - user: Some("test".to_string()), - }; - - let response = openai_client - .images() - .create(create_request) - .await - .unwrap(); - -// let create_edit_request = CreateImageEditRequest { -// image: ImageInput { path: PathBuf::from("runtime_data/scaled_test.png") }, -// mask: ImageInput { path: PathBuf::from("runtime_data/scaled_mask.png") }, -// prompt: "Closure found after WWII; moving, emotional, joyous, triumphant, proud. -//Art style: Impressionism. -//Setting: A coastal beach with a few people looking out to sea, with a large American flag waving in the background. Objects: a few boats in the distant, a lighthouse, and some driftwood on the shore. A photo or painting of this might be a peaceful beachscape with vibrant colors of the sky, sea, and flag.".to_string(), -// n: Some(1), -// size: Some(ImageSize::S1024x1024), -// response_format: Some(ResponseFormat::Url), -// user: Some("test".to_string()), -// }; -// -// let response = openai_client -// .images() -// .create_edit(create_edit_request) -// .await -// .unwrap(); - - - println!("Response: {:?}", response); - - Ok(()) -} - diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/level/get_current_level.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/level/get_current_level.rs deleted file mode 100644 index 25b6caef72..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/level/get_current_level.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::sync::Arc; - -use actix_http::StatusCode; -use actix_web::{HttpRequest, HttpResponse, ResponseError, web}; -use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use log::error; - -use crate::shared_state::app_control_state::AppControlState; - -#[derive(Serialize)] -pub struct GetCurrentLevelResponse { - pub success: bool, - pub current_level: String, -} - -#[derive(Debug, Serialize)] -pub enum GetCurrentLevelError { - ServerError, -} - -impl ResponseError for GetCurrentLevelError { - fn status_code(&self) -> StatusCode { - match *self { - GetCurrentLevelError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, - } - } - - fn error_response(&self) -> HttpResponse { - serialize_as_json_error(self) - } -} - -// NB: Not using derive_more::Display since Clion doesn't understand it. -impl std::fmt::Display for GetCurrentLevelError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -pub async fn get_current_level_handler( - _http_request: HttpRequest, - control_state: web::Data> -) -> Result { - - let current_level = control_state.get_level() - .map_err(|err| { - error!("Error: {:?}", err); - GetCurrentLevelError::ServerError - })?; - - let response = GetCurrentLevelResponse { - success: true, - current_level: current_level.tts_model_token_str().to_string(), - }; - - let body = serde_json::to_string(&response) - .map_err(|e| GetCurrentLevelError::ServerError)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/level/mod.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/level/mod.rs deleted file mode 100644 index 9381d19b5c..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/level/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod get_current_level; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/get_next_audio_file_handler.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/get_next_audio_file_handler.rs deleted file mode 100644 index eaf143ac9e..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/get_next_audio_file_handler.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::sync::Arc; - -use actix_http::StatusCode; -use actix_web::{HttpRequest, HttpResponse, ResponseError, web}; -use actix_web::web::Query; -use filesys::file_exists::file_exists; -use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use log::{error, info}; - -use crate::shared_state::app_control_state::AppControlState; -use crate::web_server::server_state::ServerState; - -#[derive(Deserialize)] -pub struct GetNextAudioQuery { - pub cursor: u64, -} - -#[derive(Serialize)] -pub struct GetNextAudioFileResponse { - pub success: bool, - pub is_paused: bool, - pub audio_filename_platform: Option, - /// The audio filename, in a Unix style (forward slashes). - /// Note, this might have a windows drive letter. - pub audio_filename_unixy: Option, - pub next_cursor: u64, -} - -#[derive(Debug, Serialize)] -pub enum GetNextAudioFileError { - ServerError, -} - -impl ResponseError for GetNextAudioFileError { - fn status_code(&self) -> StatusCode { - match *self { - GetNextAudioFileError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, - } - } - - fn error_response(&self) -> HttpResponse { - serialize_as_json_error(self) - } -} - -// NB: Not using derive_more::Display since Clion doesn't understand it. -impl std::fmt::Display for GetNextAudioFileError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -pub async fn get_next_audio_file_handler( - _http_request: HttpRequest, - control_state: web::Data>, - server_state: web::Data>, - request: Query, -) -> Result { - - info!("Requested cursor: {}", request.cursor); - - let is_paused = control_state.is_paused() - .map_err(|err| { - error!("Error: {:?}", err); - GetNextAudioFileError::ServerError - })?; - - - let audio_file_dir = server_state.save_directory.get_audio_files_dir_v1(); - - let maybe_audio_filename = format!("{}.wav", request.cursor); - let maybe_audio_filename = audio_file_dir.join(maybe_audio_filename); - - info!("Hypothetical audio file: {:?}", maybe_audio_filename); - - let mut next_cursor; - let mut audio_filename : Option = None; - let mut audio_filename_unixy : Option = None; - - if file_exists(&maybe_audio_filename) { - next_cursor = request.cursor + 1; - audio_filename = maybe_audio_filename.to_str() - .map(|s| s.to_string()); - audio_filename_unixy = audio_filename.as_deref() - .map(|s| s.to_string()) - .map(|s| s.replace("\\", "/")); - } else { - next_cursor = 0; - audio_filename = None; - }; - - let maybe_next_audio_filename = format!("{}.wav", next_cursor); - let maybe_next_audio_filename = audio_file_dir.join(maybe_next_audio_filename); - - if !file_exists(&maybe_next_audio_filename) { - next_cursor = 0; - } - - let response = GetNextAudioFileResponse { - success: true, - is_paused, - next_cursor, - audio_filename_platform: audio_filename, - audio_filename_unixy, - }; - - let body = serde_json::to_string(&response) - .map_err(|e| GetNextAudioFileError::ServerError)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/index_handler.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/index_handler.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/mod.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/mod.rs deleted file mode 100644 index 53e34478ba..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod get_next_audio_file_handler; -pub mod index_handler; -pub mod next_audio_file_handler; -pub mod openai_inference_handler; diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/next_audio_file_handler.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/next_audio_file_handler.rs deleted file mode 100644 index d278efdbed..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/next_audio_file_handler.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::sync::Arc; - -use actix_http::StatusCode; -use actix_web::{HttpRequest, HttpResponse, ResponseError, web}; -use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use log::error; - -use crate::shared_state::app_control_state::AppControlState; - -#[derive(Serialize)] -pub struct NextAudioFileResponse { - pub success: bool, - pub is_paused: bool, -} - -#[derive(Debug, Serialize)] -pub enum NextAudioFileError { - ServerError, -} - -impl ResponseError for NextAudioFileError { - fn status_code(&self) -> StatusCode { - match *self { - NextAudioFileError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, - } - } - - fn error_response(&self) -> HttpResponse { - serialize_as_json_error(self) - } -} - -// NB: Not using derive_more::Display since Clion doesn't understand it. -impl std::fmt::Display for NextAudioFileError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -pub async fn next_audio_file_handler( - _http_request: HttpRequest, - control_state: web::Data> -) -> Result { - - let is_paused = control_state.is_paused() - .map_err(|err| { - error!("Error: {:?}", err); - NextAudioFileError::ServerError - })?; - - let response = NextAudioFileResponse { - success: true, - is_paused, - }; - - let body = serde_json::to_string(&response) - .map_err(|e| NextAudioFileError::ServerError)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/openai_inference_handler.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/openai_inference_handler.rs deleted file mode 100644 index 16b8bcbe13..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/misc/openai_inference_handler.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::sync::Arc; - -use actix_http::StatusCode; -use actix_web::{HttpRequest, HttpResponse, ResponseError, web}; -use async_openai::Client; -use async_openai::types::CreateCompletionRequestArgs; -use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use log::{error, info}; - -use crate::shared_state::app_control_state::AppControlState; - -#[derive(Serialize)] -pub struct OpenAiInferenceResponse { - pub success: bool, - pub openai_results: String, -} - -#[derive(Debug, Serialize)] -pub enum OpenAiInferenceError { - ServerError, -} - -impl ResponseError for OpenAiInferenceError { - fn status_code(&self) -> StatusCode { - match *self { - OpenAiInferenceError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, - } - } - - fn error_response(&self) -> HttpResponse { - serialize_as_json_error(self) - } -} - -// NB: Not using derive_more::Display since Clion doesn't understand it. -impl std::fmt::Display for OpenAiInferenceError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -pub async fn openai_inference_handler( - _http_request: HttpRequest, - control_state: web::Data>, - openai_client: web::Data>, -) -> Result { - - let article = r#" -The U.S. military has been monitoring a suspected Chinese surveillance balloon that has been hovering over the northern U.S. for the past few days, and military and defense leaders have discussed shooting it out of the sky, according to two U.S. officials and a senior defense official. - -“The United States government has detected and is tracking a high-altitude surveillance balloon that is over the continental United States right now,” Pentagon spokesperson Brig. Gen. Pat Ryder told NBC News. “We continue to track and monitor it closely.” - -“Once the balloon was detected, the U.S. government acted immediately to protect against the collection of sensitive information,” Ryder said. - "#.to_string(); - - let prompt = format!(r#"The following is a news article: - - {} - - Please reword this article as if it was spoken by a reporter. - "#, article); - - - let request = CreateCompletionRequestArgs::default() - .model("text-davinci-003") - .prompt(prompt) - .max_tokens(1200_u16) - .build() - .map_err(|err| { - error!("Could not create OpenAI request: {:?}", err); - OpenAiInferenceError::ServerError - })?; - - let response = openai_client - .completions() - .create(request) - .await - .map_err(|err| { - error!("Error calling OpenAI: {:?}", err); - OpenAiInferenceError::ServerError - })?; - - info!("Open AI response: {:?}", response); - - let text = response.choices.get(0) - .map(|option| option.text.clone()) - .unwrap_or("".to_string()); - - let response = OpenAiInferenceResponse { - success: true, - openai_results: text, - }; - - let body = serde_json::to_string(&response) - .map_err(|e| OpenAiInferenceError::ServerError)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/mod.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/mod.rs deleted file mode 100644 index d25e05f091..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod level; -pub mod misc; -pub mod news_stories; diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/get_next_news_story_audio_file_handler.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/get_next_news_story_audio_file_handler.rs deleted file mode 100644 index 4a22f02067..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/get_next_news_story_audio_file_handler.rs +++ /dev/null @@ -1,188 +0,0 @@ -use std::path::PathBuf; -use std::sync::Arc; - -use actix_http::StatusCode; -use actix_web::{HttpRequest, HttpResponse, ResponseError, web}; -use actix_web::web::Query; -use filesys::file_exists::file_exists; -use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use log::{error, info, warn}; -use rand::seq::SliceRandom; -use sqlite_queries::queries::by_table::news_stories::get_news_story_by_token::get_news_story_by_token; -use sqlite_queries::queries::by_table::tts_render_tasks::list::list_tts_render_tasks_for_story_token::list_tts_render_tasks_for_story_token; -use sqlite_queries::queries::by_table::tts_render_tasks::list::tts_render_task::TtsRenderTask; -use tokens::tokens::news_stories::NewsStoryToken; - -use crate::shared_state::app_control_state::AppControlState; -use crate::web_server::handlers::misc::get_next_audio_file_handler::GetNextAudioFileError; -use crate::web_server::server_state::ServerState; - -#[derive(Deserialize, Debug)] -pub struct GetNextNewsStoryAudioFileQuery { - /// News Story Token. REQUIRED. - pub news_story_token: Option, - - /// Audio cursor, 0-indexed. - pub audio_cursor: Option, -} - -#[derive(Serialize, Debug)] -pub struct GetNextNewsStoryAudioFileResponse { - pub success: bool, - pub news_story_token: NewsStoryToken, - - //pub original_news_canonical_url: String, - //pub original_news_title: String, - - /// The number of audio files in the current sequence. - pub sequence_audio_file_count: u64, - - /// Current audio cursor (1-indexed). This is the one to play. - pub current_audio_index: u64, - - /// The local filesystem path of the audio file. - pub audio_file_path: PathBuf, - - /// The local headline image file path. - pub headline_image_file_path: PathBuf, - - /// Whether there's a next cursor in the current sequence. - pub has_next_in_sequence: bool, - - /// If there's a next cursor in the current sequence, this is it. - /// If no such cursor, the field will be set to JSON NULL. - pub maybe_next_cursor: Option, - - /// If there's a next cursor in the current sequence, this is it. - /// If no such cursor, the field will be set to the sigil "-1". - /// This is for Unreal Engine's sake, which is sloppy with handling JSON. - pub maybe_next_cursor_else_sigil_value: i64, - - //pub audio_total_duration_seconds: u64, -} - -#[derive(Debug, Serialize)] -pub enum GetNextNewsStoryAudioFileError { - ServerError, - BadRequest, - NotFound, -} - -impl ResponseError for GetNextNewsStoryAudioFileError { - fn status_code(&self) -> StatusCode { - match *self { - GetNextNewsStoryAudioFileError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, - GetNextNewsStoryAudioFileError::BadRequest => StatusCode::BAD_REQUEST, - GetNextNewsStoryAudioFileError::NotFound => StatusCode::NOT_FOUND, - } - } - - fn error_response(&self) -> HttpResponse { - serialize_as_json_error(self) - } -} - -// NB: Not using derive_more::Display since Clion doesn't understand it. -impl std::fmt::Display for GetNextNewsStoryAudioFileError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -pub async fn get_next_news_story_audio_file_handler( - _http_request: HttpRequest, - control_state: web::Data>, - server_state: web::Data>, - query: Query, -) -> Result { - - warn!("get_next_news_story_audio_file_handler() : {:?}", &query); - - let news_story_token = query.news_story_token - .clone() - .ok_or(GetNextNewsStoryAudioFileError::BadRequest)?; - - let query_result = get_news_story_by_token( - &server_state.sqlite_pool, - &news_story_token - ).await; - - let news_story = match query_result { - Ok(Some(news_story)) => news_story, - Ok(None) => return Err(GetNextNewsStoryAudioFileError::NotFound), - Err(err) => { - error!("Database error: {:?}", err); - return Err(GetNextNewsStoryAudioFileError::NotFound) - }, - }; - - let story_type = "news_story"; // TODO: Enumlike. - let story_token = news_story_token.as_str(); - - let tts_render_tasks = list_tts_render_tasks_for_story_token( - story_type, - story_token, - &server_state.sqlite_pool) - .await - .map_err(|err| { - error!("Database error: {:?}", err); - GetNextNewsStoryAudioFileError::ServerError - })?; - - let audio_cursor = query.audio_cursor.unwrap_or(0) as usize; - - let tts_render_task : &TtsRenderTask = match tts_render_tasks.get(audio_cursor) { - Some(task) => task, - None => { - warn!("TTS task not found for NewsStoryToken {:?} cursor {}", news_story_token, audio_cursor); - return Err(GetNextNewsStoryAudioFileError::NotFound); - } - }; - - let audio_filename = server_state.save_directory - .audio_wav_file_for_news_story(&news_story_token, tts_render_task.sequence_order) - .map_err(|err| { - error!("Path error: {:?}", err); - GetNextNewsStoryAudioFileError::ServerError - })?; - - let headline_image_filename = server_state.save_directory - .generated_headline_image_for_webpage_url(&news_story.original_news_canonical_url) - .map_err(|err| { - error!("Path error: {:?}", err); - GetNextNewsStoryAudioFileError::ServerError - })?; - - let next_audio_cursor = audio_cursor + 1; - - let mut has_next_in_sequence = false; - let mut maybe_next_cursor = None; - - if tts_render_tasks.get(next_audio_cursor).is_some() { - has_next_in_sequence = true; - maybe_next_cursor = Some(next_audio_cursor as u64); - }; - - let response = GetNextNewsStoryAudioFileResponse { - success: true, - news_story_token: news_story_token.clone(), - sequence_audio_file_count: news_story.audio_file_count as u64, - current_audio_index: audio_cursor as u64, - audio_file_path: audio_filename, - headline_image_file_path: headline_image_filename, - has_next_in_sequence, - maybe_next_cursor: maybe_next_cursor.clone(), - maybe_next_cursor_else_sigil_value: maybe_next_cursor - .map(|val| val as i64) - .unwrap_or(-1), - }; - - warn!("Response: {:?}", &response); - - let body = serde_json::to_string(&response) - .map_err(|e| GetNextNewsStoryAudioFileError::ServerError)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/get_next_news_story_handler.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/get_next_news_story_handler.rs deleted file mode 100644 index 85db841ed7..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/get_next_news_story_handler.rs +++ /dev/null @@ -1,106 +0,0 @@ -use std::sync::Arc; - -use actix_http::StatusCode; -use actix_web::{HttpRequest, HttpResponse, ResponseError, web}; -use actix_web::web::Query; -use filesys::file_exists::file_exists; -use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use log::{error, info, warn}; -use rand::seq::SliceRandom; -use sqlite_queries::queries::by_table::news_stories::list::list_news_stories_all::list_news_stories_all; -use sqlite_queries::queries::by_table::news_stories::list::list_news_stories_replayable::list_news_stories_replayable; -use tokens::tokens::news_stories::NewsStoryToken; - -use crate::shared_state::app_control_state::AppControlState; -use crate::web_server::server_state::ServerState; - -#[derive(Deserialize, Debug)] -pub struct GetNextNewsStoryQuery { - pub news_story_token: Option, -} - -#[derive(Serialize, Debug)] -pub struct GetNextNewsStoryFileResponse { - pub success: bool, - pub news_story_token: NewsStoryToken, - pub original_news_canonical_url: String, - pub original_news_title: String, - pub summary_news_title: String, - pub audio_file_count: u64, - pub audio_total_duration_seconds: u64, -} - -#[derive(Debug, Serialize)] -pub enum GetNextNewsStoryFileError { - ServerError, -} - -impl ResponseError for GetNextNewsStoryFileError { - fn status_code(&self) -> StatusCode { - match *self { - GetNextNewsStoryFileError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, - } - } - - fn error_response(&self) -> HttpResponse { - serialize_as_json_error(self) - } -} - -// NB: Not using derive_more::Display since Clion doesn't understand it. -impl std::fmt::Display for GetNextNewsStoryFileError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -pub async fn get_next_news_story_handler( - _http_request: HttpRequest, - control_state: web::Data>, - server_state: web::Data>, - query: Query, -) -> Result { - - warn!("get_next_news_story_handler() : {:?}", &query); - - let mut stories = list_news_stories_replayable(&server_state.sqlite_pool) - .await - .map_err(|err| { - error!("Error querying: {:?}", err); - GetNextNewsStoryFileError::ServerError - })?; - - // TODO: Probably shouldn't fall back on old stories! Maybe flag this. - if stories.is_empty() { - stories = list_news_stories_all(&server_state.sqlite_pool) - .await - .map_err(|err| { - error!("Error querying: {:?}", err); - GetNextNewsStoryFileError::ServerError - })?; - } - - // TODO: Use history information to skip recently played. - - let story = stories.choose(&mut rand::thread_rng()) - .ok_or(GetNextNewsStoryFileError::ServerError)?; - - let response = GetNextNewsStoryFileResponse { - success: true, - news_story_token: story.news_story_token.clone(), - original_news_canonical_url: story.original_news_canonical_url.clone(), - original_news_title: story.original_news_title.clone(), - summary_news_title: story.summary_news_title.clone(), - audio_file_count: story.audio_file_count as u64, - audio_total_duration_seconds: story.audio_total_duration_seconds as u64, - }; - - warn!("Response: {:?}", &response); - - let body = serde_json::to_string(&response) - .map_err(|e| GetNextNewsStoryFileError::ServerError)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/mod.rs b/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/mod.rs deleted file mode 100644 index 3bcbf0e772..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/handlers/news_stories/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod get_next_news_story_audio_file_handler; -pub mod get_next_news_story_handler; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/web_server/launch_web_server.rs b/crates/programs/aichatbot-sidecar/src/web_server/launch_web_server.rs deleted file mode 100644 index cc74163ae0..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/launch_web_server.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::sync::Arc; - -use actix_helpers::route_builder::RouteBuilder; -use actix_web::{App, HttpResponse, HttpServer, web}; -use async_openai::Client; -use errors::AnyhowResult; -use http_server_common::endpoints::root_index::get_root_index; -use sqlx::{Pool, Sqlite}; - -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::app_control_state::AppControlState; -use crate::web_server::handlers::level::get_current_level::get_current_level_handler; -use crate::web_server::handlers::misc::get_next_audio_file_handler::get_next_audio_file_handler; -use crate::web_server::handlers::misc::next_audio_file_handler::next_audio_file_handler; -use crate::web_server::handlers::misc::openai_inference_handler::openai_inference_handler; -use crate::web_server::handlers::news_stories::get_next_news_story_audio_file_handler::get_next_news_story_audio_file_handler; -use crate::web_server::handlers::news_stories::get_next_news_story_handler::get_next_news_story_handler; -use crate::web_server::server_state::ServerState; - -pub struct LaunchWebServerArgs { - pub app_control_state: Arc, - pub openai_client: Arc, - pub save_directory: SaveDirectory, - pub sqlite_pool: Pool, -} - -pub async fn launch_web_server(args: LaunchWebServerArgs) -> AnyhowResult<()> { - - let server_state = Arc::new(ServerState { - app_control_state: args.app_control_state.clone(), - openai_client: args.openai_client.clone(), - save_directory: args.save_directory, - sqlite_pool: args.sqlite_pool, - }); - - HttpServer::new(move || { - let app = App::new() - .app_data(web::Data::new(args.app_control_state.clone())) - .app_data(web::Data::new(args.openai_client.clone())) - .app_data(web::Data::new(server_state.clone())); - - let mut route_builder = RouteBuilder::from_app(app); - - let app = route_builder - .add_get("/", get_root_index) - .add_get("/get_next_audio", get_next_audio_file_handler) - .add_post("/next_audio", next_audio_file_handler) - .add_get("/openai", openai_inference_handler) - .add_get("/news_story/next_story", get_next_news_story_handler) - .add_get("/news_story/audio", get_next_news_story_audio_file_handler) - .add_get("/current_level", get_current_level_handler) - .into_app(); - - /*app.service( - web::resource("/next") - .route(web::get().to(get_next_audio_file_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - .service( - web::resource("/next") - .route(web::get().to(get_next_audio_file_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - )*/ - - app - }) - .bind("localhost:23333")? - .workers(8) - .run() - .await?; - - Ok(()) -} \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/web_server/mod.rs b/crates/programs/aichatbot-sidecar/src/web_server/mod.rs deleted file mode 100644 index 42d5a7d424..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod handlers; -pub mod launch_web_server; -pub mod server_state; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/web_server/server_state.rs b/crates/programs/aichatbot-sidecar/src/web_server/server_state.rs deleted file mode 100644 index a19f63b7c6..0000000000 --- a/crates/programs/aichatbot-sidecar/src/web_server/server_state.rs +++ /dev/null @@ -1,15 +0,0 @@ -use std::sync::Arc; - -use async_openai::Client; -use sqlx::{Pool, Sqlite}; - -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::app_control_state::AppControlState; - -#[derive(Clone)] -pub struct ServerState { - pub app_control_state: Arc, - pub openai_client: Arc, - pub save_directory: SaveDirectory, - pub sqlite_pool: Pool, -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/main_loop.rs deleted file mode 100644 index 77896c4d2a..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/main_loop.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::tts_render_tasks::tts_render_status::TtsRenderStatus; -use enums::by_table::web_scraping_targets::scraping_status::ScrapingStatus; -use errors::AnyhowResult; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::tts_render_tasks::list::list_tts_render_tasks_awaiting_render::list_tts_render_tasks_awaiting_render; -use sqlite_queries::queries::by_table::web_scraping_targets::insert_web_scraping_target::{Args, insert_web_scraping_target}; -use sqlx::sqlite::SqlitePoolOptions; -use strum::IntoEnumIterator; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; -use web_scrapers::payloads::web_scraping_target::WebScrapingTarget; -use web_scrapers::sites::cnn::cnn_indexer::{cnn_indexer, CnnFeed}; -use web_scrapers::sites::techcrunch::techcrunch_indexer::{techcrunch_indexer, TechcrunchFeed}; - -use crate::shared_state::job_state::JobState; -use crate::workers::audio::fakeyou_audio_create::process_single_record::process_single_record; - -/// Get audio jobs and kick off FakeYou requests -pub async fn fakeyou_audio_create_main_loop(job_state: Arc) { - loop { - debug!("fakeyou_audio_create main loop"); - - while job_state.app_control_state.is_fakeyou_paused() { - thread::sleep(Duration::from_secs(5)); - } - - single_job_loop_iteration(&job_state).await; - - info!("fakeyou_audio_create loop finished; waiting..."); - thread::sleep(Duration::from_secs(60)); - } -} - -// NB: No failures at this level, because we don't want to prevent progress on a stuck feed. -async fn single_job_loop_iteration(job_state: &Arc) { - let statuses = vec![TtsRenderStatus::New, TtsRenderStatus::Failed]; - for status in statuses { - scrape_jobs_of_status(status, job_state).await; - } -} - -async fn scrape_jobs_of_status(status: TtsRenderStatus, job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("fakeyou_audio_create querying {:?} targets from id > {} ...", &status, last_id); - - let query_result = list_tts_render_tasks_awaiting_render( - status, last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Render audio: {}/{}", target.story_type, target.story_token); - - while job_state.app_control_state.is_fakeyou_paused() { - thread::sleep(Duration::from_secs(5)); - } - - let result = process_single_record(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(1)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/mod.rs deleted file mode 100644 index c8e8378aeb..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_record; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/process_single_record.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/process_single_record.rs deleted file mode 100644 index c1a3c742b9..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_create/process_single_record.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::sync::Arc; - -use errors::{anyhow, AnyhowResult}; -use fakeyou_client::api::tts_inference::CreateTtsInferenceRequest; -use idempotency::uuid::generate_random_uuid; -use log::{error, info}; -use sqlite_queries::queries::by_table::tts_render_tasks::list::tts_render_task::TtsRenderTask; -use sqlite_queries::queries::by_table::tts_render_tasks::update::update_tts_render_task_successfully_submitted::Args as SuccessArgs; -use sqlite_queries::queries::by_table::tts_render_tasks::update::update_tts_render_task_successfully_submitted::update_tts_render_task_successfully_submitted; -use sqlite_queries::queries::by_table::tts_render_tasks::update::update_tts_render_task_unsuccessfully_submitted::Args as UnsuccessfulArgs; -use sqlite_queries::queries::by_table::tts_render_tasks::update::update_tts_render_task_unsuccessfully_submitted::update_tts_render_task_unsuccessfully_submitted; -use tokens::tokens::tts_models::TtsModelToken; - -use crate::shared_state::job_state::JobState; - -pub async fn process_single_record(target: &TtsRenderTask, job_state: &Arc) -> AnyhowResult<()> { - - info!("Posting FakeYou create TTS request..."); - - let tts_model_token = TtsModelToken::new_from_str(&target.tts_voice_identifier); - let uuid_idempotency_token = generate_random_uuid(); - let tts_render_attempts = target.tts_render_attempts + 1; - - let result = job_state - .fakeyou_client - .create_tts_inference_with_backoff(CreateTtsInferenceRequest { - uuid_idempotency_token: &uuid_idempotency_token, - tts_model_token: &tts_model_token, - inference_text: &target.full_text, - }).await; - - match result { - Err(err) => { - error!("problem submitting to FakeYou: {:}", err); - - update_tts_render_task_unsuccessfully_submitted(UnsuccessfulArgs { - tts_render_task_token: &target.token, - tts_render_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - }, - Ok(res) => { - if !res.success { - error!("unknown problem in submitting TTS request to FakeYou"); - - update_tts_render_task_unsuccessfully_submitted(UnsuccessfulArgs { - tts_render_task_token: &target.token, - tts_render_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - } else { - update_tts_render_task_successfully_submitted(SuccessArgs { - tts_render_task_token: &target.token, - tts_inference_job_token: &res.inference_job_token.ok_or(anyhow!("no token"))?, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - } - }, - } - - Ok(()) -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/main_loop.rs deleted file mode 100644 index 7bdb379f46..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/main_loop.rs +++ /dev/null @@ -1,96 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::tts_render_tasks::tts_render_status::TtsRenderStatus; -use enums::by_table::web_scraping_targets::scraping_status::ScrapingStatus; -use errors::AnyhowResult; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::tts_render_tasks::list::list_tts_render_tasks_awaiting_download::list_tts_render_tasks_awaiting_download; -use sqlite_queries::queries::by_table::tts_render_tasks::list::list_tts_render_tasks_awaiting_render::list_tts_render_tasks_awaiting_render; -use sqlite_queries::queries::by_table::web_scraping_targets::insert_web_scraping_target::{Args, insert_web_scraping_target}; -use sqlx::sqlite::SqlitePoolOptions; -use strum::IntoEnumIterator; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; -use web_scrapers::payloads::web_scraping_target::WebScrapingTarget; -use web_scrapers::sites::cnn::cnn_indexer::{cnn_indexer, CnnFeed}; -use web_scrapers::sites::techcrunch::techcrunch_indexer::{techcrunch_indexer, TechcrunchFeed}; - -use crate::shared_state::job_state::JobState; -use crate::workers::audio::fakeyou_audio_download::process_single_record::process_single_record; - -/// See if jobs are complete and download the audio. -pub async fn fakeyou_audio_download_main_loop(job_state: Arc) { - loop { - debug!("fakeyou_audio_download main loop"); - - while job_state.app_control_state.is_fakeyou_paused() { - thread::sleep(Duration::from_secs(5)); - } - - query_and_process_jobs(&job_state).await; - - info!("fakeyou_audio_download loop finished; waiting..."); - thread::sleep(Duration::from_secs(60)); - } -} - - -async fn query_and_process_jobs(job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("fakeyou_audio_create querying targets from id > {} ...", last_id); - - let query_result = list_tts_render_tasks_awaiting_download( - last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Download audio: {}/{}", target.story_type, target.story_token); - - while job_state.app_control_state.is_fakeyou_paused() { - thread::sleep(Duration::from_secs(5)); - } - - let result = process_single_record(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(1)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/mod.rs deleted file mode 100644 index c8e8378aeb..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_record; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/process_single_record.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/process_single_record.rs deleted file mode 100644 index 0eafcc3268..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/fakeyou_audio_download/process_single_record.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::io::Cursor; -use std::sync::Arc; - -use errors::{anyhow, AnyhowResult}; -use fakeyou_client::api::tts_inference::{CreateTtsInferenceRequest, TtsInferenceJobStatusStatePayload}; -use fakeyou_client::get_audio_url::get_audio_url; -use log::{error, info}; -use media::decode_basic_audio_info::decode_basic_audio_bytes_info; -use sqlite_queries::queries::by_table::tts_render_tasks::list::tts_render_task::TtsRenderTask; -use sqlite_queries::queries::by_table::tts_render_tasks::update::update_tts_render_task_successfully_downloaded::Args; -use sqlite_queries::queries::by_table::tts_render_tasks::update::update_tts_render_task_successfully_downloaded::update_tts_render_task_successfully_downloaded; -use tokens::tokens::news_stories::NewsStoryToken; -use tokens::tokens::tts_models::TtsModelToken; -use tokens::tokens::tts_render_tasks::TtsRenderTaskToken; - -use crate::shared_state::job_state::JobState; - -pub async fn process_single_record(target: &TtsRenderTask, job_state: &Arc) -> AnyhowResult<()> { - - info!("Attempting to download audio..."); - - let inference_job_token = match &target.maybe_inference_job_token { - None => return Err(anyhow!("tts result has no inference job token")), - Some(token) => token.to_string(), - }; - - let result = job_state - .fakeyou_client - .get_tts_inference_job_status(&inference_job_token).await; - - match result { - Err(err) => { - error!("problem submitting to FakeYou: {:}", err); - - // TODO: Errors - //update_tts_render_task_unsuccessfully_submitted(UnsuccessfulArgs { - // tts_render_task_token: &target.token, - // tts_render_attempts, - // sqlite_pool: &job_state.sqlite_pool, - //}).await?; - }, - Ok(res) => { - match res.state { - None => { - error!("unknown problem in checking FakeYou TTS inference job status"); - // TODO: Errors - //update_tts_render_task_unsuccessfully_submitted(UnsuccessfulArgs { - // tts_render_task_token: &target.token, - // tts_render_attempts, - // sqlite_pool: &job_state.sqlite_pool, - //}).await?; - } - Some(payload) => { - process_download(&target, &payload, job_state).await?; - } - } - }, - } - - Ok(()) -} - -async fn process_download(target: &TtsRenderTask, payload: &TtsInferenceJobStatusStatePayload, job_state: &Arc) -> AnyhowResult<()> { - let tts_result_token = match &payload.maybe_result_token { - None => return Ok(()), // TODO: Wait - Some(result_token) => result_token.to_string(), - }; - - let bucket_path = match &payload.maybe_public_bucket_wav_audio_path { - None => return Ok(()), // TODO: Wait - Some(path) => path.to_string(), - }; - - let audio_url = get_audio_url(&bucket_path, true); - let news_story_token = NewsStoryToken::new_from_str(&target.story_token); - - { - let directory = job_state.save_directory.directory_for_audio(&news_story_token)?; - std::fs::create_dir_all(&directory)?; - } - - let download_filename = job_state.save_directory - .audio_wav_file_for_news_story(&news_story_token, target.sequence_order)?; - - { - let response = reqwest::get(&audio_url).await?; - let mut file = std::fs::File::create(&download_filename)?; - let mut content = Cursor::new(response.bytes().await?); - std::io::copy(&mut content, &mut file)?; - } - - let audio_info = { - let bytes = std::fs::read(&download_filename)?; - decode_basic_audio_bytes_info( - &bytes, - Some("audio/wav"), - Some(".wav"))? - }; - - let audio_duration_millis = audio_info.duration_millis.unwrap_or(0) as i64; - - update_tts_render_task_successfully_downloaded(Args { - tts_render_task_token: &target.token, - tts_result_token: &tts_result_token, - result_url: &audio_url, - audio_duration_millis, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - - Ok(()) -} \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/audio/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/audio/mod.rs deleted file mode 100644 index 7dd1ee36ce..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/audio/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod fakeyou_audio_create; -pub mod fakeyou_audio_download; diff --git a/crates/programs/aichatbot-sidecar/src/workers/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/mod.rs deleted file mode 100644 index a73d738a31..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod audio; -pub mod news_stories; -pub mod web; diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/mod.rs deleted file mode 100644 index 60cc61835b..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod phase_1; -pub mod phase_2; -pub mod phase_3; -pub mod phase_4; -pub mod phase_5; diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/mod.rs deleted file mode 100644 index 3c625d8dd8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod news_story_greenlighting; diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/main_loop.rs deleted file mode 100644 index 7dd3d01859..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/main_loop.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_greenlight::list_news_story_productions_awaiting_greenlight; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_1::news_story_greenlighting::process_target_record::process_target_record; - -/// Decide which potential news stories to greenlight -pub async fn news_story_greenlighting_main_loop(job_state: Arc) { - loop { - debug!("news_story_greenlighting main loop iteration start"); - - query_and_process_all_batches(&job_state).await; - - debug!("news_story_greenlighting loop finished; waiting..."); - thread::sleep(Duration::from_secs(5)); - } -} - -async fn query_and_process_all_batches(job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("news_story_greenlighting querying targets from id > {} ...", last_id); - - let query_result = list_news_story_productions_awaiting_greenlight( - last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("process greenlighting for {}", target.news_story_token); - let result = process_target_record(&target, job_state).await; - - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - thread::sleep(Duration::from_millis(100)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/mod.rs deleted file mode 100644 index 169dfbe320..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod main_loop; -pub mod process_target_record; -pub mod site_handlers; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/process_target_record.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/process_target_record.rs deleted file mode 100644 index a9b959c23d..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/process_target_record.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::sync::Arc; - -use enums::common::sqlite::skip_reason::SkipReason; -use enums::common::sqlite::web_content_type::WebContentType; -use errors::AnyhowResult; -use log::info; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_production_greenlit_status::{Args, update_news_story_production_greenlit_status}; - -use crate::persistence::load_scraped_result::load_scraped_result; -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_1::news_story_greenlighting::site_handlers::cnn_greenlighting::cnn_greenlighting; - -pub async fn process_target_record(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - // TODO: Decide which articles to skip with heuristics (and soon AI)! - - let mut maybe_skip_reason = None; - - { - let scraping_result = load_scraped_result( - &target.original_news_canonical_url, - &job_state.save_directory).await?; - - let body_text = scraping_result.body_text.trim(); - - if body_text.is_empty() || body_text.len() < 50 { - maybe_skip_reason = Some(SkipReason::EmptyContent); - } - } - - if maybe_skip_reason.is_none() { - maybe_skip_reason = match target.web_content_type { - WebContentType::CnnArticle => cnn_greenlighting(target), - _ => None, - }; - } - - let is_greenlit = maybe_skip_reason.is_none(); - - info!("news story {} greenlit: {}", &target.news_story_token, is_greenlit); - - update_news_story_production_greenlit_status(Args { - news_story_token: &target.news_story_token, - maybe_skip_reason, - is_greenlit, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - - Ok(()) -} - diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/site_handlers/cnn_greenlighting.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/site_handlers/cnn_greenlighting.rs deleted file mode 100644 index edbcbca995..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/site_handlers/cnn_greenlighting.rs +++ /dev/null @@ -1,19 +0,0 @@ -use enums::common::sqlite::skip_reason::SkipReason; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; - -pub fn cnn_greenlighting(target: &NewsStoryProductionItem) -> Option { - - if target.original_news_canonical_url.contains("/deals/") - || target.original_news_canonical_url.contains("cnn-underscored") { - // We got a 3-minute long ad for Levi's with the "/deals/" URL. - // CNN underscored is nothing but ads: https://www.cnn.com/cnn-underscored - return Some(SkipReason::Advertisement); - } - - if target.original_news_canonical_url.contains("/videos/") { - // Video content tends to have little text - return Some(SkipReason::VideoContent); - } - - None -} \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/site_handlers/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/site_handlers/mod.rs deleted file mode 100644 index f3a8391259..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_1/news_story_greenlighting/site_handlers/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod cnn_greenlighting; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/mod.rs deleted file mode 100644 index 5eb6ef30c8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod news_story_image_generation; -pub mod news_story_llm_category_summary; -pub mod news_story_llm_rendition; -pub mod news_story_llm_title_summary; diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/main_loop.rs deleted file mode 100644 index 765c6f198e..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/main_loop.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use enums::common::sqlite::awaitable_job_status::AwaitableJobStatus; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_image_generation::list_news_story_productions_awaiting_image_generation; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_2::news_story_image_generation::process_single_item::process_single_item; - -// TODO: Stop copy/pasting this. Come up with a generalizable task runner with dependencies, etc. - -/// Generate images for the news story -pub async fn news_story_image_generation_main_loop(job_state: Arc) { - loop { - debug!("image generation main loop"); - - single_job_loop_iteration(&job_state).await; - - debug!("image generation finished; waiting..."); - thread::sleep(Duration::from_secs(1)); - } -} - -// NB: No failures at this level, because we don't want to prevent progress on a stuck feed. -async fn single_job_loop_iteration(job_state: &Arc) { - let statuses = vec![AwaitableJobStatus::ReadyWaiting, AwaitableJobStatus::RetryablyFailed]; - for status in statuses { - rendition_jobs_of_status(status, job_state).await; - } -} - -async fn rendition_jobs_of_status(status: AwaitableJobStatus, job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("image generation querying {:?} targets from id > {} ...", &status, last_id); - - let query_result = list_news_story_productions_awaiting_image_generation( - status, last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Rendition for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(5)); // NB: We probably (?) need to throttle API calls to OpenAI - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/process_single_item.rs deleted file mode 100644 index b380ec20d0..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_image_generation/process_single_item.rs +++ /dev/null @@ -1,130 +0,0 @@ -use std::io::Write; -use std::sync::Arc; - -use async_openai::Client; -use async_openai::error::OpenAIError; -use async_openai::types::{CreateCompletionRequestArgs, CreateImageRequest, ImageData, ImageSize, ResponseFormat}; -use base64::{Engine as _, engine::general_purpose}; -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use errors::{anyhow, AnyhowResult}; -use log::{debug, error, info, warn}; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_image_generation_status::Args; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_image_generation_status::update_news_story_image_generation_status; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; - -use crate::persistence::image_generation_debug_data::ImageGenerationDebugData; -use crate::persistence::load_scraped_result::load_scraped_result; -use crate::persistence::rendition_data::RenditionData; -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::job_state::JobState; - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - let scraping_result = load_scraped_result( - &target.original_news_canonical_url, - &job_state.save_directory).await?; - - let title = scraping_result.maybe_title - .unwrap_or("kitsune walking in a forest".to_string()); - - let dalle_prompt = generate_dalle_prompt_with_gpt(&title, &job_state.openai_client).await?; - - let create_request = CreateImageRequest { - n: Some(1), - prompt: dalle_prompt.clone(), - size: Some(ImageSize::S1024x1024), - response_format: Some(ResponseFormat::B64Json), - user: Some("article".to_string()), - }; - - // TODO: Save both prompts for debugging. - - let response = job_state.openai_client - .images() - .create(create_request) - .await?; - - let maybe_image = response.data.get(0) - .map(|image| image.as_ref()); - - match maybe_image { - Some(ImageData::B64Json(image_data)) => { - let decoded_bytes = general_purpose::STANDARD.decode(image_data.as_bytes())?; - - let image_filename = job_state.save_directory - .generated_headline_image_for_webpage_url(&target.original_news_canonical_url)?; - - let mut file = std::fs::File::create(image_filename)?; - file.write_all(&decoded_bytes)?; - } - _ => {}, - } - - let debug_data = ImageGenerationDebugData { - image_generation_prompt: dalle_prompt.to_string(), - maybe_preconditioning_prompt: None, // TODO: Plumb this through. - }; - - let yaml_filename = job_state.save_directory - .image_generation_prompt_debug_file_webpage_url(&target.original_news_canonical_url)?; - - let _r = debug_data.write_to_yaml_file(yaml_filename)?; - - let image_generation_attempts = target.image_generation_attempts + 1; - - update_news_story_image_generation_status(Args { - news_story_token: &target.news_story_token, - is_successful: true, - image_generation_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - -// { -// let yaml_filename = job_state.save_directory -// .rendition_file_for_webpage_url(&target.original_news_canonical_url)?; -// rendition_data.write_to_yaml_file(yaml_filename)?; -// } - - Ok(()) -} - -async fn generate_dalle_prompt_with_gpt(headline: &str, openai_client: &Arc) -> AnyhowResult { - info!("Building OpenAI Request (GPT for Dall-E prompt)..."); - - let mut prompt = r#" - Turn this headline into a five word or less summary, then add five descriptive adjectives, - then add the most fitting art style or director. Then describe a setting and potential objects - in this scene. Describe what a photo or painting of this might look like: - "#.to_string(); - - prompt.push_str("\n\n"); - prompt.push_str(headline); - - let request = CreateCompletionRequestArgs::default() - .model("text-davinci-003") - .prompt(prompt) - .max_tokens(2500_u16) - .build() - .map_err(|err| { - error!("Error building request: {:?}", err); - err - })?; - - debug!("Making OpenAI Request (GPT for Dall-E prompt)..."); - - let response = openai_client - .completions() - .create(request) - .await - .map_err(|err| { - error!("OpenAI Error: {:?}", err); - err - })?; - - let response_text = response.choices.get(0) - .map(|option| option.text.clone()) - .unwrap_or(headline.to_string()); - - Ok(response_text) -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/main_loop.rs deleted file mode 100644 index fb4e12b41d..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/main_loop.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use enums::common::sqlite::awaitable_job_status::AwaitableJobStatus; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_llm_rendition::list_news_story_productions_awaiting_llm_rendition; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_2::news_story_llm_category_summary::process_single_item::process_single_item; - -/// Project scraped, summarize the categories. -pub async fn news_story_llm_category_summary_main_loop(job_state: Arc) { - loop { - debug!("news_story_llm_category_summary_main_loop main loop"); - - single_job_loop_iteration(&job_state).await; - - debug!("llm_category_summary loop finished; waiting..."); - thread::sleep(Duration::from_secs(1)); - } -} - -// NB: No failures at this level, because we don't want to prevent progress on a stuck feed. -async fn single_job_loop_iteration(job_state: &Arc) { - let statuses = vec![AwaitableJobStatus::ReadyWaiting, AwaitableJobStatus::RetryablyFailed]; - for status in statuses { - rendition_jobs_of_status(status, job_state).await; - } -} - -async fn rendition_jobs_of_status(status: AwaitableJobStatus, job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("web_rendition querying {:?} targets from id > {} ...", &status, last_id); - - let query_result = list_news_story_productions_awaiting_llm_rendition( - status, last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Rendition for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(5)); // NB: We probably (?) need to throttle API calls to OpenAI - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/process_single_item.rs deleted file mode 100644 index 22e30b68f8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_category_summary/process_single_item.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::sync::Arc; - -use async_openai::Client; -use async_openai::error::OpenAIError; -use async_openai::types::CreateCompletionRequestArgs; -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use errors::{anyhow, AnyhowResult}; -use log::{error, info, warn}; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_llm_categorization_status::Args; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_llm_categorization_status::update_news_story_llm_categorization_status; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; - -use crate::gpt_prompts::categorization_gpt_prompt::CategorizationGptPrompt; -use crate::persistence::load_scraped_result::load_scraped_result; -use crate::persistence::rendition_data::RenditionData; -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::job_state::JobState; - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - let scraping_result = load_scraped_result( - &target.original_news_canonical_url, - &job_state.save_directory).await?; - - let prompt = CategorizationGptPrompt::new(&scraping_result.paragraphs); - let prompt = prompt.make_prompt(); - - let rendition_result = call_openai_gpt( - &target.original_news_canonical_url, - &prompt, - &job_state.openai_client - ).await; - - let llm_categorization_attempts = target.llm_categorization_attempts + 1; - - let rendition_data = match rendition_result { - Err(err) => { - error!("Error using GPT: {:?}", err); - - match &err { - WrappedOpenAiError::Other(_) => {} - WrappedOpenAiError::OpenAiError(inner) => { - match inner { - OpenAIError::Reqwest(e) => { error!("Request error: {:?}", e) } - OpenAIError::ApiError(e) => { error!("API error: {:?}", e) } - OpenAIError::JSONDeserialize(e) => { error!("JSON error: {:?}", e) } - OpenAIError::FileSaveError(e) => { error!("File save error: {:?}", e) } - OpenAIError::FileReadError(e) => { error!("File read error: {:?}", e) } - OpenAIError::StreamError(e) => { error!("Stream error: {:?}", e) } - OpenAIError::InvalidArgument(e) => { error!("Invalid args error: {:?}", e) } - } - } - } - - update_news_story_llm_categorization_status(Args { - news_story_token: &target.news_story_token, - is_successful: false, - maybe_categorization: None, - llm_categorization_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - - return Err(anyhow!("OpenAI Rendition Error for {}: {:?}", target.news_story_token, err)); - } - Ok(rendition_data) => rendition_data, - }; - - let categorization = rendition_data.response.trim(); - - // NB: GPT often completes the prompt we used itself, so we grab the last line (presumably output) - let categorization = categorization.split("\n") - .map(|line| line.trim().to_string()) - .filter(|line| line.len() > 5) - .last() - .unwrap_or("".to_string()); - - if categorization.len() < 5 { - update_news_story_llm_categorization_status(Args { - news_story_token: &target.news_story_token, - is_successful: false, - maybe_categorization: None, - llm_categorization_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - - return Err(anyhow!("too short")); - } - - update_news_story_llm_categorization_status(Args { - news_story_token: &target.news_story_token, - is_successful: true, - maybe_categorization: Some(categorization.to_string()), - llm_categorization_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - - Ok(()) -} - -#[derive(Debug)] -pub enum WrappedOpenAiError { - OpenAiError(OpenAIError), - Other(String), -} - -async fn call_openai_gpt(url: &str, prompt: &str, openai_client: &Arc) -> Result { - warn!("Building OpenAI Request..."); - let request = CreateCompletionRequestArgs::default() - .model("text-davinci-003") - .prompt(prompt) - .max_tokens(2500_u16) - .build() - .map_err(|err| { - error!("Error building request: {:?}", err); - WrappedOpenAiError::Other(format!("error: {:?}", err)) - })?; - - warn!("Making OpenAI Request..."); - let response = openai_client - .completions() - .create(request) - .await - .map_err(|err| { - error!("OpenAI Error: {:?}", err); - WrappedOpenAiError::OpenAiError(err) - })?; - - info!("Open AI response: {:?}", response); - - let rendition_text = response.choices.get(0) - .map(|option| option.text.clone()) - .unwrap_or("".to_string()); - - Ok(RenditionData { - original_content_url: url.to_string(), - original_prompt: prompt.to_string(), - response: rendition_text, - }) -} - -//fn next_status(rendition_attempts: i64) -> RenditionStatus { -// if rendition_attempts >= 2 { -// RenditionStatus::PermanentlyFailed -// } else { -// RenditionStatus::Failed -// } -//} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/main_loop.rs deleted file mode 100644 index 2b2ffe61eb..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/main_loop.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use enums::common::sqlite::awaitable_job_status::AwaitableJobStatus; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_llm_rendition::list_news_story_productions_awaiting_llm_rendition; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_2::news_story_llm_rendition::process_single_item::process_single_item; - -/// Project scraped, etc. content into the desired shape with GPT. -pub async fn news_story_llm_rendition_main_loop(job_state: Arc) { - loop { - debug!("news_story_llm_rendition_main_loop main loop"); - - single_job_loop_iteration(&job_state).await; - - debug!("gpt_rendition loop finished; waiting..."); - thread::sleep(Duration::from_secs(1)); - } -} - -// NB: No failures at this level, because we don't want to prevent progress on a stuck feed. -async fn single_job_loop_iteration(job_state: &Arc) { - let statuses = vec![AwaitableJobStatus::ReadyWaiting, AwaitableJobStatus::RetryablyFailed]; - for status in statuses { - rendition_jobs_of_status(status, job_state).await; - } -} - -async fn rendition_jobs_of_status(status: AwaitableJobStatus, job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("web_rendition querying {:?} targets from id > {} ...", &status, last_id); - - let query_result = list_news_story_productions_awaiting_llm_rendition( - status, last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Rendition for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(5)); // NB: We probably (?) need to throttle API calls to OpenAI - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/process_single_item.rs deleted file mode 100644 index e1d3f267f0..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_rendition/process_single_item.rs +++ /dev/null @@ -1,137 +0,0 @@ -use std::sync::Arc; - -use async_openai::Client; -use async_openai::error::OpenAIError; -use async_openai::types::CreateCompletionRequestArgs; -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use errors::{anyhow, AnyhowResult}; -use log::{error, info, warn}; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_llm_rendition_status::{Args, update_news_story_llm_rendition_status}; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; - -use crate::gpt_prompts::news_article_prompt::NewsArticlePrompt; -use crate::persistence::load_scraped_result::load_scraped_result; -use crate::persistence::rendition_data::RenditionData; -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::job_state::JobState; - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - let scraping_result = load_scraped_result( - &target.original_news_canonical_url, - &job_state.save_directory).await?; - - let prompt = NewsArticlePrompt::new(&scraping_result.paragraphs); - let prompt = prompt.make_prompt(); - - let rendition_result = call_openai_gpt( - &target.original_news_canonical_url, - &prompt, - &job_state.openai_client - ).await; - - let llm_rendition_attempts = target.llm_rendition_attempts + 1; - - let rendition_data = match rendition_result { - Err(err) => { - error!("Error using GPT: {:?}", err); - - match &err { - WrappedOpenAiError::Other(_) => {} - WrappedOpenAiError::OpenAiError(inner) => { - match inner { - OpenAIError::Reqwest(e) => { error!("Request error: {:?}", e) } - OpenAIError::ApiError(e) => { error!("API error: {:?}", e) } - OpenAIError::JSONDeserialize(e) => { error!("JSON error: {:?}", e) } - OpenAIError::FileSaveError(e) => { error!("File save error: {:?}", e) } - OpenAIError::FileReadError(e) => { error!("File read error: {:?}", e) } - OpenAIError::StreamError(e) => { error!("Stream error: {:?}", e) } - OpenAIError::InvalidArgument(e) => { error!("Invalid args error: {:?}", e) } - } - } - } - - update_news_story_llm_rendition_status(Args { - news_story_token: &target.news_story_token, - is_successful: false, - llm_rendition_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - - return Err(anyhow!("OpenAI Rendition Error for {}: {:?}", target.news_story_token, err)); - } - Ok(rendition_data) => rendition_data, - }; - - update_news_story_llm_rendition_status(Args { - news_story_token: &target.news_story_token, - is_successful: true, - llm_rendition_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - -// update_web_rendition_target(Args { -// canonical_url: &target.original_news_canonical_url, -// rendition_status: RenditionStatus::Success, -// rendition_attempts: target.llm_rendition_attempts + 1, -// sqlite_pool: &job_state.sqlite_pool, -// }).await?; // NB: If these queries fail, we could get stuck. - - { - let yaml_filename = job_state.save_directory - .rendition_file_for_webpage_url(&target.original_news_canonical_url)?; - rendition_data.write_to_yaml_file(yaml_filename)?; - } - - Ok(()) -} - -#[derive(Debug)] -pub enum WrappedOpenAiError { - OpenAiError(OpenAIError), - Other(String), -} - -async fn call_openai_gpt(url: &str, prompt: &str, openai_client: &Arc) -> Result { - warn!("Building OpenAI Request..."); - let request = CreateCompletionRequestArgs::default() - .model("text-davinci-003") - .prompt(prompt) - .max_tokens(2500_u16) - .build() - .map_err(|err| { - error!("Error building request: {:?}", err); - WrappedOpenAiError::Other(format!("error: {:?}", err)) - })?; - - warn!("Making OpenAI Request..."); - let response = openai_client - .completions() - .create(request) - .await - .map_err(|err| { - error!("OpenAI Error: {:?}", err); - WrappedOpenAiError::OpenAiError(err) - })?; - - info!("Open AI response: {:?}", response); - - let rendition_text = response.choices.get(0) - .map(|option| option.text.clone()) - .unwrap_or("".to_string()); - - Ok(RenditionData { - original_content_url: url.to_string(), - original_prompt: prompt.to_string(), - response: rendition_text, - }) -} - -//fn next_status(rendition_attempts: i64) -> RenditionStatus { -// if rendition_attempts >= 2 { -// RenditionStatus::PermanentlyFailed -// } else { -// RenditionStatus::Failed -// } -//} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/main_loop.rs deleted file mode 100644 index 2cf59849ba..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/main_loop.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use enums::common::sqlite::awaitable_job_status::AwaitableJobStatus; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_llm_title_summary::list_news_story_productions_awaiting_llm_title_summary; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_2::news_story_llm_title_summary::process_single_item::process_single_item; - -/// Project scraped, summarize the title. -pub async fn news_story_llm_title_summary_main_loop(job_state: Arc) { - loop { - debug!("news_story_llm_title_summary_main_loop main loop"); - - single_job_loop_iteration(&job_state).await; - - debug!("llm_title_summary loop finished; waiting..."); - thread::sleep(Duration::from_secs(1)); - } -} - -// NB: No failures at this level, because we don't want to prevent progress on a stuck feed. -async fn single_job_loop_iteration(job_state: &Arc) { - let statuses = vec![AwaitableJobStatus::ReadyWaiting, AwaitableJobStatus::RetryablyFailed]; - for status in statuses { - rendition_jobs_of_status(status, job_state).await; - } -} - -async fn rendition_jobs_of_status(status: AwaitableJobStatus, job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("llm_title_summary querying {:?} targets from id > {} ...", &status, last_id); - - let query_result = list_news_story_productions_awaiting_llm_title_summary( - status, last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("LLM title summary for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(5)); // NB: We probably (?) need to throttle API calls to OpenAI - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/process_single_item.rs deleted file mode 100644 index 57cdf13088..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_2/news_story_llm_title_summary/process_single_item.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::sync::Arc; - -use async_openai::Client; -use async_openai::error::OpenAIError; -use async_openai::types::CreateCompletionRequestArgs; -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use errors::{anyhow, AnyhowResult}; -use log::{error, info, warn}; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_llm_title_summary_status::Args; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_llm_title_summary_status::update_news_story_llm_title_summary_status; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; - -use crate::gpt_prompts::concise_title_gpt_prompt::ConciseTitleGptPrompt; -use crate::persistence::load_scraped_result::load_scraped_result; -use crate::persistence::rendition_data::RenditionData; -use crate::persistence::save_directory::SaveDirectory; -use crate::shared_state::job_state::JobState; - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - let scraping_result = load_scraped_result( - &target.original_news_canonical_url, - &job_state.save_directory).await?; - - let prompt = ConciseTitleGptPrompt::new( - scraping_result.maybe_title.as_deref().unwrap_or("Article"), - &scraping_result.paragraphs); - - let prompt = prompt.make_prompt(); - - let rendition_result = call_openai_gpt( - &target.original_news_canonical_url, - &prompt, - &job_state.openai_client - ).await; - - let llm_title_summary_attempts = target.llm_title_summary_attempts + 1; - - let rendition_data = match rendition_result { - Err(err) => { - error!("Error using GPT: {:?}", err); - - match &err { - WrappedOpenAiError::Other(_) => {} - WrappedOpenAiError::OpenAiError(inner) => { - match inner { - OpenAIError::Reqwest(e) => { error!("Request error: {:?}", e) } - OpenAIError::ApiError(e) => { error!("API error: {:?}", e) } - OpenAIError::JSONDeserialize(e) => { error!("JSON error: {:?}", e) } - OpenAIError::FileSaveError(e) => { error!("File save error: {:?}", e) } - OpenAIError::FileReadError(e) => { error!("File read error: {:?}", e) } - OpenAIError::StreamError(e) => { error!("Stream error: {:?}", e) } - OpenAIError::InvalidArgument(e) => { error!("Invalid args error: {:?}", e) } - } - } - } - - update_news_story_llm_title_summary_status(Args { - news_story_token: &target.news_story_token, - is_successful: false, - maybe_title_summary: None, - llm_title_summary_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - - return Err(anyhow!("OpenAI Rendition Error for {}: {:?}", target.news_story_token, err)); - } - - Ok(rendition_data) => rendition_data, - }; - - let title_summary = rendition_data.response.trim(); - - // NB: GPT often completes the prompt we used itself, so we grab the last line (presumably output) - let title_summary = title_summary.split("\n") - .map(|line| line.trim().to_string()) - .filter(|line| line.len() > 5) - .last() - .unwrap_or("".to_string()); - - // NB: GPT often includes quotes in the output. - let title_summary = title_summary.replace("\"", ""); - - if title_summary.len() < 5 { - update_news_story_llm_title_summary_status(Args { - news_story_token: &target.news_story_token, - is_successful: false, - maybe_title_summary: None, - llm_title_summary_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - } - - update_news_story_llm_title_summary_status(Args { - news_story_token: &target.news_story_token, - is_successful: true, - maybe_title_summary: Some(title_summary.to_string()), - llm_title_summary_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck in retry hell. - - Ok(()) -} - -#[derive(Debug)] -pub enum WrappedOpenAiError { - OpenAiError(OpenAIError), - Other(String), -} - -async fn call_openai_gpt(url: &str, prompt: &str, openai_client: &Arc) -> Result { - warn!("Building OpenAI Request..."); - let request = CreateCompletionRequestArgs::default() - .model("text-davinci-003") - .prompt(prompt) - .max_tokens(2500_u16) - .build() - .map_err(|err| { - error!("Error building request: {:?}", err); - WrappedOpenAiError::Other(format!("error: {:?}", err)) - })?; - - warn!("Making OpenAI Request..."); - let response = openai_client - .completions() - .create(request) - .await - .map_err(|err| { - error!("OpenAI Error: {:?}", err); - WrappedOpenAiError::OpenAiError(err) - })?; - - info!("Open AI response: {:?}", response); - - let rendition_text = response.choices.get(0) - .map(|option| option.text.clone()) - .unwrap_or("".to_string()); - - Ok(RenditionData { - original_content_url: url.to_string(), - original_prompt: prompt.to_string(), - response: rendition_text, - }) -} - -//fn next_status(rendition_attempts: i64) -> RenditionStatus { -// if rendition_attempts >= 2 { -// RenditionStatus::PermanentlyFailed -// } else { -// RenditionStatus::Failed -// } -//} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/mod.rs deleted file mode 100644 index 2ea87597df..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod news_story_audio_preprocessing; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/main_loop.rs deleted file mode 100644 index 4d2477a39e..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/main_loop.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use log::{debug, error}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_audio_generation::list_news_story_productions_awaiting_audio_generation; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_3::news_story_audio_preprocessing::process_single_item::process_single_item; - -/// Split text into text segments fit for rendering. -pub async fn news_story_audio_preprocessing_main_loop(job_state: Arc) { - loop { - debug!("news_story_audio_preprocessing main loop"); - - query_and_process_all_batches(&job_state).await; - - debug!("news_story_audio_preprocessing loop finished; waiting..."); - thread::sleep(Duration::from_secs(5)); - } -} - -async fn query_and_process_all_batches(job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("querying targets from id > {} ...", last_id); - - let query_result = list_news_story_productions_awaiting_audio_generation( - last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Split audio for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_millis(100)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/process_single_item.rs deleted file mode 100644 index 1d1ab136c3..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_3/news_story_audio_preprocessing/process_single_item.rs +++ /dev/null @@ -1,184 +0,0 @@ -use std::sync::Arc; - -use errors::AnyhowResult; -use once_cell::sync::Lazy; -use regex::Regex; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_audio_preprocessing_status::Args as UpdateArgs; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_audio_preprocessing_status::update_news_story_audio_preprocessing_status; -use sqlite_queries::queries::by_table::tts_render_tasks::insert_tts_render_task::Args as InsertArgs; -use sqlite_queries::queries::by_table::tts_render_tasks::insert_tts_render_task::insert_tts_render_task; -use tokens::tokens::tts_models::TtsModelToken; - -use crate::configs::fakeyou_voice_option::FakeYouVoiceOption; -use crate::persistence::rendition_data::RenditionData; -use crate::persistence::speakable_monologue::SpeakableMonologue; -use crate::shared_state::job_state::JobState; - -static NEWLINE_REGEX : Lazy = Lazy::new(|| { - Regex::new(r"[\r\n]+").expect("regex should parse") -}); - -static SPACE_REGEX : Lazy = Lazy::new(|| { - Regex::new(r"[\s]+").expect("regex should parse") -}); - -// Regex at current version doesn't support look-around. UGH. -//static SPACE_REGEX : Lazy = Lazy::new(|| { -// Regex::new(r"(?<=.{150,}[\.?])").expect("regex should parse") -//}); - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - let rendition_data = { - let yaml_filename = job_state.save_directory - .rendition_file_for_webpage_url(&target.original_news_canonical_url)?; - RenditionData::try_from_yaml_file(yaml_filename)? - }; - - let text = rendition_data.response.trim(); - - let paragraphs = split_into_manageable_portions(&text); - - let speakable_monologue = SpeakableMonologue { - paragraphs: paragraphs.clone(), - }; - - { - let yaml_filename = job_state.save_directory - .speakable_monologue_file_for_webpage_url(&target.original_news_canonical_url)?; - speakable_monologue.write_to_yaml_file(yaml_filename)?; - } - - let tts_model_token = job_state.app_control_state - .fakeyou_voice() - .unwrap_or(FakeYouVoiceOption::default()) - .tts_model_token(); - - let sequence_length = paragraphs.len() as i64; - - for (i, paragraph) in paragraphs.iter().enumerate() { - let sequence_order = (i + 1) as i64; - - insert_tts_render_task(InsertArgs { - news_story_token: &target.news_story_token, - sequence_order, - sequence_length, - tts_voice_identifier: &tts_model_token, - full_text: ¶graph, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - } - - update_news_story_audio_preprocessing_status(UpdateArgs { - news_story_token: &target.news_story_token, - is_success: true, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - - Ok(()) -} - -fn split_into_manageable_portions(text: &str) -> Vec { - let trimmed_text = text.trim(); - - let mut speakable_portions = Vec::new(); - - for paragraph in NEWLINE_REGEX.split(trimmed_text) { - let trimmed_paragraph = paragraph.trim(); - if trimmed_paragraph.is_empty() { - continue; - } - - if trimmed_paragraph.len() > 250 { - speakable_portions.extend(split_paragraph(&trimmed_paragraph)); - } else { - speakable_portions.push(trimmed_paragraph.to_string()); - } - } - - let filtered = speakable_portions.into_iter() - .filter(|portion| { - match portion.as_ref() { - "." | ":" | "," => false, - _ => true, - } - }) - .collect::>(); - - filtered -} - -fn split_paragraph(text: &str) -> Vec { - let trimmed_text = text.trim(); - - let mut speakable_portions = Vec::new(); - - // TODO: Use a binary search like algorithm instead. Or better, understand the underlying NLP task. - let mut word_buffer = Vec::new(); - let mut word_counter = 0; - let mut character_counter = 0; - let mut should_cut = false; - - for wordlike in SPACE_REGEX.split(trimmed_text) { - let wordlike_trimmed = wordlike.trim(); - - word_counter += 1; - character_counter += wordlike_trimmed.len(); - - word_buffer.push(wordlike_trimmed.to_string()); - - if word_counter > 70 || character_counter > 400 { - should_cut = true; - } - - if should_cut && ( - wordlike_trimmed.ends_with(".") - || wordlike_trimmed.ends_with("?") - || wordlike_trimmed.ends_with("\"") - || wordlike_trimmed.ends_with("!")) { - - speakable_portions.push(word_buffer.join(" ")); - word_buffer.clear(); - - word_counter = 0; - character_counter = 0; - should_cut = false; - } - } - - if word_buffer.len() > 0 { - speakable_portions.push(word_buffer.join(" ")); - } - - speakable_portions -} - -#[cfg(test)] -mod tests { - use crate::workers::news_stories::phase_3::news_story_audio_preprocessing::process_single_item::split_into_manageable_portions; - - #[test] - fn test_split_long_text() { - let text = concat!( - r#"Arkansas Governor Sarah Huckabee Sanders gave a vehement speech Tuesday night in response to President Joe Biden's State of the Union address, "#, - r#"critically comparing herself to the President. Sanders, who is forty years old, connected her age to Biden's, who is eighty, saying that this shows "#, - r#"a divide between the two in generations. She portrayed Biden as unfit to be commander-in-chief and described the current political condition as a "#, - r#"struggle between "normal and crazy". Prior to her line of criticism, Sanders gave a nod to newly established Republican control of the House and said "#, - r#"that Speaker Kevin McCarthy and Senate Republican Leader Mitch McConnell would hold the Biden administration to its word. Serving as White House press "#, - r#"secretary under President Donald Trump, Sanders talked about her memories of a Christmas trip the two took together to Iraq, how the troops cheered upon "#, - r#"their entrance, and the Unity of Americans in the service of their country. On education policy, Sarah Huckabee Sanders spoke about the need for "#, - r#"instruction and not indoctrination for students of all backgrounds, referring to an executive order she passed last year. In statements released ahead of "#, - r#"the address, McConnell and McCarthy both commended the Youngest Governor in the nation for her leadership skills. The response to the State of the Union "#, - r#"was provided by Palin Huckabee Sanders."# - ); - - // TODO: This test isn't very well thought out. We should make better assertions and have more tests. - let results = split_into_manageable_portions(&text); - - assert_eq!(results.len(), 3); // Total paragraph count - - for paragraph in results.iter() { - assert!(results.len() < 450); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/mod.rs deleted file mode 100644 index 7e560cf3a8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod news_story_audio_final_verification; diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/main_loop.rs deleted file mode 100644 index 1271b6d494..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/main_loop.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use enums::common::sqlite::awaitable_job_status::AwaitableJobStatus; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_audio_final_verification::list_news_story_productions_awaiting_audio_final_verification; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_llm_rendition::list_news_story_productions_awaiting_llm_rendition; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_4::news_story_audio_final_verification::process_single_item::process_single_item; - -/// Verify all audio files have been requested, generated, and downloaded. -pub async fn news_story_audio_final_verification_main_loop(job_state: Arc) { - loop { - debug!("news_story_audio_final_verification main loop"); - - query_all_batches(&job_state).await; - - debug!("news_story_audio_final_verification loop finished; waiting..."); - thread::sleep(Duration::from_secs(1)); - } -} - -async fn query_all_batches(job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("audio_final_verification querying targets from id > {} ...", last_id); - - let query_result = list_news_story_productions_awaiting_audio_final_verification( - last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Audio verification for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_millis(100)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/process_single_item.rs deleted file mode 100644 index 3cbb72ab91..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_4/news_story_audio_final_verification/process_single_item.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::sync::Arc; - -use enums::by_table::tts_render_tasks::tts_render_status::TtsRenderStatus; -use errors::AnyhowResult; -use log::{debug, info}; -use once_cell::sync::Lazy; -use regex::Regex; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_audio_finalized_failure::update_news_story_audio_finalized_failure; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_audio_finalized_success::update_news_story_audio_finalized_success; -use sqlite_queries::queries::by_table::tts_render_tasks::list::list_tts_render_tasks_for_story_token::list_tts_render_tasks_for_story_token; - -use crate::shared_state::job_state::JobState; - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - let story_type = "news_story"; - let story_token = target.news_story_token.to_string(); - - let tts_render_tasks = list_tts_render_tasks_for_story_token( - story_type, - &story_token, - &job_state.sqlite_pool).await?; - - let complete_count = tts_render_tasks.iter() - .filter(|target| target.tts_render_status == TtsRenderStatus::Success) - .count(); - - // TODO: Include new column "tts_render_tasks.sequence_length" to verify. Math.max() it. - // This is to prevent a race condition. - let total_count = tts_render_tasks.len(); - - if complete_count != total_count { - // NB: We're still waiting on the TTS tasks to complete. Keep waiting. - debug!("Audio not yet rendered for story: {:?}", target.news_story_token); - return Ok(()) - } - - for tts_render_task in tts_render_tasks.iter() { - match tts_render_task.maybe_audio_duration_millis { - None => { - // TODO: This might be an error given the above ^ - debug!("Audio not yet rendered for story: {:?}", target.news_story_token); - return Ok(()) - } - Some(millis) => { - if millis > 100000 { - // NB: > 1.666 minutes, which is likely a TTS stroke - - update_news_story_audio_finalized_failure( - &target.news_story_token, - &job_state.sqlite_pool, - ).await?; - - return Ok(()) - } - } - } - } - - update_news_story_audio_finalized_success( - &target.news_story_token, - &job_state.sqlite_pool, - ).await?; - - Ok(()) -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/mod.rs deleted file mode 100644 index 4e50542ba6..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod news_story_post_production_finalization; diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/main_loop.rs deleted file mode 100644 index f59fea6625..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/main_loop.rs +++ /dev/null @@ -1,80 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_rendition_targets::rendition_status::RenditionStatus; -use enums::common::sqlite::awaitable_job_status::AwaitableJobStatus; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_audio_final_verification::list_news_story_productions_awaiting_audio_final_verification; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_awaiting_llm_rendition::list_news_story_productions_awaiting_llm_rendition; -use sqlite_queries::queries::by_table::news_story_productions::list::list_news_story_productions_ready_for_debut::list_news_story_productions_ready_for_debut; - -use crate::shared_state::job_state::JobState; -use crate::workers::news_stories::phase_5::news_story_post_production_finalization::process_single_item::process_single_item; - -/// Find in-production stories with all tasks done, then promote them to stories -pub async fn news_story_post_production_finalization_main_loop(job_state: Arc) { - loop { - debug!("news_story_post_production main loop"); - - query_all_batches(&job_state).await; - - debug!("news_story_post_production loop finished; waiting..."); - thread::sleep(Duration::from_secs(1)); - } -} - -async fn query_all_batches(job_state: &Arc) { - const BATCH_SIZE : i64 = 10; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("news_story_post_production querying targets from id > {} ...", last_id); - - let query_result = list_news_story_productions_ready_for_debut( - last_id, BATCH_SIZE, &job_state.sqlite_pool).await; - - let targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - for target in targets { - debug!("Final post production for target: {:?}", target.original_news_canonical_url); - - let result = process_single_item(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_millis(200)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/mod.rs deleted file mode 100644 index 69b2dcb3e8..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod process_single_item; \ No newline at end of file diff --git a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/process_single_item.rs b/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/process_single_item.rs deleted file mode 100644 index 98e59ffde0..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/news_stories/phase_5/news_story_post_production_finalization/process_single_item.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::ops::Add; -use std::sync::Arc; - -use chrono::Duration; -use chrono::Utc; -use enums::by_table::tts_render_tasks::tts_render_status::TtsRenderStatus; -use errors::AnyhowResult; -use log::{debug, info}; -use once_cell::sync::Lazy; -use regex::Regex; -use sqlite_queries::queries::by_table::news_stories::insert_news_story::Args as InsertArgs; -use sqlite_queries::queries::by_table::news_stories::insert_news_story::insert_news_story; -use sqlite_queries::queries::by_table::news_story_productions::list::news_story_production_item::NewsStoryProductionItem; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_post_production_complete::Args as UpdateArgs; -use sqlite_queries::queries::by_table::news_story_productions::update::update_news_story_post_production_complete::update_news_story_post_production_complete; -use sqlite_queries::queries::by_table::tts_render_tasks::list::list_tts_render_tasks_for_story_token::list_tts_render_tasks_for_story_token; - -use crate::shared_state::job_state::JobState; - -/// Stop playing stories after 24 hours elapses -static STORY_FRESHNESS_THRESHOLD : Lazy = Lazy::new(|| { - Duration::days(1) -}); - -pub async fn process_single_item(target: &NewsStoryProductionItem, job_state: &Arc) -> AnyhowResult<()> { - - let story_type = "news_story"; - let story_token = target.news_story_token.to_string(); - - let tts_render_tasks = list_tts_render_tasks_for_story_token( - story_type, - &story_token, - &job_state.sqlite_pool).await?; - - let audio_total_duration_millis : i64 = tts_render_tasks.iter() - .map(|task| task.maybe_audio_duration_millis.unwrap_or(0)) - .sum(); - - let audio_total_duration_seconds = audio_total_duration_millis / 1000; - - // TODO: Include new column "tts_render_tasks.sequence_length" to verify. Math.max() it. - let audio_file_count = tts_render_tasks.len() as i64; - - let replayable_until = Utc::now().add(*STORY_FRESHNESS_THRESHOLD); - - // TODO: Fail on missing data. - let summary_news_title = target.maybe_summary_news_title.as_deref().unwrap_or(""); - let llm_categorization = target.maybe_categorization.as_deref().unwrap_or(""); - - insert_news_story(InsertArgs { - news_story_token: &target.news_story_token, - original_news_canonical_url: &target.original_news_canonical_url, - web_content_type: target.web_content_type, - original_news_title: &target.original_news_title, - summary_news_title, - llm_categorization, - audio_file_count, - audio_total_duration_seconds, - replayable_until, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - - update_news_story_post_production_complete(UpdateArgs { - news_story_token: &target.news_story_token, - sqlite_pool: &job_state.sqlite_pool, - }).await?; - - Ok(()) -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/web/mod.rs deleted file mode 100644 index 2f14cbbc78..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod web_content_scraping; -pub mod web_index_ingestion; diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/main_loop.rs deleted file mode 100644 index 74c7f977c0..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/main_loop.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use enums::by_table::web_scraping_targets::scraping_status::ScrapingStatus; -use errors::AnyhowResult; -use log::{debug, error, info}; -use rand::seq::SliceRandom; -use rand::thread_rng; -use sqlite_queries::queries::by_table::web_scraping_targets::insert_web_scraping_target::{Args, insert_web_scraping_target}; -use sqlite_queries::queries::by_table::web_scraping_targets::list::list_all_web_scraping_targets::list_all_web_scraping_targets; -use sqlite_queries::queries::by_table::web_scraping_targets::list::web_scraping_target::WebScrapingTarget as WebScrapingTargetRecord; -use sqlx::sqlite::SqlitePoolOptions; -use strum::IntoEnumIterator; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; -use web_scrapers::payloads::web_scraping_target::WebScrapingTarget; -use web_scrapers::sites::cnn::cnn_indexer::{cnn_indexer, CnnFeed}; -use web_scrapers::sites::techcrunch::techcrunch_indexer::{techcrunch_indexer, TechcrunchFeed}; - -use crate::shared_state::job_state::JobState; -use crate::workers::web::web_content_scraping::single_target::process_target_record::process_target_record; - -/// Follow up on articles tagged to be indexed by downloading and scraping their contents. -pub async fn web_content_scraping_main_loop(job_state: Arc) { - loop { - debug!("web_content_scraping main loop"); - - while job_state.app_control_state.is_scraping_paused() { - thread::sleep(Duration::from_secs(5)); - } - - single_job_loop_iteration(&job_state).await; - - debug!("web_content_scraping loop finished; waiting..."); - thread::sleep(Duration::from_secs(60)); - } -} - -// NB: No failures at this level, because we don't want to prevent progress on a stuck feed. -async fn single_job_loop_iteration(job_state: &Arc) { - let statuses = vec![ScrapingStatus::New, ScrapingStatus::Failed]; - for status in statuses { - scrape_jobs_of_status(status, job_state).await; - } -} - -async fn scrape_jobs_of_status(status: ScrapingStatus, job_state: &Arc) { - // NB: Low batch size so we can shuffle in memory and process stories in a more random order - const BATCH_SIZE : usize = 5; - const SHUFFLE : bool = true; - - let mut last_id = 0; - let mut failure_count = 0; - - loop { - // NB: Protect sqlite from contention. - thread::sleep(Duration::from_millis(500)); - - debug!("web_content_scraping querying {:?} targets from id > {} ...", &status, last_id); - - // NB: We query the whole list so we can randomly select in-memory. - // There were some problems with SQLX' RANDOM() making non-null fields nullable. - let query_result = list_all_web_scraping_targets( - status, &job_state.sqlite_pool).await; - - let mut targets = match query_result { - Ok(targets) => targets, - Err(err) => { - error!("failure querying batch: {:?}", err); - - failure_count += 1; - - // NB: Don't starve progress. - if failure_count > 2 { - failure_count = 0; - last_id += 1; - } else if failure_count > 3 { - return; - } - - continue; - } - }; - - failure_count = 0; - - if targets.is_empty() { - return; // Done with batches. - } - - if SHUFFLE { - targets.shuffle(&mut thread_rng()); - } - - targets.truncate(BATCH_SIZE); - - for target in targets { - info!("Download and scrape target: {:?}", target.canonical_url); - - while job_state.app_control_state.is_scraping_paused() { - thread::sleep(Duration::from_secs(5)); - } - - let result = process_target_record(&target, job_state).await; - if let Err(err) = result { - error!("Error processing target: {:?}", err); - } - - last_id = target.id; - - thread::sleep(Duration::from_secs(5)); - } - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/mod.rs deleted file mode 100644 index e98bc899e3..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod main_loop; -pub mod single_target; diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/filter_scraped_result_heuristics.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/filter_scraped_result_heuristics.rs deleted file mode 100644 index 83d02cfb54..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/filter_scraped_result_heuristics.rs +++ /dev/null @@ -1,72 +0,0 @@ -use enums::common::sqlite::skip_reason::SkipReason; -use enums::common::sqlite::web_content_type::WebContentType; -use errors::AnyhowResult; -use web_scrapers::payloads::web_scraping_result::{ScrapedWebArticle, WebScrapingResult}; - -pub async fn filter_scraped_result_heuristics(web_scrape_result: &WebScrapingResult) -> AnyhowResult> { - // TODO: Write some heuristics to determine if we should skip the article. - - let scrape_result = &web_scrape_result.result; - - // Must have a title - if lacks_title(scrape_result) { - return Ok(Some(SkipReason::EmptyContent)) - } - - if lacks_body(scrape_result) { - return Ok(Some(SkipReason::EmptyContent)) - } - - if has_politics(scrape_result) { - return Ok(Some(SkipReason::FilteredTopicPolitics)) - } - - if is_boring_techcrunch_article(scrape_result) { - return Ok(Some(SkipReason::NobodyCares)) - } - - Ok(None) -} - -fn lacks_title(scrape_result: &ScrapedWebArticle) -> bool { - if let Some(title) = scrape_result.maybe_title.as_deref() { - title.trim().is_empty() - } else { - true - } -} - -fn lacks_body(scrape_result: &ScrapedWebArticle) -> bool { - scrape_result.body_text.trim().is_empty() -} - -fn has_politics(scrape_result: &ScrapedWebArticle) -> bool { - let contents = scrape_result.body_text.to_lowercase(); - - if contents.contains("marjorie") && contents.contains("greene") { - return true; - } - - false -} - -/// Filter out no-name startups -fn is_boring_techcrunch_article(scrape_result: &ScrapedWebArticle) -> bool { - if !scrape_result.web_content_type.eq(&WebContentType::TechCrunchArticle) { - return false; - } - - if let Some(title) = scrape_result.maybe_title.as_deref() { - if title.contains("$") - || title.contains("raises") - || title.contains("VC") - || title.contains("startup") - || title.contains("deck") - || title.contains("pitch") - { - return true; // Lazy heuristic - } - } - - false -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/ingest_url_scrape_and_save.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/ingest_url_scrape_and_save.rs deleted file mode 100644 index 104d257ec4..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/ingest_url_scrape_and_save.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::io::Write; - -use enums::common::sqlite::web_content_type::WebContentType; -use errors::AnyhowResult; -use web_scrapers::payloads::web_scraping_result::WebScrapingResult; -use web_scrapers::scrape_supported_webpage::scrape_supported_webpage; - -use crate::persistence::save_directory::SaveDirectory; - -pub async fn ingest_url_scrape_and_save( - url: &str, - _web_content_type: WebContentType, - save_directory: &SaveDirectory -) -> AnyhowResult> -{ - let scraping_result = scrape_supported_webpage(url).await?; - - { - let directory = save_directory.directory_for_webpage_url(url)?; - std::fs::create_dir_all(&directory)?; - } - - { - let html_filename = save_directory.html_file_for_webpage_url(url)?; - let mut file = std::fs::File::create(&html_filename)?; - file.write_all(scraping_result.original_html.as_bytes())?; - } - - { - let yaml_filename = save_directory.scrape_summary_file_for_webpage_url(url)?; - let mut file = std::fs::File::create(&yaml_filename)?; - serde_yaml::to_writer(file, &scraping_result.result)?; - } - - Ok(Some(scraping_result)) -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/mod.rs deleted file mode 100644 index 304c21b2ad..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod ingest_url_scrape_and_save; -pub mod process_target_record; -pub mod filter_scraped_result_heuristics; diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/process_target_record.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/process_target_record.rs deleted file mode 100644 index 6779faca2c..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_content_scraping/single_target/process_target_record.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::sync::Arc; - -use enums::by_table::web_scraping_targets::scraping_status::ScrapingStatus; -use errors::AnyhowResult; -use log::error; -use sqlite_queries::queries::by_table::news_story_productions::insert_news_story_production::Args as ProductionArgs; -use sqlite_queries::queries::by_table::news_story_productions::insert_news_story_production::insert_news_story_production; -use sqlite_queries::queries::by_table::web_scraping_targets::list::web_scraping_target::WebScrapingTarget as WebScrapingTargetRecord; -use sqlite_queries::queries::by_table::web_scraping_targets::update_web_scraping_target::Args as ScrapingArgs; -use sqlite_queries::queries::by_table::web_scraping_targets::update_web_scraping_target::update_web_scraping_target; -use tokens::tokens::news_stories::NewsStoryToken; - -use crate::shared_state::job_state::JobState; -use crate::workers::web::web_content_scraping::single_target::filter_scraped_result_heuristics::filter_scraped_result_heuristics; -use crate::workers::web::web_content_scraping::single_target::ingest_url_scrape_and_save::ingest_url_scrape_and_save; - -pub async fn process_target_record(target: &WebScrapingTargetRecord, job_state: &Arc) -> AnyhowResult<()> { - let result = ingest_url_scrape_and_save( - &target.canonical_url, - target.web_content_type, - &job_state.save_directory).await; - - let scrape_attempts = target.scrape_attempts + 1; - - match result { - Err(err) => { - error!("error ingesting url: {:?}", err); - - let next_scraping_status = next_status(target.scrape_attempts); - - update_web_scraping_target(ScrapingArgs { - canonical_url: &target.canonical_url, - scraping_status: next_scraping_status, - scrape_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck. - - Err(err) - }, - Ok(None) => { - error!("nothing was scraped from url: {:?}", &target.canonical_url); - - // Nothing was scraped. - let next_scraping_status = next_status(target.scrape_attempts); - - update_web_scraping_target(ScrapingArgs { - canonical_url: &target.canonical_url, - scraping_status: next_scraping_status, - scrape_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck. - - Ok(()) - }, - Ok(Some(result)) => { - update_web_scraping_target(ScrapingArgs { - canonical_url: &target.canonical_url, - scraping_status: ScrapingStatus::Success, - scrape_attempts, - sqlite_pool: &job_state.sqlite_pool, - }).await?; // NB: If these queries fail, we could get stuck. - - let maybe_skip_reason = filter_scraped_result_heuristics(&result) - .await?; - - let news_story_token = NewsStoryToken::generate(); - - insert_news_story_production(ProductionArgs { - news_story_token: &news_story_token, - original_news_canonical_url: &target.canonical_url, - web_content_type: target.web_content_type, - original_news_title: target.maybe_title.as_deref().unwrap_or(""), - // maybe_skip_reason, // TODO: Should I do this? - sqlite_pool: &job_state.sqlite_pool, - }).await?; - - Ok(()) - }, - } -} - -fn next_status(scrape_attempts: i64) -> ScrapingStatus { - if scrape_attempts > 2 { - ScrapingStatus::PermanentlyFailed - } else { - ScrapingStatus::Failed - } -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_index_ingestion/main_loop.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_index_ingestion/main_loop.rs deleted file mode 100644 index a81ee5892f..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_index_ingestion/main_loop.rs +++ /dev/null @@ -1,92 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use errors::AnyhowResult; -use log::{debug, error, info}; -use sqlite_queries::queries::by_table::web_scraping_targets::insert_web_scraping_target::{Args, insert_web_scraping_target}; -use sqlx::sqlite::SqlitePoolOptions; -use strum::IntoEnumIterator; -use web_scrapers::payloads::web_scraping_result::ScrapedWebArticle; -use web_scrapers::payloads::web_scraping_target::WebScrapingTarget; -use web_scrapers::sites::cnn::cnn_indexer::{cnn_indexer, CnnFeed}; -use web_scrapers::sites::gizmodo::gizmodo_indexer::gizmodo_indexer; -use web_scrapers::sites::kotaku::kotaku_indexer::kotaku_indexer; -use web_scrapers::sites::techcrunch::techcrunch_indexer::{techcrunch_indexer, TechcrunchFeed}; - -use crate::shared_state::job_state::JobState; - -/// Download RSS feeds and index pages to determine which articles and content will be scraped (async/downstream of this) -pub async fn web_index_ingestion_main_loop(job_state: Arc) { - loop { - debug!("web_index_ingestion main loop"); - - while job_state.app_control_state.is_scraping_paused() { - thread::sleep(Duration::from_secs(5)); - } - - match single_iteration(&job_state).await { - Ok(_) => { - debug!("web_index_ingestion loop finished; waiting..."); - thread::sleep(Duration::from_secs(300)) - }, - Err(err) => { - error!("web_index_ingestion - error with indexing: {:?}", err); - thread::sleep(Duration::from_secs(60)); - } - } - } -} - -async fn single_iteration(job_state: &Arc) -> AnyhowResult<()> { - - // Kotaku - { - let index_targets = kotaku_indexer().await?; - insert_targets(job_state, &index_targets).await?; - thread::sleep(Duration::from_secs(2)); - } - - // Gizmodo - { - let index_targets = gizmodo_indexer().await?; - insert_targets(job_state, &index_targets).await?; - thread::sleep(Duration::from_secs(2)); - } - - // CNN - for variant in CnnFeed::iter() { - let index_targets = cnn_indexer(variant).await?; - insert_targets(job_state, &index_targets).await?; - thread::sleep(Duration::from_secs(2)); - } - - // TechCrunch - for variant in TechcrunchFeed::iter() { - let index_targets = techcrunch_indexer(variant).await?; - insert_targets(job_state, &index_targets).await?; - thread::sleep(Duration::from_secs(2)); - } - - Ok(()) -} - -async fn insert_targets(job_state: &Arc, targets: &Vec) -> AnyhowResult<()> { - while job_state.app_control_state.is_scraping_paused() { - thread::sleep(Duration::from_secs(5)); - } - - for target in targets.iter() { - let _r = insert_web_scraping_target(Args { - canonical_url: &target.canonical_url, - web_content_type: target.web_content_type, - maybe_title: target.maybe_title.as_deref(), - maybe_article_full_image_url: target.maybe_full_image_url.as_deref(), - maybe_article_thumbnail_image_url: target.maybe_thumbnail_image_url.as_deref(), - maybe_skip_reason: target.maybe_skip_reason, - sqlite_pool: &job_state.sqlite_pool, - }).await; - } - - Ok(()) -} diff --git a/crates/programs/aichatbot-sidecar/src/workers/web/web_index_ingestion/mod.rs b/crates/programs/aichatbot-sidecar/src/workers/web/web_index_ingestion/mod.rs deleted file mode 100644 index ccca46ee14..0000000000 --- a/crates/programs/aichatbot-sidecar/src/workers/web/web_index_ingestion/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod main_loop; diff --git a/crates/programs/bevy-experiments/.gitignore b/crates/programs/bevy-experiments/.gitignore deleted file mode 100644 index 4f96631dab..0000000000 --- a/crates/programs/bevy-experiments/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -/dist diff --git a/crates/programs/bevy-experiments/Cargo.lock b/crates/programs/bevy-experiments/Cargo.lock deleted file mode 100644 index 869b154820..0000000000 --- a/crates/programs/bevy-experiments/Cargo.lock +++ /dev/null @@ -1,3447 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" - -[[package]] -name = "accesskit" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704d532b1cd3d912bb37499c55a81ac748cc1afa737eedd100ba441acdd47d38" - -[[package]] -name = "accesskit_consumer" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba8b23cfca3944012ee2e5c71c02077a400e034c720eed6bd927cb6b4d1fd9" -dependencies = [ - "accesskit", -] - -[[package]] -name = "accesskit_macos" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d062544d6cc36f4213323b7cb3a0d74ddff4b0d2311ab5e7596f4278bb2cc9" -dependencies = [ - "accesskit", - "accesskit_consumer", - "objc2", - "once_cell", -] - -[[package]] -name = "accesskit_windows" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf5b3c3828397ee832ba4a72fb1a4ace10f781e31885f774cbd531014059115" -dependencies = [ - "accesskit", - "accesskit_consumer", - "arrayvec", - "once_cell", - "paste", - "windows 0.44.0", -] - -[[package]] -name = "accesskit_winit" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcb615217efc79c4bed3094c4ca76c4bc554751d1da16f3ed4ba0459b1e8f31" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_windows", - "winit", -] - -[[package]] -name = "addr2line" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" -dependencies = [ - "memchr", -] - -[[package]] -name = "alsa" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44" -dependencies = [ - "alsa-sys", - "bitflags", - "libc", - "nix 0.24.3", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "android-activity" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c77a0045eda8b888c76ea473c2b0515ba6f471d318f8927c5c72240937035a6" -dependencies = [ - "android-properties", - "bitflags", - "cc", - "jni-sys", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "android_log-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayvec" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8868f09ff8cea88b079da74ae569d9b8c62a23c68c746240b704ee6f7525c89c" - -[[package]] -name = "ash" -version = "0.37.3+1.3.251" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" -dependencies = [ - "libloading", -] - -[[package]] -name = "async-channel" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-lock" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-task" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide 0.6.2", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "bevy" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93f906133305915d63f04108e6873c1b93a6605fe374b8f3391f6bda093e396" -dependencies = [ - "bevy_internal", -] - -[[package]] -name = "bevy_a11y" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037c4063f7dac1a5d596eb47f40782a04ca5838dc4274dbbadc90eb81efe5169" -dependencies = [ - "accesskit", - "bevy_app", - "bevy_derive", - "bevy_ecs", -] - -[[package]] -name = "bevy_animation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0dc19f21846ebf8ba4d96617c2517b5119038774aa5dbbaf1bff122332b359c" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_ecs", - "bevy_hierarchy", - "bevy_math", - "bevy_reflect", - "bevy_time", - "bevy_transform", - "bevy_utils", -] - -[[package]] -name = "bevy_app" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01db46963eb9486f7884121527ec69751d0e448f9e1d5329e80ea3424118a31a" -dependencies = [ - "bevy_derive", - "bevy_ecs", - "bevy_reflect", - "bevy_utils", - "downcast-rs", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "bevy_asset" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98609b4b0694a23bde0628aed626644967991f167aad9db2afb68dacb0017540" -dependencies = [ - "anyhow", - "bevy_app", - "bevy_diagnostic", - "bevy_ecs", - "bevy_log", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bevy_winit", - "crossbeam-channel", - "downcast-rs", - "fastrand", - "js-sys", - "notify", - "parking_lot", - "serde", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "bevy_audio" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b9f9b87b0d094268ce52bb75ff346ae0054573f7acc5d66bf032e2c88f748d" -dependencies = [ - "anyhow", - "bevy_app", - "bevy_asset", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_transform", - "bevy_utils", - "oboe", - "parking_lot", - "rodio", -] - -[[package]] -name = "bevy_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee53d7b4691b57207d72e996992c995a53f3e8d21ca7151ca3956d9ce7d232e" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bytemuck", -] - -[[package]] -name = "bevy_core_pipeline" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093ae5ced77251602ad6e43521e2acc1a5570bf85b80f232f1a7fdd43b50f8d8" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bitflags", - "radsort", - "serde", -] - -[[package]] -name = "bevy_derive" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff0add5ab4a6b2b7e86e18f9043bb48b6386faa3b56abaa0ed97a3d669a1992" -dependencies = [ - "bevy_macro_utils", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bevy_diagnostic" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c778422643b0adee9e82abbd07e1e906eb9947c274a9b18e0f7fbf137d4c34" -dependencies = [ - "bevy_app", - "bevy_core", - "bevy_ecs", - "bevy_log", - "bevy_time", - "bevy_utils", - "sysinfo", -] - -[[package]] -name = "bevy_ecs" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed2f74687ccf13046c0f8e3b00dc61d7e656877b4a1380cf04635bb74d8e586" -dependencies = [ - "async-channel", - "bevy_ecs_macros", - "bevy_ptr", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "downcast-rs", - "event-listener", - "fixedbitset", - "rustc-hash", - "serde", - "thread_local", -] - -[[package]] -name = "bevy_ecs_macros" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97fd126a0db7b30fb1833614b3a657b44ac88485741c33b2780e25de0f96d78" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bevy_encase_derive" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c086ebdc1f5522787d63772943277cc74a279445fb65db4d58c2c5330654648e" -dependencies = [ - "bevy_macro_utils", - "encase_derive_impl", -] - -[[package]] -name = "bevy_gilrs" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f32eb07e8c9ea4be7195ccec10d8f9ad70200f3ae2e13adc4b84df9f50bb1c6" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_utils", - "gilrs", -] - -[[package]] -name = "bevy_gltf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2707632208617c3660ea7a1d2ef2ccc84b59f217c2f01a1d0abe81db4ae7bbde" -dependencies = [ - "anyhow", - "base64", - "bevy_animation", - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_hierarchy", - "bevy_log", - "bevy_math", - "bevy_pbr", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_tasks", - "bevy_transform", - "bevy_utils", - "gltf", - "percent-encoding", - "thiserror", -] - -[[package]] -name = "bevy_hierarchy" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d04099865a13d1fd8bf3c044a80148cb3d23bfe8c3d5f082dda2ce091d85532" -dependencies = [ - "bevy_app", - "bevy_core", - "bevy_ecs", - "bevy_log", - "bevy_reflect", - "bevy_utils", - "smallvec", -] - -[[package]] -name = "bevy_input" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15d40aa636bb656967ac16ca36066ab7a7bb9179e1b0390c5705e54208e8fd7" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_utils", - "thiserror", -] - -[[package]] -name = "bevy_internal" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862b11931c5874cb00778ffb715fc526ee49e52a493d3bcf50e8010f301858b3" -dependencies = [ - "bevy_a11y", - "bevy_animation", - "bevy_app", - "bevy_asset", - "bevy_audio", - "bevy_core", - "bevy_core_pipeline", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_gilrs", - "bevy_gltf", - "bevy_hierarchy", - "bevy_input", - "bevy_log", - "bevy_math", - "bevy_pbr", - "bevy_ptr", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_sprite", - "bevy_tasks", - "bevy_text", - "bevy_time", - "bevy_transform", - "bevy_ui", - "bevy_utils", - "bevy_window", - "bevy_winit", -] - -[[package]] -name = "bevy_log" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25980c90ceaad34d09a53291e72ca56fcc754a974cd4654fffcf5b68b283b7a7" -dependencies = [ - "android_log-sys", - "bevy_app", - "bevy_ecs", - "bevy_utils", - "console_error_panic_hook", - "tracing-log", - "tracing-subscriber", - "tracing-wasm", -] - -[[package]] -name = "bevy_macro_utils" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b2fee53b2497cdc3bffff2ddf52afa751242424a5fd0d51d227d4dab081d0d9" -dependencies = [ - "quote", - "syn 1.0.109", - "toml_edit", -] - -[[package]] -name = "bevy_math" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da6a1109d06fe947990db032e719e162414cf9bf7a478dcc52742f1c7136c42a" -dependencies = [ - "glam", - "serde", -] - -[[package]] -name = "bevy_mikktspace" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39106bc2ee21fce9496d2e15e0ba7925dff63e3eae10f7c1fc0094b56ad9f2bb" -dependencies = [ - "glam", -] - -[[package]] -name = "bevy_pbr" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f507cef55812aa70c2ec2b30fb996eb285fa7497d974cf03f76ec49c77fbe27" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags", - "bytemuck", - "radsort", -] - -[[package]] -name = "bevy_ptr" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b88451d4c5a353bff67dbaa937b6886efd26ae114769c17f2b35099c7a4de" - -[[package]] -name = "bevy_reflect" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc3979471890e336f3ba87961ef3ecd45c331cf2cb2f582c885e541af228b48" -dependencies = [ - "bevy_math", - "bevy_ptr", - "bevy_reflect_derive", - "bevy_utils", - "downcast-rs", - "erased-serde", - "glam", - "once_cell", - "parking_lot", - "serde", - "smallvec", - "thiserror", -] - -[[package]] -name = "bevy_reflect_derive" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc7ea7c9bc2c531eb29ba5619976613d6680453ff5dd4a7fcd08848e8bec5ad" -dependencies = [ - "bevy_macro_utils", - "bit-set", - "proc-macro2", - "quote", - "syn 1.0.109", - "uuid", -] - -[[package]] -name = "bevy_render" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1e126226f0a4d439bf82fe07c1104f894a6a365888e3eba7356f9647e77a83" -dependencies = [ - "anyhow", - "async-channel", - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_derive", - "bevy_ecs", - "bevy_encase_derive", - "bevy_hierarchy", - "bevy_log", - "bevy_math", - "bevy_mikktspace", - "bevy_reflect", - "bevy_render_macros", - "bevy_tasks", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags", - "codespan-reporting", - "downcast-rs", - "encase", - "futures-lite", - "hexasphere", - "image", - "ktx2", - "naga", - "once_cell", - "parking_lot", - "regex", - "ruzstd", - "serde", - "smallvec", - "thiserror", - "thread_local", - "wgpu", - "wgpu-hal", -] - -[[package]] -name = "bevy_render_macros" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652f8c4d9577c6e6a8b3dfd8a4ce331e8b6ecdbb99636a4b2701dec50104d6bc" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bevy_scene" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de59637d27726251091120ce6f63917328ffd60aaccbda4d65a615873aff631" -dependencies = [ - "anyhow", - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "ron", - "serde", - "thiserror", - "uuid", -] - -[[package]] -name = "bevy_sprite" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c110358fe3651a5796fd1c07989635680738f5b5c7e9b8a463dd50d12bb78410" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bitflags", - "bytemuck", - "fixedbitset", - "guillotiere", - "rectangle-pack", - "thiserror", -] - -[[package]] -name = "bevy_tasks" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de86364316e151aeb0897eaaa917c3ad5ee5ef1471a939023cf7f2d5ab76955" -dependencies = [ - "async-channel", - "async-executor", - "async-task", - "concurrent-queue", - "futures-lite", - "once_cell", - "wasm-bindgen-futures", -] - -[[package]] -name = "bevy_text" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995188f59dc06da3fc951e1f58a105cde2c817d5330ae67ddc0a140f46482f6b" -dependencies = [ - "ab_glyph", - "anyhow", - "bevy_app", - "bevy_asset", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_transform", - "bevy_utils", - "bevy_window", - "glyph_brush_layout", - "serde", - "thiserror", -] - -[[package]] -name = "bevy_time" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3edbd605df1bced312eb9888d6be3d5a5fcac3d4140038bbe3233d218399eef" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_reflect", - "bevy_utils", - "crossbeam-channel", - "thiserror", -] - -[[package]] -name = "bevy_transform" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24383dfb97d8a14b17721ecfdf58556eff5ea9a4b2a3d91accf2b472783880b0" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_hierarchy", - "bevy_math", - "bevy_reflect", -] - -[[package]] -name = "bevy_ui" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb597aeed4e1bf5e6913879c3e22a7d50a843b822a7f71a4a80ebdfdf79e68d4" -dependencies = [ - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_input", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_text", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bytemuck", - "serde", - "smallvec", - "taffy", - "thiserror", -] - -[[package]] -name = "bevy_utils" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a88ebbca55d360d72e9fe78df0d22e25cd419933c9559e79dae2757f7c4d066" -dependencies = [ - "ahash", - "bevy_utils_proc_macros", - "getrandom", - "hashbrown", - "instant", - "petgraph", - "thiserror", - "tracing", - "uuid", -] - -[[package]] -name = "bevy_utils_proc_macros" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630b92e32fa5cd7917c7d4fdbf63a90af958b01e096239f71bc4f8f3cf40c0d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bevy_window" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad31234754268fbe12050290b0496e2296252a16995a38f94bfb9680a4f09fda" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_reflect", - "bevy_utils", - "raw-window-handle", -] - -[[package]] -name = "bevy_winit" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf17bd6330f7e633b7c56754c776511a8f52cde4bf54c0278f34d7527548f253" -dependencies = [ - "accesskit_winit", - "approx", - "bevy_a11y", - "bevy_app", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_input", - "bevy_math", - "bevy_utils", - "bevy_window", - "crossbeam-channel", - "once_cell", - "raw-window-handle", - "wasm-bindgen", - "web-sys", - "winit", -] - -[[package]] -name = "bindgen" -version = "0.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 1.0.109", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-sys" -version = "0.1.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" -dependencies = [ - "block-sys", - "objc2-encode", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bytemuck" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "clang-sys" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "com-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" - -[[package]] -name = "combine" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "concurrent-queue" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "const_panic" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys 0.8.4", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation", - "foreign-types", - "libc", -] - -[[package]] -name = "coreaudio-rs" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb17e2d1795b1996419648915df94bc7103c28f7b48062d7acf4652fc371b2ff" -dependencies = [ - "bitflags", - "core-foundation-sys 0.6.2", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" -dependencies = [ - "alsa", - "core-foundation-sys 0.8.4", - "coreaudio-rs", - "dasp_sample", - "jni 0.19.0", - "js-sys", - "libc", - "mach2", - "ndk", - "ndk-context", - "oboe", - "once_cell", - "parking_lot", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.46.0", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "d3d12" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da" -dependencies = [ - "bitflags", - "libloading", - "winapi", -] - -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "encase" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6591f13a63571c4821802eb5b10fd1155b1290bce87086440003841c8c3909b" -dependencies = [ - "const_panic", - "encase_derive", - "glam", - "thiserror", -] - -[[package]] -name = "encase_derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1da6deed1f8b6f5909616ffa695f63a5de54d6a0f084fa715c70c8ed3abac9" -dependencies = [ - "encase_derive_impl", -] - -[[package]] -name = "encase_derive_impl" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae489d58959f3c4cdd1250866a05acfb341469affe4fced71aff3ba228be1693" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "erased-serde" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" -dependencies = [ - "serde", -] - -[[package]] -name = "euclid" -version = "0.22.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" -dependencies = [ - "num-traits", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fdeflate" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "filetime" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" -dependencies = [ - "crc32fast", - "miniz_oxide 0.7.1", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gilrs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fd19844d0eb919aca41d3e4ea0e0b6bf60e1e827558b101c269015b8f5f27a" -dependencies = [ - "fnv", - "gilrs-core", - "log", - "uuid", - "vec_map", -] - -[[package]] -name = "gilrs-core" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd745b0cb1a207756e8fabacf5623066ad6aa543ea0be4bab34e897e6bbe24f9" -dependencies = [ - "core-foundation", - "io-kit-sys", - "js-sys", - "libc", - "libudev-sys", - "log", - "nix 0.26.2", - "uuid", - "vec_map", - "wasm-bindgen", - "web-sys", - "windows 0.48.0", -] - -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "glam" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" -dependencies = [ - "bytemuck", - "serde", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "glow" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "807edf58b70c0b5b2181dd39fe1839dbdb3ba02645630dc5f753e23da307f762" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "gltf" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fe8d5192923fbd783c15e74627de8e27c97e1e3dec22bf54515a407249febf" -dependencies = [ - "byteorder", - "gltf-json", - "lazy_static", -] - -[[package]] -name = "gltf-derive" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec223c88f017861193ae128239aff8fbc4478f38a036d9d7b2ce10a52b46b1f2" -dependencies = [ - "inflections", - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "gltf-json" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1ba7523fcf32541f4aec96e13024c255d928eab3223f99ab945045f2a6de18" -dependencies = [ - "gltf-derive", - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" -dependencies = [ - "ab_glyph", - "approx", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" -dependencies = [ - "bitflags", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags", -] - -[[package]] -name = "gpu-allocator" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" -dependencies = [ - "backtrace", - "log", - "thiserror", - "winapi", - "windows 0.44.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" -dependencies = [ - "bitflags", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags", -] - -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", - "serde", -] - -[[package]] -name = "hassle-rs" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90601c6189668c7345fc53842cb3f3a3d872203d523be1b3cb44a36a3e62fb85" -dependencies = [ - "bitflags", - "com-rs", - "libc", - "libloading", - "thiserror", - "widestring", - "winapi", -] - -[[package]] -name = "hexasphere" -version = "8.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd41d443f978bfa380a6dad58b62a08c43bcb960631f13e9d015b911eaf73588" -dependencies = [ - "glam", - "once_cell", -] - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "image" -version = "0.24.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-rational", - "num-traits", - "png", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inflections" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "io-kit-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2d4429acc1deff0fbdece0325b4997bdb02b2c245ab7023fd5deca0f6348de" -dependencies = [ - "core-foundation-sys 0.8.4", - "mach2", -] - -[[package]] -name = "itoa" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[package]] -name = "kqueue" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "ktx2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838" -dependencies = [ - "bitflags", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - -[[package]] -name = "libc" -version = "0.2.146" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libudev-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" - -[[package]] -name = "mach2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "metal" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" -dependencies = [ - "bitflags", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "naga" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c3d4269bcb7d50121097702fde1afb75f4ea8083aeb7a55688dcf289a853271" -dependencies = [ - "bit-set", - "bitflags", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "num-traits", - "petgraph", - "pp-rs", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys", - "num_enum", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "static_assertions", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "notify" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" -dependencies = [ - "bitflags", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "mio", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-sys" -version = "0.2.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" - -[[package]] -name = "objc2" -version = "0.3.0-beta.3.patch-leaks.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" -dependencies = [ - "block2", - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-encode" -version = "2.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "object" -version = "0.30.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" -dependencies = [ - "memchr", -] - -[[package]] -name = "oboe" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8868cc237ee02e2d9618539a23a8d228b9bb3fc2e7a5b11eed3831de77c395d0" -dependencies = [ - "jni 0.20.0", - "ndk", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f44155e7fb718d3cfddcf70690b2b51ac4412f347cd9e4fbe511abe9cd7b5f2" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "orbclient" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1" -dependencies = [ - "redox_syscall 0.3.5", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "owned_ttf_parser" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "parking" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.3.5", - "smallvec", - "windows-targets 0.48.0", -] - -[[package]] -name = "paste" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "petgraph" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "png" -version = "0.17.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide 0.7.1", -] - -[[package]] -name = "pp-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" - -[[package]] -name = "quote" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radsort" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fd96390ed3feda12e1dfe2645ed587e0bea749e319333f104a33ff62f77a0b" - -[[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] -name = "rectangle-pack" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.7.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" - -[[package]] -name = "renderdoc-sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" - -[[package]] -name = "rodio" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf1d4dea18dff2e9eb6dca123724f8b60ef44ad74a9ad283cdfe025df7e73fa" -dependencies = [ - "cpal", - "lewton", -] - -[[package]] -name = "ron" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff" -dependencies = [ - "base64", - "bitflags", - "serde", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "ruzstd" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cada0ef59efa6a5f4dc5e491f93d9f31e3fc7758df421ff1de8a706338e1100" -dependencies = [ - "byteorder", - "twox-hash", -] - -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serde" -version = "1.0.164" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.164" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" - -[[package]] -name = "simd-adler32" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "slotmap" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -dependencies = [ - "serde", -] - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "svg_fmt" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sysinfo" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2f3ca6693feb29a89724516f016488e9aafc7f37264f898593ee4b942f31b" -dependencies = [ - "cfg-if", - "core-foundation-sys 0.8.4", - "libc", - "ntapi", - "once_cell", - "winapi", -] - -[[package]] -name = "taffy" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3540ec65df399929a04a485feb50144475735920cc47eaf8eba09c70b1df4055" -dependencies = [ - "arrayvec", - "num-traits", - "slotmap", -] - -[[package]] -name = "temp-bevy" -version = "0.1.0" -dependencies = [ - "bevy", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "toml_datetime" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" - -[[package]] -name = "toml_edit" -version = "0.19.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "tracing-wasm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - -[[package]] -name = "ttf-parser" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "uuid" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" -dependencies = [ - "getrandom", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.18", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wgpu" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d745a1b6d91d85c33defbb29f0eee0450e1d2614d987e14bf6baf26009d132d7" -dependencies = [ - "arrayvec", - "cfg-if", - "js-sys", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7131408d940e335792645a98f03639573b0480e9e2e7cddbbab74f7c6d9f3fff" -dependencies = [ - "arrayvec", - "bit-vec", - "bitflags", - "codespan-reporting", - "fxhash", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "thiserror", - "web-sys", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcf61a283adc744bb5453dd88ea91f3f86d5ca6b027661c6c73c7734ae0288b" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags", - "block", - "core-graphics-types", - "d3d12", - "foreign-types", - "fxhash", - "glow", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hassle-rs", - "js-sys", - "khronos-egl", - "libc", - "libloading", - "log", - "metal", - "naga", - "objc", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "smallvec", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-types" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32444e121b0bd00cb02c0de32fde457a9491bd44e03e7a5db6df9b1da2f6f110" -dependencies = [ - "bitflags", - "js-sys", - "web-sys", -] - -[[package]] -name = "widestring" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-targets 0.42.2", -] - -[[package]] -name = "windows" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-implement" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce87ca8e3417b02dc2a8a22769306658670ec92d78f1bd420d6310a67c245c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "windows-interface" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853f69a591ecd4f810d29f17e902d40e349fb05b0b11fff63b08b826bfe39c7f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "winit" -version = "0.28.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866db3f712fffba75d31bf0cdecf357c8aeafd158c5b7ab51dba2a2b2d47f196" -dependencies = [ - "android-activity", - "bitflags", - "cfg_aliases", - "core-foundation", - "core-graphics", - "dispatch", - "instant", - "libc", - "log", - "mio", - "ndk", - "objc2", - "once_cell", - "orbclient", - "percent-encoding", - "raw-window-handle", - "redox_syscall 0.3.5", - "wasm-bindgen", - "wayland-scanner", - "web-sys", - "windows-sys 0.45.0", - "x11-dl", -] - -[[package]] -name = "winnow" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" -dependencies = [ - "memchr", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" diff --git a/crates/programs/bevy-experiments/Cargo.toml b/crates/programs/bevy-experiments/Cargo.toml deleted file mode 100644 index eb06634e7c..0000000000 --- a/crates/programs/bevy-experiments/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "temp-bevy" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bevy = "0.10.1" - -[profile.release] -opt-level = "z" -lto = "fat" diff --git a/crates/programs/bevy-experiments/assets/Roko.glb b/crates/programs/bevy-experiments/assets/Roko.glb deleted file mode 100644 index 628da7f469..0000000000 Binary files a/crates/programs/bevy-experiments/assets/Roko.glb and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/Roko_AllAnim_Baked.glb b/crates/programs/bevy-experiments/assets/Roko_AllAnim_Baked.glb deleted file mode 100644 index 79b01c8693..0000000000 Binary files a/crates/programs/bevy-experiments/assets/Roko_AllAnim_Baked.glb and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/Roko_Anim_Wave.glb b/crates/programs/bevy-experiments/assets/Roko_Anim_Wave.glb deleted file mode 100644 index 4f6bd10398..0000000000 Binary files a/crates/programs/bevy-experiments/assets/Roko_Anim_Wave.glb and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/Roko_Anim_Wave_noGameRig.glb b/crates/programs/bevy-experiments/assets/Roko_Anim_Wave_noGameRig.glb deleted file mode 100644 index f65230496b..0000000000 Binary files a/crates/programs/bevy-experiments/assets/Roko_Anim_Wave_noGameRig.glb and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/Roko_Anim_Wave_noOptimization.glb b/crates/programs/bevy-experiments/assets/Roko_Anim_Wave_noOptimization.glb deleted file mode 100644 index 644344c8ab..0000000000 Binary files a/crates/programs/bevy-experiments/assets/Roko_Anim_Wave_noOptimization.glb and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/Roko_nogamerig.glb b/crates/programs/bevy-experiments/assets/Roko_nogamerig.glb deleted file mode 100644 index b19b4cb31c..0000000000 Binary files a/crates/programs/bevy-experiments/assets/Roko_nogamerig.glb and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/fonts/FiraMono-Bold.ttf b/crates/programs/bevy-experiments/assets/fonts/FiraMono-Bold.ttf deleted file mode 100644 index 23bc30f6c4..0000000000 Binary files a/crates/programs/bevy-experiments/assets/fonts/FiraMono-Bold.ttf and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/fonts/FiraMono-Medium.ttf b/crates/programs/bevy-experiments/assets/fonts/FiraMono-Medium.ttf deleted file mode 100644 index 793c60df15..0000000000 Binary files a/crates/programs/bevy-experiments/assets/fonts/FiraMono-Medium.ttf and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/fonts/FiraSans-Bold.ttf b/crates/programs/bevy-experiments/assets/fonts/FiraSans-Bold.ttf deleted file mode 100644 index e3593fb0f3..0000000000 Binary files a/crates/programs/bevy-experiments/assets/fonts/FiraSans-Bold.ttf and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/fonts/FiraSans-Medium.ttf b/crates/programs/bevy-experiments/assets/fonts/FiraSans-Medium.ttf deleted file mode 100644 index 001ebe7e63..0000000000 Binary files a/crates/programs/bevy-experiments/assets/fonts/FiraSans-Medium.ttf and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/pisa_diffuse_rgb9e5_zstd.ktx2 b/crates/programs/bevy-experiments/assets/pisa_diffuse_rgb9e5_zstd.ktx2 deleted file mode 100644 index e260df24bd..0000000000 Binary files a/crates/programs/bevy-experiments/assets/pisa_diffuse_rgb9e5_zstd.ktx2 and /dev/null differ diff --git a/crates/programs/bevy-experiments/assets/pisa_specular_rgb9e5_zstd.ktx2 b/crates/programs/bevy-experiments/assets/pisa_specular_rgb9e5_zstd.ktx2 deleted file mode 100644 index 2018838de5..0000000000 Binary files a/crates/programs/bevy-experiments/assets/pisa_specular_rgb9e5_zstd.ktx2 and /dev/null differ diff --git a/crates/programs/bevy-experiments/index.html b/crates/programs/bevy-experiments/index.html deleted file mode 100644 index c256fcca28..0000000000 --- a/crates/programs/bevy-experiments/index.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/crates/programs/bevy-experiments/src/main.rs b/crates/programs/bevy-experiments/src/main.rs deleted file mode 100644 index b0a1b9f546..0000000000 --- a/crates/programs/bevy-experiments/src/main.rs +++ /dev/null @@ -1,513 +0,0 @@ -//! Loads and renders a glTF file as a scene. - -use core::time::Duration; -use std::f32::consts::*; - -use bevy::{ - animation::{AnimationClip, AnimationPlayer}, - pbr::{CascadeShadowConfigBuilder, DirectionalLightShadowMap}, - prelude::*, - scene::SceneInstance, -}; -use bevy::input::mouse::MouseMotion; - -fn main() { - App::new() - .insert_resource(AmbientLight { - color: Color::WHITE, - brightness: 1.0 / 5.0f32, - }) - .insert_resource(DirectionalLightShadowMap { size: 4096 }) - .add_plugins(DefaultPlugins) - .add_startup_system(setup) - .add_system(setup_scene_once_loaded) - //.add_system(animate_light_direction) - //.add_system(animate_model_direction) - .add_system(keyboard_animation_control) - .add_system(camera_controller) - .add_system(text_update_system) - .run(); -} - -#[derive(Resource)] -struct Animations(Vec>); - -#[derive(Component)] -struct PosText; - -#[derive(Component)] -struct RotText; - -#[derive(Component)] -struct MainCamera; - -fn setup(mut commands: Commands, asset_server: Res) { - - - commands.insert_resource(Animations(vec![ - asset_server.load("Roko_Anim_Wave_noOptimization.glb#Animation0"), - ])); - - - commands.spawn(( - Camera3dBundle { - transform: Transform::from_xyz(0.0, 1.5, 1.5), - //transform: Transform { - //translation: Vec3::new(0.0, -10.0, 5.0), - //rotation: Quat::from_xyzw(0.574, 0.0, 0.0, 0.819), - //scale: Vec3::new(1.0, 1.0, 1.0), - //}, - //projection: Projection::Orthographic(OrthographicProjection{ - //near: 0.1, - //far: 100.0, - //scale: 7.312, - //..default() - //} - //), - ..default() - }, - MainCamera, - CameraController::default(), - EnvironmentMapLight { - diffuse_map: asset_server.load("pisa_diffuse_rgb9e5_zstd.ktx2"), - specular_map: asset_server.load("pisa_specular_rgb9e5_zstd.ktx2"), - }, - )); - - commands.spawn(( - TextBundle::from_sections([ - TextSection::new( - "Position: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::new( - "X: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - TextSection::new( - "Y: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - TextSection::new( - "Z: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - - ]).with_style( - Style { - position_type: PositionType::Absolute, - position: UiRect { - right: Val::Px(00.0), - ..default() - }, - ..default() - } - ), - - PosText, - )); - - commands.spawn(( - TextBundle::from_sections([ - TextSection::new( - "Rotation: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::new( - "X: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - TextSection::new( - "Y: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - TextSection::new( - "Z: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - TextSection::new( - "W: ", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 20.0, - color: Color::WHITE, - }, - ), - TextSection::from_style(TextStyle { - font: asset_server.load("fonts/FiraMono-Medium.ttf"), - font_size: 20.0, - color: Color::GOLD, - }), - ]).with_style( - Style { - position_type: PositionType::Absolute, - position: UiRect { - top: Val::Px(20.0), - right: Val::Px(00.0), - ..default() - }, - ..default() - } - ), - RotText, - )); - - - - commands.spawn(DirectionalLightBundle { - directional_light: DirectionalLight { - shadows_enabled: true, - ..default() - }, - // This is a relatively small scene, so use tighter shadow - // cascade bounds than the default for better quality. - // We also adjusted the shadow map to be larger since we're - // only using a single cascade. - cascade_shadow_config: CascadeShadowConfigBuilder { - num_cascades: 1, - maximum_distance: 1.6, - ..default() - } - .into(), - transform: Transform { - translation: Vec3::new(0.0, 0.0, 0.0), - rotation: Quat::from_xyzw(-0.5, 0.0, 0.0, 0.8517), - scale: Vec3::ONE, - }, - ..default() - }); - commands.spawn(SceneBundle { - scene: asset_server.load("Roko_nogamerig.glb#Scene0"), - transform: Transform::from_xyz(0.0, 0.0, 0.0), - //transform: Transform::from_rotation(Quat::from_rotation_x(3.14)), - ..default() - }); - - //commands.spawn(AnimationPlayer::default()); - -} - -fn animate_light_direction( - time: Res