From b3e02c507d64a327ea5f6e927ccb572e99deb2bf Mon Sep 17 00:00:00 2001 From: Coco Date: Mon, 30 Jun 2025 17:49:34 -0700 Subject: [PATCH 01/11] Initial implementation --- mediabridge/api/app.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mediabridge/api/app.py b/mediabridge/api/app.py index 6d6e4b2..7ff7487 100644 --- a/mediabridge/api/app.py +++ b/mediabridge/api/app.py @@ -51,6 +51,23 @@ def search_movies() -> tuple[Response, int]: movies_list = [row._asdict() for row in movies] return jsonify(movies_list), 200 + @app.route("/api/v1/movie/recommend") # type: ignore + def recommend_movies() -> tuple[Response, int]: + query = request.args.get("q") + if not query: + return jsonify({"error": "Query parameter 'q' is required."}), 400 # type: ignore + + with db.engine.connect() as conn: + pattern = f"%{query}%" + movies = conn.execute( + text( + "SELECT * FROM movie_title WHERE LOWER(title) LIKE LOWER(:pattern) LIMIT 10" + ), + {"pattern": pattern}, + ).fetchall() + movies_list = [row._asdict() for row in movies] + return jsonify(movies_list), 200 + return app From 26ccdb96b340c35e2b5fa0097dc17b5738c7d2ec Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 1 Jul 2025 13:39:07 -0700 Subject: [PATCH 02/11] Fix frontend --- Pipfile.lock | 756 +++++++++--------- mediabridge-frontend/src/api/movie.ts | 7 + .../src/components/MovieSearch.tsx | 33 +- mediabridge/api/app.py | 22 +- package-lock.json | 6 + 5 files changed, 419 insertions(+), 405 deletions(-) create mode 100644 package-lock.json diff --git a/Pipfile.lock b/Pipfile.lock index ead8d8d..1f3a971 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "fbefe8aae0d8aa07e853fbe7b434288b8d97c078d98629292cda438b54755e9e" + "sha256": "4519d3024097a2e6436b2588e155c59fdae1c1bc53a94e72ec918041a8d09210" }, "pipfile-spec": 6, "requires": { @@ -67,11 +67,11 @@ }, "certifi": { "hashes": [ - "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", - "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3" + "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", + "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b" ], - "markers": "python_version >= '3.6'", - "version": "==2025.4.26" + "markers": "python_version >= '3.7'", + "version": "==2025.6.15" }, "charset-normalizer": { "hashes": [ @@ -173,11 +173,11 @@ }, "click": { "hashes": [ - "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", - "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a" + "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", + "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b" ], - "markers": "python_version >= '3.7'", - "version": "==8.1.8" + "markers": "python_version >= '3.10'", + "version": "==8.2.1" }, "click-default-group": { "hashes": [ @@ -215,12 +215,12 @@ }, "flask-cors": { "hashes": [ - "sha256:6ccb38d16d6b72bbc156c1c3f192bc435bfcc3c2bc864b2df1eb9b2d97b2403c", - "sha256:fa5cb364ead54bbf401a26dbf03030c6b18fb2fcaf70408096a572b409586b0c" + "sha256:c7b2cbfb1a31aa0d2e5341eea03a6805349f7a61647daee1a15c46bbe981494c", + "sha256:d81bcb31f07b0985be7f48406247e9243aced229b7747219160a0559edd678db" ], "index": "pypi", "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==5.0.1" + "version": "==6.0.1" }, "flask-sqlalchemy": { "hashes": [ @@ -455,52 +455,52 @@ }, "pandas": { "hashes": [ - "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", - "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", - "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5", - "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", - "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", - "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", - "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea", - "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", - "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f", - "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348", - "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", - "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", - "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", - "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e", - "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", - "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", - "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", - "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30", - "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", - "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", - "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", - "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", - "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", - "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", - "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", - "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761", - "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", - "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57", - "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c", - "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c", - "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", - "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", - "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", - "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42", - "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", - "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39", - "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", - "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", - "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed", - "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", - "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", - "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319" + "sha256:034abd6f3db8b9880aaee98f4f5d4dbec7c4829938463ec046517220b2f8574e", + "sha256:094e271a15b579650ebf4c5155c05dcd2a14fd4fdd72cf4854b2f7ad31ea30be", + "sha256:14a0cc77b0f089d2d2ffe3007db58f170dae9b9f54e569b299db871a3ab5bf46", + "sha256:1a881bc1309f3fce34696d07b00f13335c41f5f5a8770a33b09ebe23261cfc67", + "sha256:1d2b33e68d0ce64e26a4acc2e72d747292084f4e8db4c847c6f5f6cbe56ed6d8", + "sha256:213cd63c43263dbb522c1f8a7c9d072e25900f6975596f883f4bebd77295d4f3", + "sha256:23c2b2dc5213810208ca0b80b8666670eb4660bbfd9d45f58592cc4ddcfd62e1", + "sha256:2c7e2fc25f89a49a11599ec1e76821322439d90820108309bf42130d2f36c983", + "sha256:2eb4728a18dcd2908c7fccf74a982e241b467d178724545a48d0caf534b38ebf", + "sha256:34600ab34ebf1131a7613a260a61dbe8b62c188ec0ea4c296da7c9a06b004133", + "sha256:39ff73ec07be5e90330cc6ff5705c651ace83374189dcdcb46e6ff54b4a72cd6", + "sha256:404d681c698e3c8a40a61d0cd9412cc7364ab9a9cc6e144ae2992e11a2e77a20", + "sha256:40cecc4ea5abd2921682b57532baea5588cc5f80f0231c624056b146887274d2", + "sha256:430a63bae10b5086995db1b02694996336e5a8ac9a96b4200572b413dfdfccb9", + "sha256:4930255e28ff5545e2ca404637bcc56f031893142773b3468dc021c6c32a1390", + "sha256:6021910b086b3ca756755e86ddc64e0ddafd5e58e076c72cb1585162e5ad259b", + "sha256:625466edd01d43b75b1883a64d859168e4556261a5035b32f9d743b67ef44634", + "sha256:75651c14fde635e680496148a8526b328e09fe0572d9ae9b638648c46a544ba3", + "sha256:84141f722d45d0c2a89544dd29d35b3abfc13d2250ed7e68394eda7564bd6324", + "sha256:8adff9f138fc614347ff33812046787f7d43b3cef7c0f0171b3340cae333f6ca", + "sha256:951805d146922aed8357e4cc5671b8b0b9be1027f0619cea132a9f3f65f2f09c", + "sha256:9efc0acbbffb5236fbdf0409c04edce96bec4bdaa649d49985427bd1ec73e085", + "sha256:9ff730713d4c4f2f1c860e36c005c7cefc1c7c80c21c0688fd605aa43c9fcf09", + "sha256:a6872d695c896f00df46b71648eea332279ef4077a409e2fe94220208b6bb675", + "sha256:b198687ca9c8529662213538a9bb1e60fa0bf0f6af89292eb68fea28743fcd5a", + "sha256:b9d8c3187be7479ea5c3d30c32a5d73d62a621166675063b2edd21bc47614027", + "sha256:ba24af48643b12ffe49b27065d3babd52702d95ab70f50e1b34f71ca703e2c0d", + "sha256:bb32dc743b52467d488e7a7c8039b821da2826a9ba4f85b89ea95274f863280f", + "sha256:bb3be958022198531eb7ec2008cfc78c5b1eed51af8600c6c5d9160d89d8d249", + "sha256:bf5be867a0541a9fb47a4be0c5790a4bccd5b77b92f0a59eeec9375fafc2aa14", + "sha256:c06f6f144ad0a1bf84699aeea7eff6068ca5c63ceb404798198af7eb86082e33", + "sha256:c6da97aeb6a6d233fb6b17986234cc723b396b50a3c6804776351994f2a658fd", + "sha256:e0f51973ba93a9f97185049326d75b942b9aeb472bec616a129806facb129ebb", + "sha256:e1991bbb96f4050b09b5f811253c4f3cf05ee89a589379aa36cd623f21a31d6f", + "sha256:e5f08eb9a445d07720776df6e641975665c9ea12c9d8a331e0f6890f2dcd76ef", + "sha256:e78ad363ddb873a631e92a3c063ade1ecfb34cae71e9a2be6ad100f875ac1042", + "sha256:ed16339bc354a73e0a609df36d256672c7d296f3f767ac07257801aa064ff73c", + "sha256:f4dd97c19bd06bc557ad787a15b6489d2614ddaab5d104a0310eb314c724b2d2", + "sha256:f925f1ef673b4bd0271b1809b72b3270384f2b7d9d14a189b12b7fc02574d575", + "sha256:f95a2aef32614ed86216d3c450ab12a4e82084e8102e355707a1d96e33d51c34", + "sha256:fa07e138b3f6c04addfeaf56cc7fdb96c3b68a3fe5e5401251f231fce40a0d7a", + "sha256:fa35c266c8cd1a67d75971a1912b185b492d257092bdd2709bbdebe574ed228d" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==2.2.3" + "version": "==2.3.0" }, "pip": { "hashes": [ @@ -528,75 +528,75 @@ }, "pygments": { "hashes": [ - "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", - "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c" + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" ], "markers": "python_version >= '3.8'", - "version": "==2.19.1" + "version": "==2.19.2" }, "pymongo": { "hashes": [ - "sha256:007450b8c8d17b4e5b779ab6e1938983309eac26b5b8f0863c48effa4b151b07", - "sha256:02f0e1af87280697a1a8304238b863d4eee98c8b97f554ee456c3041c0f3a021", - "sha256:1397eac713b84946210ab556666cfdd787eee824e910fbbe661d147e110ec516", - "sha256:1bac84ee40032bec4c089e92970893157fcd0ef40b81157404ceb4c1dac8ba72", - "sha256:209efd3b62cdbebd3cc7a76d5e37414ad08c9bfe8b28ae73695ade065d5b1277", - "sha256:267eff6a66da5cf5255b3bcd257984619e9c4d41a53578d4e1d827553a51cf40", - "sha256:2d377bb0811e0a9676bacb21a4f87ef307f2e9a40a625660c113a9c0ae897e8c", - "sha256:3d631d879e934b46222f5092d8951cbb9fe83542649697c8d342ea7b5479f118", - "sha256:3f33b8c1405d05517dce06756f2800b37dd098216cae5903cd80ad4f0a9dad08", - "sha256:46c8bce9af98556110a950939f3eaa3f7648308d60df65feb783c780f8b9bfa9", - "sha256:50c503b7e809e54740704ec4c87a0f2ccdb910c3b1d36c07dbd2029b6eaa6a50", - "sha256:51081910a91e3451db74b7265ee290c72220412aa8897d6dfe28f6e5d80b685b", - "sha256:5303e2074b85234e337ebe622d353ce38a35696cd47a7d970f84b545288aee01", - "sha256:5adc1349fd5c94d5dfbcbd1ad9858d1df61945a07f5905dcf17bb62eb4c81f93", - "sha256:5dea2f6b44697eda38a11ef754d2adfff5373c51b1ffda00b9fedc5facbd605f", - "sha256:61733c8f1ded90ab671a08033ee99b837073c73e505b3b3b633a55a0326e77f4", - "sha256:6208b83e7d566935218c0837f3b74c7d2dda83804d5d843ce21a55f22255ab74", - "sha256:66800de4f4487e7c437991b44bc1e717aadaf06e67451a760efe5cd81ce86575", - "sha256:6a8f060f8ad139d1d45f75ef7aa0084bd7f714fc666f98ef00009efc7db34acd", - "sha256:6b91f59137e46cd3ff17d5684a18e8006d65d0ee62eb1068b512262d1c2c5ae8", - "sha256:81b46d9bc62128c3d968336f8635bcfce33d8e9e1fc6be6ebdfb98effaccb9c7", - "sha256:82c36928c1c26580ce4f2497a6875968636e87c77108ff253d76b1355181a405", - "sha256:899a5ea9cd32b1b0880015fdceaa36a41140a8c2ce8621626c52f7023724aed6", - "sha256:8af08ba2886f08d334bc7e5d5c662c60ea2f16e813a2c35106f399463fa11087", - "sha256:8e11ea726ff8ddc8c8393895cd7e93a57e2558c27273d3712797895c53d25692", - "sha256:8e90195cb5aee24a67a29adde54c1dae4d9744e17e4585bea3a83bfff96db46c", - "sha256:92a06e3709e3c7e50820d352d3d4e60015406bcba69808937dac2a6d22226fde", - "sha256:92f5e75ae265e798be1a8a40a29e2ab934e156f3827ca0e1c47e69d43f4dcb31", - "sha256:936f7be9ed6919e3be7369b858d1c58ebaa4f3ef231cf4860779b8ba3b4fcd11", - "sha256:99a52cfbf31579cc63c926048cd0ada6f96c98c1c4c211356193e07418e6207c", - "sha256:a9fe172e93551ddfdb94b9ad34dccebc4b7b680dc1d131bc6bd661c4a5b2945c", - "sha256:b2afe49109b4d498d8e55ac9692915f2a3fce0bd31646bb7ed41f9ab3546ca19", - "sha256:b54e19e0f6c8a7ad0c5074a8cbefb29c12267c784ceb9a1577a62bbc43150161", - "sha256:b63d9d8be87f4be11972c5a63d815974c298ada59a2e1d56ef5b6984d81c544a", - "sha256:b9288188101506a9d1aa3f70f65b7f5f499f8f7d5c23ec86a47551d756e32059", - "sha256:bd0c9322fdf1b9e8a5c99ca337bd9a99d972ba57c976e77b5017366ba26725e1", - "sha256:bd23119f9d0358aa1f78174d2eda88ca5c882a722e25ca31197402278acddc6e", - "sha256:be048fb78e165243272a8cdbeb40d53eace82424b95417ab3ab6ec8e9b00c59b", - "sha256:c02160ab3a67eca393a2a2bb83dccddf4db2196d0d7c6a980a55157e4bdadc06", - "sha256:c03e02129ad202d8e146480b398c4a3ea18266ee0754b6a4805de6baf4a6a8c7", - "sha256:c7d740560710be0c514bc9d26f5dcbb3c85dbb6b450c4c3246d8136ca84055bd", - "sha256:cef461fae88ac51cd6b3f81adf58171113c58c0e77c82c751b3bdcef516cfeb1", - "sha256:d10d3967e87c21869f084af5716d02626a17f6f9ccc9379fcbece5821c2a9fb4", - "sha256:d4b4942e5566a134fe34c03d7182a0b346e4a478defe625dc430dd5a178ad96e", - "sha256:d684d9b385d97ab821d2ae74628c81a8bd12a4e5004a3ded0ec8c20381d62d0e", - "sha256:d81d159bd23d8ac53a6e819cccee991cb9350ab2541dfaa25aeb2f712d23b0a5", - "sha256:d842e11eb94f7074314ff1d97a05790539a1d74c3048ce50ea9f0da1f4f96b0a", - "sha256:d9a1d7d49d0d364520894116133d017b6e0e2d5131eb31c8553552fa77a65085", - "sha256:dc9e412911f210d9b0eca42d25c22d3725809dda03dedbaf6f9ffa192d461905", - "sha256:e4a7855933011026898ea0d4532fbd83cef63a76205c823a4ef5557d970df1f1", - "sha256:e7d349066f4c229d638a30f1f53ec3a4aaf4a4fc568491bdf77e7415a96003fb", - "sha256:ea47a64ed9918be0fa8a4a11146a80f546c09e0d65fd08e90a5c00366a59bdb0", - "sha256:f0b26cd4e090161927b7a81741a3627a41b74265dfb41c6957bfb474504b4b42", - "sha256:f39791a88cd5ec1760f65e878af419747c6f94ce74f9293735cbba6025ff4d0d", - "sha256:fb780d9d284ffdf7922edd4a6d7ba08e54a6680f85f64f91fa9cc2617dd488b7", - "sha256:fca24e4df05501420b2ce2207c03f21fcbdfac1e3f41e312e61b8f416c5b4963", - "sha256:fe497c885b08600a022646f00f4d3303697c5289990acec250e2be2e1699ca23" + "sha256:01065eb1838e3621a30045ab14d1a60ee62e01f65b7cf154e69c5c722ef14d2f", + "sha256:01c184b612f67d5a4c8f864ae7c40b6cc33c0e9bb05e39d08666f8831d120504", + "sha256:02f131a6e61559613b1171b53fbe21fed64e71b0cb4858c47fc9bc7c8e0e501c", + "sha256:0603145c9be5e195ae61ba7a93eb283abafdbd87f6f30e6c2dfc242940fe280c", + "sha256:0cce9428d12ba396ea245fc4c51f20228cead01119fcc959e1c80791ea45f820", + "sha256:0f64c6469c2362962e6ce97258ae1391abba1566a953a492562d2924b44815c2", + "sha256:16440d0da30ba804c6c01ea730405fdbbb476eae760588ea09e6e7d28afc06de", + "sha256:239b5f83b83008471d54095e145d4c010f534af99e87cc8877fc6827736451a0", + "sha256:34cc7d4cd7586c1c4f7af2b97447404046c2d8e7ed4c7214ed0e21dbeb17d57d", + "sha256:389cb6415ec341c73f81fbf54970ccd0cd5d3fa7c238dcdb072db051d24e2cb4", + "sha256:3dcb0b8cdd499636017a53f63ef64cf9b6bd3fd9355796c5a1d228e4be4a4c94", + "sha256:3e20862b81e3863bcd72334e3577a3107604553b614a8d25ee1bb2caaea4eb90", + "sha256:3efc4c515b371a9fa1d198b6e03340985bfe1a55ae2d2b599a714934e7bc61ab", + "sha256:49f9968ea7e6a86d4c9bd31d2095f0419efc498ea5e6067e75ade1f9e64aea3d", + "sha256:4dc60b3f5e1448fd011c729ad5d8735f603b0a08a8773ec8e34a876ccc7de45f", + "sha256:51040e1ba78d6671f8c65b29e2864483451e789ce93b1536de9cc4456ede87fa", + "sha256:54a89739a86da31adcef41f6c3ae62b38a8bad156bba71fe5898871746c5af83", + "sha256:66f168f8c5b1e2e3d518507cf9f200f0c86ac79e2b2be9e7b6c8fd1e2f7d7824", + "sha256:6b4d5794ca408317c985d7acfb346a60f96f85a7c221d512ff0ecb3cce9d6110", + "sha256:6bceb524110c32319eb7119422e400dbcafc5b21bcc430d2049a894f69b604e5", + "sha256:75462d6ce34fb2dd98f8ac3732a7a1a1fbb2e293c4f6e615766731d044ad730e", + "sha256:7ab86b98a18c8689514a9f8d0ec7d9ad23a949369b31c9a06ce4a45dcbffcc5e", + "sha256:7af8c56d0a7fcaf966d5292e951f308fb1f8bac080257349e14742725fd7990d", + "sha256:812a473d584bcb02ab819d379cd5e752995026a2bb0d7713e78462b6650d3f3a", + "sha256:850168d115680ab66a0931a6aa9dd98ed6aa5e9c3b9a6c12128049b9a5721bc5", + "sha256:884cb88a9d4c4c9810056b9c71817bd9714bbe58c461f32b65be60c56759823b", + "sha256:8860445a8da1b1545406fab189dc20319aff5ce28e65442b2b4a8f4228a88478", + "sha256:8c942d1c6334e894271489080404b1a2e3b8bd5de399f2a0c14a77d966be5bc9", + "sha256:8ef6ae029a3390565a0510c872624514dde350007275ecd8126b09175aa02cca", + "sha256:9ab0325d436075f5f1901cde95afae811141d162bc42d9a5befb647fda585ae6", + "sha256:9c8e0420fb4901006ae7893e76108c2a36a343b4f8922466d51c45e9e2ceb717", + "sha256:a10069454195d1d2dda98d681b1dbac9a425f4b0fe744aed5230c734021c1cb9", + "sha256:a457d2ac34c05e9e8a6bb724115b093300bf270f0655fb897df8d8604b2e3700", + "sha256:ab87484c97ae837b0a7bbdaa978fa932fbb6acada3f42c3b2bee99121a594715", + "sha256:ac9241b727a69c39117c12ac1e52d817ea472260dadc66262c3fdca0bab0709b", + "sha256:ad24f5864706f052b05069a6bc59ff875026e28709548131448fe1e40fc5d80f", + "sha256:ad9a2d1357aed5d6750deb315f62cb6f5b3c4c03ffb650da559cb09cb29e6fe8", + "sha256:ae07315bb106719c678477e61077cd28505bb7d3fd0a2341e75a9510118cb785", + "sha256:ae2ea8c62d5f3c6529407c12471385d9a05f9fb890ce68d64976340c85cd661b", + "sha256:af7dfff90647ee77c53410f7fe8ca4fe343f8b768f40d2d0f71a5602f7b5a541", + "sha256:b00ab04630aa4af97294e9abdbe0506242396269619c26f5761fd7b2524ef501", + "sha256:b7e04c45f6a7d5a13fe064f42130d29b0730cb83dd387a623563ff3b9bd2f4d1", + "sha256:bf43ae07804d7762b509f68e5ec73450bb8824e960b03b861143ce588b41f467", + "sha256:c38168263ed94a250fc5cf9c6d33adea8ab11c9178994da1c3481c2a49d235f8", + "sha256:c793223aef21a8c415c840af1ca36c55a05d6fa3297378da35de3fb6661c0174", + "sha256:c9c7d345d57f17b1361008aea78a37e8c139631a46aeb185dd2749850883c7ba", + "sha256:cdd8041902963c84dc4e27034fa045ac55fabcb2a4ba5b68b880678557573e70", + "sha256:cfc69d7bc4d4d5872fd1e6de25e6a16e2372c7d5556b75c3b8e2204dce73e3fb", + "sha256:d13556e91c4a8cb07393b8c8be81e66a11ebc8335a40fa4af02f4d8d3b40c8a1", + "sha256:d6044ca0eb74d97f7d3415264de86a50a401b7b0b136d30705f022f9163c3124", + "sha256:dd326bcb92d28d28a3e7ef0121602bad78691b6d4d1f44b018a4616122f1ba8b", + "sha256:de529aebd1ddae2de778d926b3e8e2e42a9b37b5c668396aad8f28af75e606f9", + "sha256:dfb0c21bdd58e58625c9cd8de13e859630c29c9537944ec0a14574fdf88c2ac4", + "sha256:ec89516622dfc8b0fdff499612c0bd235aa45eeb176c9e311bcc0af44bf952b6", + "sha256:f30eab4d4326df54fee54f31f93e532dc2918962f733ee8e115b33e6fe151d92", + "sha256:f57a664aa74610eb7a52fa93f2cf794a1491f4f76098343485dd7da5b3bcff06", + "sha256:f8057f9bc9c94a8fd54ee4f5e5106e445a8f406aff2df74746f21c8791ee2403" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==4.13.0" + "version": "==4.13.2" }, "python-dateutil": { "hashes": [ @@ -608,12 +608,12 @@ }, "python-dotenv": { "hashes": [ - "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", - "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" + "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", + "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==1.1.0" + "version": "==1.1.1" }, "python-multipart": { "hashes": [ @@ -699,12 +699,12 @@ }, "requests": { "hashes": [ - "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", - "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", + "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.32.3" + "version": "==2.32.4" }, "rich": { "hashes": [ @@ -716,65 +716,60 @@ }, "ruff": { "hashes": [ - "sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112", - "sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4", - "sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b", - "sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345", - "sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b", - "sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f", - "sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d", - "sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6", - "sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875", - "sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639", - "sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092", - "sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81", - "sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709", - "sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4", - "sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd", - "sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8", - "sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1", - "sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac" + "sha256:069052605fe74c765a5b4272eb89880e0ff7a31e6c0dbf8767203c1fbd31c7ff", + "sha256:2be9d32a147f98a1972c1e4df9a6956d612ca5f5578536814372113d09a27a6c", + "sha256:49b7ce354eed2a322fbaea80168c902de9504e6e174fd501e9447cad0232f9e6", + "sha256:6013a46d865111e2edb71ad692fbb8262e6c172587a57c0669332a449384a36b", + "sha256:6cc32e863adcf9e71690248607ccdf25252eeeab5193768e6873b901fd441fed", + "sha256:70d52a058c0e7b88b602f575d23596e89bd7d8196437a4148381a3f73fcd5010", + "sha256:78ad09a022c64c13cc6077707f036bab0fac8cd7088772dcd1e5be21c5002efc", + "sha256:7fd49a4619f90d5afc65cf42e07b6ae98bb454fd5029d03b306bd9e2273d44cc", + "sha256:801d626de15e6bf988fbe7ce59b303a914ff9c616d5866f8c79eb5012720ae13", + "sha256:806bbc17f1104fd57451a98a58df35388ee3ab422e029e8f5cf30aa4af2c138c", + "sha256:84d0a69d1e8d716dfeab22d8d5e7c786b73f2106429a933cee51d7b09f861d4e", + "sha256:9a256522893cb7e92bb1e1153283927f842dea2e48619c803243dccc8437b8be", + "sha256:9e1123b1c033f77bd2590e4c1fe7e8ea72ef990a85d2484351d408224d603013", + "sha256:a684f125a4fec2d5a6501a466be3841113ba6847827be4573fddf8308b83477d", + "sha256:b3f75a19e03a4b0757d1412edb7f27cffb0c700365e9d6b60bc1b68d35bc89e0", + "sha256:bdecdef753bf1e95797593007569d8e1697a54fca843d78f6862f7dc279e23bd", + "sha256:d973fa626d4c8267848755bd0414211a456e99e125dcab147f24daa9e991a245", + "sha256:ed5af6aaaea20710e77698e2055b9ff9b3494891e1b24d26c07055459bb717e9" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.11.11" + "version": "==0.12.1" }, "scikit-learn": { "hashes": [ - "sha256:0650e730afb87402baa88afbf31c07b84c98272622aaba002559b614600ca691", - "sha256:0c8d036eb937dbb568c6242fa598d551d88fb4399c0344d95c001980ec1c7d36", - "sha256:1061b7c028a8663fb9a1a1baf9317b64a257fcb036dae5c8752b2abef31d136f", - "sha256:25fc636bdaf1cc2f4a124a116312d837148b5e10872147bdaf4887926b8c03d8", - "sha256:2c2cae262064e6a9b77eee1c8e768fc46aa0b8338c6a8297b9b6759720ec0ff2", - "sha256:2e69fab4ebfc9c9b580a7a80111b43d214ab06250f8a7ef590a4edf72464dd86", - "sha256:2ffa1e9e25b3d93990e74a4be2c2fc61ee5af85811562f1288d5d055880c4322", - "sha256:3f59fe08dc03ea158605170eb52b22a105f238a5d512c4470ddeca71feae8e5f", - "sha256:44a17798172df1d3c1065e8fcf9019183f06c87609b49a124ebdf57ae6cb0107", - "sha256:6849dd3234e87f55dce1db34c89a810b489ead832aaf4d4550b7ea85628be6c1", - "sha256:6a7aa5f9908f0f28f4edaa6963c0a6183f1911e63a69aa03782f0d924c830a35", - "sha256:70b1d7e85b1c96383f872a519b3375f92f14731e279a7b4c6cfd650cf5dffc52", - "sha256:72abc587c75234935e97d09aa4913a82f7b03ee0b74111dcc2881cba3c5a7b33", - "sha256:775da975a471c4f6f467725dff0ced5c7ac7bda5e9316b260225b48475279a1b", - "sha256:7a1c43c8ec9fde528d664d947dc4c0789be4077a3647f232869f41d9bf50e0fb", - "sha256:7a73d457070e3318e32bdb3aa79a8d990474f19035464dfd8bede2883ab5dc3b", - "sha256:8634c4bd21a2a813e0a7e3900464e6d593162a29dd35d25bdf0103b3fce60ed5", - "sha256:8a600c31592bd7dab31e1c61b9bbd6dea1b3433e67d264d17ce1017dbdce8002", - "sha256:926f207c804104677af4857b2c609940b743d04c4c35ce0ddc8ff4f053cddc1b", - "sha256:a17c1dea1d56dcda2fac315712f3651a1fea86565b64b48fa1bc090249cbf236", - "sha256:b3b00cdc8f1317b5f33191df1386c0befd16625f49d979fe77a8d44cae82410d", - "sha256:b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e", - "sha256:b8b7a3b86e411e4bce21186e1c180d792f3d99223dcfa3b4f597ecc92fa1a422", - "sha256:c06beb2e839ecc641366000ca84f3cf6fa9faa1777e29cf0c04be6e4d096a348", - "sha256:d056391530ccd1e501056160e3c9673b4da4805eb67eb2bdf4e983e1f9c9204e", - "sha256:dc4765af3386811c3ca21638f63b9cf5ecf66261cc4815c1db3f1e7dc7b79db2", - "sha256:dc5cf3d68c5a20ad6d571584c0750ec641cc46aeef1c1507be51300e6003a7e1", - "sha256:e7be3fa5d2eb9be7d77c3734ff1d599151bb523674be9b834e8da6abe132f44e", - "sha256:e8ca8cb270fee8f1f76fa9bfd5c3507d60c6438bbee5687f81042e2bb98e5a97", - "sha256:fa909b1a36e000a03c382aade0bd2063fd5680ff8b8e501660c0f59f021a6415" + "sha256:014e07a23fe02e65f9392898143c542a50b6001dbe89cb867e19688e468d049b", + "sha256:0521cb460426c56fee7e07f9365b0f45ec8ca7b2d696534ac98bfb85e7ae4775", + "sha256:0b2f8a0b1e73e9a08b7cc498bb2aeab36cdc1f571f8ab2b35c6e5d1c7115d97d", + "sha256:126c09740a6f016e815ab985b21e3a0656835414521c81fc1a8da78b679bdb75", + "sha256:1babf2511e6ffd695da7a983b4e4d6de45dce39577b26b721610711081850906", + "sha256:2726c8787933add436fb66fb63ad18e8ef342dfb39bbbd19dc1e83e8f828a85a", + "sha256:317ca9f83acbde2883bd6bb27116a741bfcb371369706b4f9973cf30e9a03b0d", + "sha256:34cc8d9d010d29fb2b7cbcd5ccc24ffdd80515f65fe9f1e4894ace36b267ce19", + "sha256:5abd2acff939d5bd4701283f009b01496832d50ddafa83c90125a4e41c33e314", + "sha256:5b7974f1f32bc586c90145df51130e02267e4b7e77cab76165c76cf43faca0d9", + "sha256:63017a5f9a74963d24aac7590287149a8d0f1a0799bbe7173c0d8ba1523293c0", + "sha256:7d7240c7b19edf6ed93403f43b0fcb0fe95b53bc0b17821f8fb88edab97085ef", + "sha256:80bd3bd4e95381efc47073a720d4cbab485fc483966f1709f1fd559afac57ab8", + "sha256:8ef09b1615e1ad04dc0d0054ad50634514818a8eb3ee3dee99af3bffc0ef5007", + "sha256:8fa979313b2ffdfa049ed07252dc94038def3ecd49ea2a814db5401c07f1ecfa", + "sha256:9dbe48d69aa38ecfc5a6cda6c5df5abef0c0ebdb2468e92437e2053f84abb8bc", + "sha256:9f39f6a811bf3f15177b66c82cbe0d7b1ebad9f190737dcdef77cfca1ea3c19c", + "sha256:9fe7f51435f49d97bd41d724bb3e11eeb939882af9c29c931a8002c357e8cdd5", + "sha256:bf3755f25f145186ad8c403312f74fb90df82a4dfa1af19dc96ef35f57237a94", + "sha256:c01e869b15aec88e2cdb73d27f15bdbe03bce8e2fb43afbe77c45d399e73a5a3", + "sha256:c2c7243d34aaede0efca7a5a96d67fddaebb4ad7e14a70991b9abee9dc5c0379", + "sha256:d0c93294e1e1acbee2d029b1f2a064f26bd928b284938d51d412c22e0c977eb3", + "sha256:e2539bb58886a531b6e86a510c0348afaadd25005604ad35966a85c2ec378800", + "sha256:e39d95a929b112047c25b775035c8c234c5ca67e681ce60d12413afb501129f7", + "sha256:e7e7ced20582d3a5516fb6f405fd1d254e1f5ce712bfef2589f51326af6346e8" ], "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==1.6.1" + "markers": "python_version >= '3.10'", + "version": "==1.7.0" }, "scikit-surprise": { "hashes": [ @@ -786,64 +781,55 @@ }, "scipy": { "hashes": [ - "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477", - "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c", - "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", - "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", - "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539", - "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", - "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6", - "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594", - "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92", - "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82", - "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49", - "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", - "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba", - "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982", - "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", - "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65", - "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", - "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", - "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed", - "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c", - "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", - "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", - "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019", - "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e", - "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1", - "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889", - "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", - "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", - "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9", - "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", - "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", - "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b", - "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13", - "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", - "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40", - "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c", - "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253", - "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb", - "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f", - "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", - "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45", - "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", - "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", - "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", - "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e", - "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126" + "sha256:03931b4e870c6fef5b5c0970d52c9f6ddd8c8d3e934a98f09308377eba6f3824", + "sha256:1d8747f7736accd39289943f7fe53a8333be7f15a82eea08e4afe47d79568c32", + "sha256:1dbc8fdba23e4d80394ddfab7a56808e3e6489176d559c6c71935b11a2d59db1", + "sha256:26ec28675f4a9d41587266084c626b02899db373717d9312fa96ab17ca1ae94d", + "sha256:4f720300a3024c237ace1cb11f9a84c38beb19616ba7c4cdcd771047a10a1706", + "sha256:512c4f4f85912767c351a0306824ccca6fd91307a9f4318efe8fdbd9d30562ef", + "sha256:58e0d4354eacb6004e7aa1cd350e5514bd0270acaa8d5b36c0627bb3bb486974", + "sha256:6b65d232157a380fdd11a560e7e21cde34fdb69d65c09cb87f6cc024ee376351", + "sha256:6c4abb4c11fc0b857474241b812ce69ffa6464b4bd8f4ecb786cf240367a36a7", + "sha256:75b2094ec975c80efc273567436e16bb794660509c12c6a31eb5c195cbf4b6dc", + "sha256:79a3c13d43c95aa80b87328a46031cf52508cf5f4df2767602c984ed1d3c6bbe", + "sha256:7dcf42c380e1e3737b343dec21095c9a9ad3f9cbe06f9c05830b44b1786c9e90", + "sha256:7eb6bd33cef4afb9fa5f1fb25df8feeb1e52d94f21a44f1d17805b41b1da3180", + "sha256:88a6ca658fb94640079e7a50b2ad3b67e33ef0f40e70bdb7dc22017dae73ac08", + "sha256:8cb824c1fc75ef29893bc32b3ddd7b11cf9ab13c1127fe26413a05953b8c32ed", + "sha256:90452f6a9f3fe5a2cf3748e7be14f9cc7d9b124dce19667b54f5b429d680d539", + "sha256:952358b7e58bd3197cfbd2f2f2ba829f258404bdf5db59514b515a8fe7a36c52", + "sha256:a16ba90847249bedce8aa404a83fb8334b825ec4a8e742ce6012a7a5e639f95c", + "sha256:a2f0bf2f58031c8701a8b601df41701d2a7be17c7ffac0a4816aeba89c4cdac8", + "sha256:aad603e9339ddb676409b104c48a027e9916ce0d2838830691f39552b38a352e", + "sha256:adf9b1999323ba335adc5d1dc7add4781cb5a4b0ef1e98b79768c05c796c4e49", + "sha256:ae902626972f1bd7e4e86f58fd72322d7f4ec7b0cfc17b15d4b7006efc385176", + "sha256:b2243561b45257f7391d0f49972fca90d46b79b8dbcb9b2cb0f9df928d370ad4", + "sha256:b370f8f6ac6ef99815b0d5c9f02e7ade77b33007d74802efc8316c8db98fd11e", + "sha256:b5ef54021e832869c8cfb03bc3bf20366cbcd426e02a58e8a58d7584dfbb8f62", + "sha256:bbba55fb97ba3cdef9b1ee973f06b09d518c0c7c66a009c729c7d1592be1935e", + "sha256:d2b83c37edbfa837a8923d19c749c1935ad3d41cf196006a24ed44dba2ec4358", + "sha256:d30c0fe579bb901c61ab4bb7f3eeb7281f0d4c4a7b52dbf563c89da4fd2949be", + "sha256:de2db7250ff6514366a9709c2cba35cb6d08498e961cba20d7cff98a7ee88938", + "sha256:deec06d831b8f6b5fb0b652433be6a09db29e996368ce5911faf673e78d20085", + "sha256:e69f798847e9add03d512eaf5081a9a5c9a98757d12e52e6186ed9681247a1ac", + "sha256:e6d7dfc148135e9712d87c5f7e4f2ddc1304d1582cb3a7d698bbadedb61c7afd", + "sha256:e85800274edf4db8dd2e4e93034f92d1b05c9421220e7ded9988b16976f849c1", + "sha256:e9f414cbe9ca289a73e0cc92e33a6a791469b6619c240aa32ee18abdce8ab451", + "sha256:eb9f147a1b8529bb7fec2a85cf4cf42bdfadf9e83535c309a11fdae598c88e8b", + "sha256:f56296fefca67ba605fd74d12f7bd23636267731a72cb3947963e76b8c0a25db", + "sha256:f91b87e1689f0370690e8470916fe1b2308e5b2061317ff76977c8f836452a47" ], "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==1.15.3" + "markers": "python_version >= '3.11'", + "version": "==1.16.0" }, "setuptools": { "hashes": [ - "sha256:49f7af965996f26d43c8ae34539c8d99c5042fbff34302ea151eaa9c207cd257", - "sha256:95a60484590d24103af13b686121328cc2736bee85de8936383111e421b9edc0" + "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", + "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" ], "markers": "python_version >= '3.9'", - "version": "==80.8.0" + "version": "==80.9.0" }, "shellingham": { "hashes": [ @@ -952,20 +938,20 @@ }, "typer": { "hashes": [ - "sha256:89507b104f9b6a0730354f27c39fae5b63ccd0c95b1ce1f1a6ba0cfd329997c3", - "sha256:eb0651654dcdea706780c466cf06d8f174405a659ffff8f163cfbfee98c0e173" + "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855", + "sha256:af377ffaee1dbe37ae9440cb4e8f11686ea5ce4e9bae01b84ae7c63b87f1dd3b" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.15.4" + "version": "==0.16.0" }, "typing-extensions": { "hashes": [ - "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", - "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef" + "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", + "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af" ], - "markers": "python_version >= '3.8'", - "version": "==4.13.2" + "markers": "python_version >= '3.9'", + "version": "==4.14.0" }, "tzdata": { "hashes": [ @@ -977,19 +963,19 @@ }, "urllib3": { "hashes": [ - "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", - "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813" + "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", + "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" ], "markers": "python_version >= '3.9'", - "version": "==2.4.0" + "version": "==2.5.0" }, "uvicorn": { "hashes": [ - "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", - "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403" + "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", + "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01" ], "markers": "python_version >= '3.9'", - "version": "==0.34.2" + "version": "==0.35.0" }, "werkzeug": { "hashes": [ @@ -1014,76 +1000,76 @@ "toml" ], "hashes": [ - "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7", - "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be", - "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404", - "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11", - "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5", - "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d", - "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347", - "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36", - "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3", - "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3", - "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b", - "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e", - "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85", - "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279", - "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d", - "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a", - "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3", - "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7", - "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57", - "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8", - "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625", - "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b", - "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740", - "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a", - "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be", - "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257", - "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622", - "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6", - "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879", - "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a", - "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a", - "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a", - "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050", - "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0", - "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32", - "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1", - "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48", - "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f", - "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008", - "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223", - "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2", - "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53", - "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975", - "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7", - "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199", - "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f", - "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7", - "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27", - "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c", - "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca", - "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787", - "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9", - "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a", - "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8", - "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20", - "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d", - "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99", - "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108", - "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7", - "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c", - "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb", - "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46", - "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca", - "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d", - "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837", - "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54", - "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3" + "sha256:02532fd3290bb8fa6bec876520842428e2a6ed6c27014eca81b031c2d30e3f71", + "sha256:0a4be2a28656afe279b34d4f91c3e26eccf2f85500d4a4ff0b1f8b54bf807338", + "sha256:0b3496922cb5f4215bf5caaef4cf12364a26b0be82e9ed6d050f3352cf2d7ef0", + "sha256:0c804506d624e8a20fb3108764c52e0eef664e29d21692afa375e0dd98dc384f", + "sha256:0f16649a7330ec307942ed27d06ee7e7a38417144620bb3d6e9a18ded8a2d3e5", + "sha256:16aa0830d0c08a2c40c264cef801db8bc4fc0e1892782e45bcacbd5889270509", + "sha256:18a0912944d70aaf5f399e350445738a1a20b50fbea788f640751c2ed9208b6c", + "sha256:1c503289ffef1d5105d91bbb4d62cbe4b14bec4d13ca225f9c73cde9bb46207d", + "sha256:2241ad5dbf79ae1d9c08fe52b36d03ca122fb9ac6bca0f34439e99f8327ac89f", + "sha256:25308bd3d00d5eedd5ae7d4357161f4df743e3c0240fa773ee1b0f75e6c7c0f1", + "sha256:2a876e4c3e5a2a1715a6608906aa5a2e0475b9c0f68343c2ada98110512ab1d8", + "sha256:2d04b16a6062516df97969f1ae7efd0de9c31eb6ebdceaa0d213b21c0ca1a683", + "sha256:30f445f85c353090b83e552dcbbdad3ec84c7967e108c3ae54556ca69955563e", + "sha256:31324f18d5969feef7344a932c32428a2d1a3e50b15a6404e97cba1cc9b2c631", + "sha256:34ed2186fe52fcc24d4561041979a0dec69adae7bce2ae8d1c49eace13e55c43", + "sha256:37ab6be0859141b53aa89412a82454b482c81cf750de4f29223d52268a86de67", + "sha256:37ae0383f13cbdcf1e5e7014489b0d71cc0106458878ccde52e8a12ced4298ed", + "sha256:382e7ddd5289f140259b610e5f5c58f713d025cb2f66d0eb17e68d0a94278875", + "sha256:3bb5838701ca68b10ebc0937dbd0eb81974bac54447c55cd58dea5bca8451029", + "sha256:437c576979e4db840539674e68c84b3cda82bc824dd138d56bead1435f1cb5d7", + "sha256:49f1d0788ba5b7ba65933f3a18864117c6506619f5ca80326b478f72acf3f385", + "sha256:52e92b01041151bf607ee858e5a56c62d4b70f4dac85b8c8cb7fb8a351ab2c10", + "sha256:535fde4001b2783ac80865d90e7cc7798b6b126f4cd8a8c54acfe76804e54e58", + "sha256:56f5eb308b17bca3bbff810f55ee26d51926d9f89ba92707ee41d3c061257e55", + "sha256:5add197315a054e92cee1b5f686a2bcba60c4c3e66ee3de77ace6c867bdee7cb", + "sha256:5f646a99a8c2b3ff4c6a6e081f78fad0dde275cd59f8f49dc4eab2e394332e74", + "sha256:600a1d4106fe66f41e5d0136dfbc68fe7200a5cbe85610ddf094f8f22e1b0300", + "sha256:60c458224331ee3f1a5b472773e4a085cc27a86a0b48205409d364272d67140d", + "sha256:64bdd969456e2d02a8b08aa047a92d269c7ac1f47e0c977675d550c9a0863643", + "sha256:66b974b145aa189516b6bf2d8423e888b742517d37872f6ee4c5be0073bd9a3c", + "sha256:684e2110ed84fd1ca5f40e89aa44adf1729dc85444004111aa01866507adf363", + "sha256:68cd53aec6f45b8e4724c0950ce86eacb775c6be01ce6e3669fe4f3a21e768ed", + "sha256:69aa417a030bf11ec46149636314c24c8d60fadb12fc0ee8f10fda0d918c879d", + "sha256:6ad935f0016be24c0e97fc8c40c465f9c4b85cbbe6eac48934c0dc4d2568321e", + "sha256:6b55ad10a35a21b8015eabddc9ba31eb590f54adc9cd39bcf09ff5349fd52125", + "sha256:6cf43c78c4282708a28e466316935ec7489a9c487518a77fa68f716c67909cec", + "sha256:6f424507f57878e424d9a95dc4ead3fbdd72fd201e404e861e465f28ea469951", + "sha256:70760b4c5560be6ca70d11f8988ee6542b003f982b32f83d5ac0b72476607b70", + "sha256:73e9439310f65d55a5a1e0564b48e34f5369bee943d72c88378f2d576f5a5751", + "sha256:7931b9e249edefb07cd6ae10c702788546341d5fe44db5b6108a25da4dca513f", + "sha256:81f34346dd63010453922c8e628a52ea2d2ccd73cb2487f7700ac531b247c8a5", + "sha256:888f8eee13f2377ce86d44f338968eedec3291876b0b8a7289247ba52cb984cd", + "sha256:95335095b6c7b1cc14c3f3f17d5452ce677e8490d101698562b2ffcacc304c8d", + "sha256:9565c3ab1c93310569ec0d86b017f128f027cab0b622b7af288696d7ed43a16d", + "sha256:95c765060e65c692da2d2f51a9499c5e9f5cf5453aeaf1420e3fc847cc060582", + "sha256:9969ef1e69b8c8e1e70d591f91bbc37fc9a3621e447525d1602801a24ceda898", + "sha256:9ca8e220006966b4a7b68e8984a6aee645a0384b0769e829ba60281fe61ec4f7", + "sha256:a39d18b3f50cc121d0ce3838d32d58bd1d15dab89c910358ebefc3665712256c", + "sha256:a66e8f628b71f78c0e0342003d53b53101ba4e00ea8dabb799d9dba0abbbcebe", + "sha256:a8de12b4b87c20de895f10567639c0797b621b22897b0af3ce4b4e204a743626", + "sha256:af41da5dca398d3474129c58cb2b106a5d93bbb196be0d307ac82311ca234342", + "sha256:b30a25f814591a8c0c5372c11ac8967f669b97444c47fd794926e175c4047ece", + "sha256:ba383dc6afd5ec5b7a0d0c23d38895db0e15bcba7fb0fa8901f245267ac30d86", + "sha256:bb4fbcab8764dc072cb651a4bcda4d11fb5658a1d8d68842a862a6610bd8cfa3", + "sha256:be9e3f68ca9edb897c2184ad0eee815c635565dbe7a0e7e814dc1f7cbab92c0a", + "sha256:bfa447506c1a52271f1b0de3f42ea0fa14676052549095e378d5bff1c505ff7b", + "sha256:cc94d7c5e8423920787c33d811c0be67b7be83c705f001f7180c7b186dcf10ca", + "sha256:cea0a27a89e6432705fffc178064503508e3c0184b4f061700e771a09de58187", + "sha256:cf95981b126f23db63e9dbe4cf65bd71f9a6305696fa5e2262693bc4e2183f5b", + "sha256:d4fe2348cc6ec372e25adec0219ee2334a68d2f5222e0cba9c0d613394e12d86", + "sha256:db0f04118d1db74db6c9e1cb1898532c7dcc220f1d2718f058601f7c3f499514", + "sha256:dd24bd8d77c98557880def750782df77ab2b6885a18483dc8588792247174b32", + "sha256:e1b5191d1648acc439b24721caab2fd0c86679d8549ed2c84d5a7ec1bedcc244", + "sha256:e5532482344186c543c37bfad0ee6069e8ae4fc38d073b8bc836fc8f03c9e250", + "sha256:e980b53a959fa53b6f05343afbd1e6f44a23ed6c23c4b4c56c6662bbb40c82ce", + "sha256:ef64c27bc40189f36fcc50c3fb8f16ccda73b6a0b80d9bd6e6ce4cffcd810bbd", + "sha256:f05031cf21699785cd47cb7485f67df619e7bcdae38e0fde40d23d3d0210d3c3" ], "markers": "python_version >= '3.9'", - "version": "==7.8.2" + "version": "==7.9.1" }, "distlib": { "hashes": [ @@ -1118,42 +1104,42 @@ }, "mypy": { "hashes": [ - "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", - "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", - "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", - "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", - "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", - "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", - "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", - "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", - "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", - "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", - "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", - "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", - "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", - "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", - "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", - "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", - "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", - "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", - "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", - "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", - "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", - "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", - "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", - "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", - "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", - "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", - "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", - "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", - "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", - "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", - "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", - "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5" + "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", + "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", + "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", + "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", + "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", + "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", + "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", + "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", + "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", + "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", + "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", + "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", + "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", + "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", + "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", + "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", + "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", + "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", + "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", + "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", + "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", + "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", + "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", + "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", + "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", + "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", + "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", + "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", + "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", + "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", + "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", + "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==1.15.0" + "version": "==1.16.1" }, "mypy-extensions": { "hashes": [ @@ -1224,12 +1210,20 @@ }, "pandas-stubs": { "hashes": [ - "sha256:3a6e9daf161f00b85c83772ed3d5cff9522028f07a94817472c07b91f46710fd", - "sha256:a377edff3b61f8b268c82499fdbe7c00fdeed13235b8b71d6a1dc347aeddc74d" + "sha256:cd0a49a95b8c5f944e605be711042a4dd8550e2c559b43d70ba2c4b524b66163", + "sha256:e2d694c4e72106055295ad143664e5c99e5815b07190d1ff85b73b13ff019e63" ], "index": "pypi", "markers": "python_version >= '3.10'", - "version": "==2.2.3.250308" + "version": "==2.2.3.250527" + }, + "pathspec": { + "hashes": [ + "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", + "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.1" }, "platformdirs": { "hashes": [ @@ -1256,23 +1250,31 @@ "markers": "python_version >= '3.9'", "version": "==4.2.0" }, + "pygments": { + "hashes": [ + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" + ], + "markers": "python_version >= '3.8'", + "version": "==2.19.2" + }, "pyright": { "hashes": [ - "sha256:6fde30492ba5b0d7667c16ecaf6c699fab8d7a1263f6a18549e0b00bf7724c06", - "sha256:788a82b6611fa5e34a326a921d86d898768cddf59edde8e93e56087d277cc6f1" + "sha256:2c721f11869baac1884e846232800fe021c33f1b4acb3929cff321f7ea4e2982", + "sha256:85a33c2d40cd4439c66aa946fd4ce71ab2f3f5b8c22ce36a623f59ac22937683" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==1.1.401" + "version": "==1.1.402" }, "pytest": { "hashes": [ - "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", - "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" + "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", + "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==8.3.5" + "markers": "python_version >= '3.9'", + "version": "==8.4.1" }, "pytest-cov": { "hashes": [ @@ -1344,28 +1346,28 @@ }, "ruff": { "hashes": [ - "sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112", - "sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4", - "sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b", - "sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345", - "sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b", - "sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f", - "sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d", - "sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6", - "sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875", - "sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639", - "sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092", - "sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81", - "sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709", - "sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4", - "sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd", - "sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8", - "sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1", - "sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac" + "sha256:069052605fe74c765a5b4272eb89880e0ff7a31e6c0dbf8767203c1fbd31c7ff", + "sha256:2be9d32a147f98a1972c1e4df9a6956d612ca5f5578536814372113d09a27a6c", + "sha256:49b7ce354eed2a322fbaea80168c902de9504e6e174fd501e9447cad0232f9e6", + "sha256:6013a46d865111e2edb71ad692fbb8262e6c172587a57c0669332a449384a36b", + "sha256:6cc32e863adcf9e71690248607ccdf25252eeeab5193768e6873b901fd441fed", + "sha256:70d52a058c0e7b88b602f575d23596e89bd7d8196437a4148381a3f73fcd5010", + "sha256:78ad09a022c64c13cc6077707f036bab0fac8cd7088772dcd1e5be21c5002efc", + "sha256:7fd49a4619f90d5afc65cf42e07b6ae98bb454fd5029d03b306bd9e2273d44cc", + "sha256:801d626de15e6bf988fbe7ce59b303a914ff9c616d5866f8c79eb5012720ae13", + "sha256:806bbc17f1104fd57451a98a58df35388ee3ab422e029e8f5cf30aa4af2c138c", + "sha256:84d0a69d1e8d716dfeab22d8d5e7c786b73f2106429a933cee51d7b09f861d4e", + "sha256:9a256522893cb7e92bb1e1153283927f842dea2e48619c803243dccc8437b8be", + "sha256:9e1123b1c033f77bd2590e4c1fe7e8ea72ef990a85d2484351d408224d603013", + "sha256:a684f125a4fec2d5a6501a466be3841113ba6847827be4573fddf8308b83477d", + "sha256:b3f75a19e03a4b0757d1412edb7f27cffb0c700365e9d6b60bc1b68d35bc89e0", + "sha256:bdecdef753bf1e95797593007569d8e1697a54fca843d78f6862f7dc279e23bd", + "sha256:d973fa626d4c8267848755bd0414211a456e99e125dcab147f24daa9e991a245", + "sha256:ed5af6aaaea20710e77698e2055b9ff9b3494891e1b24d26c07055459bb717e9" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.11.11" + "version": "==0.12.1" }, "types-pytz": { "hashes": [ @@ -1377,12 +1379,12 @@ }, "types-requests": { "hashes": [ - "sha256:09c8b63c11318cb2460813871aaa48b671002e59fda67ca909e9883777787581", - "sha256:f8eba93b3a892beee32643ff836993f15a785816acca21ea0ffa006f05ef0fb2" + "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", + "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==2.32.0.20250515" + "version": "==2.32.4.20250611" }, "types-tqdm": { "hashes": [ @@ -1395,19 +1397,19 @@ }, "typing-extensions": { "hashes": [ - "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", - "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef" + "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", + "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af" ], - "markers": "python_version >= '3.8'", - "version": "==4.13.2" + "markers": "python_version >= '3.9'", + "version": "==4.14.0" }, "urllib3": { "hashes": [ - "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", - "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813" + "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", + "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" ], "markers": "python_version >= '3.9'", - "version": "==2.4.0" + "version": "==2.5.0" }, "virtualenv": { "hashes": [ diff --git a/mediabridge-frontend/src/api/movie.ts b/mediabridge-frontend/src/api/movie.ts index 2c1e18e..143a5ad 100644 --- a/mediabridge-frontend/src/api/movie.ts +++ b/mediabridge-frontend/src/api/movie.ts @@ -8,3 +8,10 @@ export const searchMovies = async (query: string) => { }); return response.data; }; + +export const getRecommendations = async (movies: string[]) => { + const response = await axios.post(`${API_ENDPOINT}/v1/movie/recommend`, { + movies, + }); + return response.data; +}; diff --git a/mediabridge-frontend/src/components/MovieSearch.tsx b/mediabridge-frontend/src/components/MovieSearch.tsx index 7477ec0..b725cd9 100644 --- a/mediabridge-frontend/src/components/MovieSearch.tsx +++ b/mediabridge-frontend/src/components/MovieSearch.tsx @@ -9,8 +9,8 @@ import { } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import SearchBar from "@/components/ui/searchbar"; -import { Movie } from "../types/Movie"; -import { searchMovies } from "@/api/movie"; +import { Movie } from "../types/Movie"; +import { searchMovies, getRecommendations } from "@/api/movie"; type Props = { @@ -26,37 +26,44 @@ const MovieSearch = ({ movies, addMovie }: Props) => { const [title, setTitle] = useState(""); const [warning, setWarning] = useState(""); const [suggestions, setSuggestions] = useState([]); + const [recommendations, setRecommendations] = useState([]); + const handleGetRecommendations = async () => { + const movieTitles = movies.map((movie: Movie) => movie.title); + const data = await getRecommendations(movieTitles); + console.log(data); + setRecommendations(data); + }; const handleAddMovie = async (selectedMovie?: Movie) => { const movieToAdd = selectedMovie ?? null; - + if (!title.trim() && !movieToAdd) return; - + try { const data = await searchMovies(title); - + const foundMovie = movieToAdd || data.find((movie: Movie) => movie.title === title); - + if (!foundMovie) { - setWarning(`‘${title}’ not found. Please check your spelling.`); + setWarning(`'${title}' not found. Please check your spelling.`); return; } - + if (isMoviePresent(movies, foundMovie.title)) { - setWarning(`‘${foundMovie.title}’ already added.`); + setWarning(`'${foundMovie.title}' already added.`); return; } - + addMovie({ id: foundMovie.id.toString(), title: foundMovie.title, year: foundMovie.year, image: `https://picsum.photos/seed/${foundMovie.id}/200/300`, }); - + setWarning(""); setTitle(""); } catch (error) { @@ -90,10 +97,10 @@ const MovieSearch = ({ movies, addMovie }: Props) => { - + ); }; -export default MovieSearch; \ No newline at end of file +export default MovieSearch; diff --git a/mediabridge/api/app.py b/mediabridge/api/app.py index 7ff7487..4fb29f8 100644 --- a/mediabridge/api/app.py +++ b/mediabridge/api/app.py @@ -51,22 +51,14 @@ def search_movies() -> tuple[Response, int]: movies_list = [row._asdict() for row in movies] return jsonify(movies_list), 200 - @app.route("/api/v1/movie/recommend") # type: ignore + @app.route("/api/v1/movie/recommend", methods=["POST"]) # type: ignore def recommend_movies() -> tuple[Response, int]: - query = request.args.get("q") - if not query: - return jsonify({"error": "Query parameter 'q' is required."}), 400 # type: ignore - - with db.engine.connect() as conn: - pattern = f"%{query}%" - movies = conn.execute( - text( - "SELECT * FROM movie_title WHERE LOWER(title) LIKE LOWER(:pattern) LIMIT 10" - ), - {"pattern": pattern}, - ).fetchall() - movies_list = [row._asdict() for row in movies] - return jsonify(movies_list), 200 + data = request.get_json() + if not data or "movies" not in data: + return jsonify({"error": "JSON body with 'movies' array is required."}), 400 + movies = data["movies"] + # Placeholder: echo back the received movies as recommendations + return jsonify({"recommendations": movies}), 200 return app diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..67896af --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "MediaBridge", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} From 41ab228c84aa594e84ed7cb73fc2485528c0e929 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 1 Jul 2025 14:04:26 -0700 Subject: [PATCH 03/11] Implement backend function --- mediabridge/api/app.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mediabridge/api/app.py b/mediabridge/api/app.py index 4fb29f8..94359cc 100644 --- a/mediabridge/api/app.py +++ b/mediabridge/api/app.py @@ -8,6 +8,7 @@ from mediabridge.config.backend import ENV_TO_CONFIG from mediabridge.db.tables import Base +from mediabridge.recommender.make_recommendation import get_title, recommend typer_app = typer.Typer() db = SQLAlchemy(model_class=Base) @@ -57,8 +58,16 @@ def recommend_movies() -> tuple[Response, int]: if not data or "movies" not in data: return jsonify({"error": "JSON body with 'movies' array is required."}), 400 movies = data["movies"] - # Placeholder: echo back the received movies as recommendations - return jsonify({"recommendations": movies}), 200 + if not isinstance(movies, list) or not all(isinstance(m, str) for m in movies): + return jsonify({"error": "'movies' must be a list of strings."}), 400 + + try: + rec_ids = recommend() + rec_titles = [get_title(int(mid)) for mid in rec_ids] + except Exception as e: + return jsonify({"error": f"Recommendation failed: {str(e)}"}), 500 + + return jsonify({"recommendations": rec_titles}), 200 return app From 59c31de18facffff4f35b6831e45781865785186 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 1 Jul 2025 14:20:06 -0700 Subject: [PATCH 04/11] Display recommendations onclick --- .../src/components/MovieSearch.tsx | 25 +++++++++++-------- .../src/pages/SelectMovies.tsx | 18 ++++++++++--- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/mediabridge-frontend/src/components/MovieSearch.tsx b/mediabridge-frontend/src/components/MovieSearch.tsx index b725cd9..47a6f64 100644 --- a/mediabridge-frontend/src/components/MovieSearch.tsx +++ b/mediabridge-frontend/src/components/MovieSearch.tsx @@ -10,30 +10,26 @@ import { import { Button } from "@/components/ui/button"; import SearchBar from "@/components/ui/searchbar"; import { Movie } from "../types/Movie"; -import { searchMovies, getRecommendations } from "@/api/movie"; +import { getRecommendations, searchMovies } from "@/api/movie"; type Props = { movies: Movie[]; addMovie: (movie: Movie) => void; + setRecommendations: (movies: string[]) => void; }; const isMoviePresent = (movies: Movie[], title: string) => { return movies.some((movie) => movie.title.toLowerCase() === title.toLowerCase()); }; -const MovieSearch = ({ movies, addMovie }: Props) => { + + + +const MovieSearch = ({ movies, addMovie, setRecommendations }: Props) => { const [title, setTitle] = useState(""); const [warning, setWarning] = useState(""); const [suggestions, setSuggestions] = useState([]); - const [recommendations, setRecommendations] = useState([]); - - const handleGetRecommendations = async () => { - const movieTitles = movies.map((movie: Movie) => movie.title); - const data = await getRecommendations(movieTitles); - console.log(data); - setRecommendations(data); - }; const handleAddMovie = async (selectedMovie?: Movie) => { const movieToAdd = selectedMovie ?? null; @@ -71,6 +67,13 @@ const MovieSearch = ({ movies, addMovie }: Props) => { console.error("Error searching for movie:", error); } }; + + const handleRecommendations = async () => { + const movieTitles = movies.map((movie: Movie) => movie.title); + const data = await getRecommendations(movieTitles); + setRecommendations(data.recommendations); + }; + return ( @@ -97,7 +100,7 @@ const MovieSearch = ({ movies, addMovie }: Props) => { - + ); diff --git a/mediabridge-frontend/src/pages/SelectMovies.tsx b/mediabridge-frontend/src/pages/SelectMovies.tsx index b12ea63..f6b8e52 100644 --- a/mediabridge-frontend/src/pages/SelectMovies.tsx +++ b/mediabridge-frontend/src/pages/SelectMovies.tsx @@ -1,6 +1,7 @@ import MovieList from "../components/MovieList"; import MovieSearch from "../components/MovieSearch"; import { Movie } from "../types/Movie.ts"; +import { useState } from "react"; const SelectMovies = ({ movies, @@ -11,21 +12,32 @@ const SelectMovies = ({ addMovie: (movie: Movie) => void; removeMovie: (id: string) => void; }) => { + const [recommendations, setRecommendations] = useState([]); + console.log(recommendations); + return (
{/* Top full-width section */}
- +
{/* Content section below */} -
+ { + recommendations.length > 0 ? +
+ {recommendations.map(recommendation => (
{recommendation}
))} +
+ : +
+ } +
); }; -export default SelectMovies; \ No newline at end of file +export default SelectMovies; From d48b32f5cbc8ccfd4fbda3c6a3f1ac0a49f40729 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 1 Jul 2025 14:25:34 -0700 Subject: [PATCH 05/11] Remove console log --- mediabridge-frontend/src/pages/SelectMovies.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mediabridge-frontend/src/pages/SelectMovies.tsx b/mediabridge-frontend/src/pages/SelectMovies.tsx index f6b8e52..fdd90c3 100644 --- a/mediabridge-frontend/src/pages/SelectMovies.tsx +++ b/mediabridge-frontend/src/pages/SelectMovies.tsx @@ -13,7 +13,6 @@ const SelectMovies = ({ removeMovie: (id: string) => void; }) => { const [recommendations, setRecommendations] = useState([]); - console.log(recommendations); return (
@@ -27,7 +26,7 @@ const SelectMovies = ({ {/* Content section below */} { recommendations.length > 0 ? -
+
{recommendations.map(recommendation => (
{recommendation}
))}
: From 9620f560f50f348282cfec5e64a23cb9ff938d1e Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 8 Jul 2025 14:05:57 -0700 Subject: [PATCH 06/11] Address PR comments --- mediabridge/api/app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mediabridge/api/app.py b/mediabridge/api/app.py index 94359cc..7fae833 100644 --- a/mediabridge/api/app.py +++ b/mediabridge/api/app.py @@ -52,14 +52,14 @@ def search_movies() -> tuple[Response, int]: movies_list = [row._asdict() for row in movies] return jsonify(movies_list), 200 - @app.route("/api/v1/movie/recommend", methods=["POST"]) # type: ignore + @app.route("/api/v1/movie/recommend", methods=["GET"]) # type: ignore def recommend_movies() -> tuple[Response, int]: data = request.get_json() if not data or "movies" not in data: return jsonify({"error": "JSON body with 'movies' array is required."}), 400 movies = data["movies"] - if not isinstance(movies, list) or not all(isinstance(m, str) for m in movies): - return jsonify({"error": "'movies' must be a list of strings."}), 400 + if not isinstance(movies, list) or not all(isinstance(m, int) for m in movies): + return jsonify({"error": "'movies' must be a list of integers."}), 400 try: rec_ids = recommend() From f0302d1e617bebfac7a956fd79782c9640d377d4 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 8 Jul 2025 14:35:57 -0700 Subject: [PATCH 07/11] Typo? --- .vscode/settings.json | 8 ++++++ mediabridge-frontend/src/api/movie.ts | 9 +++++-- .../src/components/MovieSearch.tsx | 21 ++++++++------- .../src/pages/SelectMovies.tsx | 7 ++--- mediabridge/api/app.py | 27 ++++++++++++++----- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2862ed2..54fb2e7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,13 @@ "source.organizeImports": "explicit" } }, + "[javascript]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "[typescript]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, "editor.indentSize": "tabSize" } diff --git a/mediabridge-frontend/src/api/movie.ts b/mediabridge-frontend/src/api/movie.ts index 143a5ad..09b8f7f 100644 --- a/mediabridge-frontend/src/api/movie.ts +++ b/mediabridge-frontend/src/api/movie.ts @@ -10,8 +10,13 @@ export const searchMovies = async (query: string) => { }; export const getRecommendations = async (movies: string[]) => { - const response = await axios.post(`${API_ENDPOINT}/v1/movie/recommend`, { - movies, + const response = await axios.get(`${API_ENDPOINT}/v1/movie/recommend`, { + params: { movies }, }); return response.data; }; + +export const getMovieById = async (id: string) => { + const response = await axios.get(`${API_ENDPOINT}/v1/movie/${id}`); + return response.data; +}; diff --git a/mediabridge-frontend/src/components/MovieSearch.tsx b/mediabridge-frontend/src/components/MovieSearch.tsx index 47a6f64..709a87c 100644 --- a/mediabridge-frontend/src/components/MovieSearch.tsx +++ b/mediabridge-frontend/src/components/MovieSearch.tsx @@ -10,22 +10,18 @@ import { import { Button } from "@/components/ui/button"; import SearchBar from "@/components/ui/searchbar"; import { Movie } from "../types/Movie"; -import { getRecommendations, searchMovies } from "@/api/movie"; - +import { getRecommendations, searchMovies, getMovieById } from "@/api/movie"; type Props = { movies: Movie[]; addMovie: (movie: Movie) => void; - setRecommendations: (movies: string[]) => void; + setRecommendations: (movies: Movie[]) => void; }; const isMoviePresent = (movies: Movie[], title: string) => { return movies.some((movie) => movie.title.toLowerCase() === title.toLowerCase()); }; - - - const MovieSearch = ({ movies, addMovie, setRecommendations }: Props) => { const [title, setTitle] = useState(""); const [warning, setWarning] = useState(""); @@ -69,9 +65,16 @@ const MovieSearch = ({ movies, addMovie, setRecommendations }: Props) => { }; const handleRecommendations = async () => { - const movieTitles = movies.map((movie: Movie) => movie.title); - const data = await getRecommendations(movieTitles); - setRecommendations(data.recommendations); + const movieIds = movies.map((movie: Movie) => movie.id); + const data = await getRecommendations(movieIds); + const recommendedMovies = ( + await Promise.all( + data.recommendations.map(async (id: string) => { + return await getMovieById(id); + }) + ) + ).filter(Boolean); + setRecommendations(recommendedMovies); }; return ( diff --git a/mediabridge-frontend/src/pages/SelectMovies.tsx b/mediabridge-frontend/src/pages/SelectMovies.tsx index fdd90c3..7f66c56 100644 --- a/mediabridge-frontend/src/pages/SelectMovies.tsx +++ b/mediabridge-frontend/src/pages/SelectMovies.tsx @@ -12,7 +12,7 @@ const SelectMovies = ({ addMovie: (movie: Movie) => void; removeMovie: (id: string) => void; }) => { - const [recommendations, setRecommendations] = useState([]); + const [recommendations, setRecommendations] = useState([]); return (
@@ -27,8 +27,9 @@ const SelectMovies = ({ { recommendations.length > 0 ?
- {recommendations.map(recommendation => (
{recommendation}
))} -
+

Recommendations:

+ {}} /> +
:
diff --git a/mediabridge/api/app.py b/mediabridge/api/app.py index 7fae833..8e52306 100644 --- a/mediabridge/api/app.py +++ b/mediabridge/api/app.py @@ -52,22 +52,35 @@ def search_movies() -> tuple[Response, int]: movies_list = [row._asdict() for row in movies] return jsonify(movies_list), 200 + @app.route("/api/v1/movie/") + def get_movie_by_id(movie_id): + with db.engine.connect() as conn: + movie = conn.execute( + text("SELECT * FROM movie_title WHERE id = :id"), + {"id": movie_id}, + ).fetchone() + if not movie: + return jsonify({"error": "Movie not found"}), 404 + return jsonify(dict(movie._mapping)), 200 + @app.route("/api/v1/movie/recommend", methods=["GET"]) # type: ignore def recommend_movies() -> tuple[Response, int]: - data = request.get_json() - if not data or "movies" not in data: - return jsonify({"error": "JSON body with 'movies' array is required."}), 400 - movies = data["movies"] - if not isinstance(movies, list) or not all(isinstance(m, int) for m in movies): + movies = request.args.getlist("movies[]", type=int) + if not movies: + return jsonify( + { + "error": "Query parameter 'movies[]' is required and must be a list of integers." + } + ), 400 + if not all(isinstance(m, int) for m in movies): return jsonify({"error": "'movies' must be a list of integers."}), 400 try: rec_ids = recommend() - rec_titles = [get_title(int(mid)) for mid in rec_ids] except Exception as e: return jsonify({"error": f"Recommendation failed: {str(e)}"}), 500 - return jsonify({"recommendations": rec_titles}), 200 + return jsonify({"recommendations": list(rec_ids)}), 200 return app From f464cf134619f4dbcaa2ba9d754b392ba05e1444 Mon Sep 17 00:00:00 2001 From: Corrie Date: Tue, 8 Jul 2025 14:43:05 -0700 Subject: [PATCH 08/11] Update settings.json --- .vscode/settings.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 54fb2e7..2862ed2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,13 +6,5 @@ "source.organizeImports": "explicit" } }, - "[javascript]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "dbaeumer.vscode-eslint" - }, - "[typescript]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "dbaeumer.vscode-eslint" - }, "editor.indentSize": "tabSize" } From f35b8b068bdaef9a27c3f92454ba84d6359ebd99 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 8 Jul 2025 14:45:10 -0700 Subject: [PATCH 09/11] Changes --- .../src/components/MovieItem.tsx | 31 ++++++++++--------- .../src/components/MovieList.tsx | 17 +++++----- .../src/components/MovieSearch.tsx | 3 +- .../src/pages/SelectMovies.tsx | 2 +- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/mediabridge-frontend/src/components/MovieItem.tsx b/mediabridge-frontend/src/components/MovieItem.tsx index 45204d7..cd2d24c 100644 --- a/mediabridge-frontend/src/components/MovieItem.tsx +++ b/mediabridge-frontend/src/components/MovieItem.tsx @@ -7,13 +7,12 @@ import { } from "@/components/ui/card"; import { Movie } from "@/types/Movie"; -const MovieItem = ({ - movie, - onRemove, -}: { +type Props = { movie: Movie; - onRemove: () => void; -}) => { + onRemove?: () => void; +}; + +const MovieItem = ({ movie, onRemove }: Props) => { return (
{movie.title} - + {onRemove && ( + + )}
@@ -44,4 +45,4 @@ const MovieItem = ({ ); }; -export default MovieItem; \ No newline at end of file +export default MovieItem; diff --git a/mediabridge-frontend/src/components/MovieList.tsx b/mediabridge-frontend/src/components/MovieList.tsx index 4a3de84..aeb32d9 100644 --- a/mediabridge-frontend/src/components/MovieList.tsx +++ b/mediabridge-frontend/src/components/MovieList.tsx @@ -1,17 +1,20 @@ import { Movie } from "../types/Movie"; import MovieItem from "./MovieItem"; -const MovieList = ({ - movies, - removeMovie, -}: { +type Props = { movies: Movie[]; - removeMovie: (id: string) => void; -}) => { + removeMovie?: (id: string) => void; +}; + +const MovieList = ({ movies, removeMovie }: Props) => { return (
{movies.map((movie) => ( - removeMovie(movie.id)} /> + removeMovie(movie.id) } : {})} + /> ))}
); diff --git a/mediabridge-frontend/src/components/MovieSearch.tsx b/mediabridge-frontend/src/components/MovieSearch.tsx index 709a87c..b9a61c0 100644 --- a/mediabridge-frontend/src/components/MovieSearch.tsx +++ b/mediabridge-frontend/src/components/MovieSearch.tsx @@ -73,7 +73,8 @@ const MovieSearch = ({ movies, addMovie, setRecommendations }: Props) => { return await getMovieById(id); }) ) - ).filter(Boolean); + ); + recommendedMovies.map(movie => movie.image = `https://picsum.photos/seed/${movie.id}/200/300`) setRecommendations(recommendedMovies); }; diff --git a/mediabridge-frontend/src/pages/SelectMovies.tsx b/mediabridge-frontend/src/pages/SelectMovies.tsx index 7f66c56..1c7788c 100644 --- a/mediabridge-frontend/src/pages/SelectMovies.tsx +++ b/mediabridge-frontend/src/pages/SelectMovies.tsx @@ -28,7 +28,7 @@ const SelectMovies = ({ recommendations.length > 0 ?

Recommendations:

- {}} /> +
:
From 728303b409e9c99e465fafeff84725b1c97bdb56 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 8 Jul 2025 14:46:22 -0700 Subject: [PATCH 10/11] Remove unused import --- mediabridge/api/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediabridge/api/app.py b/mediabridge/api/app.py index 8e52306..a327e93 100644 --- a/mediabridge/api/app.py +++ b/mediabridge/api/app.py @@ -8,7 +8,7 @@ from mediabridge.config.backend import ENV_TO_CONFIG from mediabridge.db.tables import Base -from mediabridge.recommender.make_recommendation import get_title, recommend +from mediabridge.recommender.make_recommendation import recommend typer_app = typer.Typer() db = SQLAlchemy(model_class=Base) From a7bf10200d3f818dc2267c3f1ec3cb8001fdc6e4 Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 8 Jul 2025 14:48:16 -0700 Subject: [PATCH 11/11] Fix linting error --- mediabridge/engine/recommendation_engine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediabridge/engine/recommendation_engine.py b/mediabridge/engine/recommendation_engine.py index 1489696..f09fb25 100644 --- a/mediabridge/engine/recommendation_engine.py +++ b/mediabridge/engine/recommendation_engine.py @@ -23,7 +23,7 @@ def get_movie_id(self, title: str) -> str: movies = self.db["movies"] movie = movies.find_one({"title": title}) assert movie, title - return f"{movie.get("netflix_id")}" + return f"{movie.get('netflix_id')}" def get_movie_title(self, netflix_id: str) -> str: movies = self.db["movies"]