From 7ca9c5580f7dcbc1e7799fa08ea733416aca1130 Mon Sep 17 00:00:00 2001 From: nohkwanok Date: Thu, 14 Mar 2024 15:36:56 +0900 Subject: [PATCH 1/4] wip --- web/league_entry.py | 81 +++ web/poetry.lock | 474 +++++++++++++++++- web/project/app/migrations/0002_champion.py | 32 ++ web/project/app/migrations/0003_summoner.py | 25 + .../app/migrations/0004_leagueentry.py | 47 ++ web/project/app/models.py | 44 ++ web/project/app/riot_assets.py | 53 ++ web/project/app/riot_client.py | 38 ++ web/project/app/urls.py | 9 +- web/project/app/views.py | 18 +- web/project/templates/recommend/ai.html | 23 +- web/project/templates/recommend/result.html | 30 ++ web/pyproject.toml | 2 + 13 files changed, 868 insertions(+), 8 deletions(-) create mode 100644 web/league_entry.py create mode 100644 web/project/app/migrations/0002_champion.py create mode 100644 web/project/app/migrations/0003_summoner.py create mode 100644 web/project/app/migrations/0004_leagueentry.py create mode 100644 web/project/app/riot_assets.py create mode 100644 web/project/app/riot_client.py create mode 100644 web/project/templates/recommend/result.html diff --git a/web/league_entry.py b/web/league_entry.py new file mode 100644 index 0000000..6ba3853 --- /dev/null +++ b/web/league_entry.py @@ -0,0 +1,81 @@ +import asyncio +import os +import asyncpg +import aiohttp + + +class LeagueEntryCrawler: + def __init__(self): + self.session = aiohttp.ClientSession() + + self.base_url = ( + "https://kr.api.riotgames.com/lol/league/v4/entries/RANKED_SOLO_5x5" + ) + self.api_key = os.environ.get("RIOT_API_KEY") + self.tiers = ["IRON", "BRONZE", "SILVER", "GOLD", "PLATINUM", "DIAMOND"] + self.divisions = ["I", "II", "III", "IV"] + + async def run(self): + # for tier in self.tiers: + # for division in self.divisions: + # await self.get_league_entries(tier, division) + + await self.get_league_entries(self.tiers[0], self.divisions[0]) + + await self.session.close() + + async def get_league_entries(self, tier: str, division: str): + url = f"{self.base_url}/{tier}/{division}?api_key={self.api_key}" + page = 1 + + league_entries = await self._fetch(url + f"&page={page}") + + summoners = [] + + while league_entries: + summoners.extend(league_entries) + print(f"Fetching page {page}") + + page += 1 + league_entries = await self._fetch(url + f"&page={page}") + + print(summoners) + + async def _fetch(self, url: str) -> list: + async with self.session.get(url) as response: + response = await self.session.get(url) + + while response.status == 429: + retry_after = response.headers.get("Retry-After") + print(f"Retrying after {retry_after} seconds") + + await asyncio.sleep(int(retry_after)) + response = await self.session.get(url) + + return await response.json() + + +async def main(): + # crawler = LeagueEntryCrawler() + # await crawler.run() + + db_user = os.environ.get("POSTGRES_USER") + db_password = os.environ.get("POSTGRES_PASSWORD") + db_host = "localhost" + db_port = os.environ.get("POSTGRES_PORT") + db_name = os.environ.get("POSTGRES_WEB_DB") + + db_url = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}" + + print(f"Connecting to database: {db_url}") + + pool = await asyncpg.create_pool(db_url) + + print("Connected to database") + + await pool.close() + + +loop = asyncio.get_event_loop() +loop.run_until_complete(main()) +loop.close() diff --git a/web/poetry.lock b/web/poetry.lock index 8ca8d7c..e95e7ef 100644 --- a/web/poetry.lock +++ b/web/poetry.lock @@ -1,4 +1,113 @@ -# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "aiohttp" +version = "3.9.3" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, + {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, + {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, + {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, + {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, + {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, + {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, + {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, + {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, + {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, + {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, + {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" [[package]] name = "asgiref" @@ -14,6 +123,79 @@ files = [ [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] +[[package]] +name = "asyncpg" +version = "0.29.0" +description = "An asyncio PostgreSQL driver" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "asyncpg-0.29.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72fd0ef9f00aeed37179c62282a3d14262dbbafb74ec0ba16e1b1864d8a12169"}, + {file = "asyncpg-0.29.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52e8f8f9ff6e21f9b39ca9f8e3e33a5fcdceaf5667a8c5c32bee158e313be385"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e6823a7012be8b68301342ba33b4740e5a166f6bbda0aee32bc01638491a22"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:746e80d83ad5d5464cfbf94315eb6744222ab00aa4e522b704322fb182b83610"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ff8e8109cd6a46ff852a5e6bab8b0a047d7ea42fcb7ca5ae6eaae97d8eacf397"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97eb024685b1d7e72b1972863de527c11ff87960837919dac6e34754768098eb"}, + {file = "asyncpg-0.29.0-cp310-cp310-win32.whl", hash = "sha256:5bbb7f2cafd8d1fa3e65431833de2642f4b2124be61a449fa064e1a08d27e449"}, + {file = "asyncpg-0.29.0-cp310-cp310-win_amd64.whl", hash = "sha256:76c3ac6530904838a4b650b2880f8e7af938ee049e769ec2fba7cd66469d7772"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4900ee08e85af01adb207519bb4e14b1cae8fd21e0ccf80fac6aa60b6da37b4"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a65c1dcd820d5aea7c7d82a3fdcb70e096f8f70d1a8bf93eb458e49bfad036ac"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b52e46f165585fd6af4863f268566668407c76b2c72d366bb8b522fa66f1870"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc600ee8ef3dd38b8d67421359779f8ccec30b463e7aec7ed481c8346decf99f"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:039a261af4f38f949095e1e780bae84a25ffe3e370175193174eb08d3cecab23"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6feaf2d8f9138d190e5ec4390c1715c3e87b37715cd69b2c3dfca616134efd2b"}, + {file = "asyncpg-0.29.0-cp311-cp311-win32.whl", hash = "sha256:1e186427c88225ef730555f5fdda6c1812daa884064bfe6bc462fd3a71c4b675"}, + {file = "asyncpg-0.29.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfe73ffae35f518cfd6e4e5f5abb2618ceb5ef02a2365ce64f132601000587d3"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6011b0dc29886ab424dc042bf9eeb507670a3b40aece3439944006aafe023178"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b544ffc66b039d5ec5a7454667f855f7fec08e0dfaf5a5490dfafbb7abbd2cfb"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d84156d5fb530b06c493f9e7635aa18f518fa1d1395ef240d211cb563c4e2364"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54858bc25b49d1114178d65a88e48ad50cb2b6f3e475caa0f0c092d5f527c106"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bde17a1861cf10d5afce80a36fca736a86769ab3579532c03e45f83ba8a09c59"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a2ec1b9ff88d8773d3eb6d3784dc7e3fee7756a5317b67f923172a4748a175"}, + {file = "asyncpg-0.29.0-cp312-cp312-win32.whl", hash = "sha256:bb1292d9fad43112a85e98ecdc2e051602bce97c199920586be83254d9dafc02"}, + {file = "asyncpg-0.29.0-cp312-cp312-win_amd64.whl", hash = "sha256:2245be8ec5047a605e0b454c894e54bf2ec787ac04b1cb7e0d3c67aa1e32f0fe"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0009a300cae37b8c525e5b449233d59cd9868fd35431abc470a3e364d2b85cb9"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cad1324dbb33f3ca0cd2074d5114354ed3be2b94d48ddfd88af75ebda7c43cc"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:012d01df61e009015944ac7543d6ee30c2dc1eb2f6b10b62a3f598beb6531548"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000c996c53c04770798053e1730d34e30cb645ad95a63265aec82da9093d88e7"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e0bfe9c4d3429706cf70d3249089de14d6a01192d617e9093a8e941fea8ee775"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:642a36eb41b6313ffa328e8a5c5c2b5bea6ee138546c9c3cf1bffaad8ee36dd9"}, + {file = "asyncpg-0.29.0-cp38-cp38-win32.whl", hash = "sha256:a921372bbd0aa3a5822dd0409da61b4cd50df89ae85150149f8c119f23e8c408"}, + {file = "asyncpg-0.29.0-cp38-cp38-win_amd64.whl", hash = "sha256:103aad2b92d1506700cbf51cd8bb5441e7e72e87a7b3a2ca4e32c840f051a6a3"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5340dd515d7e52f4c11ada32171d87c05570479dc01dc66d03ee3e150fb695da"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e17b52c6cf83e170d3d865571ba574577ab8e533e7361a2b8ce6157d02c665d3"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f100d23f273555f4b19b74a96840aa27b85e99ba4b1f18d4ebff0734e78dc090"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48e7c58b516057126b363cec8ca02b804644fd012ef8e6c7e23386b7d5e6ce83"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9ea3f24eb4c49a615573724d88a48bd1b7821c890c2effe04f05382ed9e8810"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8d36c7f14a22ec9e928f15f92a48207546ffe68bc412f3be718eedccdf10dc5c"}, + {file = "asyncpg-0.29.0-cp39-cp39-win32.whl", hash = "sha256:797ab8123ebaed304a1fad4d7576d5376c3a006a4100380fb9d517f0b59c1ab2"}, + {file = "asyncpg-0.29.0-cp39-cp39-win_amd64.whl", hash = "sha256:cce08a178858b426ae1aa8409b5cc171def45d4293626e7aa6510696d46decd8"}, + {file = "asyncpg-0.29.0.tar.gz", hash = "sha256:d1c49e1f44fffafd9a55e1a9b101590859d881d639ea2922516f5d9c512d354e"}, +] + +[package.extras] +docs = ["Sphinx (>=5.3.0,<5.4.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["flake8 (>=6.1,<7.0)", "uvloop (>=0.15.3)"] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + [[package]] name = "black" version = "24.2.0" @@ -229,6 +411,92 @@ develop = ["coverage[toml] (>=5.0a4)", "furo (>=2021.8.17b43,<2021.9.dev0)", "py docs = ["furo (>=2021.8.17b43,<2021.9.dev0)", "sphinx (>=3.5.0)", "sphinx-notfound-page"] testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"] +[[package]] +name = "frozenlist" +version = "1.4.1" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + [[package]] name = "gunicorn" version = "21.2.0" @@ -346,6 +614,105 @@ files = [ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -519,7 +886,110 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "2037ccbc8be9a47d386e625857af07bd9238250004833ff143a712e2197e4181" +content-hash = "67ecdd445fcde0fc782806a9812f1569cba8d2c002a991588cb97ec984a0dbd6" diff --git a/web/project/app/migrations/0002_champion.py b/web/project/app/migrations/0002_champion.py new file mode 100644 index 0000000..1371f53 --- /dev/null +++ b/web/project/app/migrations/0002_champion.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.2 on 2024-03-14 04:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="Champion", + fields=[ + ("version", models.CharField(max_length=255)), + ( + "id", + models.CharField(max_length=255, primary_key=True, serialize=False), + ), + ("key", models.CharField(max_length=255)), + ("name", models.CharField(max_length=255)), + ("title", models.CharField(max_length=255)), + ("blurb", models.TextField()), + ("info", models.JSONField()), + ("image", models.JSONField()), + ("tags", models.JSONField()), + ("partype", models.CharField(max_length=255)), + ("stats", models.JSONField()), + ], + ), + ] diff --git a/web/project/app/migrations/0003_summoner.py b/web/project/app/migrations/0003_summoner.py new file mode 100644 index 0000000..324d98c --- /dev/null +++ b/web/project/app/migrations/0003_summoner.py @@ -0,0 +1,25 @@ +# Generated by Django 5.0.2 on 2024-03-14 05:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0002_champion"), + ] + + operations = [ + migrations.CreateModel( + name="Summoner", + fields=[ + ( + "id", + models.CharField(max_length=100, primary_key=True, serialize=False), + ), + ("name", models.CharField(max_length=100)), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ], + ), + ] diff --git a/web/project/app/migrations/0004_leagueentry.py b/web/project/app/migrations/0004_leagueentry.py new file mode 100644 index 0000000..54d4cc1 --- /dev/null +++ b/web/project/app/migrations/0004_leagueentry.py @@ -0,0 +1,47 @@ +# Generated by Django 5.0.2 on 2024-03-14 05:49 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0003_summoner"), + ] + + operations = [ + migrations.CreateModel( + name="LeagueEntry", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("tier", models.CharField(max_length=255)), + ("rank", models.CharField(max_length=255)), + ("league_points", models.IntegerField()), + ("wins", models.IntegerField()), + ("losses", models.IntegerField()), + ("veteran", models.BooleanField()), + ("inactive", models.BooleanField()), + ("fresh_blood", models.BooleanField()), + ("hot_streak", models.BooleanField()), + ("queue_type", models.CharField(max_length=255)), + ("league_id", models.CharField(max_length=255)), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ( + "summoner", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="app.summoner" + ), + ), + ], + ), + ] diff --git a/web/project/app/models.py b/web/project/app/models.py index c292b55..e049ab4 100644 --- a/web/project/app/models.py +++ b/web/project/app/models.py @@ -11,3 +11,47 @@ class UserActivity(models.Model): def __str__(self): return f"{self.user.username} - {self.path}" + + +class Champion(models.Model): + version = models.CharField(max_length=255) + id = models.CharField(max_length=255, primary_key=True) + key = models.CharField(max_length=255) + name = models.CharField(max_length=255) + title = models.CharField(max_length=255) + blurb = models.TextField() + info = models.JSONField() + image = models.JSONField() + tags = models.JSONField() + partype = models.CharField(max_length=255) + stats = models.JSONField() + + +class Summoner(models.Model): + id = models.CharField(max_length=100, blank=False, null=False, primary_key=True) + name = models.CharField(max_length=100, blank=False, null=False) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name + + +class LeagueEntry(models.Model): + summoner = models.ForeignKey(Summoner, on_delete=models.CASCADE) + tier = models.CharField(max_length=255) + rank = models.CharField(max_length=255) + league_points = models.IntegerField() + wins = models.IntegerField() + losses = models.IntegerField() + veteran = models.BooleanField() + inactive = models.BooleanField() + fresh_blood = models.BooleanField() + hot_streak = models.BooleanField() + queue_type = models.CharField(max_length=255) + league_id = models.CharField(max_length=255) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"{self.summoner.name} - {self.tier} {self.rank}" diff --git a/web/project/app/riot_assets.py b/web/project/app/riot_assets.py new file mode 100644 index 0000000..cf3081a --- /dev/null +++ b/web/project/app/riot_assets.py @@ -0,0 +1,53 @@ +import requests +from app.models import Champion + + +class RiotAssets: + def __init__(self): + pass + + def get_champion(self, champion_id: str) -> dict: + try: + champion = Champion.objects.get(key=champion_id) + except Champion.DoesNotExist: + champion = None + + if champion is None: + self._upsert_champions() + champion = Champion.objects.get(key=champion_id) + + return champion + + def _fetch_all_champions(self) -> list: + champions = requests.get( + "https://ddragon.leagueoflegends.com/cdn/10.6.1/data/ko_KR/champion.json" + ).json()["data"] + return champions + + def _upsert_champions(self) -> None: + champions = self._fetch_all_champions() + + for champion in champions: + data = champions[champion] + Champion.objects.update_or_create( + version=data["version"], + id=data["id"], + key=data["key"], + name=data["name"], + title=data["title"], + blurb=data["blurb"], + info=data["info"], + image=data["image"], + tags=data["tags"], + partype=data["partype"], + stats=data["stats"], + ) + + return None + + +riot_assets = RiotAssets() + + +def get_riot_assets(): + return riot_assets diff --git a/web/project/app/riot_client.py b/web/project/app/riot_client.py new file mode 100644 index 0000000..9b63e0a --- /dev/null +++ b/web/project/app/riot_client.py @@ -0,0 +1,38 @@ +import os +import requests + + +KR_API_HOST = "https://kr.api.riotgames.com" +ASIA_API_HOST = "https://asia.api.riotgames.com" + + +class RiotClient: + def __init__(self): + self.api_key = os.environ.get("RIOT_API_KEY") + + def get_account_by_summoner_name(self, summoner_name) -> requests.Response: + url = f"{KR_API_HOST}/lol/summoner/v4/summoners/by-name/{summoner_name}" + response = requests.get(url, headers={"X-Riot-Token": self.api_key}) + return response + + def get_match_list(self, puuid: str) -> requests.Response: + url = f"{ASIA_API_HOST}/lol/match/v5/matches/by-puuid/{puuid}/ids" + response = requests.get(url, headers={"X-Riot-Token": self.api_key}) + return response + + def get_match(self, match_id: str) -> requests.Response: + url = f"{ASIA_API_HOST}/lol/match/v5/matches/{match_id}" + response = requests.get(url, headers={"X-Riot-Token": self.api_key}) + return response + + def get_champion_masteries_by_puuid_top(self, puuid: str) -> requests.Response: + url = f"{KR_API_HOST}/lol/champion-mastery/v4/champion-masteries/by-puuid/{puuid}/top" + response = requests.get(url, headers={"X-Riot-Token": self.api_key}) + return response + + +client = RiotClient() + + +def get_client(): + return client diff --git a/web/project/app/urls.py b/web/project/app/urls.py index 2b3beb5..bd33a8f 100644 --- a/web/project/app/urls.py +++ b/web/project/app/urls.py @@ -1,9 +1,16 @@ from django.urls import path -from .views import index, get_account_by_summoner_name, recommend_ai, riot_txt +from .views import ( + index, + get_account_by_summoner_name, + recommend_ai, + recommend_result, + riot_txt, +) urlpatterns = [ path("riot.txt", riot_txt), path("", index, name="home"), path("summoner/", get_account_by_summoner_name, name="summoner"), path("recommend-ai/", recommend_ai, name="recommend-ai"), + path("recommend-result/", recommend_result, name="recommend-result"), ] diff --git a/web/project/app/views.py b/web/project/app/views.py index 6a1a148..f64a65f 100644 --- a/web/project/app/views.py +++ b/web/project/app/views.py @@ -1,9 +1,13 @@ import os +import uuid from django.shortcuts import redirect, render from django.core.handlers.wsgi import WSGIRequest import requests +from django.contrib.auth.decorators import login_required from users.models import SummonerInfo +from app.riot_client import get_client +from app.riot_assets import get_riot_assets def riot_txt(request: WSGIRequest): @@ -38,10 +42,9 @@ def get_account_by_summoner_name(request: WSGIRequest): return render(request, "summoner/index.html", {"summoner": summoner_info}) - url = f"https://kr.api.riotgames.com/lol/summoner/v4/summoners/by-name/{summoner_name}" - api_key = os.environ.get("RIOT_API_KEY") + client = get_client() - response = requests.get(url, headers={"X-Riot-Token": api_key}) + response = client.get_account_by_summoner_name(summoner_name) if response.status_code == 200: data = response.json() @@ -65,3 +68,12 @@ def get_account_by_summoner_name(request: WSGIRequest): def recommend_ai(request: WSGIRequest): return render(request, "recommend/ai.html", {"user": request.user}) + + +@login_required +def recommend_result(request: WSGIRequest): + return render( + request, + "recommend/result.html", + {"user": request.user}, + ) diff --git a/web/project/templates/recommend/ai.html b/web/project/templates/recommend/ai.html index 9da6eb0..1faa87a 100644 --- a/web/project/templates/recommend/ai.html +++ b/web/project/templates/recommend/ai.html @@ -16,10 +16,29 @@

