diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d4ea37f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +.github +.git +.gitignore +frontend/node_modules +.env +.idea +README.md +LICENSE +.dockerignore +docker-compose.yml +target +backend/Dockerfile +frontend/Dockerfile +.qodo \ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 82d7327..cabc485 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -13,25 +13,25 @@ jobs: linter: runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Rust toolchain uses: dtolnay/rust-toolchain@master #uses: actions-rust-lang/setup-rust-toolchain@v1 with: components: clippy - toolchain: stable + toolchain: nightly - name: Install and Cache Apt packages uses: awalsh128/cache-apt-pkgs-action@latest with: packages: nasm version: 1.0 - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2.8.0 + uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - name: Run linter (clippy action) #env: SQLX_OFFLINE: true - uses: clechasseur/rs-clippy-check@v5.0.1 + uses: clechasseur/rs-clippy-check@v5 with: #token: ${{ secrets.GITHUB_TOKEN }} args: --workspace @@ -40,10 +40,11 @@ jobs: formatting: runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Rustfmt Toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 with: + toolchain: nightly components: rustfmt - name: Rust fmt check uses: actions-rust-lang/rustfmt@v1 diff --git a/.gitignore b/.gitignore index 76485ea..4c99a5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -.qodo .idea .env +prod.env /target \ No newline at end of file diff --git a/.sqlx/query-01526138d0cd787dd0121a8a0ced390d439346378ab4d3590328aad7f6fae62a.json b/.sqlx/query-01526138d0cd787dd0121a8a0ced390d439346378ab4d3590328aad7f6fae62a.json new file mode 100644 index 0000000..b4059db --- /dev/null +++ b/.sqlx/query-01526138d0cd787dd0121a8a0ced390d439346378ab4d3590328aad7f6fae62a.json @@ -0,0 +1,98 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH base_search AS (\n SELECT\n s.id, s.title, s.original_title, s.description, s.cover_image_url,\n s.current_source_url, s.updated_at, s.processing_status,\n -- Calculate similarity score for ranking\n similarity(s.title, $3) as sim_score\n FROM series s\n WHERE\n s.title ILIKE '%' || $3 || '%'\n OR\n (s.title % $3 AND similarity(s.title, $3) >= $4)\n ),\n ranked_results AS (\n SELECT\n *,\n CASE\n WHEN title ILIKE $3 THEN 10\n WHEN title ILIKE $3 || '%' THEN 8\n WHEN title ILIKE '%' || $3 || '%' THEN 6\n ELSE 4\n END as search_rank\n FROM base_search\n ),\n total_count AS (\n SELECT COUNT(*) AS total FROM ranked_results\n )\n SELECT\n rr.id, rr.title, rr.original_title, rr.description,\n rr.cover_image_url, rr.current_source_url, rr.updated_at,\n rr.processing_status as \"processing_status: SeriesStatus\",\n -- Aggregate author names into a JSON array for each series\n COALESCE(\n json_agg(a.name) FILTER (WHERE a.id IS NOT NULL),\n '[]'::json\n ) AS \"authors!\",\n tc.total as total_items\n FROM ranked_results rr\n CROSS JOIN total_count tc\n LEFT JOIN series_authors sa ON rr.id = sa.series_id\n LEFT JOIN authors a ON sa.author_id = a.id\n GROUP BY\n rr.id, rr.title, rr.original_title, rr.description, rr.cover_image_url,\n rr.current_source_url, rr.updated_at, rr.processing_status,\n rr.search_rank, rr.sim_score, tc.total\n -- Order by the best rank, then by similarity, then by ID for stable sorting\n ORDER BY rr.search_rank DESC, rr.sim_score DESC, rr.id ASC\n LIMIT $1\n OFFSET $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "original_title", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "cover_image_url", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "current_source_url", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "processing_status: SeriesStatus", + "type_info": { + "Custom": { + "name": "series_status", + "kind": { + "Enum": [ + "Pending", + "Processing", + "Available", + "Ongoing", + "Completed", + "Hiatus", + "Discontinued", + "Error", + "Pending Deletion", + "Deleting", + "Deletion Failed" + ] + } + } + } + }, + { + "ordinal": 8, + "name": "authors!", + "type_info": "Json" + }, + { + "ordinal": 9, + "name": "total_items", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Text", + "Float4" + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + false, + false, + false, + null, + null + ] + }, + "hash": "01526138d0cd787dd0121a8a0ced390d439346378ab4d3590328aad7f6fae62a" +} diff --git a/.sqlx/query-dd47d4bddabc76774508545fc208c4c6d489d419158fefa65a0e13644e81b7bd.json b/.sqlx/query-05d49b961d5dfb46828c18d6a6df8f46c7d61c38add6c75d7708f2bd7e93be78.json similarity index 52% rename from .sqlx/query-dd47d4bddabc76774508545fc208c4c6d489d419158fefa65a0e13644e81b7bd.json rename to .sqlx/query-05d49b961d5dfb46828c18d6a6df8f46c7d61c38add6c75d7708f2bd7e93be78.json index 988009a..eb399ad 100644 --- a/.sqlx/query-dd47d4bddabc76774508545fc208c4c6d489d419158fefa65a0e13644e81b7bd.json +++ b/.sqlx/query-05d49b961d5dfb46828c18d6a6df8f46c7d61c38add6c75d7708f2bd7e93be78.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT a.name FROM authors a\n JOIN series_authors sa ON a.id = sa.author_id\n WHERE sa.series_id = $1", + "query": "\n SELECT a.name FROM authors a\n JOIN series_authors sa ON a.id = sa.author_id\n WHERE sa.series_id = $1\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "dd47d4bddabc76774508545fc208c4c6d489d419158fefa65a0e13644e81b7bd" + "hash": "05d49b961d5dfb46828c18d6a6df8f46c7d61c38add6c75d7708f2bd7e93be78" } diff --git a/.sqlx/query-05dbbd810e571d1653e73d5001b1fc262cd779d1439ca255421fa51118744048.json b/.sqlx/query-05dbbd810e571d1653e73d5001b1fc262cd779d1439ca255421fa51118744048.json new file mode 100644 index 0000000..62062de --- /dev/null +++ b/.sqlx/query-05dbbd810e571d1653e73d5001b1fc262cd779d1439ca255421fa51118744048.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO series_ratings (series_id, user_id, rating) VALUES ($1, $2, $3)\n ON CONFLICT (user_id, series_id) DO UPDATE SET rating = $3, updated_at = NOW()\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Int4", + "Int2" + ] + }, + "nullable": [] + }, + "hash": "05dbbd810e571d1653e73d5001b1fc262cd779d1439ca255421fa51118744048" +} diff --git a/.sqlx/query-07eba14e32d72782dde094c1597bde9607276fd32ad7392be4e77eacbdfabd69.json b/.sqlx/query-07eba14e32d72782dde094c1597bde9607276fd32ad7392be4e77eacbdfabd69.json new file mode 100644 index 0000000..d24ade4 --- /dev/null +++ b/.sqlx/query-07eba14e32d72782dde094c1597bde9607276fd32ad7392be4e77eacbdfabd69.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE series\n SET last_chapter_found_in_storage = GREATEST(COALESCE(last_chapter_found_in_storage, 0), $1),\n updated_at = NOW()\n WHERE id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Float4", + "Int4" + ] + }, + "nullable": [] + }, + "hash": "07eba14e32d72782dde094c1597bde9607276fd32ad7392be4e77eacbdfabd69" +} diff --git a/.sqlx/query-0e2fbcf5a2d66a4ee1b5fd28dc178db72e2189d3fd4464ed7adbb54ed0ef0d5c.json b/.sqlx/query-0e2fbcf5a2d66a4ee1b5fd28dc178db72e2189d3fd4464ed7adbb54ed0ef0d5c.json new file mode 100644 index 0000000..bd056a7 --- /dev/null +++ b/.sqlx/query-0e2fbcf5a2d66a4ee1b5fd28dc178db72e2189d3fd4464ed7adbb54ed0ef0d5c.json @@ -0,0 +1,119 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH RECURSIVE comment_thread AS (\n -- Anchor member: top-level comments\n SELECT * FROM comments\n WHERE\n CASE\n WHEN $4::bigint IS NOT NULL THEN id = $4\n ELSE comments_type = $1 AND comments_id = $2 AND parent_id IS NULL\n END\n UNION ALL\n -- Recursive member: replies to comments already in the thread\n SELECT c.*\n FROM comments c\n JOIN comment_thread ct ON c.parent_id = ct.id\n ),\n vote_summary AS (\n SELECT\n cv.comment_vote_id,\n COUNT(*) FILTER (WHERE cv.vote_type = 1) AS upvotes,\n COUNT(*) FILTER (WHERE cv.vote_type = -1) AS downvotes\n FROM comment_votes cv\n WHERE cv.comment_vote_id IN (SELECT id FROM comment_thread)\n GROUP BY cv.comment_vote_id\n ),\n attachments_summary AS (\n -- Aggregate all attachment URLs for each comment into a JSON array\n SELECT\n comment_id,\n array_agg(file_url) as attachment_urls\n FROM comment_attachments\n WHERE comment_id IN (SELECT id FROM comment_thread)\n GROUP BY comment_id\n )\n SELECT\n ct.id as \"id!\",\n ct.parent_id,\n ct.content_html as \"content_html!\",\n ct.content_user_markdown as \"content_markdown!\",\n ct.created_at as \"created_at!\",\n ct.updated_at as \"updated_at!\",\n ct.user_id as \"user_id!\",\n COALESCE(up.display_name, u.username) as \"user_username!\",\n up.avatar_url as \"user_avatar_url\",\n u.role_id as \"user_role_id!\",\n COALESCE(vs.upvotes, 0) as \"upvotes!\",\n COALESCE(vs.downvotes, 0) as \"downvotes!\",\n (ct.deleted_at IS NOT NULL ) as \"is_deleted!\",\n cv.vote_type as \"current_user_vote\",\n ats.attachment_urls as \"attachment_urls\"\n FROM comment_thread ct\n JOIN users u ON ct.user_id = u.id\n LEFT JOIN user_profiles up ON u.id = up.user_id\n LEFT JOIN vote_summary vs ON ct.id = vs.comment_vote_id\n LEFT JOIN comment_votes cv ON ct.id = cv.comment_vote_id AND cv.user_id = $3\n LEFT JOIN attachments_summary ats ON ct.id = ats.comment_id\n -- ORDER BY ct.created_at ASC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id!", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "parent_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "content_html!", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "content_markdown!", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "created_at!", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "updated_at!", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "user_id!", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "user_username!", + "type_info": "Text" + }, + { + "ordinal": 8, + "name": "user_avatar_url", + "type_info": "Text" + }, + { + "ordinal": 9, + "name": "user_role_id!", + "type_info": "Int4" + }, + { + "ordinal": 10, + "name": "upvotes!", + "type_info": "Int8" + }, + { + "ordinal": 11, + "name": "downvotes!", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "is_deleted!", + "type_info": "Bool" + }, + { + "ordinal": 13, + "name": "current_user_vote", + "type_info": "Int2" + }, + { + "ordinal": 14, + "name": "attachment_urls", + "type_info": "TextArray" + } + ], + "parameters": { + "Left": [ + { + "Custom": { + "name": "comments_entity", + "kind": { + "Enum": [ + "series", + "series_chapters" + ] + } + } + }, + "Int4", + "Int4", + "Int8" + ] + }, + "nullable": [ + true, + true, + true, + true, + true, + true, + true, + null, + true, + true, + null, + null, + null, + true, + true + ] + }, + "hash": "0e2fbcf5a2d66a4ee1b5fd28dc178db72e2189d3fd4464ed7adbb54ed0ef0d5c" +} diff --git a/.sqlx/query-154c0b1e89ad82e920973a00897ed0374bc15ccf8eec3df2a02b657bcef3a6b2.json b/.sqlx/query-10714d781c4f88bb58ac8ac3393631dbfe9484d8ab62f69e25babbf449daa17d.json similarity index 60% rename from .sqlx/query-154c0b1e89ad82e920973a00897ed0374bc15ccf8eec3df2a02b657bcef3a6b2.json rename to .sqlx/query-10714d781c4f88bb58ac8ac3393631dbfe9484d8ab62f69e25babbf449daa17d.json index f14cbf3..543d797 100644 --- a/.sqlx/query-154c0b1e89ad82e920973a00897ed0374bc15ccf8eec3df2a02b657bcef3a6b2.json +++ b/.sqlx/query-10714d781c4f88bb58ac8ac3393631dbfe9484d8ab62f69e25babbf449daa17d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n sr.id,\n sr.title,\n sr.original_title,\n sr.description,\n sr.cover_image_url,\n sr.current_source_url,\n sr.updated_at,\n sr.processing_status as \"processing_status: SeriesStatus\",\n COALESCE(\n json_agg(a.name) FILTER (WHERE a.id IS NOT NULL),\n '[]'::json\n ) as \"authors!\",\n COUNT(*) OVER () as total_items\n FROM\n series sr\n LEFT JOIN\n series_authors sa ON sr.id = sa.series_id\n LEFT JOIN\n authors a ON sa.author_id = a.id\n WHERE\n ($3::TEXT IS NULL OR sr.title_tsv @@ plainto_tsquery('english', $3))\n GROUP BY\n sr.id\n ORDER BY\n sr.updated_at DESC\n LIMIT $1\n OFFSET $2\n ", + "query": "\n SELECT\n s.id, s.title, s.original_title, s.description, s.cover_image_url,\n s.current_source_url, s.updated_at,\n s.processing_status as \"processing_status: SeriesStatus\",\n COALESCE(\n json_agg(a.name) FILTER (WHERE a.id IS NOT NULL),\n '[]'::json\n ) as \"authors!\",\n COUNT(*) OVER () as total_items\n FROM\n series s\n LEFT JOIN series_authors sa ON s.id = sa.series_id\n LEFT JOIN authors a ON sa.author_id = a.id\n GROUP BY s.id\n ORDER BY s.updated_at DESC\n LIMIT $1 OFFSET $2\n ", "describe": { "columns": [ { @@ -76,8 +76,7 @@ "parameters": { "Left": [ "Int8", - "Int8", - "Text" + "Int8" ] }, "nullable": [ @@ -93,5 +92,5 @@ null ] }, - "hash": "154c0b1e89ad82e920973a00897ed0374bc15ccf8eec3df2a02b657bcef3a6b2" + "hash": "10714d781c4f88bb58ac8ac3393631dbfe9484d8ab62f69e25babbf449daa17d" } diff --git a/.sqlx/query-172c20fbd5dc86fb2320ccb218652409751f86f3783c19b1e944618ee8b0b0e5.json b/.sqlx/query-172c20fbd5dc86fb2320ccb218652409751f86f3783c19b1e944618ee8b0b0e5.json deleted file mode 100644 index f7ed995..0000000 --- a/.sqlx/query-172c20fbd5dc86fb2320ccb218652409751f86f3783c19b1e944618ee8b0b0e5.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n WITH search_results AS (\n SELECT\n u.id,\n u.username,\n u.email,\n r.role_name,\n u.user_tsv\n FROM users u\n JOIN roles r ON u.role_id = r.id\n WHERE\n -- ILIKE for substring matches\n u.username ILIKE '%' || $3 || '%'\n OR u.email ILIKE '%' || $3 || '%'\n -- FTS for whole-word/prefix matches\n OR u.user_tsv @@ to_tsquery('simple', $4)\n -- fuzzy match filtering\n OR (u.username || ' ' || u.email) % $3\n ),\n ranked_results AS (\n SELECT\n *,\n CASE\n WHEN username ILIKE '%' || $3 || '%' OR email ILIKE '%' || $3 || '%' THEN 10\n WHEN user_tsv @@ to_tsquery('simple', $4) THEN 8\n ELSE 6\n END as search_rank,\n -- Calculate similarity score for ranking\n similarity(username || ' ' || email, $3) as sim_score\n FROM search_results\n ),\n total_count AS (\n SELECT COUNT(*) AS total FROM ranked_results WHERE search_rank > 0\n )\n SELECT\n rr.id,\n rr.username,\n rr.email,\n rr.role_name,\n tc.total as total_items\n FROM ranked_results rr\n CROSS JOIN total_count tc\n WHERE rr.search_rank > 0\n ORDER BY rr.search_rank DESC, rr.sim_score DESC, rr.id ASC\n LIMIT $1 OFFSET $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "username", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "email", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "role_name", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "total_items", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8", - "Text", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false, - null - ] - }, - "hash": "172c20fbd5dc86fb2320ccb218652409751f86f3783c19b1e944618ee8b0b0e5" -} diff --git a/.sqlx/query-d37354f165f68b157b032bb2eae1045abec8f8f2a1669f4f75a740527cff2997.json b/.sqlx/query-19151ec4a77c3cd1e182f0cfb6ccb83911c0075d35280252566d378120bc4c0e.json similarity index 79% rename from .sqlx/query-d37354f165f68b157b032bb2eae1045abec8f8f2a1669f4f75a740527cff2997.json rename to .sqlx/query-19151ec4a77c3cd1e182f0cfb6ccb83911c0075d35280252566d378120bc4c0e.json index 79306af..323f153 100644 --- a/.sqlx/query-d37354f165f68b157b032bb2eae1045abec8f8f2a1669f4f75a740527cff2997.json +++ b/.sqlx/query-19151ec4a77c3cd1e182f0cfb6ccb83911c0075d35280252566d378120bc4c0e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT c.id, c.name FROM categories c\n JOIN series_categories sc ON c.id = sc.category_id\n WHERE sc.series_id = $1", + "query": "\n SELECT c.id, c.name FROM categories c\n JOIN series_categories sc ON c.id = sc.category_id\n WHERE sc.series_id = $1\n ", "describe": { "columns": [ { @@ -24,5 +24,5 @@ false ] }, - "hash": "d37354f165f68b157b032bb2eae1045abec8f8f2a1669f4f75a740527cff2997" + "hash": "19151ec4a77c3cd1e182f0cfb6ccb83911c0075d35280252566d378120bc4c0e" } diff --git a/.sqlx/query-19fc91b1024527bce698cc654c619dfdceca6f5938542bea66b025a89cd5dcd2.json b/.sqlx/query-19fc91b1024527bce698cc654c619dfdceca6f5938542bea66b025a89cd5dcd2.json deleted file mode 100644 index 53373cc..0000000 --- a/.sqlx/query-19fc91b1024527bce698cc654c619dfdceca6f5938542bea66b025a89cd5dcd2.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n s.id,\n s.title,\n s.cover_image_url,\n s.updated_at,\n s.last_chapter_found_in_storage,\n sc.title as chapter_title,\n COUNT(*) OVER () as total_items\n FROM\n series s\n LEFT JOIN\n series_chapters sc ON s.id = sc.series_id\n AND s.last_chapter_found_in_storage = sc.chapter_number\n WHERE\n s.updated_at >= NOW() - interval '7 days'\n ORDER BY\n s.updated_at DESC\n LIMIT $1\n OFFSET $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "title", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "cover_image_url", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 4, - "name": "last_chapter_found_in_storage", - "type_info": "Float4" - }, - { - "ordinal": 5, - "name": "chapter_title", - "type_info": "Text" - }, - { - "ordinal": 6, - "name": "total_items", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - true, - true, - null - ] - }, - "hash": "19fc91b1024527bce698cc654c619dfdceca6f5938542bea66b025a89cd5dcd2" -} diff --git a/.sqlx/query-21c0768f87efd70066db55b20a68a28e3b5f31ab8e697035628e0a1cc5e8578b.json b/.sqlx/query-25fab2cf9710a5c5922ff95f1ce25dc38e7b9fb9b7b2b69d1764dbd3dcc376fd.json similarity index 52% rename from .sqlx/query-21c0768f87efd70066db55b20a68a28e3b5f31ab8e697035628e0a1cc5e8578b.json rename to .sqlx/query-25fab2cf9710a5c5922ff95f1ce25dc38e7b9fb9b7b2b69d1764dbd3dcc376fd.json index c01bde9..c23d602 100644 --- a/.sqlx/query-21c0768f87efd70066db55b20a68a28e3b5f31ab8e697035628e0a1cc5e8578b.json +++ b/.sqlx/query-25fab2cf9710a5c5922ff95f1ce25dc38e7b9fb9b7b2b69d1764dbd3dcc376fd.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n WITH vote_summary AS (\n SELECT\n cv.comment_vote_id,\n COUNT(*) FILTER (WHERE cv.vote_type = 1) AS upvotes,\n COUNT(*) FILTER (WHERE cv.vote_type = -1) AS downvotes\n FROM comment_votes cv\n WHERE cv.comment_vote_id = $1\n GROUP BY cv.comment_vote_id\n ),\n attachments_summary AS (\n SELECT\n comment_id,\n json_agg(file_url) as attachment_urls\n FROM comment_attachments\n WHERE comment_id = $1\n GROUP BY comment_id\n )\n SELECT\n c.id as \"id!\",\n c.parent_id,\n c.content_html as \"content_html!\",\n c.content_user_markdown as \"content_markdown!\",\n c.created_at as \"created_at!\",\n c.updated_at as \"updated_at!\",\n c.user_id as \"user_id!\",\n COALESCE(up.display_name, u.username) as \"user_username!\",\n up.avatar_url as \"user_avatar_url\",\n COALESCE(vs.upvotes, 0) as \"upvotes!\",\n COALESCE(vs.downvotes, 0) as \"downvotes!\",\n cv.vote_type as \"current_user_vote: _\",\n ats.attachment_urls as \"attachment_urls: _\"\n FROM comments c\n JOIN users u ON c.user_id = u.id\n LEFT JOIN user_profiles up ON u.id = up.user_id\n LEFT JOIN vote_summary vs ON c.id = vs.comment_vote_id\n LEFT JOIN comment_votes cv ON c.id = cv.comment_vote_id AND cv.user_id = $2\n LEFT JOIN attachments_summary ats ON c.id = ats.comment_id\n WHERE c.id = $1 AND c.deleted_at IS NULL\n ", + "query": "\n WITH vote_summary AS (\n SELECT\n cv.comment_vote_id,\n COUNT(*) FILTER (WHERE cv.vote_type = 1) AS upvotes,\n COUNT(*) FILTER (WHERE cv.vote_type = -1) AS downvotes\n FROM comment_votes cv\n WHERE cv.comment_vote_id = $1\n GROUP BY cv.comment_vote_id\n ),\n attachments_summary AS (\n SELECT\n comment_id,\n array_agg(file_url) as attachment_urls\n FROM comment_attachments\n WHERE comment_id = $1\n GROUP BY comment_id\n )\n SELECT\n c.id as \"id!\",\n c.parent_id,\n c.content_html as \"content_html!\",\n c.content_user_markdown as \"content_markdown!\",\n c.created_at as \"created_at!\",\n c.updated_at as \"updated_at!\",\n c.user_id as \"user_id!\",\n COALESCE(up.display_name, u.username) as \"user_username!\",\n up.avatar_url as \"user_avatar_url\",\n u.role_id as \"user_role_id!\",\n COALESCE(vs.upvotes, 0) as \"upvotes!\",\n COALESCE(vs.downvotes, 0) as \"downvotes!\",\n (c.deleted_at IS NOT NULL ) as \"is_deleted!\",\n cv.vote_type as \"current_user_vote?\",\n ats.attachment_urls as \"attachment_urls?\"\n FROM comments c\n JOIN users u ON c.user_id = u.id\n LEFT JOIN user_profiles up ON u.id = up.user_id\n LEFT JOIN vote_summary vs ON c.id = vs.comment_vote_id\n LEFT JOIN comment_votes cv ON c.id = cv.comment_vote_id AND cv.user_id = $2\n LEFT JOIN attachments_summary ats ON c.id = ats.comment_id\n WHERE c.id = $1 AND c.deleted_at IS NULL\n ", "describe": { "columns": [ { @@ -50,23 +50,33 @@ }, { "ordinal": 9, + "name": "user_role_id!", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "upvotes!", "type_info": "Int8" }, { - "ordinal": 10, + "ordinal": 11, "name": "downvotes!", "type_info": "Int8" }, { - "ordinal": 11, - "name": "current_user_vote: _", + "ordinal": 12, + "name": "is_deleted!", + "type_info": "Bool" + }, + { + "ordinal": 13, + "name": "current_user_vote?", "type_info": "Int2" }, { - "ordinal": 12, - "name": "attachment_urls: _", - "type_info": "Json" + "ordinal": 14, + "name": "attachment_urls?", + "type_info": "TextArray" } ], "parameters": { @@ -85,11 +95,13 @@ false, null, true, + false, + null, null, null, false, null ] }, - "hash": "21c0768f87efd70066db55b20a68a28e3b5f31ab8e697035628e0a1cc5e8578b" + "hash": "25fab2cf9710a5c5922ff95f1ce25dc38e7b9fb9b7b2b69d1764dbd3dcc376fd" } diff --git a/.sqlx/query-26f6acf048a86178ceb4bfff6e7229dd503b9870fc635c24292b265c02a8ac1d.json b/.sqlx/query-26f6acf048a86178ceb4bfff6e7229dd503b9870fc635c24292b265c02a8ac1d.json new file mode 100644 index 0000000..0076e9a --- /dev/null +++ b/.sqlx/query-26f6acf048a86178ceb4bfff6e7229dd503b9870fc635c24292b265c02a8ac1d.json @@ -0,0 +1,38 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO series_chapters (series_id, chapter_number, title, source_url, status)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (series_id, chapter_number)\n DO UPDATE SET\n updated_at = NOW(),\n source_url = EXCLUDED.source_url,\n status = EXCLUDED.status\n RETURNING id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Int4", + "Float4", + "Text", + "Text", + { + "Custom": { + "name": "chapter_status", + "kind": { + "Enum": [ + "Processing", + "Available", + "NoImagesFound", + "Error" + ] + } + } + } + ] + }, + "nullable": [ + false + ] + }, + "hash": "26f6acf048a86178ceb4bfff6e7229dd503b9870fc635c24292b265c02a8ac1d" +} diff --git a/.sqlx/query-29e707635ce688d1e26f9e73cc57338483557621742f5caedb9f6cd2814dbc39.json b/.sqlx/query-29e707635ce688d1e26f9e73cc57338483557621742f5caedb9f6cd2814dbc39.json new file mode 100644 index 0000000..f3a8cda --- /dev/null +++ b/.sqlx/query-29e707635ce688d1e26f9e73cc57338483557621742f5caedb9f6cd2814dbc39.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT EXISTS(\n SELECT 1 FROM comments WHERE parent_id = $1 AND deleted_at IS NULL\n )\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + null + ] + }, + "hash": "29e707635ce688d1e26f9e73cc57338483557621742f5caedb9f6cd2814dbc39" +} diff --git a/.sqlx/query-31329106b5e77ff191cdb52bbd811af71244672925f91cc8f83e21d14f979ece.json b/.sqlx/query-31329106b5e77ff191cdb52bbd811af71244672925f91cc8f83e21d14f979ece.json deleted file mode 100644 index df11f16..0000000 --- a/.sqlx/query-31329106b5e77ff191cdb52bbd811af71244672925f91cc8f83e21d14f979ece.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n WITH candidate AS (\n SELECT id FROM series\n WHERE processing_status = $1\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n )\n UPDATE series\n SET processing_status = $2\n WHERE id = (SELECT id FROM candidate)\n RETURNING\n id, title, original_title, description, cover_image_url, current_source_url,\n source_website_host, views_count, bookmarks_count, total_rating_score, total_ratings_count, last_chapter_found_in_storage,\n processing_status as \"processing_status: SeriesStatus\", check_interval_minutes, last_checked_at,\n next_checked_at, created_at, updated_at\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "title", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "original_title", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "cover_image_url", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "current_source_url", - "type_info": "Text" - }, - { - "ordinal": 6, - "name": "source_website_host", - "type_info": "Text" - }, - { - "ordinal": 7, - "name": "views_count", - "type_info": "Int4" - }, - { - "ordinal": 8, - "name": "bookmarks_count", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "total_rating_score", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "total_ratings_count", - "type_info": "Int4" - }, - { - "ordinal": 11, - "name": "last_chapter_found_in_storage", - "type_info": "Float4" - }, - { - "ordinal": 12, - "name": "processing_status: SeriesStatus", - "type_info": { - "Custom": { - "name": "series_status", - "kind": { - "Enum": [ - "Pending", - "Processing", - "Available", - "Ongoing", - "Completed", - "Hiatus", - "Discontinued", - "Error", - "Pending Deletion", - "Deleting", - "Deletion Failed" - ] - } - } - } - }, - { - "ordinal": 13, - "name": "check_interval_minutes", - "type_info": "Int4" - }, - { - "ordinal": 14, - "name": "last_checked_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 15, - "name": "next_checked_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 16, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 17, - "name": "updated_at", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [ - { - "Custom": { - "name": "series_status", - "kind": { - "Enum": [ - "Pending", - "Processing", - "Available", - "Ongoing", - "Completed", - "Hiatus", - "Discontinued", - "Error", - "Pending Deletion", - "Deleting", - "Deletion Failed" - ] - } - } - }, - { - "Custom": { - "name": "series_status", - "kind": { - "Enum": [ - "Pending", - "Processing", - "Available", - "Ongoing", - "Completed", - "Hiatus", - "Discontinued", - "Error", - "Pending Deletion", - "Deleting", - "Deletion Failed" - ] - } - } - } - ] - }, - "nullable": [ - false, - false, - true, - false, - false, - false, - false, - false, - false, - false, - false, - true, - false, - false, - true, - true, - false, - false - ] - }, - "hash": "31329106b5e77ff191cdb52bbd811af71244672925f91cc8f83e21d14f979ece" -} diff --git a/.sqlx/query-32bd2bb5781954c16789f5e68c442e02186b6fee3dc13c9fe1d1753b654aff2c.json b/.sqlx/query-32bd2bb5781954c16789f5e68c442e02186b6fee3dc13c9fe1d1753b654aff2c.json new file mode 100644 index 0000000..78f0f91 --- /dev/null +++ b/.sqlx/query-32bd2bb5781954c16789f5e68c442e02186b6fee3dc13c9fe1d1753b654aff2c.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE users\n SET username = $1, email = $2, role_id = $3, is_active = $4, updated_at = NOW()\n WHERE id = $5\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Int4", + "Bool", + "Int4" + ] + }, + "nullable": [] + }, + "hash": "32bd2bb5781954c16789f5e68c442e02186b6fee3dc13c9fe1d1753b654aff2c" +} diff --git a/.sqlx/query-a5d63c05f2e3140963dc2808e75003f4c5f948511401d8259c5ca8b61318bf90.json b/.sqlx/query-35fbad5e10a60481b24b5b3529ed6df8469dc31fbd21875a1d9fb196e2e3aa8d.json similarity index 83% rename from .sqlx/query-a5d63c05f2e3140963dc2808e75003f4c5f948511401d8259c5ca8b61318bf90.json rename to .sqlx/query-35fbad5e10a60481b24b5b3529ed6df8469dc31fbd21875a1d9fb196e2e3aa8d.json index 6f104df..7e307af 100644 --- a/.sqlx/query-a5d63c05f2e3140963dc2808e75003f4c5f948511401d8259c5ca8b61318bf90.json +++ b/.sqlx/query-35fbad5e10a60481b24b5b3529ed6df8469dc31fbd21875a1d9fb196e2e3aa8d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, title, original_title, description, cover_image_url, current_source_url,\n source_website_host, views_count, bookmarks_count, total_rating_score, total_ratings_count, last_chapter_found_in_storage,\n processing_status as \"processing_status: SeriesStatus\",\n check_interval_minutes, last_checked_at, next_checked_at, created_at, updated_at\n FROM series WHERE id = $1", + "query": "\n SELECT id, title, original_title, description, cover_image_url, current_source_url,\n source_website_host, views_count, bookmarks_count, total_rating_score, total_ratings_count,\n last_chapter_found_in_storage, processing_status as \"processing_status: SeriesStatus\",\n check_interval_minutes, last_checked_at, next_checked_at, created_at, updated_at\n FROM series \n WHERE id = $1\n ", "describe": { "columns": [ { @@ -139,5 +139,5 @@ false ] }, - "hash": "a5d63c05f2e3140963dc2808e75003f4c5f948511401d8259c5ca8b61318bf90" + "hash": "35fbad5e10a60481b24b5b3529ed6df8469dc31fbd21875a1d9fb196e2e3aa8d" } diff --git a/.sqlx/query-414bdbf62eab2c725d434c1026c83c8c94aa15e7084581ef95cafea37737223c.json b/.sqlx/query-414bdbf62eab2c725d434c1026c83c8c94aa15e7084581ef95cafea37737223c.json new file mode 100644 index 0000000..52fbd5b --- /dev/null +++ b/.sqlx/query-414bdbf62eab2c725d434c1026c83c8c94aa15e7084581ef95cafea37737223c.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n u.role_id,\n c.user_id\n FROM comments c\n JOIN users u ON c.user_id = u.id\n WHERE c.id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "role_id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "user_id", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "414bdbf62eab2c725d434c1026c83c8c94aa15e7084581ef95cafea37737223c" +} diff --git a/.sqlx/query-4708b47aab9e8b20cbfebb16287313b98c461c8f57e0f612d53917a286f7a54c.json b/.sqlx/query-4708b47aab9e8b20cbfebb16287313b98c461c8f57e0f612d53917a286f7a54c.json new file mode 100644 index 0000000..ca09274 --- /dev/null +++ b/.sqlx/query-4708b47aab9e8b20cbfebb16287313b98c461c8f57e0f612d53917a286f7a54c.json @@ -0,0 +1,52 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n u.id,\n u.username,\n u.email,\n u.role_id,\n COALESCE(u.is_active, false) as \"is_active!\",\n r.role_name\n FROM users u\n JOIN roles r ON u.role_id = r.id\n WHERE u.id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "username", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "email", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "role_id", + "type_info": "Int4" + }, + { + "ordinal": 4, + "name": "is_active!", + "type_info": "Bool" + }, + { + "ordinal": 5, + "name": "role_name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + false, + null, + false + ] + }, + "hash": "4708b47aab9e8b20cbfebb16287313b98c461c8f57e0f612d53917a286f7a54c" +} diff --git a/.sqlx/query-46e71b9fdf391246eeed01dad5b40ae863fda9d9d7ae2b2652c6a5b815adab18.json b/.sqlx/query-49005252d64c1f75617187b2c904218bfdde0826bc8810c260fdc1d82c72575f.json similarity index 83% rename from .sqlx/query-46e71b9fdf391246eeed01dad5b40ae863fda9d9d7ae2b2652c6a5b815adab18.json rename to .sqlx/query-49005252d64c1f75617187b2c904218bfdde0826bc8810c260fdc1d82c72575f.json index dfa89aa..9694ca5 100644 --- a/.sqlx/query-46e71b9fdf391246eeed01dad5b40ae863fda9d9d7ae2b2652c6a5b815adab18.json +++ b/.sqlx/query-49005252d64c1f75617187b2c904218bfdde0826bc8810c260fdc1d82c72575f.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, title, original_title, description, cover_image_url, current_source_url,\n source_website_host, views_count, bookmarks_count, total_rating_score, total_ratings_count, last_chapter_found_in_storage,\n processing_status as \"processing_status: SeriesStatus\",\n check_interval_minutes, last_checked_at, next_checked_at, created_at, updated_at\n FROM series WHERE title = $1", + "query": "\n SELECT id, title, original_title, description, cover_image_url, current_source_url,\n source_website_host, views_count, bookmarks_count, total_rating_score, total_ratings_count,\n last_chapter_found_in_storage, processing_status as \"processing_status: SeriesStatus\",\n check_interval_minutes, last_checked_at, next_checked_at, created_at, updated_at\n FROM series \n WHERE title = $1\n ", "describe": { "columns": [ { @@ -139,5 +139,5 @@ false ] }, - "hash": "46e71b9fdf391246eeed01dad5b40ae863fda9d9d7ae2b2652c6a5b815adab18" + "hash": "49005252d64c1f75617187b2c904218bfdde0826bc8810c260fdc1d82c72575f" } diff --git a/.sqlx/query-4bc9cada744d2c91bf58c583fda5d5c9e97d9fd394391e623845d2834f95625b.json b/.sqlx/query-4bc9cada744d2c91bf58c583fda5d5c9e97d9fd394391e623845d2834f95625b.json new file mode 100644 index 0000000..2a29e13 --- /dev/null +++ b/.sqlx/query-4bc9cada744d2c91bf58c583fda5d5c9e97d9fd394391e623845d2834f95625b.json @@ -0,0 +1,73 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH candidate AS (\n SELECT id FROM series\n WHERE processing_status = $1\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n )\n UPDATE series\n SET processing_status = $2\n WHERE id = (SELECT id FROM candidate)\n RETURNING\n id,\n title,\n cover_image_url\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "cover_image_url", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + { + "Custom": { + "name": "series_status", + "kind": { + "Enum": [ + "Pending", + "Processing", + "Available", + "Ongoing", + "Completed", + "Hiatus", + "Discontinued", + "Error", + "Pending Deletion", + "Deleting", + "Deletion Failed" + ] + } + } + }, + { + "Custom": { + "name": "series_status", + "kind": { + "Enum": [ + "Pending", + "Processing", + "Available", + "Ongoing", + "Completed", + "Hiatus", + "Discontinued", + "Error", + "Pending Deletion", + "Deleting", + "Deletion Failed" + ] + } + } + } + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "4bc9cada744d2c91bf58c583fda5d5c9e97d9fd394391e623845d2834f95625b" +} diff --git a/.sqlx/query-4e99507d676e4da8900cace2df44e52907f74d57a294980dd4fb683267690f14.json b/.sqlx/query-4e99507d676e4da8900cace2df44e52907f74d57a294980dd4fb683267690f14.json new file mode 100644 index 0000000..d52ed59 --- /dev/null +++ b/.sqlx/query-4e99507d676e4da8900cace2df44e52907f74d57a294980dd4fb683267690f14.json @@ -0,0 +1,58 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH locked_rows AS ( \n SELECT id\n FROM series_chapters\n WHERE status = 'Processing'\n ORDER BY created_at ASC \n LIMIT $1\n FOR UPDATE SKIP LOCKED\n )\n UPDATE series_chapters sc\n SET \n status = 'Processing', \n updated_at = NOW()\n FROM locked_rows lr, series s\n WHERE sc.id = lr.id AND sc.series_id = s.id\n RETURNING\n sc.id as chapter_id,\n sc.chapter_number,\n sc.source_url as chapter_url,\n s.id as series_id,\n s.title as series_title,\n s.source_website_host as source_host,\n s.current_source_url as series_url\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "chapter_id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "chapter_number", + "type_info": "Float4" + }, + { + "ordinal": 2, + "name": "chapter_url", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "series_id", + "type_info": "Int4" + }, + { + "ordinal": 4, + "name": "series_title", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "source_host", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "series_url", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false + ] + }, + "hash": "4e99507d676e4da8900cace2df44e52907f74d57a294980dd4fb683267690f14" +} diff --git a/.sqlx/query-50293c2e54af11d4c2a553e29b671cef087a159c6ee7182d8ca929ecb748f3b7.json b/.sqlx/query-50293c2e54af11d4c2a553e29b671cef087a159c6ee7182d8ca929ecb748f3b7.json new file mode 100644 index 0000000..cf6c805 --- /dev/null +++ b/.sqlx/query-50293c2e54af11d4c2a553e29b671cef087a159c6ee7182d8ca929ecb748f3b7.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM users WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "50293c2e54af11d4c2a553e29b671cef087a159c6ee7182d8ca929ecb748f3b7" +} diff --git a/.sqlx/query-687d52591357a48a7755284ffd589a5b834dc49ff7b053e488ecc7a2e6a3e1b7.json b/.sqlx/query-687d52591357a48a7755284ffd589a5b834dc49ff7b053e488ecc7a2e6a3e1b7.json deleted file mode 100644 index 3b499f3..0000000 --- a/.sqlx/query-687d52591357a48a7755284ffd589a5b834dc49ff7b053e488ecc7a2e6a3e1b7.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE series SET last_chapter_found_in_storage = $1, updated_at = NOW() WHERE id = $2", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Float4", - "Int4" - ] - }, - "nullable": [] - }, - "hash": "687d52591357a48a7755284ffd589a5b834dc49ff7b053e488ecc7a2e6a3e1b7" -} diff --git a/.sqlx/query-6c1e46896cea195631b6c54e78bff51c0a9c6d899b1bc467119826213a7e9c63.json b/.sqlx/query-6c1e46896cea195631b6c54e78bff51c0a9c6d899b1bc467119826213a7e9c63.json new file mode 100644 index 0000000..8dbff1e --- /dev/null +++ b/.sqlx/query-6c1e46896cea195631b6c54e78bff51c0a9c6d899b1bc467119826213a7e9c63.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM comments WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "6c1e46896cea195631b6c54e78bff51c0a9c6d899b1bc467119826213a7e9c63" +} diff --git a/.sqlx/query-6dc1d469d73360b6bf38fd405305dc551708e2d45b502c97dbe7bab97aa0ba9d.json b/.sqlx/query-6dc1d469d73360b6bf38fd405305dc551708e2d45b502c97dbe7bab97aa0ba9d.json new file mode 100644 index 0000000..d08fbbf --- /dev/null +++ b/.sqlx/query-6dc1d469d73360b6bf38fd405305dc551708e2d45b502c97dbe7bab97aa0ba9d.json @@ -0,0 +1,60 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n s.id,\n s.title,\n s.original_title,\n s.cover_image_url,\n s.last_chapter_found_in_storage,\n s.updated_at,\n COALESCE(json_agg(DISTINCT a.name ORDER BY a.name) FILTER (WHERE a.id IS NOT NULL),\n '[]'::json) as authors\n FROM series s\n LEFT JOIN series_authors sa ON s.id = sa.series_id\n LEFT JOIN authors a ON sa.author_id = a.id\n WHERE\n (\n s.title ILIKE '%' || $1 || '%'\n OR (s.title % $1 AND similarity(s.title, $1) >= $2)\n )\n OR\n (\n s.original_title IS NOT NULL AND (\n s.original_title ILIKE '%' || $1 || '%'\n OR (s.original_title % $1 AND similarity(s.original_title, $1) >= $2)\n )\n )\n GROUP BY s.id\n ORDER BY GREATEST(\n similarity(s.title, $1),\n similarity(COALESCE(s.original_title, ''), $1)\n ) DESC\n LIMIT $3\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "original_title", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "cover_image_url", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "last_chapter_found_in_storage", + "type_info": "Float4" + }, + { + "ordinal": 5, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "authors", + "type_info": "Json" + } + ], + "parameters": { + "Left": [ + "Text", + "Float4", + "Int8" + ] + }, + "nullable": [ + false, + false, + true, + false, + true, + false, + null + ] + }, + "hash": "6dc1d469d73360b6bf38fd405305dc551708e2d45b502c97dbe7bab97aa0ba9d" +} diff --git a/.sqlx/query-6ea09619b5ba51afcddbc8bebc42d1ddf2ae9cbd22d8ee31e6ae54c82fc3be67.json b/.sqlx/query-6ea09619b5ba51afcddbc8bebc42d1ddf2ae9cbd22d8ee31e6ae54c82fc3be67.json deleted file mode 100644 index d9d101d..0000000 --- a/.sqlx/query-6ea09619b5ba51afcddbc8bebc42d1ddf2ae9cbd22d8ee31e6ae54c82fc3be67.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n u.id,\n u.username,\n u.email,\n r.role_name,\n COUNT(*) OVER() as total_items\n FROM users u\n JOIN roles r ON u.role_id = r.id\n ORDER BY u.id ASC\n LIMIT $1 OFFSET $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "username", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "email", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "role_name", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "total_items", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - null - ] - }, - "hash": "6ea09619b5ba51afcddbc8bebc42d1ddf2ae9cbd22d8ee31e6ae54c82fc3be67" -} diff --git a/.sqlx/query-731032aa92d1405c18f5d6534092dfa6afa93aef6c1e2eb0506dad4d389e44e6.json b/.sqlx/query-731032aa92d1405c18f5d6534092dfa6afa93aef6c1e2eb0506dad4d389e44e6.json new file mode 100644 index 0000000..a1ebb55 --- /dev/null +++ b/.sqlx/query-731032aa92d1405c18f5d6534092dfa6afa93aef6c1e2eb0506dad4d389e44e6.json @@ -0,0 +1,102 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n r.id,\n u.username as reporter_username,\n r.reporter_id,\n r.created_at,\n r.reason as \"reason!: ReportReason\",\n sc.id as chapter_id,\n sc.chapter_number as chapter_number,\n sc.title as chapter_series_title,\n c.id as comment_id,\n SUBSTRING(c.content_html, 1, 50) as comment_preview,\n COUNT(*) OVER() as total_items\n FROM reports r\n INNER JOIN users u ON r.reporter_id = u.id\n LEFT JOIN series_chapters sc ON r.chapter_id = sc.id\n LEFT JOIN series s ON sc.series_id = s.id\n LEFT JOIN comments c ON r.comment_id = c.id\n ORDER BY r.created_at DESC\n LIMIT $1\n OFFSET $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "reporter_username", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "reporter_id", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "reason!: ReportReason", + "type_info": { + "Custom": { + "name": "report_reason", + "kind": { + "Enum": [ + "broken_image", + "wrong_chapter", + "duplicate_chapter", + "missing_image", + "missing_chapter", + "slow_loading", + "broken_text", + "toxic", + "racist", + "spam", + "other" + ] + } + } + } + }, + { + "ordinal": 5, + "name": "chapter_id", + "type_info": "Int4" + }, + { + "ordinal": 6, + "name": "chapter_number", + "type_info": "Float4" + }, + { + "ordinal": 7, + "name": "chapter_series_title", + "type_info": "Text" + }, + { + "ordinal": 8, + "name": "comment_id", + "type_info": "Int8" + }, + { + "ordinal": 9, + "name": "comment_preview", + "type_info": "Text" + }, + { + "ordinal": 10, + "name": "total_items", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + true, + false, + null, + null + ] + }, + "hash": "731032aa92d1405c18f5d6534092dfa6afa93aef6c1e2eb0506dad4d389e44e6" +} diff --git a/.sqlx/query-77e09aa662d7eb1f5badd4bf3471545489a797440862aa30b5d1b3ef90cc6a01.json b/.sqlx/query-77e09aa662d7eb1f5badd4bf3471545489a797440862aa30b5d1b3ef90cc6a01.json new file mode 100644 index 0000000..003ceef --- /dev/null +++ b/.sqlx/query-77e09aa662d7eb1f5badd4bf3471545489a797440862aa30b5d1b3ef90cc6a01.json @@ -0,0 +1,47 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE comments\n SET\n content_user_markdown = '',\n content_html = '
[Deleted]
', -- Or any placeholder\n deleted_at = NOW(),\n updated_at = NOW()\n WHERE id = $1 AND user_id = $2\n RETURNING id, content_user_markdown, content_html, updated_at, (deleted_at IS NOT NULL) as \"is_deleted!\"\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "content_user_markdown", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "content_html", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "is_deleted!", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + false, + null + ] + }, + "hash": "77e09aa662d7eb1f5badd4bf3471545489a797440862aa30b5d1b3ef90cc6a01" +} diff --git a/.sqlx/query-7802e84b32168e8ea3d4f75f65d491327ddc6d01f7c959aad77326b251bed291.json b/.sqlx/query-7802e84b32168e8ea3d4f75f65d491327ddc6d01f7c959aad77326b251bed291.json new file mode 100644 index 0000000..53315bc --- /dev/null +++ b/.sqlx/query-7802e84b32168e8ea3d4f75f65d491327ddc6d01f7c959aad77326b251bed291.json @@ -0,0 +1,59 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n u.id,\n u.username,\n u.email,\n u.role_id,\n r.role_name,\n u.is_active,\n COUNT(*) OVER() as \"total_items\"\n FROM users u\n JOIN roles r ON u.role_id = r.id\n ORDER BY u.id ASC\n LIMIT $1 OFFSET $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "username", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "email", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "role_id", + "type_info": "Int4" + }, + { + "ordinal": 4, + "name": "role_name", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "is_active", + "type_info": "Bool" + }, + { + "ordinal": 6, + "name": "total_items", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + true, + null + ] + }, + "hash": "7802e84b32168e8ea3d4f75f65d491327ddc6d01f7c959aad77326b251bed291" +} diff --git a/.sqlx/query-81d81bb83838ea176ab82fe89ebc299b8d579961bfb2691343a3d9cff1f9490f.json b/.sqlx/query-81d81bb83838ea176ab82fe89ebc299b8d579961bfb2691343a3d9cff1f9490f.json new file mode 100644 index 0000000..6d0000a --- /dev/null +++ b/.sqlx/query-81d81bb83838ea176ab82fe89ebc299b8d579961bfb2691343a3d9cff1f9490f.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM reports WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "81d81bb83838ea176ab82fe89ebc299b8d579961bfb2691343a3d9cff1f9490f" +} diff --git a/.sqlx/query-898ddd8b20b52f9781f447b88af5d1d0accc2c839bf05f776664de9f2ba36c92.json b/.sqlx/query-898ddd8b20b52f9781f447b88af5d1d0accc2c839bf05f776664de9f2ba36c92.json new file mode 100644 index 0000000..7b4bf64 --- /dev/null +++ b/.sqlx/query-898ddd8b20b52f9781f447b88af5d1d0accc2c839bf05f776664de9f2ba36c92.json @@ -0,0 +1,24 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT 1 FROM users WHERE (username = $1 OR email = $2) AND id != $3 LIMIT 1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "?column?", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Int4" + ] + }, + "nullable": [ + null + ] + }, + "hash": "898ddd8b20b52f9781f447b88af5d1d0accc2c839bf05f776664de9f2ba36c92" +} diff --git a/.sqlx/query-8a18ab3263d1286f8dacf3875d58b57334a2844ecdfdbc207be3987b8daa3349.json b/.sqlx/query-8a18ab3263d1286f8dacf3875d58b57334a2844ecdfdbc207be3987b8daa3349.json new file mode 100644 index 0000000..93f8167 --- /dev/null +++ b/.sqlx/query-8a18ab3263d1286f8dacf3875d58b57334a2844ecdfdbc207be3987b8daa3349.json @@ -0,0 +1,46 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE comments\n SET\n content_user_markdown = '',\n content_html = '[Removed by Mod]
',\n deleted_at = NOW(),\n updated_at = NOW()\n WHERE id = $1\n RETURNING id, content_user_markdown, content_html, updated_at, (deleted_at IS NOT NULL) as \"is_deleted!\"\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "content_user_markdown", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "content_html", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "is_deleted!", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + null + ] + }, + "hash": "8a18ab3263d1286f8dacf3875d58b57334a2844ecdfdbc207be3987b8daa3349" +} diff --git a/.sqlx/query-21643eac78fdc89735010102e25e48311a4bb482726b2425efbd7fac55271f34.json b/.sqlx/query-8a3fa527c2b92f4b1e6421cafb12670397d643659533a6ddcc90cb84fcd3c4bc.json similarity index 87% rename from .sqlx/query-21643eac78fdc89735010102e25e48311a4bb482726b2425efbd7fac55271f34.json rename to .sqlx/query-8a3fa527c2b92f4b1e6421cafb12670397d643659533a6ddcc90cb84fcd3c4bc.json index d52269f..17a6c1c 100644 --- a/.sqlx/query-21643eac78fdc89735010102e25e48311a4bb482726b2425efbd7fac55271f34.json +++ b/.sqlx/query-8a3fa527c2b92f4b1e6421cafb12670397d643659533a6ddcc90cb84fcd3c4bc.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE series SET processing_status = $1,\n updated_at = NOW() WHERE id = $2 AND processing_status NOT IN ($3, $4)", + "query": "UPDATE series\n SET processing_status = $1, updated_at = NOW()\n WHERE id = $2\n AND processing_status NOT IN ($3, $4)", "describe": { "columns": [], "parameters": { @@ -70,5 +70,5 @@ }, "nullable": [] }, - "hash": "21643eac78fdc89735010102e25e48311a4bb482726b2425efbd7fac55271f34" + "hash": "8a3fa527c2b92f4b1e6421cafb12670397d643659533a6ddcc90cb84fcd3c4bc" } diff --git a/.sqlx/query-92d7089f1eb432ab54f67fc21f7a4a6f91fe7f1bb2c163ff8d36f44020fcc5b7.json b/.sqlx/query-92d7089f1eb432ab54f67fc21f7a4a6f91fe7f1bb2c163ff8d36f44020fcc5b7.json deleted file mode 100644 index 6d1e1b2..0000000 --- a/.sqlx/query-92d7089f1eb432ab54f67fc21f7a4a6f91fe7f1bb2c163ff8d36f44020fcc5b7.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO series_chapters (series_id, chapter_number, title, source_url)\n VALUES ($1, $2, $3, $4)\n ON CONFLICT (source_url) DO UPDATE SET updated_at = NOW()\n RETURNING id", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Int4", - "Float4", - "Text", - "Text" - ] - }, - "nullable": [ - false - ] - }, - "hash": "92d7089f1eb432ab54f67fc21f7a4a6f91fe7f1bb2c163ff8d36f44020fcc5b7" -} diff --git a/.sqlx/query-9a4af2e1957f9d886b4bf067163dbb89c076da206155c7b7820ecd63d13a61b3.json b/.sqlx/query-9a4af2e1957f9d886b4bf067163dbb89c076da206155c7b7820ecd63d13a61b3.json deleted file mode 100644 index 556a56a..0000000 --- a/.sqlx/query-9a4af2e1957f9d886b4bf067163dbb89c076da206155c7b7820ecd63d13a61b3.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n WITH RECURSIVE comment_thread AS (\n -- Anchor member: top-level comments\n SELECT * FROM comments\n WHERE comments_type = $1 AND comments_id = $2 AND parent_id IS NULL AND deleted_at IS NULL\n UNION ALL\n -- Recursive member: replies to comments already in the thread\n SELECT c.*\n FROM comments c\n JOIN comment_thread ct ON c.parent_id = ct.id\n WHERE c.deleted_at IS NULL\n ),\n vote_summary AS (\n SELECT\n cv.comment_vote_id,\n COUNT(*) FILTER (WHERE cv.vote_type = 1) AS upvotes,\n COUNT(*) FILTER (WHERE cv.vote_type = -1) AS downvotes\n FROM comment_votes cv\n WHERE cv.comment_vote_id IN (SELECT id FROM comment_thread)\n GROUP BY cv.comment_vote_id\n ),\n attachments_summary AS (\n -- Aggregate all attachment URLs for each comment into a JSON array\n SELECT\n comment_id,\n json_agg(file_url) as attachment_urls\n FROM comment_attachments\n WHERE comment_id IN (SELECT id FROM comment_thread)\n GROUP BY comment_id\n )\n SELECT\n ct.id as \"id!\",\n ct.parent_id,\n ct.content_html as \"content_html!\",\n ct.content_user_markdown as \"content_markdown!\",\n ct.created_at as \"created_at!\",\n ct.updated_at as \"updated_at!\",\n ct.user_id as \"user_id!\",\n COALESCE(up.display_name, u.username) as \"user_username!\",\n up.avatar_url as \"user_avatar_url\",\n COALESCE(vs.upvotes, 0) as \"upvotes!\",\n COALESCE(vs.downvotes, 0) as \"downvotes!\",\n cv.vote_type as \"current_user_vote: _\",\n ats.attachment_urls as \"attachment_urls: _\"\n FROM comment_thread ct\n JOIN users u ON ct.user_id = u.id\n LEFT JOIN user_profiles up ON u.id = up.user_id\n LEFT JOIN vote_summary vs ON ct.id = vs.comment_vote_id\n LEFT JOIN comment_votes cv ON ct.id = cv.comment_vote_id AND cv.user_id = $3\n LEFT JOIN attachments_summary ats ON ct.id = ats.comment_id\n ORDER BY ct.created_at ASC\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id!", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "parent_id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "content_html!", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "content_markdown!", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "created_at!", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "updated_at!", - "type_info": "Timestamptz" - }, - { - "ordinal": 6, - "name": "user_id!", - "type_info": "Int4" - }, - { - "ordinal": 7, - "name": "user_username!", - "type_info": "Text" - }, - { - "ordinal": 8, - "name": "user_avatar_url", - "type_info": "Text" - }, - { - "ordinal": 9, - "name": "upvotes!", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "downvotes!", - "type_info": "Int8" - }, - { - "ordinal": 11, - "name": "current_user_vote: _", - "type_info": "Int2" - }, - { - "ordinal": 12, - "name": "attachment_urls: _", - "type_info": "Json" - } - ], - "parameters": { - "Left": [ - { - "Custom": { - "name": "comments_entity", - "kind": { - "Enum": [ - "series", - "series_chapters" - ] - } - } - }, - "Int4", - "Int4" - ] - }, - "nullable": [ - null, - null, - null, - null, - null, - null, - null, - null, - true, - null, - null, - false, - null - ] - }, - "hash": "9a4af2e1957f9d886b4bf067163dbb89c076da206155c7b7820ecd63d13a61b3" -} diff --git a/.sqlx/query-a0d21a213952a7b0cf5310928e80fecfc9cfca68c0df7222da50817a9e649bf6.json b/.sqlx/query-a0d21a213952a7b0cf5310928e80fecfc9cfca68c0df7222da50817a9e649bf6.json new file mode 100644 index 0000000..6fe9e51 --- /dev/null +++ b/.sqlx/query-a0d21a213952a7b0cf5310928e80fecfc9cfca68c0df7222da50817a9e649bf6.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n DELETE FROM comments\n WHERE id = $1 AND user_id = $2\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int4" + ] + }, + "nullable": [] + }, + "hash": "a0d21a213952a7b0cf5310928e80fecfc9cfca68c0df7222da50817a9e649bf6" +} diff --git a/.sqlx/query-a4d5abc3b51e7e82774d067146a2e8e371a3684339e1bca5c2b1a3c4116d26a0.json b/.sqlx/query-a4d5abc3b51e7e82774d067146a2e8e371a3684339e1bca5c2b1a3c4116d26a0.json new file mode 100644 index 0000000..ccf7448 --- /dev/null +++ b/.sqlx/query-a4d5abc3b51e7e82774d067146a2e8e371a3684339e1bca5c2b1a3c4116d26a0.json @@ -0,0 +1,61 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH base_search AS (\n SELECT\n u.id,\n u.username,\n u.email,\n u.role_id,\n u.is_active,\n r.role_name,\n similarity(u.username || ' ' || u.email, $3) AS sim_score\n FROM users u\n JOIN roles r ON u.role_id = r.id\n WHERE\n (u.username ILIKE '%' || $3 || '%')\n OR\n (u.email ILIKE '%' || $3 || '%')\n OR\n (\n (u.username || ' ' || u.email) % $3\n AND\n similarity(u.username || ' ' || u.email, $3) >= $4\n )\n ),\n ranked_results AS (\n SELECT\n *,\n CASE\n WHEN username ILIKE $3 OR email ILIKE $3 THEN 10\n WHEN username ILIKE '%' || $3 || '%' OR email ILIKE '%' || $3 || '%' THEN 8\n ELSE 6\n END as search_rank\n FROM base_search\n ),\n total_count AS (\n SELECT COUNT(*) AS total FROM ranked_results\n )\n SELECT\n rr.id,\n rr.username,\n rr.email,\n rr.role_name,\n rr.role_id,\n rr.is_active,\n tc.total as total_items\n FROM ranked_results rr\n CROSS JOIN total_count tc\n -- We can order by columns (search_rank, sim_score) that are not in the final SELECT list\n ORDER BY rr.search_rank DESC, rr.sim_score DESC, rr.id ASC\n LIMIT $1\n OFFSET $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "username", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "email", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "role_name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "role_id", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "is_active", + "type_info": "Bool" + }, + { + "ordinal": 6, + "name": "total_items", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Text", + "Float4" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + true, + null + ] + }, + "hash": "a4d5abc3b51e7e82774d067146a2e8e371a3684339e1bca5c2b1a3c4116d26a0" +} diff --git a/.sqlx/query-a6c2db6e77868f6e17f3dfb16738904b79c6925efedd814fa4cfc70d8af27561.json b/.sqlx/query-a6c2db6e77868f6e17f3dfb16738904b79c6925efedd814fa4cfc70d8af27561.json new file mode 100644 index 0000000..0b0f118 --- /dev/null +++ b/.sqlx/query-a6c2db6e77868f6e17f3dfb16738904b79c6925efedd814fa4cfc70d8af27561.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT file_url FROM comment_attachments WHERE comment_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "file_url", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + }, + "hash": "a6c2db6e77868f6e17f3dfb16738904b79c6925efedd814fa4cfc70d8af27561" +} diff --git a/.sqlx/query-b79a867a9a0819e972ae6e36f6103ad1043fa3ca33fa3690258a9ddff5b1fc27.json b/.sqlx/query-b79a867a9a0819e972ae6e36f6103ad1043fa3ca33fa3690258a9ddff5b1fc27.json new file mode 100644 index 0000000..c9512e4 --- /dev/null +++ b/.sqlx/query-b79a867a9a0819e972ae6e36f6103ad1043fa3ca33fa3690258a9ddff5b1fc27.json @@ -0,0 +1,77 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n s.id,\n s.title,\n s.original_title,\n s.description,\n s.cover_image_url,\n s.updated_at,\n s.last_chapter_found_in_storage,\n sc.title as chapter_title,\n COALESCE(json_agg(DISTINCT a.name ORDER BY a.name) FILTER (WHERE a.id IS NOT NULL),\n '[]'::json) as authors,\n COUNT(*) OVER () as total_items\n FROM\n series s\n LEFT JOIN\n series_chapters sc ON s.id = sc.series_id\n AND s.last_chapter_found_in_storage = sc.chapter_number\n LEFT JOIN\n series_authors sa ON s.id = sa.series_id\n LEFT JOIN\n authors a ON sa.author_id = a.id\n WHERE\n s.updated_at >= NOW() - interval '7 days'\n GROUP BY\n s.id, sc.title\n ORDER BY\n s.updated_at DESC\n LIMIT $1\n OFFSET $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "original_title", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "cover_image_url", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "last_chapter_found_in_storage", + "type_info": "Float4" + }, + { + "ordinal": 7, + "name": "chapter_title", + "type_info": "Text" + }, + { + "ordinal": 8, + "name": "authors", + "type_info": "Json" + }, + { + "ordinal": 9, + "name": "total_items", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + false, + true, + true, + null, + null + ] + }, + "hash": "b79a867a9a0819e972ae6e36f6103ad1043fa3ca33fa3690258a9ddff5b1fc27" +} diff --git a/.sqlx/query-c07704f7b459b9bacce8fabba895c6310650c485e6770f7ab9749330064825de.json b/.sqlx/query-c07704f7b459b9bacce8fabba895c6310650c485e6770f7ab9749330064825de.json deleted file mode 100644 index caaa490..0000000 --- a/.sqlx/query-c07704f7b459b9bacce8fabba895c6310650c485e6770f7ab9749330064825de.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO series_ratings (series_id, user_id, rating) VALUES ($1, $2, $3)\n ON CONFLICT (user_id, series_id) DO UPDATE SET rating = $3, updated_at = NOW()\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int4", - "Int4", - "Int2" - ] - }, - "nullable": [] - }, - "hash": "c07704f7b459b9bacce8fabba895c6310650c485e6770f7ab9749330064825de" -} diff --git a/.sqlx/query-d2d972c1a48715a0c8da941c399a8d5deaac035cf929300fdb795024ba6fed1c.json b/.sqlx/query-c2aea4e6e939393b141fa4035d8062e0ca5f3546d608aa1e5a4ef69814e05531.json similarity index 57% rename from .sqlx/query-d2d972c1a48715a0c8da941c399a8d5deaac035cf929300fdb795024ba6fed1c.json rename to .sqlx/query-c2aea4e6e939393b141fa4035d8062e0ca5f3546d608aa1e5a4ef69814e05531.json index b105148..8122dac 100644 --- a/.sqlx/query-d2d972c1a48715a0c8da941c399a8d5deaac035cf929300fdb795024ba6fed1c.json +++ b/.sqlx/query-c2aea4e6e939393b141fa4035d8062e0ca5f3546d608aa1e5a4ef69814e05531.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n WITH candidate AS (\n SELECT id FROM series\n WHERE\n processing_status = $1\n AND next_checked_at <= NOW()\n ORDER BY next_checked_at ASC\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n )\n UPDATE series\n SET processing_status = $2\n WHERE id = (SELECT id FROM candidate)\n RETURNING\n id, title, original_title, description, cover_image_url, current_source_url,\n source_website_host, views_count, bookmarks_count, total_rating_score, total_ratings_count, last_chapter_found_in_storage,\n processing_status as \"processing_status: SeriesStatus\", check_interval_minutes, last_checked_at,\n next_checked_at, created_at, updated_at\n ", + "query": "\n WITH candidate AS (\n SELECT id FROM series\n WHERE\n processing_status = $1\n AND next_checked_at <= NOW()\n ORDER BY next_checked_at ASC\n LIMIT $2\n FOR UPDATE SKIP LOCKED\n )\n UPDATE series\n SET processing_status = $3\n WHERE id IN (SELECT id FROM candidate)\n RETURNING\n id, \n title, \n current_source_url, source_website_host,\n last_chapter_found_in_storage,\n processing_status as \"processing_status: SeriesStatus\",\n check_interval_minutes\n ", "describe": { "columns": [ { @@ -15,56 +15,21 @@ }, { "ordinal": 2, - "name": "original_title", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "cover_image_url", - "type_info": "Text" - }, - { - "ordinal": 5, "name": "current_source_url", "type_info": "Text" }, { - "ordinal": 6, + "ordinal": 3, "name": "source_website_host", "type_info": "Text" }, { - "ordinal": 7, - "name": "views_count", - "type_info": "Int4" - }, - { - "ordinal": 8, - "name": "bookmarks_count", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "total_rating_score", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "total_ratings_count", - "type_info": "Int4" - }, - { - "ordinal": 11, + "ordinal": 4, "name": "last_chapter_found_in_storage", "type_info": "Float4" }, { - "ordinal": 12, + "ordinal": 5, "name": "processing_status: SeriesStatus", "type_info": { "Custom": { @@ -88,29 +53,9 @@ } }, { - "ordinal": 13, + "ordinal": 6, "name": "check_interval_minutes", "type_info": "Int4" - }, - { - "ordinal": 14, - "name": "last_checked_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 15, - "name": "next_checked_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 16, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 17, - "name": "updated_at", - "type_info": "Timestamptz" } ], "parameters": { @@ -135,6 +80,7 @@ } } }, + "Int8", { "Custom": { "name": "series_status", @@ -158,25 +104,14 @@ ] }, "nullable": [ - false, - false, - true, - false, - false, - false, false, false, false, false, - false, - true, - false, - false, - true, true, false, false ] }, - "hash": "d2d972c1a48715a0c8da941c399a8d5deaac035cf929300fdb795024ba6fed1c" + "hash": "c2aea4e6e939393b141fa4035d8062e0ca5f3546d608aa1e5a4ef69814e05531" } diff --git a/.sqlx/query-34741bbbd599c4a18993fdbe09f58ae9c395f5369ee2522a6c0ab8d18cfe1e9a.json b/.sqlx/query-c8b0764049924eadcaafb999304a7d7b54569d083efbb6f63659e1633abe2ba3.json similarity index 51% rename from .sqlx/query-34741bbbd599c4a18993fdbe09f58ae9c395f5369ee2522a6c0ab8d18cfe1e9a.json rename to .sqlx/query-c8b0764049924eadcaafb999304a7d7b54569d083efbb6f63659e1633abe2ba3.json index 6be9026..a942d14 100644 --- a/.sqlx/query-34741bbbd599c4a18993fdbe09f58ae9c395f5369ee2522a6c0ab8d18cfe1e9a.json +++ b/.sqlx/query-c8b0764049924eadcaafb999304a7d7b54569d083efbb6f63659e1633abe2ba3.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "INSERT INTO series\n (title, original_title, description, cover_image_url, current_source_url, source_website_host, check_interval_minutes)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n RETURNING id", + "query": "\n INSERT INTO series\n (title, original_title, description, cover_image_url, current_source_url, source_website_host, check_interval_minutes)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n RETURNING id\n ", "describe": { "columns": [ { @@ -24,5 +24,5 @@ false ] }, - "hash": "34741bbbd599c4a18993fdbe09f58ae9c395f5369ee2522a6c0ab8d18cfe1e9a" + "hash": "c8b0764049924eadcaafb999304a7d7b54569d083efbb6f63659e1633abe2ba3" } diff --git a/.sqlx/query-d3eb1eeba3a3941bf56b29b24e61b3573b1a42b001e550c1a47c76d062535d4d.json b/.sqlx/query-d3eb1eeba3a3941bf56b29b24e61b3573b1a42b001e550c1a47c76d062535d4d.json deleted file mode 100644 index 792cc05..0000000 --- a/.sqlx/query-d3eb1eeba3a3941bf56b29b24e61b3573b1a42b001e550c1a47c76d062535d4d.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE comments\n SET\n content_user_markdown = $1,\n content_html = $2,\n updated_at = NOW()\n WHERE id = $3 AND user_id = $4\n RETURNING content_html\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "content_html", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Int8", - "Int4" - ] - }, - "nullable": [ - false - ] - }, - "hash": "d3eb1eeba3a3941bf56b29b24e61b3573b1a42b001e550c1a47c76d062535d4d" -} diff --git a/.sqlx/query-d50ae4eb0b10b8710170e43ee655621e97ce66fe4939870b55a10ec5c3132d2c.json b/.sqlx/query-d50ae4eb0b10b8710170e43ee655621e97ce66fe4939870b55a10ec5c3132d2c.json new file mode 100644 index 0000000..10fb256 --- /dev/null +++ b/.sqlx/query-d50ae4eb0b10b8710170e43ee655621e97ce66fe4939870b55a10ec5c3132d2c.json @@ -0,0 +1,12 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM password_reset_tokens WHERE expires_at < NOW()", + "describe": { + "columns": [], + "parameters": { + "Left": [] + }, + "nullable": [] + }, + "hash": "d50ae4eb0b10b8710170e43ee655621e97ce66fe4939870b55a10ec5c3132d2c" +} diff --git a/.sqlx/query-d65a09aee176b6dba0a9e94b3e728931f6e687475043839a396aa605e1136678.json b/.sqlx/query-d65a09aee176b6dba0a9e94b3e728931f6e687475043839a396aa605e1136678.json new file mode 100644 index 0000000..176aebb --- /dev/null +++ b/.sqlx/query-d65a09aee176b6dba0a9e94b3e728931f6e687475043839a396aa605e1136678.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT MAX(chapter_number)\n FROM series_chapters\n WHERE series_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "max", + "type_info": "Float4" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + null + ] + }, + "hash": "d65a09aee176b6dba0a9e94b3e728931f6e687475043839a396aa605e1136678" +} diff --git a/.sqlx/query-da21599581a5323de6a888f6db9cc094c2230b87a725a752373d7e605d96d30f.json b/.sqlx/query-da21599581a5323de6a888f6db9cc094c2230b87a725a752373d7e605d96d30f.json new file mode 100644 index 0000000..c737f37 --- /dev/null +++ b/.sqlx/query-da21599581a5323de6a888f6db9cc094c2230b87a725a752373d7e605d96d30f.json @@ -0,0 +1,49 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE comments\n SET\n content_user_markdown = $1,\n content_html = $2,\n deleted_at = NOW(),\n updated_at = NOW()\n WHERE id = $3 AND user_id = $4\n RETURNING id, content_user_markdown, content_html, updated_at, (deleted_at IS NOT NULL) as \"is_deleted!\"\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "content_user_markdown", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "content_html", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "is_deleted!", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Int8", + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + false, + null + ] + }, + "hash": "da21599581a5323de6a888f6db9cc094c2230b87a725a752373d7e605d96d30f" +} diff --git a/.sqlx/query-e7427da830b3095a987dc773423dfbe82e4f34e11d94898df3d3584e56c5c2af.json b/.sqlx/query-e7427da830b3095a987dc773423dfbe82e4f34e11d94898df3d3584e56c5c2af.json new file mode 100644 index 0000000..2364fa0 --- /dev/null +++ b/.sqlx/query-e7427da830b3095a987dc773423dfbe82e4f34e11d94898df3d3584e56c5c2af.json @@ -0,0 +1,36 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO reports (reporter_id, chapter_id, comment_id, reason)\n VALUES ($1, $2, $3, $4)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Int4", + "Int8", + { + "Custom": { + "name": "report_reason", + "kind": { + "Enum": [ + "broken_image", + "wrong_chapter", + "duplicate_chapter", + "missing_image", + "missing_chapter", + "slow_loading", + "broken_text", + "toxic", + "racist", + "spam", + "other" + ] + } + } + } + ] + }, + "nullable": [] + }, + "hash": "e7427da830b3095a987dc773423dfbe82e4f34e11d94898df3d3584e56c5c2af" +} diff --git a/.sqlx/query-fcd2a58a2eea797a641384f985f8cf908e3d4d612b11bf57f6529cf58f67d971.json b/.sqlx/query-fcd2a58a2eea797a641384f985f8cf908e3d4d612b11bf57f6529cf58f67d971.json new file mode 100644 index 0000000..54b85d5 --- /dev/null +++ b/.sqlx/query-fcd2a58a2eea797a641384f985f8cf908e3d4d612b11bf57f6529cf58f67d971.json @@ -0,0 +1,46 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT u.username, u.email, u.role_id, u.is_active, r.role_name\n FROM users u\n JOIN roles r ON u.role_id = r.id\n WHERE u.id = $1\n FOR UPDATE", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "username", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "email", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "role_id", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "is_active", + "type_info": "Bool" + }, + { + "ordinal": 4, + "name": "role_name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + true, + false + ] + }, + "hash": "fcd2a58a2eea797a641384f985f8cf908e3d4d612b11bf57f6529cf58f67d971" +} diff --git a/.sqlx/query-fd583e5bd160f5f65f2613fbf4a0e26db34167ad2612acc6c1cdd2d795305496.json b/.sqlx/query-fd583e5bd160f5f65f2613fbf4a0e26db34167ad2612acc6c1cdd2d795305496.json new file mode 100644 index 0000000..bd612dd --- /dev/null +++ b/.sqlx/query-fd583e5bd160f5f65f2613fbf4a0e26db34167ad2612acc6c1cdd2d795305496.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM comment_attachments WHERE comment_id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "fd583e5bd160f5f65f2613fbf4a0e26db34167ad2612acc6c1cdd2d795305496" +} diff --git a/Cargo.lock b/Cargo.lock index 26dc8b1..e2dbabe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -77,6 +68,19 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "ammonia" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f" +dependencies = [ + "cssparser 0.35.0", + "html5ever 0.35.0", + "maplit", + "tendril", + "url", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -94,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arbitrary" @@ -208,6 +212,21 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "av-metrics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "996ce95bbdb0203e5b91d4a0c9b81c0d67d11c80f884482a0c1ea19e732e3530" +dependencies = [ + "crossbeam", + "itertools 0.10.5", + "lab", + "num-traits", + "rayon", + "thiserror 1.0.69", + "v_frame", +] + [[package]] name = "av-scenechange" version = "0.14.1" @@ -253,9 +272,9 @@ dependencies = [ [[package]] name = "aws-config" -version = "1.8.3" +version = "1.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0baa720ebadea158c5bda642ac444a2af0cdf7bb66b46d1e4533de5d1f449d0" +checksum = "1856b1b48b65f71a4dd940b1c0931f9a7b646d4a924b9828ffefc1454714668a" dependencies = [ "aws-credential-types", "aws-runtime", @@ -283,9 +302,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.4" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b68c2194a190e1efc999612792e25b1ab3abfefe4306494efaaabc25933c0cbe" +checksum = "86590e57ea40121d47d3f2e131bfd873dea15d78dc2f4604f4734537ad9e56c4" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -300,6 +319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" dependencies = [ "aws-lc-sys", + "untrusted 0.7.1", "zeroize", ] @@ -318,9 +338,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.5.9" +version = "1.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2090e664216c78e766b6bac10fe74d2f451c02441d43484cd76ac9a295075f7" +checksum = "8fe0fd441565b0b318c76e7206c8d1d0b0166b3e986cf30e890b61feb6192045" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -343,9 +363,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.100.0" +version = "1.112.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c5eafbdcd898114b839ba68ac628e31c4cfc3e11dfca38dc1b2de2f35bb6270" +checksum = "eee73a27721035c46da0572b390a69fbdb333d0177c24f3d8f7ff952eeb96690" dependencies = [ "aws-credential-types", "aws-runtime", @@ -377,9 +397,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.78.0" +version = "1.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd7bc4bd34303733bded362c4c997a39130eac4310257c79aae8484b1c4b724" +checksum = "a9c1b1af02288f729e95b72bd17988c009aa72e26dcb59b3200f86d7aea726c9" dependencies = [ "aws-credential-types", "aws-runtime", @@ -399,9 +419,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.79.0" +version = "1.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77358d25f781bb106c1a69531231d4fd12c6be904edb0c47198c604df5a2dbca" +checksum = "4e8122301558dc7c6c68e878af918880b82ff41897a60c8c4e18e4dc4d93e9f1" dependencies = [ "aws-credential-types", "aws-runtime", @@ -421,9 +441,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.80.0" +version = "1.92.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e3ed2a9b828ae7763ddaed41d51724d2661a50c45f845b08967e52f4939cfc" +checksum = "a0c7808adcff8333eaa76a849e6de926c6ac1a1268b9fd6afe32de9c29ef29d2" dependencies = [ "aws-credential-types", "aws-runtime", @@ -444,9 +464,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.3.3" +version = "1.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfb9021f581b71870a17eac25b52335b82211cdc092e02b6876b2bcefa61666" +checksum = "c35452ec3f001e1f2f6db107b6373f1f48f05ec63ba2c5c9fa91f07dad32af11" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -472,9 +492,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" +checksum = "127fcfad33b7dfc531141fda7e1c402ac65f88aca5511a4d31e2e3d2cd01ce9c" dependencies = [ "futures-util", "pin-project-lite", @@ -483,9 +503,9 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.63.5" +version = "0.63.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab9472f7a8ec259ddb5681d2ef1cb1cf16c0411890063e67cdc7b62562cc496" +checksum = "95bd108f7b3563598e4dc7b62e1388c9982324a2abd622442167012690184591" dependencies = [ "aws-smithy-http", "aws-smithy-types", @@ -503,9 +523,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.10" +version = "0.60.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604c7aec361252b8f1c871a7641d5e0ba3a7f5a586e51b66bc9510a5519594d9" +checksum = "e29a304f8319781a39808847efb39561351b1bb76e933da7aa90232673638658" dependencies = [ "aws-smithy-types", "bytes", @@ -514,9 +534,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.62.2" +version = "0.62.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c82ba4cab184ea61f6edaafc1072aad3c2a17dcf4c0fce19ac5694b90d8b5f" +checksum = "445d5d720c99eed0b4aa674ed00d835d9b1427dd73e04adaf2f94c6b2d6f9fca" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -524,6 +544,7 @@ dependencies = [ "bytes", "bytes-utils", "futures-core", + "futures-util", "http 0.2.12", "http 1.3.1", "http-body 0.4.6", @@ -535,9 +556,9 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.0.6" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f108f1ca850f3feef3009bdcc977be201bca9a91058864d9de0684e64514bee0" +checksum = "623254723e8dfd535f566ee7b2381645f8981da086b5c4aa26c0c41582bb1d2c" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -558,33 +579,34 @@ dependencies = [ "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", + "tokio-rustls 0.26.2", "tower", "tracing", ] [[package]] name = "aws-smithy-json" -version = "0.61.4" +version = "0.61.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16e040799d29c17412943bdbf488fd75db04112d0c0d4b9290bacf5ae0014b9" +checksum = "2db31f727935fc63c6eeae8b37b438847639ec330a9161ece694efba257e0c54" dependencies = [ "aws-smithy-types", ] [[package]] name = "aws-smithy-observability" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9364d5989ac4dd918e5cc4c4bdcc61c9be17dcd2586ea7f69e348fc7c6cab393" +checksum = "2d1881b1ea6d313f9890710d65c158bdab6fb08c91ea825f74c1c8c357baf4cc" dependencies = [ "aws-smithy-runtime-api", ] [[package]] name = "aws-smithy-query" -version = "0.60.7" +version = "0.60.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" +checksum = "d28a63441360c477465f80c7abac3b9c4d075ca638f982e605b7dc2a2c7156c9" dependencies = [ "aws-smithy-types", "urlencoding", @@ -592,9 +614,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.8.5" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "660f70d9d8af6876b4c9aa8dcb0dbaf0f89b04ee9a4455bea1b4ba03b15f26f6" +checksum = "0bbe9d018d646b96c7be063dd07987849862b0e6d07c778aad7d93d1be6c1ef0" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -616,9 +638,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.8.5" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "937a49ecf061895fca4a6dd8e864208ed9be7546c0527d04bc07d502ec5fba1c" +checksum = "ec7204f9fd94749a7c53b26da1b961b4ac36bf070ef1e0b94bb09f79d4f6c193" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -633,9 +655,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.3.2" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d498595448e43de7f4296b7b7a18a8a02c61ec9349128c80a368f7c3b4ab11a8" +checksum = "25f535879a207fce0db74b679cfc3e91a3159c8144d717d55f5832aea9eef46e" dependencies = [ "base64-simd", "bytes", @@ -659,18 +681,18 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.10" +version = "0.60.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db87b96cb1b16c024980f133968d52882ca0daaee3a086c6decc500f6c99728" +checksum = "eab77cdd036b11056d2a30a7af7b775789fb024bf216acc13884c6c97752ae56" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.3.8" +version = "1.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b069d19bf01e46298eaedd7c6f283fe565a59263e53eebec945f3e6398f42390" +checksum = "d79fb68e3d7fe5d4833ea34dc87d2e97d26d3086cb3da660bb6b1f76d98680b6" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -682,9 +704,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" dependencies = [ "axum-core", "axum-macros", @@ -702,8 +724,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -717,9 +738,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", @@ -728,7 +749,6 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -737,15 +757,16 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.10.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d" +checksum = "5136e6c5e7e7978fe23e9876fb924af2c0f84c72127ac6ac17e7c46f457d362c" dependencies = [ "axum", "axum-core", "bytes", "cookie", "fastrand", + "futures-core", "futures-util", "headers", "http 1.3.1", @@ -754,12 +775,11 @@ dependencies = [ "mime", "multer", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", - "tower", "tower-layer", "tower-service", + "tracing", "typed-json", ] @@ -778,10 +798,12 @@ dependencies = [ name = "backend" version = "0.1.0" dependencies = [ + "ammonia", "anyhow", "arc-swap", "argon2", "async-channel", + "av-metrics", "aws-config", "aws-sdk-s3", "axum", @@ -791,11 +813,16 @@ dependencies = [ "bytes", "chrono", "dotenvy", + "dssim", + "futures", "image", + "image-compare", "jsonwebtoken", "lettre", "notify", "notify-debouncer-full", + "once_cell", + "pulldown-cmark", "rand 0.9.2", "ravif 0.12.0", "regex", @@ -806,41 +833,29 @@ dependencies = [ "serde_json", "slug", "sqlx", + "tempfile", "time", "tokio", - "toml 0.9.4", + "tokio-cron-scheduler", + "toml 0.9.8", "tower", "tower-http", + "ua_generator", "url", "uuid", ] [[package]] name = "backon" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592277618714fbcecda9a02ba7a8781f319d26532a88553bbacc77ba5d2b3a8d" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ "fastrand", "gloo-timers", "tokio", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base16ct" version = "0.1.1" @@ -892,7 +907,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn", "which", @@ -960,7 +975,17 @@ checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor", + "brotli-decompressor 5.0.0", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] @@ -993,9 +1018,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -1011,9 +1036,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "bytes-utils" @@ -1036,6 +1061,12 @@ dependencies = [ "shlex", ] +[[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" @@ -1061,6 +1092,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.41" @@ -1073,7 +1110,17 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.1.3", +] + +[[package]] +name = "chrono-tz" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" +dependencies = [ + "chrono", + "phf 0.12.1", ] [[package]] @@ -1112,6 +1159,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1199,15 +1256,15 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc-fast" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf62af4cc77d8fe1c22dde4e721d87f2f54056139d8c412e1366b740305f56f" +checksum = "6ddc2d09feefeee8bd78101665bd8645637828fa9317f9f292496dbbd8c65ff3" dependencies = [ "crc", "digest", - "libc", "rand 0.9.2", "regex", + "rustversion", ] [[package]] @@ -1219,6 +1276,39 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "croner" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c007081651a19b42931f86f7d4f74ee1c2a7d0cd2c6636a81695b5ffd4e9990" +dependencies = [ + "chrono", + "derive_builder", + "strum", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -1300,7 +1390,20 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf", + "phf 0.11.3", + "smallvec", +] + +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.13.1", "smallvec", ] @@ -1314,6 +1417,41 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "der" version = "0.6.1" @@ -1344,6 +1482,37 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "derive_more" version = "2.0.1" @@ -1399,6 +1568,35 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dssim" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eaa333e059ea555ff38041ef8245d9b9207a208ed221126a516b840a7a5562f" +dependencies = [ + "crossbeam-channel", + "dssim-core", + "getopts", + "imgref", + "load_image", + "lodepng", + "ordered-channel", + "rayon", + "rgb", +] + +[[package]] +name = "dssim-core" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c601412450ff29a9258b2f85b18b38f658caf70fad1692f40ca863d86cb753" +dependencies = [ + "imgref", + "itertools 0.14.0", + "rayon", + "rgb", +] + [[package]] name = "dtoa" version = "1.0.10" @@ -1581,6 +1779,26 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "fdeflate" version = "0.3.7" @@ -1616,6 +1834,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] @@ -1644,18 +1863,30 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ + "foreign-types-macros", "foreign-types-shared", ] +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "foreign-types-shared" -version = "0.1.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" @@ -1691,6 +1922,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -1735,6 +1981,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -1753,8 +2010,10 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -1763,15 +2022,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1784,9 +2034,9 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width", ] @@ -1811,9 +2061,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1826,12 +2078,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.2" @@ -1930,6 +2176,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hashlink" version = "0.10.0" @@ -2009,10 +2261,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4" dependencies = [ "log", - "markup5ever", + "markup5ever 0.35.0", "match_token", ] +[[package]] +name = "html5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6452c4751a24e1b99c3260d505eaeee76a050573e61f30ac2c924ddc7236f01e" +dependencies = [ + "log", + "markup5ever 0.36.1", +] + [[package]] name = "http" version = "0.2.12" @@ -2157,22 +2419,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.2", "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "webpki-roots 1.0.2", ] [[package]] @@ -2311,6 +2558,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -2334,9 +2587,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.6" +version = "0.25.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" dependencies = [ "bytemuck", "byteorder-lite", @@ -2344,6 +2597,7 @@ dependencies = [ "exr", "gif", "image-webp", + "moxcms", "num-traits", "png", "qoi", @@ -2355,6 +2609,18 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "image-compare" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf712e96694f43e33b8394265e4d4bc06998c3648718148e4584d80dc3b3165" +dependencies = [ + "image", + "itertools 0.14.0", + "rayon", + "thiserror 2.0.12", +] + [[package]] name = "image-webp" version = "0.2.3" @@ -2373,12 +2639,12 @@ checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.0", ] [[package]] @@ -2412,17 +2678,6 @@ dependencies = [ "syn", ] -[[package]] -name = "io-uring" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -2439,6 +2694,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -2463,6 +2727,28 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[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.33" @@ -2478,6 +2764,9 @@ name = "jpeg-decoder" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" +dependencies = [ + "rayon", +] [[package]] name = "js-sys" @@ -2491,16 +2780,18 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "c76e1c7d7df3e34443b3621b459b066a7b79644f059fc8b2db7070c825fd417e" dependencies = [ + "aws-lc-rs", "base64 0.22.1", + "getrandom 0.2.16", "js-sys", "pem", - "ring", "serde", "serde_json", + "signature 2.2.0", "simple_asn1", ] @@ -2524,6 +2815,12 @@ dependencies = [ "libc", ] +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + [[package]] name = "lazy_static" version = "1.5.0" @@ -2539,6 +2836,29 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lcms2" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75877b724685dd49310bdbadbf973fc69b1d01992a6d4a861b928fc3943f87b" +dependencies = [ + "bytemuck", + "foreign-types", + "lcms2-sys", +] + +[[package]] +name = "lcms2-sys" +version = "4.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c2604b23848ca80b2add60f0fb2270fd980e622c25029b6597fa01cfd5f8d5f" +dependencies = [ + "cc", + "dunce", + "libc", + "pkg-config", +] + [[package]] name = "lebe" version = "0.5.2" @@ -2566,7 +2886,7 @@ dependencies = [ "percent-encoding", "quoted_printable", "rustls 0.23.31", - "rustls-native-certs 0.8.1", + "rustls-platform-verifier", "socket2 0.6.0", "tokio", "tokio-rustls 0.26.2", @@ -2615,6 +2935,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-rs-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd" +dependencies = [ + "zlib-rs", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -2633,6 +2962,22 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +[[package]] +name = "load_image" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13af80aa49d27d6334430fcc8aa55c01acdf23209da94f670e217650320644c0" +dependencies = [ + "bytemuck", + "imgref", + "jpeg-decoder", + "lcms2", + "lodepng", + "quick-error", + "rexif", + "rgb", +] + [[package]] name = "lock_api" version = "0.4.13" @@ -2643,6 +2988,17 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lodepng" +version = "3.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a32335d22e44238e2bb0b4d726964d18952ce1f1279ec3305305d2c61539eb" +dependencies = [ + "crc32fast", + "flate2", + "rgb", +] + [[package]] name = "log" version = "0.4.27" @@ -2667,12 +3023,24 @@ dependencies = [ "hashbrown 0.15.4", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "markup5ever" version = "0.35.0" @@ -2681,7 +3049,18 @@ checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3" dependencies = [ "log", "tendril", - "web_atoms", + "web_atoms 0.1.3", +] + +[[package]] +name = "markup5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c3294c4d74d0742910f8c7b466f44dda9eb2d5742c1e430138df290a1e8451c" +dependencies = [ + "log", + "tendril", + "web_atoms 0.2.0", ] [[package]] @@ -2761,6 +3140,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "moxcms" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "multer" version = "3.1.0" @@ -2787,23 +3176,6 @@ dependencies = [ "jobserver", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -2957,47 +3329,12 @@ dependencies = [ "libm", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "openssl-probe" version = "0.1.6" @@ -3005,16 +3342,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] -name = "openssl-sys" -version = "0.9.109" +name = "ordered-channel" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "95be4d57809897b5a7539fc15a7dfe0e84141bc3dfaa2e9b1b27caa90acf61ab" [[package]] name = "outref" @@ -3116,8 +3447,28 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_macros", - "phf_shared", + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" +dependencies = [ + "phf_shared 0.12.1", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros 0.13.1", + "phf_shared 0.13.1", + "serde", ] [[package]] @@ -3126,8 +3477,18 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", ] [[package]] @@ -3136,18 +3497,41 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared", + "phf_shared 0.11.3", "rand 0.8.5", ] +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared 0.13.1", +] + [[package]] name = "phf_macros" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn", @@ -3162,6 +3546,24 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -3213,11 +3615,11 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "png" -version = "0.17.16" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "crc32fast", "fdeflate", "flate2", @@ -3302,19 +3704,102 @@ dependencies = [ ] [[package]] -name = "qoi" -version = "0.4.1" +name = "pulldown-cmark" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +dependencies = [ + "bitflags 2.9.1", + "getopts", + "memchr", + "pulldown-cmark-escape", + "unicase", +] + +[[package]] +name = "pulldown-cmark-escape" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" + +[[package]] +name = "pxfm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f9b339b02259ada5c0f4a389b7fb472f933aa17ce176fd2ad98f28bb401fde" +dependencies = [ + "num-traits", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls 0.23.31", + "socket2 0.6.0", + "thiserror 2.0.12", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ - "bytemuck", + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.1", + "rustls 0.23.31", + "rustls-pki-types", + "slab", + "thiserror 2.0.12", + "tinyvec", + "tracing", + "web-time", ] [[package]] -name = "quick-error" -version = "2.0.1" +name = "quinn-udp" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.0", + "tracing", + "windows-sys 0.60.2", +] [[package]] name = "quote" @@ -3529,9 +4014,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -3541,9 +4026,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -3578,21 +4063,21 @@ dependencies = [ "http-body-util", "hyper 1.6.0", "hyper-rustls 0.27.7", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.31", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", + "tokio-rustls 0.26.2", "tower", "tower-http", "tower-service", @@ -3600,8 +4085,15 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 1.0.2", ] +[[package]] +name = "rexif" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be932047c168919c8d5af065b16fa7d4bd24835ffa256bf0cf1ff463f91c15df" + [[package]] name = "rfc6979" version = "0.3.1" @@ -3632,7 +4124,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -3657,16 +4149,16 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.26" +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_version" @@ -3770,9 +4262,37 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be59af91596cac372a6942530653ad0c3a246cdd491aaa9dcaee47f88d67d5a0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.31", + "rustls-native-certs 0.8.1", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.4", + "security-framework 3.2.0", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -3780,7 +4300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ "ring", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -3792,7 +4312,7 @@ dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -3833,14 +4353,14 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scraper" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f3a24d916e78954af99281a455168d4a9515d65eca99a18da1b813689c4ad9" +checksum = "93cecd86d6259499c844440546d02f55f3e17bd286e529e48d1f9f67e92315cb" dependencies = [ - "cssparser", + "cssparser 0.36.0", "ego-tree", "getopts", - "html5ever", + "html5ever 0.36.1", "precomputed-hash", "selectors", "tendril", @@ -3853,7 +4373,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -3908,19 +4428,19 @@ dependencies = [ [[package]] name = "selectors" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5685b6ae43bfcf7d2e7dfcfb5d8e8f61b46442c902531e41a32a9a8bf0ee0fb6" +checksum = "feef350c36147532e1b79ea5c1f3791373e61cbd9a6a2615413b3807bb164fb7" dependencies = [ "bitflags 2.9.1", - "cssparser", + "cssparser 0.36.0", "derive_more", - "fxhash", "log", "new_debug_unreachable", - "phf", - "phf_codegen", + "phf 0.13.1", + "phf_codegen 0.13.1", "precomputed-hash", + "rustc-hash 2.1.1", "servo_arc", "smallvec", ] @@ -3933,18 +4453,28 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -3953,14 +4483,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -3984,11 +4515,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -4005,9 +4536,9 @@ dependencies = [ [[package]] name = "servo_arc" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "204ea332803bd95a0b60388590d59cf6468ec9becf626e2451f1d26a1d972de4" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" dependencies = [ "stable_deref_trait", ] @@ -4397,7 +4928,20 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.13.1", "precomputed-hash", "serde", ] @@ -4408,8 +4952,20 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", ] @@ -4425,6 +4981,33 @@ dependencies = [ "unicode-properties", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "subtle" version = "2.6.1" @@ -4504,15 +5087,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", "rustix 1.0.8", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4568,13 +5151,16 @@ dependencies = [ [[package]] name = "tiff" -version = "0.9.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" dependencies = [ + "fax", "flate2", - "jpeg-decoder", + "half", + "quick-error", "weezl", + "zune-jpeg", ] [[package]] @@ -4635,43 +5221,46 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2 0.6.0", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] -name = "tokio-macros" -version = "2.5.0" +name = "tokio-cron-scheduler" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "1f50e41f200fd8ed426489bd356910ede4f053e30cebfbd59ef0f856f0d7432a" dependencies = [ - "proc-macro2", - "quote", - "syn", + "chrono", + "chrono-tz", + "croner", + "num-derive", + "num-traits", + "tokio", + "tracing", + "uuid", ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-macros" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ - "native-tls", - "tokio", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -4732,14 +5321,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.4" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ae868b5a0f67631c14589f7e250c1ea2c574ee5ba21c6c8dd4b1485705a5a1" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ "indexmap", - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", + "serde_core", + "serde_spanned 1.0.3", + "toml_datetime 0.7.3", "toml_parser", "toml_writer", "winnow", @@ -4756,11 +5345,11 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -4778,18 +5367,18 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" [[package]] name = "tower" @@ -4802,6 +5391,7 @@ dependencies = [ "pin-project-lite", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -4895,6 +5485,26 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "ua_generator" +version = "0.5.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8003d480b7ac56acfae9f7bed79d52925a6a263b895c981e6cb5c52a5d627640" +dependencies = [ + "dotenvy", + "fastrand", + "serde", + "serde_json", + "toml 0.9.8", + "ureq", +] + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-bidi" version = "0.3.18" @@ -4928,12 +5538,38 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "brotli-decompressor 4.0.3", + "encoding_rs", + "flate2", + "log", + "once_cell", + "rustls 0.23.31", + "rustls-pki-types", + "serde", + "serde_json", + "url", + "webpki-roots 0.26.11", +] + [[package]] name = "url" version = "2.5.4" @@ -4965,13 +5601,13 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ "getrandom 0.3.3", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] @@ -5131,16 +5767,47 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web_atoms" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414" dependencies = [ - "phf", - "phf_codegen", - "string_cache", - "string_cache_codegen", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache 0.8.9", + "string_cache_codegen 0.5.4", +] + +[[package]] +name = "web_atoms" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd0c322f146d0f8aad130ce6c187953889359584497dac6561204c8e17bb43d" +dependencies = [ + "phf 0.13.1", + "phf_codegen 0.13.1", + "string_cache 0.9.0", + "string_cache_codegen 0.6.1", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +dependencies = [ + "rustls-pki-types", ] [[package]] @@ -5206,7 +5873,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -5239,13 +5906,19 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-registry" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -5256,7 +5929,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5265,7 +5938,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", +] + +[[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]] @@ -5304,6 +5986,30 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[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.5" @@ -5341,7 +6047,7 @@ version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -5352,6 +6058,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.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.5" @@ -5370,6 +6082,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[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.5" @@ -5388,6 +6106,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[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.5" @@ -5418,6 +6142,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[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.5" @@ -5436,6 +6166,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[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.5" @@ -5454,6 +6190,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[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.5" @@ -5472,6 +6214,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[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.5" @@ -5492,9 +6240,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] @@ -5630,6 +6378,12 @@ dependencies = [ "syn", ] +[[package]] +name = "zlib-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" + [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 7f3f32b..1b1b300 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,19 +4,26 @@ members = [ ] resolver = "3" +[workspace.lints.clippy] +redundant_clone = "deny" +panic = "deny" +unwrap_used = "deny" +panicking_unwrap = "deny" +implicit_clone = "deny" +perf = "deny" + [profile.dev.package.sqlx-macros] opt-level = 3 -[profile.deploy] +[profile.deployment] inherits = "release" - debug = false opt-level = 3 strip = "none" overflow-checks = false debug-assertions = false rpath = false -lto = "fat" -panic = "unwind" +lto = "thin" +panic = "abort" codegen-units = 1 incremental = false \ No newline at end of file diff --git a/Taskfile.yaml b/Taskfile.yaml index 9f5b140..4bb6252 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -5,21 +5,21 @@ tasks: cmds: - cargo run {{.CLI_ARGS}} - release: + dev-fast: cmds: - - task: backend -- --release - + - cargo run --release + + optimize: + cmds: + - cargo run --profile deployment + frontend: cmds: - bun run dev dir: ./frontend - dev: - cmds: - - task: run-backend - - task: run-frontend - - dev-release: + prod: cmds: - - task: run-backend -- --release - - task: run-frontend + - bun run build + - bun run preview + dir: ./frontend \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/backend/Cargo.toml b/backend/Cargo.toml index a60a6b3..95f01f5 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -4,56 +4,86 @@ version = "0.1.0" edition = "2024" resolver = "3" license = "AGPL-3" -rust-version = "1.89.0" +rust-version = "1.91.0" [[bin]] name = "backend" path = "src/main.rs" [dependencies] -anyhow = "1.0.98" -axum = { version = "0.8.4", features = ["macros"] } +anyhow = "1.0.100" +axum = { version = "0.8.6", features = ["macros"] } chrono = { version = "0.4.41", features = ["serde"] } -image = "0.25.6" -jsonwebtoken = "9.3.1" +image = { version = "0.25.8", features = ["png", "jpeg"] } +jsonwebtoken = { version = "10.2.0", features = ["aws_lc_rs"] } rand = "0.9.1" ravif = { version = "0.12.0", features = ["default"] } -regex = "1.11.1" -reqwest = "0.12.23" -scraper = "0.24.0" +regex = "1.12.2" +reqwest = { version = "0.12.23", default-features = false, features = [ + "http2", + "system-proxy", + "charset", + "rustls-tls"] } +scraper = "0.25.0" serde = { version = "1.0.219", features = ["derive"] } -tokio = { version = "~1.47.0", features = ["full"] } -toml = "0.9.0" +tokio = { version = "1.48.0", features = ["full"] } +toml = "0.9.8" url = "2.5.4" -axum-extra = { version = "0.10.1", features = ["typed-header", "erased-json", "cookie", "multipart"] } -axum-core = "0.5.2" -serde_json = "1.0.140" +axum-extra = { version = "0.12.1", features = [ + "typed-header", + "erased-json", + "cookie", + "multipart"] } +axum-core = "0.5.5" +serde_json = "1.0.145" time = "0.3.41" -rgb = "0.8.50" -aws-sdk-s3 = "1.100.0" -aws-config = { version = "~1.8.0", features = ["behavior-version-latest"] } -bytes = "1.10.1" +rgb = "0.8.52" +aws-sdk-s3 = "1.112.0" +aws-config = { version = "1.8.10", features = ["behavior-version-latest"] } +bytes = "1.11.0" slug = "0.1.6" -backon = { version = "1.5.2", features = ["default", "tokio"] } +backon = { version = "1.6.0", features = [ + "default", + "tokio"] } dotenvy = "0.15.7" -tower-http = { version = "0.6.6", features = ["cors", "tower", "compression-full", "async-compression", "timeout"] } +tower-http = { version = "0.6.6", features = [ + "cors", + "tower", + "compression-full", + "async-compression", + "timeout"] } argon2 = "0.5.3" -sqlx = { version = "0.8.6", features = ["postgres", "chrono", "runtime-tokio-rustls", - "macros", "runtime-tokio", "migrate"] } -uuid = { version = "1.17.0", features = ["v4", "serde"] } -lettre = { version = "0.11.17", default-features = false, features = [ +sqlx = { version = "0.8.6", features = [ + "postgres", + "chrono", + "runtime-tokio-rustls", + "macros", + "runtime-tokio", + "migrate", + "tls-rustls"] } +uuid = { version = "1.19.0", features = ["v4", "serde"] } +lettre = { version = "0.11.18", default-features = false, features = [ "tokio1-rustls", "builder", "smtp-transport", "pool", "rustls-platform-verifier", - "ring" + "aws-lc-rs" ] } async-channel = "2.5.0" -tower = "0.5.2" +tower = { version = "0.5.2", features = ["limit"] } notify = "8.2.0" notify-debouncer-full = "0.6.0" arc-swap = "1.7.1" pulldown-cmark = "0.13.0" ammonia = "4.1.1" once_cell = "1.21.3" +futures = "0.3.31" +ua_generator = "0.5.36" +tokio-cron-scheduler = "0.15.1" + +[dev-dependencies] +tempfile = "3.23" +av-metrics = "0.9" +dssim = "3.2" +image-compare = "0.4.2" \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile index 01f31dd..0b39547 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -24,15 +24,19 @@ COPY .sqlx ./.sqlx COPY backend/src ./backend/src COPY Cargo.toml Cargo.lock ./ COPY backend/Cargo.toml ./backend/ +#COPY migrations ./migrations -RUN cargo build --release --profile deploy --bin backend +RUN cargo build --profile deploy --bin backend -FROM debian:trixie-slim AS runtime +FROM ubuntu:25.04 AS runtime WORKDIR /app # Fix shared libraries: libssl.so.3. RUN apt-get update && apt-get install -y libssl3 && rm -rf /var/lib/apt/lists/* COPY --from=builder /app/target/release/backend /usr/local/bin/ +RUN chmod +x backend + +EXPOSE 8000 CMD ["backend"] diff --git a/backend/config_sites.toml b/backend/config_sites.toml index fb9da80..69e7d58 100644 --- a/backend/config_sites.toml +++ b/backend/config_sites.toml @@ -1,4 +1,3 @@ -# config.toml [sites."www.mgeko.cc"] chapter_link_selector = "#chpagedlist ul.chapter-list li a" chapter_number_from_url_regex = "chapter-([\\d]+(?:[.-][\\d]+)?)" @@ -9,14 +8,15 @@ image_url_attribute = "src" image_url_fallback_attributes = ["data-src", "data-lazy-src"] chapter_order = "desc" -#[sites."harimanga.me"] -#chapter_link_selecctor = "" -#chapter_number_from_url_regex = "chapter-([\\d]+(?:[.-][\\d]+)?)" -#chapter_number_from_text_regex = "([\\d]+(?:[.-][\\d]+)?)" -#chapter_number_data_attribute_on_parent = "" -#image_selector_on_chapter_page = "div#reading-content img" -#image_url_attribute = "src" -#image_url_fallback_attributes = ["data-src", "data-lazy-src"] +[sites."harimanga.me"] +chapter_link_selector = "div.listing-chapters_wrap ul.main li a" +chapter_number_from_url_regex = "chapter-([\\d]+(?:[.-][\\d]+)?)" +chapter_number_from_text_regex = "([\\d]+(?:[.-][\\d]+)?)" +chapter_number_data_attribute_on_parent = "" +image_selector_on_chapter_page = "div.reading-content div img" +image_url_attribute = "src" +image_url_fallback_attributes = ["data-src", "data-lazy-src"] +chapter_order = "desc" #[sites."demonicscans.org"] #image_selector_on_chapter_page = "div.main-width.center-m img" diff --git a/backend/src/api/admin/admin_comment_handler.rs b/backend/src/api/admin/admin_comment_handler.rs new file mode 100644 index 0000000..c10eade --- /dev/null +++ b/backend/src/api/admin/admin_comment_handler.rs @@ -0,0 +1,107 @@ +use axum::extract::{Path, State}; +use axum::http::StatusCode; +use axum::Json; +use axum_core::__private::tracing::{error, info}; +use axum_core::response::{IntoResponse, Response}; +use serde_json::json; + +use crate::api::extractor::ModeratorOrHigherUser; +use crate::builder::startup::AppState; +use crate::database::{DeleteCommentResult, UpdateCommentResponse}; + +pub async fn admin_delete_comment_handler( + auth: ModeratorOrHigherUser, + State(state): State