안녕하세요, {{ user.username }}님

라이엇 계정 연동을 통해 AI 추천을 받아보실 수 있습니다.

{% else %} -

안녕하세요, {{ user.username }}님

- + + {% endif %} {% endblock content %} +{% block js %} + +{% endblock js %} \ No newline at end of file diff --git a/web/project/templates/recommend/result.html b/web/project/templates/recommend/result.html new file mode 100644 index 0000000..54e36a3 --- /dev/null +++ b/web/project/templates/recommend/result.html @@ -0,0 +1,30 @@ +{% extends "base/base.html" %} +{% block title %} + | AI Recommend +{% endblock title %} +{% block content %} +
+ + +
추천 결과
+

+ {{ user.summoner_info.name }}님의 추천 결과입니다. +

+
+

+
+
+{% endblock content %} +{% block js %} + +{% endblock js %} \ No newline at end of file diff --git a/web/pyproject.toml b/web/pyproject.toml index a61da40..5a21faf 100644 --- a/web/pyproject.toml +++ b/web/pyproject.toml @@ -15,6 +15,8 @@ gunicorn = "^21.2.0" django-environ = "^0.11.2" requests = "^2.31.0" psycopg = "^3.1.18" +asyncpg = "^0.29.0" +aiohttp = "^3.9.3" [build-system] From d980db373cd0ed9817581cb2186ba2aba1eaa392 Mon Sep 17 00:00:00 2001 From: nohkwanok Date: Thu, 14 Mar 2024 21:44:40 +0900 Subject: [PATCH 2/4] drf --- web/poetry.lock | 31 ++++++++++++++++++++++++++++++- web/project/app/serializers.py | 7 +++++++ web/project/app/urls.py | 9 ++++++++- web/project/app/views.py | 8 ++++++++ web/project/project/settings.py | 1 + web/pyproject.toml | 2 ++ 6 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 web/project/app/serializers.py diff --git a/web/poetry.lock b/web/poetry.lock index e95e7ef..8727732 100644 --- a/web/poetry.lock +++ b/web/poetry.lock @@ -411,6 +411,20 @@ develop = ["coverage[toml] (>=5.0a4)", "furo (>=2021.8.17b43,<2021.9.dev0)", "py docs = ["furo (>=2021.8.17b43,<2021.9.dev0)", "sphinx (>=3.5.0)", "sphinx-notfound-page"] testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"] +[[package]] +name = "django-filter" +version = "24.1" +description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." +optional = false +python-versions = ">=3.8" +files = [ + {file = "django-filter-24.1.tar.gz", hash = "sha256:65cb43ce272077e5ac6aae1054d76c121cd6b552e296a82a13921e9371baf8c1"}, + {file = "django_filter-24.1-py3-none-any.whl", hash = "sha256:335bcae6cbd3e984b024841070f567b22faea57594f27d37c52f8f131f8d8621"}, +] + +[package.dependencies] +Django = ">=4.2" + [[package]] name = "frozenlist" version = "1.4.1" @@ -545,6 +559,21 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "markdown" +version = "3.5.2" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"}, + {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"}, +] + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + [[package]] name = "markupsafe" version = "2.1.5" @@ -992,4 +1021,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "67ecdd445fcde0fc782806a9812f1569cba8d2c002a991588cb97ec984a0dbd6" +content-hash = "eb5243b4b46e81c39f38109ec868cb7c606602b8c713e724554426c49db9878f" diff --git a/web/project/app/serializers.py b/web/project/app/serializers.py new file mode 100644 index 0000000..048c11a --- /dev/null +++ b/web/project/app/serializers.py @@ -0,0 +1,7 @@ +from app.models import Summoner +from rest_framework import serializers + +class SummonerSerializer(serializers.ModelSerializer): + class Meta: + model = Summoner + fields = "__all__" diff --git a/web/project/app/urls.py b/web/project/app/urls.py index bd33a8f..98a05f6 100644 --- a/web/project/app/urls.py +++ b/web/project/app/urls.py @@ -1,16 +1,23 @@ -from django.urls import path +from django.urls import path, include +from rest_framework import routers from .views import ( index, get_account_by_summoner_name, recommend_ai, recommend_result, riot_txt, + SummonerViewSet ) +router = routers.DefaultRouter() +router.register(r"summoners", SummonerViewSet, basename="summoner") + urlpatterns = [ path("riot.txt", riot_txt), path("", index, name="home"), path("summoner/", get_account_by_summoner_name, name="summoner"), path("recommend-ai/", recommend_ai, name="recommend-ai"), path("recommend-result/", recommend_result, name="recommend-result"), + path("api/", include(router.urls)), ] +urlpatterns += router.urls diff --git a/web/project/app/views.py b/web/project/app/views.py index f64a65f..64e26b5 100644 --- a/web/project/app/views.py +++ b/web/project/app/views.py @@ -8,6 +8,9 @@ from users.models import SummonerInfo from app.riot_client import get_client from app.riot_assets import get_riot_assets +from rest_framework import viewsets +from app.serializers import SummonerSerializer +from app.models import Summoner def riot_txt(request: WSGIRequest): @@ -77,3 +80,8 @@ def recommend_result(request: WSGIRequest): "recommend/result.html", {"user": request.user}, ) + + +class SummonerViewSet(viewsets.ModelViewSet): + queryset = Summoner.objects.all() + serializer_class = SummonerSerializer \ No newline at end of file diff --git a/web/project/project/settings.py b/web/project/project/settings.py index 1c0822d..9a2def7 100644 --- a/web/project/project/settings.py +++ b/web/project/project/settings.py @@ -53,6 +53,7 @@ "django.contrib.staticfiles", "app", "users", + "rest_framework", ] MIDDLEWARE = [ diff --git a/web/pyproject.toml b/web/pyproject.toml index 5a21faf..e19b25c 100644 --- a/web/pyproject.toml +++ b/web/pyproject.toml @@ -17,6 +17,8 @@ requests = "^2.31.0" psycopg = "^3.1.18" asyncpg = "^0.29.0" aiohttp = "^3.9.3" +markdown = "^3.5.2" +django-filter = "^24.1" [build-system] From db0ec1502fb5647185fc4de4c25194da6ecc48da Mon Sep 17 00:00:00 2001 From: kwanok Date: Fri, 15 Mar 2024 11:13:07 +0900 Subject: [PATCH 3/4] wip --- web/league_entry.py | 125 ++++++++++++++---- web/poetry.lock | 45 ++++++- .../0005_leagueentry_unique_league_entry.py | 19 +++ ...06_summoner_app_summone_name_9a15eb_idx.py | 17 +++ web/project/app/models.py | 11 ++ web/project/app/serializers.py | 8 +- web/project/app/urls.py | 9 +- web/project/app/views.py | 52 +++++++- web/project/project/settings.py | 13 +- web/pyproject.toml | 2 + 10 files changed, 258 insertions(+), 43 deletions(-) create mode 100644 web/project/app/migrations/0005_leagueentry_unique_league_entry.py create mode 100644 web/project/app/migrations/0006_summoner_app_summone_name_9a15eb_idx.py diff --git a/web/league_entry.py b/web/league_entry.py index 6ba3853..c37566d 100644 --- a/web/league_entry.py +++ b/web/league_entry.py @@ -1,4 +1,5 @@ import asyncio +import datetime import os import asyncpg import aiohttp @@ -14,15 +15,33 @@ def __init__(self): self.api_key = os.environ.get("RIOT_API_KEY") self.tiers = ["IRON", "BRONZE", "SILVER", "GOLD", "PLATINUM", "DIAMOND"] self.divisions = ["I", "II", "III", "IV"] + + self.db_user = os.environ.get("POSTGRES_USER") + self.db_password = os.environ.get("POSTGRES_PASSWORD") + self.db_host = "localhost" + self.db_port = os.environ.get("POSTGRES_PORT") + self.db_name = os.environ.get("POSTGRES_WEB_DB") + + self.pool = None + + async def create_db_pool(self): + self.pool = await asyncpg.create_pool( + user=self.db_user, + password=self.db_password, + host=self.db_host, + port=self.db_port, + database=self.db_name, + ) async def run(self): - # for tier in self.tiers: - # for division in self.divisions: - # await self.get_league_entries(tier, division) + await self.create_db_pool() - await self.get_league_entries(self.tiers[0], self.divisions[0]) + for tier in self.tiers: + for division in self.divisions: + await self.get_league_entries(tier, division) await self.session.close() + await self.pool.close() async def get_league_entries(self, tier: str, division: str): url = f"{self.base_url}/{tier}/{division}?api_key={self.api_key}" @@ -30,16 +49,82 @@ async def get_league_entries(self, tier: str, division: str): league_entries = await self._fetch(url + f"&page={page}") - summoners = [] - while league_entries: - summoners.extend(league_entries) - print(f"Fetching page {page}") + print(f"Fetching {tier} {division} page {page}... entries: {len(league_entries)}") + summoners = [ + ( + league_entry["summonerId"], + league_entry["summonerName"], + datetime.datetime.now(), + datetime.datetime.now(), + ) + for league_entry + in league_entries + ] + + async with self.pool.acquire() as connection: + async with connection.transaction(): + await connection.executemany( + "INSERT INTO app_summoner (id, name, created_at, updated_at)" + "VALUES ($1, $2, $3, $4)" + "ON CONFLICT (id)" + """ + DO UPDATE SET + name = EXCLUDED.name, + updated_at = EXCLUDED.updated_at + """, + summoners, + ) + + entries = [ + ( + league_entry["tier"], + league_entry["rank"], + league_entry["leaguePoints"], + league_entry["wins"], + league_entry["losses"], + league_entry["veteran"], + league_entry["inactive"], + league_entry["freshBlood"], + league_entry["hotStreak"], + league_entry["queueType"], + league_entry["leagueId"], + league_entry["summonerId"], + datetime.datetime.now(), + datetime.datetime.now(), + ) + for league_entry + in league_entries + ] + async with self.pool.acquire() as connection: + async with connection.transaction(): + await connection.executemany( + "INSERT INTO app_leagueentry (tier, rank, league_points, wins, losses, veteran, inactive, fresh_blood, hot_streak, queue_type, league_id, summoner_id, created_at, updated_at)" + "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)" + "ON CONFLICT (summoner_id, queue_type)" + """ + DO UPDATE SET + tier = EXCLUDED.tier, + rank = EXCLUDED.rank, + league_points = EXCLUDED.league_points, + wins = EXCLUDED.wins, + losses = EXCLUDED.losses, + veteran = EXCLUDED.veteran, + inactive = EXCLUDED.inactive, + fresh_blood = EXCLUDED.fresh_blood, + hot_streak = EXCLUDED.hot_streak, + queue_type = EXCLUDED.queue_type, + league_id = EXCLUDED.league_id, + summoner_id = EXCLUDED.summoner_id, + updated_at = EXCLUDED.updated_at + """, + entries, + ) page += 1 league_entries = await self._fetch(url + f"&page={page}") - - print(summoners) + + return [] async def _fetch(self, url: str) -> list: async with self.session.get(url) as response: @@ -56,24 +141,8 @@ async def _fetch(self, url: str) -> list: async def main(): - # crawler = LeagueEntryCrawler() - # await crawler.run() - - db_user = os.environ.get("POSTGRES_USER") - db_password = os.environ.get("POSTGRES_PASSWORD") - db_host = "localhost" - db_port = os.environ.get("POSTGRES_PORT") - db_name = os.environ.get("POSTGRES_WEB_DB") - - db_url = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}" - - print(f"Connecting to database: {db_url}") - - pool = await asyncpg.create_pool(db_url) - - print("Connected to database") - - await pool.close() + crawler = LeagueEntryCrawler() + await crawler.run() loop = asyncio.get_event_loop() diff --git a/web/poetry.lock b/web/poetry.lock index 8727732..caa745e 100644 --- a/web/poetry.lock +++ b/web/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -395,6 +395,21 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""} argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +[[package]] +name = "django-debug-toolbar" +version = "4.3.0" +description = "A configurable set of panels that display various debug information about the current request/response." +optional = false +python-versions = ">=3.8" +files = [ + {file = "django_debug_toolbar-4.3.0-py3-none-any.whl", hash = "sha256:e09b7dcb8417b743234dfc57c95a7c1d1d87a88844abd13b4c5387f807b31bf6"}, + {file = "django_debug_toolbar-4.3.0.tar.gz", hash = "sha256:0b0dddee5ea29b9cb678593bc0d7a6d76b21d7799cb68e091a2148341a80f3c4"}, +] + +[package.dependencies] +django = ">=3.2.4" +sqlparse = ">=0.2" + [[package]] name = "django-environ" version = "0.11.2" @@ -425,6 +440,21 @@ files = [ [package.dependencies] Django = ">=4.2" +[[package]] +name = "djangorestframework" +version = "3.14.0" +description = "Web APIs for Django, made easy." +optional = false +python-versions = ">=3.6" +files = [ + {file = "djangorestframework-3.14.0-py3-none-any.whl", hash = "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08"}, + {file = "djangorestframework-3.14.0.tar.gz", hash = "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8"}, +] + +[package.dependencies] +django = ">=3.0" +pytz = "*" + [[package]] name = "frozenlist" version = "1.4.1" @@ -813,6 +843,17 @@ docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)" pool = ["psycopg-pool"] test = ["anyio (>=3.6.2,<4.0)", "mypy (>=1.4.1)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + [[package]] name = "requests" version = "2.31.0" @@ -1021,4 +1062,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "eb5243b4b46e81c39f38109ec868cb7c606602b8c713e724554426c49db9878f" +content-hash = "d0847bcd7635eb1ffa4dd597fa727d32f2a655692fd01f41a5b34a33c912f2d5" diff --git a/web/project/app/migrations/0005_leagueentry_unique_league_entry.py b/web/project/app/migrations/0005_leagueentry_unique_league_entry.py new file mode 100644 index 0000000..b67a59b --- /dev/null +++ b/web/project/app/migrations/0005_leagueentry_unique_league_entry.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.2 on 2024-03-14 07:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0004_leagueentry"), + ] + + operations = [ + migrations.AddConstraint( + model_name="leagueentry", + constraint=models.UniqueConstraint( + fields=("summoner", "queue_type"), name="unique_league_entry" + ), + ), + ] diff --git a/web/project/app/migrations/0006_summoner_app_summone_name_9a15eb_idx.py b/web/project/app/migrations/0006_summoner_app_summone_name_9a15eb_idx.py new file mode 100644 index 0000000..70dbb2c --- /dev/null +++ b/web/project/app/migrations/0006_summoner_app_summone_name_9a15eb_idx.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.2 on 2024-03-14 08:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0005_leagueentry_unique_league_entry"), + ] + + operations = [ + migrations.AddIndex( + model_name="summoner", + index=models.Index(fields=["name"], name="app_summone_name_9a15eb_idx"), + ), + ] diff --git a/web/project/app/models.py b/web/project/app/models.py index e049ab4..64591a2 100644 --- a/web/project/app/models.py +++ b/web/project/app/models.py @@ -1,5 +1,6 @@ # Create your models here. +from django.contrib.postgres.search import SearchVector, SearchVectorField from users.models import AppUser as User from django.db import models @@ -35,6 +36,11 @@ class Summoner(models.Model): def __str__(self): return self.name + + class Meta: + indexes = [ + models.Index(fields=['name']) + ] class LeagueEntry(models.Model): @@ -55,3 +61,8 @@ class LeagueEntry(models.Model): def __str__(self): return f"{self.summoner.name} - {self.tier} {self.rank}" + + class Meta: + constraints = [ + models.UniqueConstraint(fields=['summoner', 'queue_type'], name='unique_league_entry') + ] diff --git a/web/project/app/serializers.py b/web/project/app/serializers.py index 048c11a..a597750 100644 --- a/web/project/app/serializers.py +++ b/web/project/app/serializers.py @@ -1,7 +1,13 @@ -from app.models import Summoner +from app.models import Summoner, LeagueEntry from rest_framework import serializers class SummonerSerializer(serializers.ModelSerializer): class Meta: model = Summoner fields = "__all__" + + +class LeagueEntrySerializer(serializers.ModelSerializer): + class Meta: + model = LeagueEntry + fields = "__all__" \ No newline at end of file diff --git a/web/project/app/urls.py b/web/project/app/urls.py index 98a05f6..ee39366 100644 --- a/web/project/app/urls.py +++ b/web/project/app/urls.py @@ -6,18 +6,15 @@ recommend_ai, recommend_result, riot_txt, - SummonerViewSet + search_summoners_by_name, ) -router = routers.DefaultRouter() -router.register(r"summoners", SummonerViewSet, basename="summoner") - urlpatterns = [ path("riot.txt", riot_txt), path("", index, name="home"), path("summoner/", get_account_by_summoner_name, name="summoner"), path("recommend-ai/", recommend_ai, name="recommend-ai"), path("recommend-result/", recommend_result, name="recommend-result"), - path("api/", include(router.urls)), + path("summoners/search/", search_summoners_by_name, name="search-summoners-by-name"), + path("__debug__/", include("debug_toolbar.urls")), ] -urlpatterns += router.urls diff --git a/web/project/app/views.py b/web/project/app/views.py index 64e26b5..5e79c89 100644 --- a/web/project/app/views.py +++ b/web/project/app/views.py @@ -1,16 +1,18 @@ import os import uuid +from django.http import JsonResponse from django.shortcuts import redirect, render from django.core.handlers.wsgi import WSGIRequest import requests from django.contrib.auth.decorators import login_required from users.models import SummonerInfo +from rest_framework.decorators import api_view from app.riot_client import get_client from app.riot_assets import get_riot_assets from rest_framework import viewsets -from app.serializers import SummonerSerializer -from app.models import Summoner +from app.serializers import SummonerSerializer, LeagueEntrySerializer +from app.models import Summoner, LeagueEntry def riot_txt(request: WSGIRequest): @@ -82,6 +84,46 @@ def recommend_result(request: WSGIRequest): ) -class SummonerViewSet(viewsets.ModelViewSet): - queryset = Summoner.objects.all() - serializer_class = SummonerSerializer \ No newline at end of file +@api_view(["GET"]) +def search_summoners_by_name(request: WSGIRequest): + name = request.GET.get("name") + count = request.GET.get("count") + if not name or not count: + return JsonResponse({"error": "name, count are required"}, status=400) + + try: + count = int(count) + except ValueError: + return JsonResponse({"error": "count must be an integer"}, status=400) + + if count > 10: + return JsonResponse({"error": "count must be less than or equal to 10"}, status=400) + + queryset = Summoner.objects.filter(name__startswith=name)[:count] + serializer = SummonerSerializer(queryset, many=True) + + summoners = serializer.data + + summoner_ids = [ + summoner["id"] + for summoner in serializer.data + ] + + queryset = LeagueEntry.objects.filter(summoner_id__in=summoner_ids) + serializer = LeagueEntrySerializer(queryset, many=True) + + league_entries = serializer.data + + result = [ + { + "summoner": summoner, + "league_entries": [ + league_entry + for league_entry in league_entries + if league_entry["summoner"] == summoner["id"] + ] + } + for summoner in summoners + ] + + return JsonResponse(result, safe=False) \ No newline at end of file diff --git a/web/project/project/settings.py b/web/project/project/settings.py index 9a2def7..465fc52 100644 --- a/web/project/project/settings.py +++ b/web/project/project/settings.py @@ -28,7 +28,7 @@ # SECURITY WARNING: don't run with debug turned on in production! if ENV == "production": - DEBUG = False + DEBUG = True SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_SECONDS = 31536000 # 1 year SESSION_COOKIE_SECURE = True @@ -54,6 +54,7 @@ "app", "users", "rest_framework", + "debug_toolbar", ] MIDDLEWARE = [ @@ -65,6 +66,7 @@ "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "project.middleware.user_activity_logger.UserActivityLoggerMiddleware", + "debug_toolbar.middleware.DebugToolbarMiddleware", ] ROOT_URLCONF = "project.urls" @@ -173,3 +175,12 @@ environ.Env.read_env(BASE_DIR / ".env") AUTH_USER_MODEL = "users.AppUser" + +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 10 +} + +INTERNAL_IPS = [ + "127.0.0.1", +] \ No newline at end of file diff --git a/web/pyproject.toml b/web/pyproject.toml index e19b25c..c9feb4e 100644 --- a/web/pyproject.toml +++ b/web/pyproject.toml @@ -19,6 +19,8 @@ asyncpg = "^0.29.0" aiohttp = "^3.9.3" markdown = "^3.5.2" django-filter = "^24.1" +djangorestframework = "^3.14.0" +django-debug-toolbar = "^4.3.0" [build-system] From 82ae9e39ba18cd2b01e15c73386f27ef298d8cc7 Mon Sep 17 00:00:00 2001 From: kwanok Date: Mon, 18 Mar 2024 18:05:18 +0900 Subject: [PATCH 4/4] wip --- web/league_entry.py | 22 +-- ...nt_id_summoner_profile_icon_id_and_more.py | 38 ++++++ web/project/app/models.py | 18 ++- web/project/app/riot_client.py | 7 + web/project/app/serializers.py | 3 +- web/project/app/urls.py | 15 ++- web/project/app/views.py | 100 ++++++++++---- web/project/project/settings.py | 8 +- web/project/templates/recommend/ai.html | 4 +- web/project/templates/recommend/result.html | 2 +- web/project/templates/users/profile.html | 125 +++++++++++++++--- web/project/users/admin.py | 4 +- ...summoner_info_appuser_summoner_and_more.py | 32 +++++ web/project/users/models.py | 15 +-- 14 files changed, 303 insertions(+), 90 deletions(-) create mode 100644 web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py create mode 100644 web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py diff --git a/web/league_entry.py b/web/league_entry.py index c37566d..2f8a061 100644 --- a/web/league_entry.py +++ b/web/league_entry.py @@ -15,15 +15,15 @@ def __init__(self): self.api_key = os.environ.get("RIOT_API_KEY") self.tiers = ["IRON", "BRONZE", "SILVER", "GOLD", "PLATINUM", "DIAMOND"] self.divisions = ["I", "II", "III", "IV"] - + self.db_user = os.environ.get("POSTGRES_USER") self.db_password = os.environ.get("POSTGRES_PASSWORD") self.db_host = "localhost" self.db_port = os.environ.get("POSTGRES_PORT") self.db_name = os.environ.get("POSTGRES_WEB_DB") - + self.pool = None - + async def create_db_pool(self): self.pool = await asyncpg.create_pool( user=self.db_user, @@ -31,7 +31,7 @@ async def create_db_pool(self): host=self.db_host, port=self.db_port, database=self.db_name, - ) + ) async def run(self): await self.create_db_pool() @@ -50,7 +50,9 @@ async def get_league_entries(self, tier: str, division: str): league_entries = await self._fetch(url + f"&page={page}") while league_entries: - print(f"Fetching {tier} {division} page {page}... entries: {len(league_entries)}") + print( + f"Fetching {tier} {division} page {page}... entries: {len(league_entries)}" + ) summoners = [ ( league_entry["summonerId"], @@ -58,10 +60,9 @@ async def get_league_entries(self, tier: str, division: str): datetime.datetime.now(), datetime.datetime.now(), ) - for league_entry - in league_entries + for league_entry in league_entries ] - + async with self.pool.acquire() as connection: async with connection.transaction(): await connection.executemany( @@ -93,8 +94,7 @@ async def get_league_entries(self, tier: str, division: str): datetime.datetime.now(), datetime.datetime.now(), ) - for league_entry - in league_entries + for league_entry in league_entries ] async with self.pool.acquire() as connection: async with connection.transaction(): @@ -123,7 +123,7 @@ async def get_league_entries(self, tier: str, division: str): page += 1 league_entries = await self._fetch(url + f"&page={page}") - + return [] async def _fetch(self, url: str) -> list: diff --git a/web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py b/web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py new file mode 100644 index 0000000..292c239 --- /dev/null +++ b/web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 5.0.2 on 2024-03-15 06:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0006_summoner_app_summone_name_9a15eb_idx"), + ] + + operations = [ + migrations.AddField( + model_name="summoner", + name="account_id", + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name="summoner", + name="profile_icon_id", + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name="summoner", + name="puuid", + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name="summoner", + name="revision_date", + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name="summoner", + name="summoner_level", + field=models.IntegerField(null=True), + ), + ] diff --git a/web/project/app/models.py b/web/project/app/models.py index 64591a2..a374022 100644 --- a/web/project/app/models.py +++ b/web/project/app/models.py @@ -1,6 +1,5 @@ # Create your models here. -from django.contrib.postgres.search import SearchVector, SearchVectorField from users.models import AppUser as User from django.db import models @@ -31,16 +30,19 @@ class Champion(models.Model): class Summoner(models.Model): id = models.CharField(max_length=100, blank=False, null=False, primary_key=True) name = models.CharField(max_length=100, blank=False, null=False) + puuid = models.CharField(max_length=100, blank=False, null=True) + account_id = models.CharField(max_length=100, blank=False, null=True) + profile_icon_id = models.IntegerField(blank=False, null=True) + revision_date = models.BigIntegerField(blank=False, null=True) + summoner_level = models.IntegerField(blank=False, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.name - + class Meta: - indexes = [ - models.Index(fields=['name']) - ] + indexes = [models.Index(fields=["name"])] class LeagueEntry(models.Model): @@ -61,8 +63,10 @@ class LeagueEntry(models.Model): def __str__(self): return f"{self.summoner.name} - {self.tier} {self.rank}" - + class Meta: constraints = [ - models.UniqueConstraint(fields=['summoner', 'queue_type'], name='unique_league_entry') + models.UniqueConstraint( + fields=["summoner", "queue_type"], name="unique_league_entry" + ) ] diff --git a/web/project/app/riot_client.py b/web/project/app/riot_client.py index 9b63e0a..47ee2e9 100644 --- a/web/project/app/riot_client.py +++ b/web/project/app/riot_client.py @@ -30,6 +30,13 @@ def get_champion_masteries_by_puuid_top(self, puuid: str) -> requests.Response: response = requests.get(url, headers={"X-Riot-Token": self.api_key}) return response + def get_summoner_by_encrypted_summoner_id( + self, encrypted_summoner_id: str + ) -> requests.Response: + url = f"{KR_API_HOST}/lol/summoner/v4/summoners/{encrypted_summoner_id}" + response = requests.get(url, headers={"X-Riot-Token": self.api_key}) + return response + client = RiotClient() diff --git a/web/project/app/serializers.py b/web/project/app/serializers.py index a597750..ae825db 100644 --- a/web/project/app/serializers.py +++ b/web/project/app/serializers.py @@ -1,6 +1,7 @@ from app.models import Summoner, LeagueEntry from rest_framework import serializers + class SummonerSerializer(serializers.ModelSerializer): class Meta: model = Summoner @@ -10,4 +11,4 @@ class Meta: class LeagueEntrySerializer(serializers.ModelSerializer): class Meta: model = LeagueEntry - fields = "__all__" \ No newline at end of file + fields = "__all__" diff --git a/web/project/app/urls.py b/web/project/app/urls.py index ee39366..3bff6e2 100644 --- a/web/project/app/urls.py +++ b/web/project/app/urls.py @@ -1,5 +1,6 @@ from django.urls import path, include -from rest_framework import routers + +from project import settings from .views import ( index, get_account_by_summoner_name, @@ -7,6 +8,7 @@ recommend_result, riot_txt, search_summoners_by_name, + save_summoner, ) urlpatterns = [ @@ -15,6 +17,13 @@ path("summoner/", get_account_by_summoner_name, name="summoner"), path("recommend-ai/", recommend_ai, name="recommend-ai"), path("recommend-result/", recommend_result, name="recommend-result"), - path("summoners/search/", search_summoners_by_name, name="search-summoners-by-name"), - path("__debug__/", include("debug_toolbar.urls")), + path( + "summoners/search/", search_summoners_by_name, name="search-summoners-by-name" + ), + path("profile/summoner", save_summoner, name="save-summoner-info"), ] + +if settings.DEBUG: + import debug_toolbar + + urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns diff --git a/web/project/app/views.py b/web/project/app/views.py index 5e79c89..01e7adf 100644 --- a/web/project/app/views.py +++ b/web/project/app/views.py @@ -1,18 +1,14 @@ -import os -import uuid from django.http import JsonResponse from django.shortcuts import redirect, render from django.core.handlers.wsgi import WSGIRequest -import requests from django.contrib.auth.decorators import login_required -from users.models import SummonerInfo +from app.models import Summoner from rest_framework.decorators import api_view from app.riot_client import get_client -from app.riot_assets import get_riot_assets -from rest_framework import viewsets from app.serializers import SummonerSerializer, LeagueEntrySerializer -from app.models import Summoner, LeagueEntry +from app.models import LeagueEntry +from users.models import AppUser def riot_txt(request: WSGIRequest): @@ -42,10 +38,10 @@ def authorize(request: WSGIRequest): def get_account_by_summoner_name(request: WSGIRequest): summoner_name = request.GET.get("summoner_name") - if SummonerInfo.objects.filter(name=summoner_name).exists(): - summoner_info = SummonerInfo.objects.get(name=summoner_name) + if Summoner.objects.filter(name=summoner_name).exists(): + summoner = Summoner.objects.get(name=summoner_name) - return render(request, "summoner/index.html", {"summoner": summoner_info}) + return render(request, "summoner/index.html", {"summoner": summoner}) client = get_client() @@ -54,7 +50,7 @@ def get_account_by_summoner_name(request: WSGIRequest): if response.status_code == 200: data = response.json() - summoner_info = SummonerInfo( + summoner = Summoner( id=data["id"], account_id=data["accountId"], profile_icon_id=data["profileIconId"], @@ -64,9 +60,9 @@ def get_account_by_summoner_name(request: WSGIRequest): summoner_level=data["summonerLevel"], ) - summoner_info.save() + summoner.save() - return render(request, "summoner/index.html", {"summoner": summoner_info}) + return render(request, "summoner/index.html", {"summoner": summoner}) return render(request, "summoner/index.html", {"error": response.json()}) @@ -90,30 +86,50 @@ def search_summoners_by_name(request: WSGIRequest): count = request.GET.get("count") if not name or not count: return JsonResponse({"error": "name, count are required"}, status=400) - + try: count = int(count) except ValueError: return JsonResponse({"error": "count must be an integer"}, status=400) - + if count > 10: - return JsonResponse({"error": "count must be less than or equal to 10"}, status=400) - + return JsonResponse( + {"error": "count must be less than or equal to 10"}, status=400 + ) + queryset = Summoner.objects.filter(name__startswith=name)[:count] serializer = SummonerSerializer(queryset, many=True) - + summoners = serializer.data - - summoner_ids = [ - summoner["id"] - for summoner in serializer.data - ] - + + summoner_ids = [summoner["id"] for summoner in serializer.data] + queryset = LeagueEntry.objects.filter(summoner_id__in=summoner_ids) serializer = LeagueEntrySerializer(queryset, many=True) - + league_entries = serializer.data - + + for summoner in summoners: + if summoner["puuid"] is None: + new_summoner = get_client().get_summoner_by_encrypted_summoner_id( + summoner["id"] + ) + + if new_summoner.status_code == 200: + summoner["puuid"] = new_summoner.json()["puuid"] + summoner["account_id"] = new_summoner.json()["accountId"] + summoner["profile_icon_id"] = new_summoner.json()["profileIconId"] + summoner["revision_date"] = new_summoner.json()["revisionDate"] + summoner["summoner_level"] = new_summoner.json()["summonerLevel"] + + Summoner.objects.filter(id=summoner["id"]).update( + puuid=summoner["puuid"], + account_id=summoner["account_id"], + profile_icon_id=summoner["profile_icon_id"], + revision_date=summoner["revision_date"], + summoner_level=summoner["summoner_level"], + ) + result = [ { "summoner": summoner, @@ -121,9 +137,35 @@ def search_summoners_by_name(request: WSGIRequest): league_entry for league_entry in league_entries if league_entry["summoner"] == summoner["id"] - ] + ], } for summoner in summoners ] - - return JsonResponse(result, safe=False) \ No newline at end of file + + return JsonResponse(result, safe=False) + + +@api_view(["POST"]) +def save_summoner(request: WSGIRequest): + me = request.user + + summoner_id = request.data["summoner_id"] + + if not summoner_id: + return JsonResponse({"error": "id is required"}, status=400) + + summoner = Summoner.objects.get(id=summoner_id) + + AppUser.objects.filter(id=me.id).update(summoner=summoner) + + return JsonResponse( + { + "name": summoner.name, + "puuid": summoner.puuid, + "level": summoner.summoner_level, + "account_id": summoner.account_id, + "profile_icon_id": summoner.profile_icon_id, + "revision_date": summoner.revision_date, + }, + safe=False, + ) diff --git a/web/project/project/settings.py b/web/project/project/settings.py index 465fc52..e9dc697 100644 --- a/web/project/project/settings.py +++ b/web/project/project/settings.py @@ -28,7 +28,7 @@ # SECURITY WARNING: don't run with debug turned on in production! if ENV == "production": - DEBUG = True + DEBUG = False SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_SECONDS = 31536000 # 1 year SESSION_COOKIE_SECURE = True @@ -177,10 +177,10 @@ AUTH_USER_MODEL = "users.AppUser" REST_FRAMEWORK = { - 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', - 'PAGE_SIZE': 10 + "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", + "PAGE_SIZE": 10, } INTERNAL_IPS = [ "127.0.0.1", -] \ No newline at end of file +] diff --git a/web/project/templates/recommend/ai.html b/web/project/templates/recommend/ai.html index 1faa87a..9c9e9c4 100644 --- a/web/project/templates/recommend/ai.html +++ b/web/project/templates/recommend/ai.html @@ -10,13 +10,13 @@

안녕하세요, 방문자님

로그인을 하시면 AI 추천을 받아보실 수 있습니다.

- {% elif not user.summoner_info %} + {% elif not user.summoner %}

안녕하세요, {{ user.username }}님

라이엇 계정 연동을 통해 AI 추천을 받아보실 수 있습니다.

{% else %} -

안녕하세요, {{ user.summoner_info.name }}님

+

안녕하세요, {{ user.summoner.name }}님

diff --git a/web/project/templates/recommend/result.html b/web/project/templates/recommend/result.html index 54e36a3..ce6b358 100644 --- a/web/project/templates/recommend/result.html +++ b/web/project/templates/recommend/result.html @@ -8,7 +8,7 @@
추천 결과

- {{ user.summoner_info.name }}님의 추천 결과입니다. + {{ user.summoner.name }}님의 추천 결과입니다.

diff --git a/web/project/templates/users/profile.html b/web/project/templates/users/profile.html index fcd7556..f5a74ac 100644 --- a/web/project/templates/users/profile.html +++ b/web/project/templates/users/profile.html @@ -26,30 +26,28 @@

👾 마이페이지

- +
-
- {% if user.summoner_info %} +
+ {% if user.summoner %} + value="{{ user.summoner.name }}"> {% else %} + name="summoner_name" + id="summoner_name" + class="block border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6" + placeholder="소환사 이름으로 라이엇 계정을 연동해보세요."> {% endif %}
+
- {% if user.summoner_info %} + {% if user.summoner %}
@@ -61,7 +59,7 @@

👾 마이페이지

autocomplete="summoner_level" class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6" disabled="disabled" - value="{{ user.summoner_info.summoner_level }}"> + value="{{ user.summoner.summoner_level }}">
@@ -69,11 +67,11 @@

👾 마이페이지

- {% if user.summoner_info %} + {% if user.summoner %} {% else %} 👾 마이페이지
{% endblock content %} +{% block js %} + +{% endblock js %} \ No newline at end of file diff --git a/web/project/users/admin.py b/web/project/users/admin.py index 6a48d48..8aa232d 100644 --- a/web/project/users/admin.py +++ b/web/project/users/admin.py @@ -6,8 +6,8 @@ class CustomUserAdmin(UserAdmin): model = AppUser # 추가된 필드를 관리자 페이지에서 보이도록 설정 - fieldsets = UserAdmin.fieldsets + ((None, {"fields": ("summoner_info",)}),) - add_fieldsets = UserAdmin.add_fieldsets + ((None, {"fields": ("summoner_info",)}),) + fieldsets = UserAdmin.fieldsets + ((None, {"fields": ("summoner",)}),) + add_fieldsets = UserAdmin.add_fieldsets + ((None, {"fields": ("summoner",)}),) admin.site.register(AppUser, CustomUserAdmin) diff --git a/web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py b/web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py new file mode 100644 index 0000000..43cc517 --- /dev/null +++ b/web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.2 on 2024-03-18 06:20 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("app", "0007_summoner_account_id_summoner_profile_icon_id_and_more"), + ("users", "0002_summonerinfo_remove_appuser_riot_id_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="appuser", + name="summoner_info", + ), + migrations.AddField( + model_name="appuser", + name="summoner", + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="app.summoner", + ), + ), + migrations.DeleteModel( + name="SummonerInfo", + ), + ] diff --git a/web/project/users/models.py b/web/project/users/models.py index 8a9671f..a603334 100644 --- a/web/project/users/models.py +++ b/web/project/users/models.py @@ -3,16 +3,7 @@ class AppUser(AbstractUser): - summoner_info = models.OneToOneField( - "SummonerInfo", on_delete=models.CASCADE, blank=True, null=True - ) - -class SummonerInfo(models.Model): - id = models.CharField(max_length=100, blank=False, null=False, primary_key=True) - account_id = models.CharField(max_length=100, blank=False, null=False) - profile_icon_id = models.IntegerField(blank=False, null=False) - revision_date = models.BigIntegerField(blank=False, null=False) - name = models.CharField(max_length=100, blank=False, null=False) - puuid = models.CharField(max_length=100, blank=False, null=False) - summoner_level = models.IntegerField(blank=False, null=False) + summoner = models.OneToOneField( + "app.Summoner", on_delete=models.CASCADE, blank=True, null=True + )