Initial commit

This commit is contained in:
Rohan Verma 2024-07-30 16:00:11 -07:00 committed by GitHub
commit 55332d1ddb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
168 changed files with 18456 additions and 0 deletions

4
apps/api/.env.example Normal file
View file

@ -0,0 +1,4 @@
DB_URL=supabase_url
DB_API_KEY=supabase_api_key
DB_EMAIl=email_address
DB_PASSWORD=password

13
apps/api/.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,13 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: FastAPI",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
"args": ["src.main:app", "--reload"],
"jinja": true
}
]
}

5
apps/api/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"python.testing.pytestArgs": ["tests"],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}

8
apps/api/README.md Normal file
View file

@ -0,0 +1,8 @@
Generate requirements.txt using Poetry package manager:
```
poetry export --without-hashes --format=requirements.txt > requirements.txt
```
Python monorepo info:
https://medium.com/@ashley.e.shultz/python-mono-repo-with-only-built-in-tooling-7c2d52c2fc66

View file

@ -0,0 +1,78 @@
id,name,description
c76a2922-ba4c-4278-baab-44defb631236,Aberto,Opens locked doors
06485500-d023-4799-93fd-77f2c3341aa3,Accio,Summons objects
acbc0ae1-12e1-4813-b51e-09d22de40475,Aguamenti,Summons water
c9d2f389-a419-4f7e-8d3d-254959638019,Alohomora,Unlocks objects
018429a5-15d5-41af-bf8f-98a966733d77,Anapneo,Clears someone's airway
c828685c-52d2-466d-bcc6-fbcd8376cfb5,Aparecium,Reveals secret written messages
7fdd393c-2608-4ef3-9fd0-f691ad6f8b88,Apparate,A non-verbal transportation spell that allows a witch or wizard to instantly travel on the spot and appear at another location (disapparate is the opposite)
73886d47-2808-4861-ae40-956f4cb56272,Ascendio,Propells someone into the air
9a6b6854-8858-4b21-b761-12526a154597,Avada Kedavra,"Also known as The Killing Curse, the most evil spell in the Wizarding World; one of three Unforgivable Curses; Harry Potter is the only known witch or wizard to survive it"
b6f20bba-c0db-4ad2-8ac6-2a375a596287,Avis,Conjures a small flock of birds
48edfe4d-ddfc-49ac-8065-bd7e73c73778,Bat,Bogey Hex - Turns the target's boogers into bats
6bd8d5c1-9375-4b70-8d6e-ad019176c7a2,Bombardo,Creates an explosion
8fc19d10-3130-4b85-95c1-f2a51ba5ee3c,Brackium Emendo,Heals broken bones
f08c17fa-7bf9-49bf-9fba-a7806815bc80,Capacious Extremis,"Known as the Extension Charm, it's a complicated spell that can greatly expand or extend the capacity of an object or space without affecting it externally"
55dec867-ac07-4975-94c7-090f6fd25c86,Confundo,"Known as the Confundus Charm, it causes confusion of the target"
816d9fee-b78f-47b4-be46-b48626c013f9,Conjunctivitis Curse,Affects the eyes and sight of a target
58b8727a-6c0c-469c-b91d-8ac0cc0dd2d8,Crinus Muto,Changes hair color and style
f1e91049-e866-4f6f-9d87-d6fd366aecbf,Crucio,"One of three Unforgivable Curses, it causes unbearable pain in the target"
7324e645-8f41-4c83-a367-0d10a72906ff,Diffindo,Used to precisely cut an object
638072b9-b7ac-405d-914b-d9293c5f9d25,Disillusionment Charm,Causes the target to take on the appearance of its surroundings
b7643e32-ef9c-41b8-83f2-03f6b5015e04,Disapparate,A non-verbal transportation spell that allows a witch or wizard to instantly travel on the spot and leave for another location (apparate is the opposite)
20476c31-4f27-49ac-876f-a4c4028f1b5b,Engorgio,Causes rapid growth in the targeted object
ecb9a882-d6d7-495e-9958-a1a06902bb65,Episkey,Heals minor injuries
317ff981-ad65-421e-92fb-5f6647d95232,Expecto patronum,"The Patronus Charm is a powerful projection of hope and happiness that drives away Dementors; a corpeal Patronus takes the the respective animal form of the caster, while a non-corpeal appears as a wisp of light; at 13, Harry Potter was the youngest known witch or wizard to prouduce a corpeal Patronus"
60149246-91cf-44a5-8885-78a7acc4bf90,Erecto,"Allows a witch or wizard to build a structure, like a tent"
6d8138c3-0773-4c23-b0bf-aab0e5c6fd95,Evanesco,Vanishes objects
678474e6-fb30-4bf0-a18c-228f6b36592d,Expelliarmus,Forces an opponent to drop whatever's in their possession
31b38b6c-4775-4e20-815d-dbf302433de6,Ferula,A healing charm that conjures wraps and bandages for wounds
37d262c9-28ab-408f-9576-acf54ce50203,Fidelius Charm,"A complex charm that conceals a secret into the soul of a chosen ""Secret Keeper"". If a location is the subject of concealment, it becomes undetectable to others"
9121b557-0ebf-4b60-a119-9d1c5ff05dee,Fiendfyre Curse,"Conjures destructive, enormous enchanted flames"
de23025f-5e6a-4ec3-b827-5c526a922a89,Finite Incantatem,A general counter-spell that's used to reverse or counter already cast charms
d536cbe5-bc0f-49e5-b063-e02c231a3988,Furnunculus Curse,A jinx that causes a breakout of boils or pimples
7915b07a-d26e-4057-9083-e457643e57a6,Geminio,Duplicates objects
2a942514-7a19-4f0e-9353-171c573abcba,Glisseo,Transforms a staircase into a slide
a42028b6-67f5-463b-b759-452103533227,Homenum Revelio,Reveals the presence of another person
552cd4ee-2c67-48fd-ae20-a83773262a8a,Homonculus Charm,Detects anyone's true identity and location on a piece of parchment; used to create the Marauder's Map
2dfca7d2-ec9b-4150-b3f3-fd972a5fd1bc,Immobulus,Immobilises living targets
a49300cc-ddbf-4ff4-b8c2-e8bddbbe4118,Impedimenta,A temporary jinx that slows the movement of the target
e5c22d31-26f1-4c88-a586-d9c09cb88c1f,Incarcerous,Conjures ropes
a53ad5be-00ee-4254-b3c0-4cec60b0c034,Imperio,"One of the three Unforgivable Curses, it places the target under the complete control of the caster"
a3b34bf6-1ff7-4fe3-81ee-e617150f5da9,Impervius,Makes an object waterproof
de048df0-b227-4376-a29b-90fe6878d950,Incendio,Conjures flames
c4a4520b-b80d-49e8-9e5a-3ca0a7f376ca,Langlock,Causes the target's tongue to stick to the roof of their mouth
0da7cb76-dabc-46ff-b8e9-c23a4f03caea,Legilimens,Invading or navigating another's mind
723dd9c9-ee62-495b-9071-cddd16087b86,Levicorpus,Levitates the target by their ankle
8add16ef-b4b1-4e2b-a91e-80aa194da438,Locomotor Mortis,The Leg-Locker curse bounds the target's legs
3b7a10ce-3339-4a36-9493-292c8775e47b,Lumos,Illuminates the caster's wand
832edaca-dbff-4a57-80c7-1d8a827c8416,Morsmordre,Conjures and projects Lord Voldemort's Dark Mark
7f4b43e0-3356-43f9-9299-15ec37cfaf76,Mucus Ad Nauseam,Inflicts an extreme runny nose or cold
f86bbf7e-94ea-4c22-89fb-809af8214a85,Muffliato,Creates a buzzing sound in the target's ears to prevent eavesdropping
66be613d-532c-46d8-a3e9-f5a2d9cccf0c,Nox,"Reverses the lumos charm, extinguishing a wand's light"
9e3c0217-652a-4763-82f8-5519026a1ea6,Obliviate,Erases the target's memory
0af49753-c8ae-4748-87a7-b7cfc47d33a0,Obscuro,Conjures a blindfold
67e838c1-4623-414e-9a91-12125631dbad,Oculus Reparo,Repairs eyeglasses
12251f32-af9d-408f-a652-3a4cc9602bc0,Oppugno,Directs an object or person to attack a victim
da9eab7b-2c7c-42de-861c-fb254bd9423c,Petrificus Totalus,Temporarily freezes or petrifies the body of the target
3e5fd245-2ecf-40c4-937d-b2c2f9eee003,Periculum,Conjures flares/red sparks
ad5685f8-6e05-49b1-a41c-d72786001d72,Piertotum Locomotor,Incantation used to bring to life inanimate objects and artifacts
0a267162-0594-4372-a3d5-89382926f495,Protean Charm,Links objects together for better communication
8808aa30-39f4-400c-a0e5-1dcbad657931,Protego,"Casts an invisible shield around the caster, protecting against spells and objects (except for The Killing Curse)"
56742dd7-3c93-4085-bea3-971e88d81dc2,Reducto,Reduces the target to pieces
2f177949-1f80-4663-9840-da8197411f2a,Reducio,Shrinks an enlarged object to its regular size
358ecb3c-e684-492c-b706-47cbd1eae02e,Renneverate,Awakens or revives the target
1b7a8a4c-8d4f-4001-8155-e68f1198ef72,Reparifors,Heals magical ailments like poisoning or paralysis
799f31a3-799e-411f-b67c-a64e48a5f503,Reparo,Fixes broken objects
32dbeb89-0978-4037-ab1b-413d62be02c3,Rictusempra,A charm that disarms an opponent by tickling them
c9dc8bed-5834-4001-8fa1-852690d027f2,Riddikulus,"Used to defeat a Boggart, the charm allows the scary creature to assume a comedic form, disarming it"
14c47e18-cbf3-4aec-afd3-5473d18ee7c0,Scourgify,Cleans objects
3617c34c-e650-4e3b-a13a-651d18471225,Sectumsempra,Inflicts severe lacerations and haemorrhaging on the target
53747fb8-bdab-466e-90fb-ca75c66f3dd9,Serpensortia,Conjures a live snake
43d3d53e-7ab9-4145-bda7-d96be99c5d31,Silencio,Silences the target
d5f71164-fa43-4566-b537-8852859bde01,Sonorus,Amplifies the witch or wizard's voice
9ec3258c-bc2f-4427-8440-ebea450a44aa,Spongify,Softens the target
37110a48-07e3-4fd7-9aae-ac1145161e1e,Stupefy,The Stunning spell freezes objects and renders living targets unconscious
daeb6f2a-5aff-43e1-964a-a06da7f66a3c,Tarantallegra,"Aimed at the legs, causes uncontrollable dancing movement"
4eaa6532-3ef2-428d-922f-101aee3d66ed,Unbreakable Vow,A magically binding contract that results in the death of whoever breaks it
e23728b2-f6fd-4c70-a1d2-ce602940d873,Wingardium Leviosa,"Causes an object to levitate; but remember what Hermione said: ""It's Wing-gar-dium Levi-o-sa, make the 'gar' nice and long.'"""
1 id name description
2 c76a2922-ba4c-4278-baab-44defb631236 Aberto Opens locked doors
3 06485500-d023-4799-93fd-77f2c3341aa3 Accio Summons objects
4 acbc0ae1-12e1-4813-b51e-09d22de40475 Aguamenti Summons water
5 c9d2f389-a419-4f7e-8d3d-254959638019 Alohomora Unlocks objects
6 018429a5-15d5-41af-bf8f-98a966733d77 Anapneo Clears someone's airway
7 c828685c-52d2-466d-bcc6-fbcd8376cfb5 Aparecium Reveals secret written messages
8 7fdd393c-2608-4ef3-9fd0-f691ad6f8b88 Apparate A non-verbal transportation spell that allows a witch or wizard to instantly travel on the spot and appear at another location (disapparate is the opposite)
9 73886d47-2808-4861-ae40-956f4cb56272 Ascendio Propells someone into the air
10 9a6b6854-8858-4b21-b761-12526a154597 Avada Kedavra Also known as The Killing Curse, the most evil spell in the Wizarding World; one of three Unforgivable Curses; Harry Potter is the only known witch or wizard to survive it
11 b6f20bba-c0db-4ad2-8ac6-2a375a596287 Avis Conjures a small flock of birds
12 48edfe4d-ddfc-49ac-8065-bd7e73c73778 Bat Bogey Hex - Turns the target's boogers into bats
13 6bd8d5c1-9375-4b70-8d6e-ad019176c7a2 Bombardo Creates an explosion
14 8fc19d10-3130-4b85-95c1-f2a51ba5ee3c Brackium Emendo Heals broken bones
15 f08c17fa-7bf9-49bf-9fba-a7806815bc80 Capacious Extremis Known as the Extension Charm, it's a complicated spell that can greatly expand or extend the capacity of an object or space without affecting it externally
16 55dec867-ac07-4975-94c7-090f6fd25c86 Confundo Known as the Confundus Charm, it causes confusion of the target
17 816d9fee-b78f-47b4-be46-b48626c013f9 Conjunctivitis Curse Affects the eyes and sight of a target
18 58b8727a-6c0c-469c-b91d-8ac0cc0dd2d8 Crinus Muto Changes hair color and style
19 f1e91049-e866-4f6f-9d87-d6fd366aecbf Crucio One of three Unforgivable Curses, it causes unbearable pain in the target
20 7324e645-8f41-4c83-a367-0d10a72906ff Diffindo Used to precisely cut an object
21 638072b9-b7ac-405d-914b-d9293c5f9d25 Disillusionment Charm Causes the target to take on the appearance of its surroundings
22 b7643e32-ef9c-41b8-83f2-03f6b5015e04 Disapparate A non-verbal transportation spell that allows a witch or wizard to instantly travel on the spot and leave for another location (apparate is the opposite)
23 20476c31-4f27-49ac-876f-a4c4028f1b5b Engorgio Causes rapid growth in the targeted object
24 ecb9a882-d6d7-495e-9958-a1a06902bb65 Episkey Heals minor injuries
25 317ff981-ad65-421e-92fb-5f6647d95232 Expecto patronum The Patronus Charm is a powerful projection of hope and happiness that drives away Dementors; a corpeal Patronus takes the the respective animal form of the caster, while a non-corpeal appears as a wisp of light; at 13, Harry Potter was the youngest known witch or wizard to prouduce a corpeal Patronus
26 60149246-91cf-44a5-8885-78a7acc4bf90 Erecto Allows a witch or wizard to build a structure, like a tent
27 6d8138c3-0773-4c23-b0bf-aab0e5c6fd95 Evanesco Vanishes objects
28 678474e6-fb30-4bf0-a18c-228f6b36592d Expelliarmus Forces an opponent to drop whatever's in their possession
29 31b38b6c-4775-4e20-815d-dbf302433de6 Ferula A healing charm that conjures wraps and bandages for wounds
30 37d262c9-28ab-408f-9576-acf54ce50203 Fidelius Charm A complex charm that conceals a secret into the soul of a chosen "Secret Keeper". If a location is the subject of concealment, it becomes undetectable to others
31 9121b557-0ebf-4b60-a119-9d1c5ff05dee Fiendfyre Curse Conjures destructive, enormous enchanted flames
32 de23025f-5e6a-4ec3-b827-5c526a922a89 Finite Incantatem A general counter-spell that's used to reverse or counter already cast charms
33 d536cbe5-bc0f-49e5-b063-e02c231a3988 Furnunculus Curse A jinx that causes a breakout of boils or pimples
34 7915b07a-d26e-4057-9083-e457643e57a6 Geminio Duplicates objects
35 2a942514-7a19-4f0e-9353-171c573abcba Glisseo Transforms a staircase into a slide
36 a42028b6-67f5-463b-b759-452103533227 Homenum Revelio Reveals the presence of another person
37 552cd4ee-2c67-48fd-ae20-a83773262a8a Homonculus Charm Detects anyone's true identity and location on a piece of parchment; used to create the Marauder's Map
38 2dfca7d2-ec9b-4150-b3f3-fd972a5fd1bc Immobulus Immobilises living targets
39 a49300cc-ddbf-4ff4-b8c2-e8bddbbe4118 Impedimenta A temporary jinx that slows the movement of the target
40 e5c22d31-26f1-4c88-a586-d9c09cb88c1f Incarcerous Conjures ropes
41 a53ad5be-00ee-4254-b3c0-4cec60b0c034 Imperio One of the three Unforgivable Curses, it places the target under the complete control of the caster
42 a3b34bf6-1ff7-4fe3-81ee-e617150f5da9 Impervius Makes an object waterproof
43 de048df0-b227-4376-a29b-90fe6878d950 Incendio Conjures flames
44 c4a4520b-b80d-49e8-9e5a-3ca0a7f376ca Langlock Causes the target's tongue to stick to the roof of their mouth
45 0da7cb76-dabc-46ff-b8e9-c23a4f03caea Legilimens Invading or navigating another's mind
46 723dd9c9-ee62-495b-9071-cddd16087b86 Levicorpus Levitates the target by their ankle
47 8add16ef-b4b1-4e2b-a91e-80aa194da438 Locomotor Mortis The Leg-Locker curse bounds the target's legs
48 3b7a10ce-3339-4a36-9493-292c8775e47b Lumos Illuminates the caster's wand
49 832edaca-dbff-4a57-80c7-1d8a827c8416 Morsmordre Conjures and projects Lord Voldemort's Dark Mark
50 7f4b43e0-3356-43f9-9299-15ec37cfaf76 Mucus Ad Nauseam Inflicts an extreme runny nose or cold
51 f86bbf7e-94ea-4c22-89fb-809af8214a85 Muffliato Creates a buzzing sound in the target's ears to prevent eavesdropping
52 66be613d-532c-46d8-a3e9-f5a2d9cccf0c Nox Reverses the lumos charm, extinguishing a wand's light
53 9e3c0217-652a-4763-82f8-5519026a1ea6 Obliviate Erases the target's memory
54 0af49753-c8ae-4748-87a7-b7cfc47d33a0 Obscuro Conjures a blindfold
55 67e838c1-4623-414e-9a91-12125631dbad Oculus Reparo Repairs eyeglasses
56 12251f32-af9d-408f-a652-3a4cc9602bc0 Oppugno Directs an object or person to attack a victim
57 da9eab7b-2c7c-42de-861c-fb254bd9423c Petrificus Totalus Temporarily freezes or petrifies the body of the target
58 3e5fd245-2ecf-40c4-937d-b2c2f9eee003 Periculum Conjures flares/red sparks
59 ad5685f8-6e05-49b1-a41c-d72786001d72 Piertotum Locomotor Incantation used to bring to life inanimate objects and artifacts
60 0a267162-0594-4372-a3d5-89382926f495 Protean Charm Links objects together for better communication
61 8808aa30-39f4-400c-a0e5-1dcbad657931 Protego Casts an invisible shield around the caster, protecting against spells and objects (except for The Killing Curse)
62 56742dd7-3c93-4085-bea3-971e88d81dc2 Reducto Reduces the target to pieces
63 2f177949-1f80-4663-9840-da8197411f2a Reducio Shrinks an enlarged object to its regular size
64 358ecb3c-e684-492c-b706-47cbd1eae02e Renneverate Awakens or revives the target
65 1b7a8a4c-8d4f-4001-8155-e68f1198ef72 Reparifors Heals magical ailments like poisoning or paralysis
66 799f31a3-799e-411f-b67c-a64e48a5f503 Reparo Fixes broken objects
67 32dbeb89-0978-4037-ab1b-413d62be02c3 Rictusempra A charm that disarms an opponent by tickling them
68 c9dc8bed-5834-4001-8fa1-852690d027f2 Riddikulus Used to defeat a Boggart, the charm allows the scary creature to assume a comedic form, disarming it
69 14c47e18-cbf3-4aec-afd3-5473d18ee7c0 Scourgify Cleans objects
70 3617c34c-e650-4e3b-a13a-651d18471225 Sectumsempra Inflicts severe lacerations and haemorrhaging on the target
71 53747fb8-bdab-466e-90fb-ca75c66f3dd9 Serpensortia Conjures a live snake
72 43d3d53e-7ab9-4145-bda7-d96be99c5d31 Silencio Silences the target
73 d5f71164-fa43-4566-b537-8852859bde01 Sonorus Amplifies the witch or wizard's voice
74 9ec3258c-bc2f-4427-8440-ebea450a44aa Spongify Softens the target
75 37110a48-07e3-4fd7-9aae-ac1145161e1e Stupefy The Stunning spell freezes objects and renders living targets unconscious
76 daeb6f2a-5aff-43e1-964a-a06da7f66a3c Tarantallegra Aimed at the legs, causes uncontrollable dancing movement
77 4eaa6532-3ef2-428d-922f-101aee3d66ed Unbreakable Vow A magically binding contract that results in the death of whoever breaks it
78 e23728b2-f6fd-4c70-a1d2-ce602940d873 Wingardium Leviosa Causes an object to levitate; but remember what Hermione said: "It's Wing-gar-dium Levi-o-sa, make the 'gar' nice and long.'"

View file

@ -0,0 +1,114 @@
id,forename,surname,email
fd142190-f1d7-4ce2-bdb3-6ed6b3edc020,Patricia,Stimpson,patriciastimpson@hogwarts.com
f94086b8-03ae-4457-ba2c-e624d0980869,Lavender,Brown,lavenderbrown@hogwarts.com
ecca342d-d345-4fb3-8a85-ece848ab8938,Milicent,Bullstroude,milicentbullstroude@hogwarts.com
ec714982-e604-40d4-bd4c-dc5155506957,Morag,MacDougal,moragmacdougal@hogwarts.com
eaea5eb3-48a3-41c6-9ea5-c695299bab16,Lisa,Turpin,lisaturpin@hogwarts.com
e7f4554e-8193-4b16-a40b-a8b38a0c3e57,Graham,Montague,grahammontague@hogwarts.com
e65c8acb-0dfc-4f15-bcf8-d32b78811093,Rose,Zeller,rosezeller@hogwarts.com
e4653b01-76a5-4769-a6a2-1f2efaf89cbb,Rose,Weasley,roseweasley@hogwarts.com
e32dd37c-91cd-4950-8ef2-e2ba1b87bd75,Lily,Moon,lilymoon@hogwarts.com
dcdc063e-cf3e-48fc-b777-65922e899b38,Albus,Severus,albusseverus@hogwarts.com
d9cec110-a1d0-4437-9a55-dced475dfe6d,Andrew,Kirke,andrewkirke@hogwarts.com
d5c4daa3-c726-426a-aa98-fb40f3fba816,Cedric,Diggory,cedricdiggory@hogwarts.com
cf3707ad-e816-4b54-90d0-403800a06ecd,Emma,Dobbs,emmadobbs@hogwarts.com
cb263aed-289b-43ad-8647-db54b8a5fc92,Michael,Corner,michaelcorner@hogwarts.com
c8aed011-ab8f-46df-9e8d-dde938256ea9,Miles,Bletchley,milesbletchley@hogwarts.com
c74b1fae-4793-4b47-bec2-ee652beabce2,Ritchie,Coote,ritchiecoote@hogwarts.com
c61b5c80-2c8e-404f-88ca-349a6344f35c,Cassius,Warrington,cassiuswarrington@hogwarts.com
c5acae3e-1a05-4f1d-bb83-3f8c7639d84e,Mandy,Brocklehurst,mandybrocklehurst@hogwarts.com
c3b1f9a5-b87b-48bf-b00d-95b093ea6390,Ron,Weasley,ronweasley@hogwarts.com
c29cd5f9-d2c3-4be9-ba1c-04169cdf511b,Alicia,Spinet,aliciaspinet@hogwarts.com
bff82738-5bb0-4edc-9cec-f80d1af4801f,Vicky,Frobisher,vickyfrobisher@hogwarts.com
b78e6677-8bb4-4eb7-97cb-2f86677e27ea,Adrian,Pucey,adrianpucey@hogwarts.com
b634f0a1-7b48-49b6-b039-27f947ee76fd,Angelina,Johnson,angelinajohnson@hogwarts.com
b01be346-290b-4f65-9c88-a49922e116ee,Orla,Quirke,orlaquirke@hogwarts.com
af95bd8a-dfae-45bb-bc69-533860d34129,Draco,Malfoy,dracomalfoy@hogwarts.com
ae068570-8419-4063-bf61-ba4a0ef41fe3,Laura,Madley,lauramadley@hogwarts.com
a93b80a0-987d-4148-944d-16043df95e8c,Dennis,Creevey,denniscreevey@hogwarts.com
a506574f-c8cf-46c6-a8ac-2f805c25e49e,Graham,Pritchard,grahampritchard@hogwarts.com
a3e5ea64-b103-4f47-bc26-dc08b799c668,Eddie,Carmichael,eddiecarmichael@hogwarts.com
a31ddc78-af12-4978-929c-3cc8a00a833e,Gregory,Goyle,gregorygoyle@hogwarts.com
a01f6dbb-bad5-426b-a7df-f9613fa1021d,Euan,Abercrombie,euanabercrombie@hogwarts.com
9e3f7ce4-b9a7-4244-b709-dae5c1f1d4a8,Harry,Potter,harrypotter@hogwarts.com
9c8ce8c7-ae0a-4646-920f-09c071862f10,James,Potter,jamespotter@hogwarts.com
9ba0ca6e-4fba-410d-9b5e-e20694dde413,Melinda,Bobbin,melindabobbin@hogwarts.com
9ac09267-92ea-444a-a395-28f3b0f6fe6f,Terrence,Higgs,terrencehiggs@hogwarts.com
98546bab-8d5b-4627-95f6-38e306d58a91,Owen,Cauldwell,owencauldwell@hogwarts.com
979ab773-944f-4ff8-88be-943a4bc2c18a,Lee,Jordan,leejordan@hogwarts.com
938559ee-e8e5-4963-8437-e7da04fd1b31,Marcus,Belby,marcusbelby@hogwarts.com
9055a7b1-6ac9-4363-977c-4dec78572fad,Terry,Boot,terryboot@hogwarts.com
8f9aa40b-5d7c-441e-ad32-4564ecda3b70,Cho,Chang,chochang@hogwarts.com
8f3b8796-c7b9-442e-ac02-113d48306fc7,Percy,Weasley,percyweasley@hogwarts.com
8e557e86-28d5-433f-8ac1-d2cecfeb8fb7,Colin,Creevey,colincreevey@hogwarts.com
88886e27-9ce2-416f-9dd6-56d4cd94a4fb,Geoffrey,Hooper,geoffreyhooper@hogwarts.com
861c4cde-2f0f-4796-8d8f-9492e74b2573,Luna,Lovegood,lunalovegood@hogwarts.com
7f2f6207-8998-4f98-92c2-8d02898a82eb,Scorpius,Malfoy,scorpiusmalfoy@hogwarts.com
7cc5e694-850d-4c44-830b-7154e23bb5c3,Susan,Bones,susanbones@hogwarts.com
781f1061-5413-40c7-8a35-b078e2e969b1,Barnabas,the,barnabasthe@hogwarts.com
7772cb4e-5c33-405a-970d-c05cae167917,Daphne,Greengrass,daphnegreengrass@hogwarts.com
6fa93583-b935-4228-91e0-729e6713bdab,Zacharias,Smith,zachariassmith@hogwarts.com
6c4350a9-2356-4bba-96bd-0458c12d99b5,Romilda,Vane,romildavane@hogwarts.com
69c18f6a-cd97-4218-9f2f-740393e6eb1f,Padma,Patil,padmapatil@hogwarts.com
61b6d68e-4128-408c-9f71-9ef167cb0e69,Anthony,Goldstein,anthonygoldstein@hogwarts.com
58a287c2-8c7a-485a-b095-8c6dcfc7f31d,Lucian,Bole,lucianbole@hogwarts.com
57fe29d4-312a-4711-bd9a-c320253d9176,Victoire,Weasley,victoireweasley@hogwarts.com
575fbbc2-ac94-4c58-92f6-e5d75846da91,Jack,Sloper,jacksloper@hogwarts.com
4eef1e03-cf1c-4441-9119-a6e47a61f880,Kevin,Whitby,kevinwhitby@hogwarts.com
4c7e6819-a91a-45b2-a454-f931e4a7cce3,Hermione,Granger,hermionegranger@hogwarts.com
4a0f4c3b-14dc-4a9e-a2f8-da23734f5d34,Marietta,Edgecombe,mariettaedgecombe@hogwarts.com
48880498-3903-4914-bd11-ec650d803199,Natalie,McDonald,nataliemcdonald@hogwarts.com
47aa7511-59b9-4760-9bd7-822a1103177b,Theodore,Nott,theodorenott@hogwarts.com
458828b3-82a5-4cad-a784-e23215825765,Peregrine,Derrick,peregrinederrick@hogwarts.com
42915280-ba56-4ab8-8b17-9511ba2ab093,Penelope,Clearwater,penelopeclearwater@hogwarts.com
3db6dc51-b461-4fa4-a6e4-b1ff352221c5,Neville,Longbottom,nevillelongbottom@hogwarts.com
3d629315-1dbb-4e1e-840d-ffbf45bd5894,Sally-Anne,Perks,sally-anneperks@hogwarts.com
341e65d4-6917-48d7-80b2-1f9af607e95a,Cormac,McLaggen,cormacmclaggen@hogwarts.com
34155375-c8c0-415e-873a-b6483f0cbf17,Justin,Finch-Fletchley,justinfinch-fletchley@hogwarts.com
2f8db183-e935-4b91-884f-fb9effe42ab8,Malcolm,Baddock,malcolmbaddock@hogwarts.com
2b203c7e-7b3d-4f27-8b3c-11473904da73,Hugo,Weasley,hugoweasley@hogwarts.com
2a0615de-8aa4-41e7-9504-dd875f5f3f01,George,Weasley,georgeweasley@hogwarts.com
29adbbf0-417a-4c97-8467-adb5341f75e5,Eleanor,Branstone,eleanorbranstone@hogwarts.com
28e9fe6b-3ca5-41ca-8a14-b995e0fb398b,Jimmy,Peakes,jimmypeakes@hogwarts.com
2899e63f-ed02-4152-8ace-0270a068a70d,Pansy,Parkinson,pansyparkinson@hogwarts.com
28741184-263c-4000-b011-ca7c60466ef4,Fred,Weasley,fredweasley@hogwarts.com
2832bea8-7aad-4160-a748-442f5770d586,Katie,Bell,katiebell@hogwarts.com
26bd4437-73fa-4865-afdd-2fc1456f4592,Kenneth,Towler,kennethtowler@hogwarts.com
1fab149b-52b1-4ffe-be52-4eda25d98f5d,Blaise,Zabini,blaisezabini@hogwarts.com
1cd6dc64-01a9-4379-9cfd-1a7167ba1bb1,Ginny,Weasley,ginnyweasley@hogwarts.com
14aca981-2b60-413e-8f8e-3534961b534b,Millicent,Bulstrode,millicentbulstrode@hogwarts.com
1413e1b3-2903-4a47-a2d5-e8abc5ce8014,Seamus,Finnigan,seamusfinnigan@hogwarts.com
13a54f8a-7f68-4add-a1b4-49f60c8e7bcc,Eloise,Midgen,eloisemidgen@hogwarts.com
0e53860c-7679-49e4-891e-fb92286f0e5b,Demelza,Robins,demelzarobins@hogwarts.com
0e42ecbe-27b2-4940-9b03-00182a92c415,Marcus,Flint,marcusflint@hogwarts.com
0c80d701-fa23-4126-9711-efe5f3c4789a,Ernie,Macmillan,erniemacmillan@hogwarts.com
0af82694-e24f-45ec-a8d7-5bb1199ce631,Hannah,Abbott,hannahabbott@hogwarts.com
0a13bf8e-a763-44cc-ac76-c6c53a639809,Roger,Davies,rogerdavies@hogwarts.com
09396e81-d317-499f-b330-25b90ba17d20,Oliver,Wood,oliverwood@hogwarts.com
05bd5fd1-f347-45e6-8ec0-59b7f11c2aec,Stewart,Ackerley,stewartackerley@hogwarts.com
04f9eb45-d843-4e29-a7d3-0bd49ed87f85,Vincent,Crabbe,vincentcrabbe@hogwarts.com
0201cf73-8a86-4358-b232-2abaa23f09af,Parvati,Patil,parvatipatil@hogwarts.com
ca3827f0-375a-4891-aaa5-f5e8a5bad225,Minerva,McGonagall,minervamcgonagall@hogwarts.com
3569d265-bd27-44d8-88e8-82fb0a848374,Severus,Snape,severussnape@hogwarts.com
36bfefd0-e0bb-4d11-be98-d1ef6117a77a,Rubeus,Hagrid,rubeushagrid@hogwarts.com
b8f9095b-9de6-4d7d-83e0-4391af8f22e4,Remus,Lupin,remuslupin@hogwarts.com
2fb675cd-5505-4c8e-a54e-579e73bf4174,Horace,Slughorn,horaceslughorn@hogwarts.com
d58e7249-19d1-40bd-a43f-1da0497fe8aa,Dolores,Umbridge,doloresumbridge@hogwarts.com
b0620914-858d-46fc-8e6d-033c565e138b,Mrs,Norris,mrsnorris@hogwarts.com
2b82cfb8-0440-4a57-a030-6d75a40c0d98,Argus,Filch,argusfilch@hogwarts.com
b415c867-1cff-455e-b194-748662ac2cca,Albus,Dumbledore,albusdumbledore@hogwarts.com
e9457467-d10a-4893-afa9-19f9602b218a,Madam,Pomfrey,madampomfrey@hogwarts.com
ba19be27-178b-4594-95b7-51ba0e3ba1dd,Quirinus,Quirrel,quirinusquirrel@hogwarts.com
e8694719-a975-48fb-9523-f4cade1c38aa,Pomona,Sprout,pomonasprout@hogwarts.com
6ea188f3-d95c-407c-ab00-a0bec8678a71,Cuthbert,Binns,cuthbertbinns@hogwarts.com
a61e0783-7914-4f8d-a800-c409c06315cf,Filius,Flitwick,filiusflitwick@hogwarts.com
0a81c4f9-b80d-45a7-a4fd-9191453815a1,Madam,Hooch,madamhooch@hogwarts.com
3d687c4d-852e-470f-bac5-5a02758b1f8f,Gilderoy,Lockhart,gilderoylockhart@hogwarts.com
cdec9b95-c7a5-4623-ad12-6fa76d168588,Madame,Pince,madamepince@hogwarts.com
8ea29415-012d-4781-ba5f-d0de63a05abe,Sybill,Trelawney,sybilltrelawney@hogwarts.com
58f2cf41-392c-4e84-b441-dbbce585f78d,Septima,Vector,septimavector@hogwarts.com
99d3ce6b-6a45-495a-a7c6-132203697d45,Aurora,Sinistra,aurorasinistra@hogwarts.com
41ebe856-f0f4-4c77-8795-4735d3a87f3d,Alastor,Moody,alastormoody@hogwarts.com
b48c5b8a-4066-4c24-ba26-7677f5ed2b6f,Wilhelmina,Grubbly-Plank,wilhelminagrubbly-plank@hogwarts.com
c4e73590-3ee2-4125-87fb-692dd991819b,Galatea,Merrythought,galateamerrythought@hogwarts.com
61d78dce-890b-4f02-844f-b41d66553802,Charity,Burbage,charityburbage@hogwarts.com
1 id forename surname email
2 fd142190-f1d7-4ce2-bdb3-6ed6b3edc020 Patricia Stimpson patriciastimpson@hogwarts.com
3 f94086b8-03ae-4457-ba2c-e624d0980869 Lavender Brown lavenderbrown@hogwarts.com
4 ecca342d-d345-4fb3-8a85-ece848ab8938 Milicent Bullstroude milicentbullstroude@hogwarts.com
5 ec714982-e604-40d4-bd4c-dc5155506957 Morag MacDougal moragmacdougal@hogwarts.com
6 eaea5eb3-48a3-41c6-9ea5-c695299bab16 Lisa Turpin lisaturpin@hogwarts.com
7 e7f4554e-8193-4b16-a40b-a8b38a0c3e57 Graham Montague grahammontague@hogwarts.com
8 e65c8acb-0dfc-4f15-bcf8-d32b78811093 Rose Zeller rosezeller@hogwarts.com
9 e4653b01-76a5-4769-a6a2-1f2efaf89cbb Rose Weasley roseweasley@hogwarts.com
10 e32dd37c-91cd-4950-8ef2-e2ba1b87bd75 Lily Moon lilymoon@hogwarts.com
11 dcdc063e-cf3e-48fc-b777-65922e899b38 Albus Severus albusseverus@hogwarts.com
12 d9cec110-a1d0-4437-9a55-dced475dfe6d Andrew Kirke andrewkirke@hogwarts.com
13 d5c4daa3-c726-426a-aa98-fb40f3fba816 Cedric Diggory cedricdiggory@hogwarts.com
14 cf3707ad-e816-4b54-90d0-403800a06ecd Emma Dobbs emmadobbs@hogwarts.com
15 cb263aed-289b-43ad-8647-db54b8a5fc92 Michael Corner michaelcorner@hogwarts.com
16 c8aed011-ab8f-46df-9e8d-dde938256ea9 Miles Bletchley milesbletchley@hogwarts.com
17 c74b1fae-4793-4b47-bec2-ee652beabce2 Ritchie Coote ritchiecoote@hogwarts.com
18 c61b5c80-2c8e-404f-88ca-349a6344f35c Cassius Warrington cassiuswarrington@hogwarts.com
19 c5acae3e-1a05-4f1d-bb83-3f8c7639d84e Mandy Brocklehurst mandybrocklehurst@hogwarts.com
20 c3b1f9a5-b87b-48bf-b00d-95b093ea6390 Ron Weasley ronweasley@hogwarts.com
21 c29cd5f9-d2c3-4be9-ba1c-04169cdf511b Alicia Spinet aliciaspinet@hogwarts.com
22 bff82738-5bb0-4edc-9cec-f80d1af4801f Vicky Frobisher vickyfrobisher@hogwarts.com
23 b78e6677-8bb4-4eb7-97cb-2f86677e27ea Adrian Pucey adrianpucey@hogwarts.com
24 b634f0a1-7b48-49b6-b039-27f947ee76fd Angelina Johnson angelinajohnson@hogwarts.com
25 b01be346-290b-4f65-9c88-a49922e116ee Orla Quirke orlaquirke@hogwarts.com
26 af95bd8a-dfae-45bb-bc69-533860d34129 Draco Malfoy dracomalfoy@hogwarts.com
27 ae068570-8419-4063-bf61-ba4a0ef41fe3 Laura Madley lauramadley@hogwarts.com
28 a93b80a0-987d-4148-944d-16043df95e8c Dennis Creevey denniscreevey@hogwarts.com
29 a506574f-c8cf-46c6-a8ac-2f805c25e49e Graham Pritchard grahampritchard@hogwarts.com
30 a3e5ea64-b103-4f47-bc26-dc08b799c668 Eddie Carmichael eddiecarmichael@hogwarts.com
31 a31ddc78-af12-4978-929c-3cc8a00a833e Gregory Goyle gregorygoyle@hogwarts.com
32 a01f6dbb-bad5-426b-a7df-f9613fa1021d Euan Abercrombie euanabercrombie@hogwarts.com
33 9e3f7ce4-b9a7-4244-b709-dae5c1f1d4a8 Harry Potter harrypotter@hogwarts.com
34 9c8ce8c7-ae0a-4646-920f-09c071862f10 James Potter jamespotter@hogwarts.com
35 9ba0ca6e-4fba-410d-9b5e-e20694dde413 Melinda Bobbin melindabobbin@hogwarts.com
36 9ac09267-92ea-444a-a395-28f3b0f6fe6f Terrence Higgs terrencehiggs@hogwarts.com
37 98546bab-8d5b-4627-95f6-38e306d58a91 Owen Cauldwell owencauldwell@hogwarts.com
38 979ab773-944f-4ff8-88be-943a4bc2c18a Lee Jordan leejordan@hogwarts.com
39 938559ee-e8e5-4963-8437-e7da04fd1b31 Marcus Belby marcusbelby@hogwarts.com
40 9055a7b1-6ac9-4363-977c-4dec78572fad Terry Boot terryboot@hogwarts.com
41 8f9aa40b-5d7c-441e-ad32-4564ecda3b70 Cho Chang chochang@hogwarts.com
42 8f3b8796-c7b9-442e-ac02-113d48306fc7 Percy Weasley percyweasley@hogwarts.com
43 8e557e86-28d5-433f-8ac1-d2cecfeb8fb7 Colin Creevey colincreevey@hogwarts.com
44 88886e27-9ce2-416f-9dd6-56d4cd94a4fb Geoffrey Hooper geoffreyhooper@hogwarts.com
45 861c4cde-2f0f-4796-8d8f-9492e74b2573 Luna Lovegood lunalovegood@hogwarts.com
46 7f2f6207-8998-4f98-92c2-8d02898a82eb Scorpius Malfoy scorpiusmalfoy@hogwarts.com
47 7cc5e694-850d-4c44-830b-7154e23bb5c3 Susan Bones susanbones@hogwarts.com
48 781f1061-5413-40c7-8a35-b078e2e969b1 Barnabas the barnabasthe@hogwarts.com
49 7772cb4e-5c33-405a-970d-c05cae167917 Daphne Greengrass daphnegreengrass@hogwarts.com
50 6fa93583-b935-4228-91e0-729e6713bdab Zacharias Smith zachariassmith@hogwarts.com
51 6c4350a9-2356-4bba-96bd-0458c12d99b5 Romilda Vane romildavane@hogwarts.com
52 69c18f6a-cd97-4218-9f2f-740393e6eb1f Padma Patil padmapatil@hogwarts.com
53 61b6d68e-4128-408c-9f71-9ef167cb0e69 Anthony Goldstein anthonygoldstein@hogwarts.com
54 58a287c2-8c7a-485a-b095-8c6dcfc7f31d Lucian Bole lucianbole@hogwarts.com
55 57fe29d4-312a-4711-bd9a-c320253d9176 Victoire Weasley victoireweasley@hogwarts.com
56 575fbbc2-ac94-4c58-92f6-e5d75846da91 Jack Sloper jacksloper@hogwarts.com
57 4eef1e03-cf1c-4441-9119-a6e47a61f880 Kevin Whitby kevinwhitby@hogwarts.com
58 4c7e6819-a91a-45b2-a454-f931e4a7cce3 Hermione Granger hermionegranger@hogwarts.com
59 4a0f4c3b-14dc-4a9e-a2f8-da23734f5d34 Marietta Edgecombe mariettaedgecombe@hogwarts.com
60 48880498-3903-4914-bd11-ec650d803199 Natalie McDonald nataliemcdonald@hogwarts.com
61 47aa7511-59b9-4760-9bd7-822a1103177b Theodore Nott theodorenott@hogwarts.com
62 458828b3-82a5-4cad-a784-e23215825765 Peregrine Derrick peregrinederrick@hogwarts.com
63 42915280-ba56-4ab8-8b17-9511ba2ab093 Penelope Clearwater penelopeclearwater@hogwarts.com
64 3db6dc51-b461-4fa4-a6e4-b1ff352221c5 Neville Longbottom nevillelongbottom@hogwarts.com
65 3d629315-1dbb-4e1e-840d-ffbf45bd5894 Sally-Anne Perks sally-anneperks@hogwarts.com
66 341e65d4-6917-48d7-80b2-1f9af607e95a Cormac McLaggen cormacmclaggen@hogwarts.com
67 34155375-c8c0-415e-873a-b6483f0cbf17 Justin Finch-Fletchley justinfinch-fletchley@hogwarts.com
68 2f8db183-e935-4b91-884f-fb9effe42ab8 Malcolm Baddock malcolmbaddock@hogwarts.com
69 2b203c7e-7b3d-4f27-8b3c-11473904da73 Hugo Weasley hugoweasley@hogwarts.com
70 2a0615de-8aa4-41e7-9504-dd875f5f3f01 George Weasley georgeweasley@hogwarts.com
71 29adbbf0-417a-4c97-8467-adb5341f75e5 Eleanor Branstone eleanorbranstone@hogwarts.com
72 28e9fe6b-3ca5-41ca-8a14-b995e0fb398b Jimmy Peakes jimmypeakes@hogwarts.com
73 2899e63f-ed02-4152-8ace-0270a068a70d Pansy Parkinson pansyparkinson@hogwarts.com
74 28741184-263c-4000-b011-ca7c60466ef4 Fred Weasley fredweasley@hogwarts.com
75 2832bea8-7aad-4160-a748-442f5770d586 Katie Bell katiebell@hogwarts.com
76 26bd4437-73fa-4865-afdd-2fc1456f4592 Kenneth Towler kennethtowler@hogwarts.com
77 1fab149b-52b1-4ffe-be52-4eda25d98f5d Blaise Zabini blaisezabini@hogwarts.com
78 1cd6dc64-01a9-4379-9cfd-1a7167ba1bb1 Ginny Weasley ginnyweasley@hogwarts.com
79 14aca981-2b60-413e-8f8e-3534961b534b Millicent Bulstrode millicentbulstrode@hogwarts.com
80 1413e1b3-2903-4a47-a2d5-e8abc5ce8014 Seamus Finnigan seamusfinnigan@hogwarts.com
81 13a54f8a-7f68-4add-a1b4-49f60c8e7bcc Eloise Midgen eloisemidgen@hogwarts.com
82 0e53860c-7679-49e4-891e-fb92286f0e5b Demelza Robins demelzarobins@hogwarts.com
83 0e42ecbe-27b2-4940-9b03-00182a92c415 Marcus Flint marcusflint@hogwarts.com
84 0c80d701-fa23-4126-9711-efe5f3c4789a Ernie Macmillan erniemacmillan@hogwarts.com
85 0af82694-e24f-45ec-a8d7-5bb1199ce631 Hannah Abbott hannahabbott@hogwarts.com
86 0a13bf8e-a763-44cc-ac76-c6c53a639809 Roger Davies rogerdavies@hogwarts.com
87 09396e81-d317-499f-b330-25b90ba17d20 Oliver Wood oliverwood@hogwarts.com
88 05bd5fd1-f347-45e6-8ec0-59b7f11c2aec Stewart Ackerley stewartackerley@hogwarts.com
89 04f9eb45-d843-4e29-a7d3-0bd49ed87f85 Vincent Crabbe vincentcrabbe@hogwarts.com
90 0201cf73-8a86-4358-b232-2abaa23f09af Parvati Patil parvatipatil@hogwarts.com
91 ca3827f0-375a-4891-aaa5-f5e8a5bad225 Minerva McGonagall minervamcgonagall@hogwarts.com
92 3569d265-bd27-44d8-88e8-82fb0a848374 Severus Snape severussnape@hogwarts.com
93 36bfefd0-e0bb-4d11-be98-d1ef6117a77a Rubeus Hagrid rubeushagrid@hogwarts.com
94 b8f9095b-9de6-4d7d-83e0-4391af8f22e4 Remus Lupin remuslupin@hogwarts.com
95 2fb675cd-5505-4c8e-a54e-579e73bf4174 Horace Slughorn horaceslughorn@hogwarts.com
96 d58e7249-19d1-40bd-a43f-1da0497fe8aa Dolores Umbridge doloresumbridge@hogwarts.com
97 b0620914-858d-46fc-8e6d-033c565e138b Mrs Norris mrsnorris@hogwarts.com
98 2b82cfb8-0440-4a57-a030-6d75a40c0d98 Argus Filch argusfilch@hogwarts.com
99 b415c867-1cff-455e-b194-748662ac2cca Albus Dumbledore albusdumbledore@hogwarts.com
100 e9457467-d10a-4893-afa9-19f9602b218a Madam Pomfrey madampomfrey@hogwarts.com
101 ba19be27-178b-4594-95b7-51ba0e3ba1dd Quirinus Quirrel quirinusquirrel@hogwarts.com
102 e8694719-a975-48fb-9523-f4cade1c38aa Pomona Sprout pomonasprout@hogwarts.com
103 6ea188f3-d95c-407c-ab00-a0bec8678a71 Cuthbert Binns cuthbertbinns@hogwarts.com
104 a61e0783-7914-4f8d-a800-c409c06315cf Filius Flitwick filiusflitwick@hogwarts.com
105 0a81c4f9-b80d-45a7-a4fd-9191453815a1 Madam Hooch madamhooch@hogwarts.com
106 3d687c4d-852e-470f-bac5-5a02758b1f8f Gilderoy Lockhart gilderoylockhart@hogwarts.com
107 cdec9b95-c7a5-4623-ad12-6fa76d168588 Madame Pince madamepince@hogwarts.com
108 8ea29415-012d-4781-ba5f-d0de63a05abe Sybill Trelawney sybilltrelawney@hogwarts.com
109 58f2cf41-392c-4e84-b441-dbbce585f78d Septima Vector septimavector@hogwarts.com
110 99d3ce6b-6a45-495a-a7c6-132203697d45 Aurora Sinistra aurorasinistra@hogwarts.com
111 41ebe856-f0f4-4c77-8795-4735d3a87f3d Alastor Moody alastormoody@hogwarts.com
112 b48c5b8a-4066-4c24-ba26-7677f5ed2b6f Wilhelmina Grubbly-Plank wilhelminagrubbly-plank@hogwarts.com
113 c4e73590-3ee2-4125-87fb-692dd991819b Galatea Merrythought galateamerrythought@hogwarts.com
114 61d78dce-890b-4f02-844f-b41d66553802 Charity Burbage charityburbage@hogwarts.com

8
apps/api/package.json Normal file
View file

@ -0,0 +1,8 @@
{
"name": "api",
"version": "0.0.0",
"scripts": {
"dev": ".\\.venv\\Scripts\\python run.py",
"generate:requirements": "poetry export --without-hashes --format=requirements.txt > requirements.txt"
}
}

1789
apps/api/poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

3
apps/api/poetry.toml Normal file
View file

@ -0,0 +1,3 @@
[virtualenvs]
in-project = true
create = true

24
apps/api/pyproject.toml Normal file
View file

@ -0,0 +1,24 @@
[tool.poetry]
name = "api"
version = "0.1.0"
description = ""
authors = ["cording12 <joncording12@gmail.com>"]
[tool.poetry.dependencies]
python = "^3.9"
fastapi = "^0.109.2"
uvicorn = "^0.27.1"
email-validator = "^2.1.0"
pydantic-settings = "^2.2.1"
python-dotenv = "^1.0.1"
supabase-py-async = "^2.5.5"
[tool.poetry.dev-dependencies]
isort = "^5.10.1"
black = "^22.6.0"
pytest = "^8.0.1"
pylint-pydantic = "^0.3.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

54
apps/api/requirements.txt Normal file
View file

@ -0,0 +1,54 @@
aiohttp==3.9.3; python_version >= "3.9" and python_version < "4.0"
aiosignal==1.3.1; python_version >= "3.9" and python_version < "4.0"
annotated-types==0.6.0; python_version >= "3.8"
anyio==4.3.0; python_version >= "3.9" and python_version < "4.0"
argcomplete==3.2.3; python_version >= "3.9" and python_version < "4.0"
async-timeout==4.0.3; python_version >= "3.9" and python_version < "3.11"
attrs==23.2.0; python_version >= "3.9" and python_version < "4.0"
certifi==2024.2.2; python_version >= "3.9" and python_version < "4.0"
charset-normalizer==3.3.2; python_version >= "3.9" and python_version < "4.0" and python_full_version >= "3.7.0"
click==8.1.7; python_version >= "3.8"
colorama==0.4.6; python_version >= "3.9" and python_full_version < "3.0.0" and platform_system == "Windows" and python_version < "4.0" or platform_system == "Windows" and python_version >= "3.9" and python_full_version >= "3.7.0" and python_version < "4.0"
commitizen==3.18.4; python_version >= "3.9" and python_version < "4.0"
decli==0.6.1; python_version >= "3.9" and python_version < "4.0"
deprecation==2.1.0; python_version >= "3.9" and python_version < "4.0"
dnspython==2.6.1; python_version >= "3.8"
email-validator==2.1.1; python_version >= "3.8"
exceptiongroup==1.2.0; python_version < "3.11" and python_version >= "3.8"
fastapi==0.109.2; python_version >= "3.8"
frozenlist==1.4.1; python_version >= "3.9" and python_version < "4.0"
gotrue==2.4.1; python_version >= "3.9" and python_version < "4.0"
h11==0.14.0; python_version >= "3.9" and python_version < "4.0"
httpcore==1.0.4; python_version >= "3.9" and python_version < "4.0"
httpx==0.25.2; python_version >= "3.9" and python_version < "4.0"
idna==3.6; python_version >= "3.9" and python_version < "4.0"
importlib-metadata==7.0.2; python_version >= "3.9" and python_version < "4.0"
jinja2==3.1.3; python_version >= "3.9" and python_version < "4.0"
markupsafe==2.1.5; python_version >= "3.9" and python_version < "4.0"
multidict==6.0.5; python_version >= "3.9" and python_version < "4.0"
packaging==24.0; python_version >= "3.9" and python_version < "4.0"
postgrest==0.16.1; python_version >= "3.9" and python_version < "4.0"
prompt-toolkit==3.0.36; python_version >= "3.9" and python_version < "4.0" and python_full_version >= "3.6.2"
pydantic-core==2.16.3; python_version >= "3.8"
pydantic-settings==2.2.1; python_version >= "3.8"
pydantic==2.6.4; python_version >= "3.9" and python_version < "4.0"
python-dateutil==2.9.0.post0; python_version >= "3.9" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.9" and python_version < "4.0" and python_full_version >= "3.3.0"
python-dotenv==1.0.1; python_version >= "3.8"
pyyaml==6.0.1; python_version >= "3.9" and python_version < "4.0"
questionary==2.0.1; python_version >= "3.9" and python_version < "4.0"
realtime==1.0.2; python_version >= "3.9" and python_version < "4.0"
six==1.16.0; python_version >= "3.9" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.9" and python_version < "4.0" and python_full_version >= "3.3.0"
sniffio==1.3.1; python_version >= "3.9" and python_version < "4.0"
starlette==0.36.3; python_version >= "3.8"
storage3==0.7.3; python_version >= "3.9" and python_version < "4.0"
strenum==0.4.15; python_version >= "3.9" and python_version < "4.0"
supabase-py-async==2.5.5; python_version >= "3.9" and python_version < "4.0"
supafunc==0.4.0; python_version >= "3.9" and python_version < "4.0"
termcolor==2.4.0; python_version >= "3.9" and python_version < "4.0"
tomlkit==0.12.4; python_version >= "3.9" and python_version < "4.0"
typing-extensions==4.10.0; python_version < "3.10" and python_version >= "3.9"
uvicorn==0.27.1; python_version >= "3.8"
wcwidth==0.2.13; python_version >= "3.9" and python_version < "4.0" and python_full_version >= "3.6.2"
websockets==11.0.3; python_version >= "3.9" and python_version < "4.0"
yarl==1.9.4; python_version >= "3.9" and python_version < "4.0"
zipp==3.18.1; python_version >= "3.9" and python_version < "4.0"

4
apps/api/run.py Normal file
View file

@ -0,0 +1,4 @@
import uvicorn
if __name__ == "__main__":
uvicorn.run("src.main:app", reload=True)

1
apps/api/src/__init__.py Normal file
View file

@ -0,0 +1 @@
__version__ = "0.1.0"

View file

View file

View file

@ -0,0 +1,6 @@
from fastapi import APIRouter
from src.api.api_v1.endpoints import users, spells
api_router = APIRouter()
api_router.include_router(users.router, prefix="/users", tags=["users"], responses={404: {"description": "Not found"}})
api_router.include_router(spells.router, prefix="/spells", tags=["spells"], responses={404: {"description": "Not found"}})

View file

@ -0,0 +1,63 @@
from typing import Literal, Optional, Union
from fastapi import APIRouter, HTTPException
from src.api.deps import SessionDep
from src.crud import spell
from src.schemas import Spell, SpellSearchResults
router = APIRouter()
@router.get("/get/", status_code=200, response_model=Spell)
async def get_spell(session: SessionDep, spell_id: str) -> Spell:
"""Returns a spell from a spell_id.
**Returns:**
- spell: spell object.
"""
return await spell.get(session, id=spell_id)
@router.get("/get-all/", status_code=200, response_model=list[Spell])
async def get_all_spells(session: SessionDep) -> list[Spell]:
"""Returns a list of all spells.
**Returns:**
- list[spell]: List of all spells.
"""
return await spell.get_all(session)
@router.get("/search/", status_code=200, response_model=SpellSearchResults)
async def search_spells(
session: SessionDep,
search_on: Literal["id", "name", "description"] = "name",
keyword: Optional[Union[str, int]] = None,
max_results: Optional[int] = 10,
) -> SpellSearchResults:
"""
Search for spells based on a keyword and return the top `max_results` items.
**Args:**
- search_on (str, optional): The field to perform the search on. Defaults to "name".
- keyword (str, optional): The keyword to search for. Defaults to None.
- max_results (int, optional): The maximum number of search results to return. Defaults to 10.
**Returns:**
- SpellSearchResults: Object containing a list of the top `max_results` items that match the keyword.
"""
if not keyword:
results = await spell.get_all(session)
return SpellSearchResults(results=results)
results = await spell.search_all(
session, field=search_on, search_value=keyword, max_results=max_results
)
if not results:
raise HTTPException(
status_code=404, detail="No spells found matching the search criteria"
)
return SpellSearchResults(results=results)

View file

@ -0,0 +1,76 @@
from typing import Literal, Optional, Union
from fastapi import APIRouter, HTTPException
from src.api.deps import SessionDep
from src.crud import user
from src.schemas import User, UserCreate, UserSearchResults
router = APIRouter()
@router.get("/get/", status_code=200, response_model=User)
async def get_user(session: SessionDep, user_id: str) -> User:
"""Returns a user from a user_id.
**Returns:**
- User: User object.
"""
return await user.get(session, id=user_id)
@router.get("/get-all/", status_code=200, response_model=list[User])
async def get_all_users(session: SessionDep) -> list[User]:
"""Returns a list of all users.
**Returns:**
- list[User]: List of all users.
"""
return await user.get_all(session)
@router.get("/search/", status_code=200, response_model=UserSearchResults)
async def search_users(
session: SessionDep,
search_on: Literal["id", "email", "forename", "surname"] = "email",
keyword: Optional[Union[str, int]] = None,
max_results: Optional[int] = 10,
) -> UserSearchResults:
"""
Search for users based on a keyword and return the top `max_results` items.
**Args:**
- keyword (str, optional): The keyword to search for. Defaults to None.
- max_results (int, optional): The maximum number of search results to return. Defaults to 10.
- search_on (str, optional): The field to perform the search on. Defaults to "email".
**Returns:**
- UserSearchResults: Object containing a list of the top `max_results` items that match the keyword.
"""
if not keyword:
results = await user.get_all(session)
return UserSearchResults(results=results)
results = await user.search_all(
session, field=search_on, search_value=keyword, max_results=max_results
)
if not results:
raise HTTPException(
status_code=404, detail="No users found matching the search criteria"
)
return UserSearchResults(results=results)
@router.post("/create", status_code=201, response_model=User)
async def create_user(user_in: UserCreate, session: SessionDep) -> User:
"""Craete a new user.
**Args:**
- user_in (UserCreate): JSON of the user to create. Forename, surname and email. Email must be unique.
**Returns:**
- User: User object
"""
return await user.create(session, obj_in=user_in)

30
apps/api/src/api/deps.py Normal file
View file

@ -0,0 +1,30 @@
from typing import Annotated
from fastapi import Depends, HTTPException
from supabase_py_async import AsyncClient, create_client
from supabase_py_async.lib.client_options import ClientOptions
from src.config import settings
async def get_db() -> AsyncClient:
client: AsyncClient | None = None
try:
client = await create_client(
settings.DB_URL,
settings.DB_API_KEY,
options=ClientOptions(
postgrest_client_timeout=10, storage_client_timeout=10
),
)
# client = await client.auth.sign_in_with_password(
# {"email": settings.DB_EMAIL, "password": settings.DB_PASSWORD}
# )
yield client
except Exception as e:
print(e)
raise
SessionDep = Annotated[AsyncClient, Depends(get_db)]

30
apps/api/src/config.py Normal file
View file

@ -0,0 +1,30 @@
import os
from dotenv import load_dotenv
from pydantic_settings import BaseSettings, SettingsConfigDict
load_dotenv()
# If the environment is Gitpod, the root path will be the workspace cluster host
# If not using gitpod, you can delete this if statement, but keep the else clause
if os.getenv("USER") == "gitpod":
ROOT_PATH = f"https://8000-cording12-nextfastturbo-qqfo0frc496.{os.getenv('GITPOD_WORKSPACE_CLUSTER_HOST')}"
else:
# Otherwise, the root path will be the local host. ROOT_PATH is an env var configured in Vercel deployment.
# The value for production is equal to the root path of the deployment URL in Vercel.
ROOT_PATH = os.getenv("ROOT_PATH", "http://127.0.0.1:8000")
class Settings(BaseSettings):
PROJECT_NAME: str = "FastAPI App"
PROJECT_DESCRIPTION: str = "A simple FastAPI app"
DB_URL: str = os.getenv("DB_URL")
DB_API_KEY: str = os.getenv("DB_API_KEY")
DB_EMAIL: str = os.getenv("DB_EMAIL")
DB_PASSWORD: str = os.getenv("DB_PASSWORD")
model_config = SettingsConfigDict(env_file=".env")
API_VERSION: str = "/api/v1"
ROOT: str = ROOT_PATH
settings = Settings()

View file

@ -0,0 +1,2 @@
from .crud_spell import spell
from .crud_user import user

74
apps/api/src/crud/base.py Normal file
View file

@ -0,0 +1,74 @@
from typing import Generic, Optional, TypeVar
from supabase_py_async import AsyncClient
from src.schemas.base import CreateBase, ResponseBase, UpdateBase
ModelType = TypeVar("ModelType", bound=ResponseBase)
CreateSchemaType = TypeVar("CreateSchemaType", bound=CreateBase)
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=UpdateBase)
class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
def __init__(self, model: type[ModelType]):
"""CRUD object with default methods to do CRUD ops
Args:
model (type[ModelType]): Model class type
"""
self.model = model
async def get(self, db: AsyncClient, *, id: str) -> Optional[ModelType]:
"""get by table_name by id"""
data, count = (
await db.table(self.model.table_name).select("*").eq("id", id).execute()
)
_, got = data
return self.model(**got[0]) if got else None
async def get_all(self, db: AsyncClient) -> list[ModelType]:
"""get all by table_name"""
data, count = await db.table(self.model.table_name).select("*").execute()
_, got = data
return [self.model(**item) for item in got]
async def search_all(
self, db: AsyncClient, *, field: str, search_value: str, max_results: int
) -> list[ModelType]:
"""search all by table_name"""
data, count = (
await db.table(self.model.table_name)
.select("*")
.ilike(field, f"%{search_value}%")
.limit(max_results)
.execute()
)
_, got = data
return [self.model(**item) for item in got]
async def create(self, db: AsyncClient, *, obj_in: CreateSchemaType) -> ModelType:
"""create by CreateSchemaType"""
data, count = (
await db.table(self.model.table_name).insert(obj_in.model_dump()).execute()
)
_, created = data
return self.model(**created[0])
async def update(self, db: AsyncClient, *, obj_in: UpdateSchemaType) -> ModelType:
"""update by UpdateSchemaType"""
data, count = (
await db.table(self.model.table_name)
.update(obj_in.model_dump())
.eq("id", obj_in.id)
.execute()
)
_, updated = data
return self.model(**updated[0])
async def delete(self, db: AsyncClient, *, id: str) -> ModelType:
"""remove by UpdateSchemaType"""
data, count = (
await db.table(self.model.table_name).delete().eq("id", id).execute()
)
_, deleted = data
return self.model(**deleted[0])

View file

@ -0,0 +1,43 @@
from typing import Optional
from fastapi import HTTPException
from supabase_py_async import AsyncClient
from src.crud.base import CRUDBase
from src.schemas import Spell, SpellCreate, SpellUpdate
class CRUDSpell(CRUDBase[Spell, SpellCreate, SpellUpdate]):
async def get(self, db: AsyncClient, *, id: str) -> Optional[Spell]:
try:
return await super().get(db, id=id)
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"{e.code}: Spell not found. {e.details}",
)
async def get_all(self, db: AsyncClient) -> list[Spell]:
try:
return await super().get_all(db)
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"An error occurred while fetching spells. {e}",
)
async def search_all(
self, db: AsyncClient, *, field: str, search_value: str, max_results: int
) -> list[Spell]:
try:
return await super().search_all(
db, field=field, search_value=search_value, max_results=max_results
)
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"An error occurred while searching for users. {e}",
)
spell = CRUDSpell(Spell)

View file

@ -0,0 +1,58 @@
from typing import Optional
from fastapi import HTTPException
from supabase_py_async import AsyncClient
from src.crud.base import CRUDBase
from src.schemas import User, UserCreate, UserUpdate
class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
async def create(self, db: AsyncClient, *, obj_in: UserCreate) -> User:
try:
return await super().create(db, obj_in=obj_in)
except Exception as e:
raise HTTPException(
status_code=400,
detail=f"{e.code}: Failed to create user. {e.details}",
)
async def get(self, db: AsyncClient, *, id: str) -> Optional[User]:
try:
return await super().get(db, id=id)
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"{e.code}: User not found. {e.details}",
)
async def get_all(self, db: AsyncClient) -> list[User]:
try:
return await super().get_all(db)
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"An error occurred while fetching users. {e}",
)
async def search_all(
self, db: AsyncClient, *, field: str, search_value: str, max_results: int
) -> list[User]:
try:
return await super().search_all(
db, field=field, search_value=search_value, max_results=max_results
)
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"An error occurred while searching for users. {e}",
)
async def update(self, db: AsyncClient, *, obj_in: UserUpdate) -> User:
return await super().update(db, obj_in=obj_in)
async def delete(self, db: AsyncClient, *, id: str) -> User:
return await super().delete(db, id=id)
user = CRUDUser(User)

51
apps/api/src/main.py Normal file
View file

@ -0,0 +1,51 @@
from fastapi import APIRouter, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.routing import APIRoute
from src.api.api_v1.api import api_router
from src.config import settings
info_router = APIRouter()
@info_router.get("/", status_code=200, include_in_schema=False)
async def info():
return [{"Status": "API Running"}]
def custom_generate_unique_id(route: APIRoute):
"""Generates a custom ID when using the TypeScript Generator Client
Args:
route (APIRoute): The route to be customised
Returns:
str: tag-route_name, e.g. items-CreateItem
"""
return f"{route.tags[0]}-{route.name}"
def get_application():
_app = FastAPI(
title=settings.PROJECT_NAME,
description=settings.PROJECT_DESCRIPTION,
generate_unique_id_function=custom_generate_unique_id,
root_path=settings.ROOT,
root_path_in_servers=True,
)
_app.include_router(api_router, prefix=settings.API_VERSION)
_app.include_router(info_router, tags=[""])
_app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
return _app
app = get_application()

View file

@ -0,0 +1,2 @@
from .spell import Spell, SpellCreate, SpellSearchResults, SpellUpdate
from .user import User, UserCreate, UserSearchResults, UserUpdate

View file

@ -0,0 +1,40 @@
from typing import ClassVar
from pydantic import BaseModel, ConfigDict
# Shared properties
# class CRUDBaseModel(BaseModel):
# # where the data
# table_name: str
# Properties to receive on item creation
# in
class CreateBase(BaseModel):
# inherent to add more properties for creating
pass
# Properties to receive on item update
# in
class UpdateBase(BaseModel):
# inherent to add more properties for updating
id: str
# response
# Properties shared by models stored in DB
class InDBBase(BaseModel):
id: str
user_id: str
created_at: str
# Properties to return to client
# crud model
# out
class ResponseBase(InDBBase):
# inherent to add more properties for responding
table_name: ClassVar[str] = "ResponseBase".lower()
Config: ClassVar[ConfigDict] = ConfigDict(
extra="ignore", arbitrary_types_allowed=True
)

View file

@ -0,0 +1,26 @@
from typing import ClassVar, Sequence
from pydantic import BaseModel
class Spell(BaseModel):
id: str
name: str
description: str
table_name: ClassVar[str] = "spells"
class SpellCreate(BaseModel):
id: str
name: str
description: str
class SpellUpdate(BaseModel):
id: str
name: str
description: str
class SpellSearchResults(BaseModel):
results: Sequence[Spell]

View file

@ -0,0 +1,31 @@
from typing import ClassVar, Sequence
from pydantic import BaseModel, EmailStr
class User(BaseModel):
id: str
forename: str
surname: str
email: EmailStr
table_name: ClassVar[str] = "user"
class UserCreate(BaseModel):
forename: str
surname: str
email: EmailStr
class UserUpdate(BaseModel):
forename: str
surname: str
email: EmailStr
class ResponseMessage(BaseModel):
message: str
class UserSearchResults(BaseModel):
results: Sequence[User]

View file

View file

@ -0,0 +1,5 @@
from src import __version__
def test_version():
assert __version__ == '0.1.0'

18
apps/api/vercel.json Normal file
View file

@ -0,0 +1,18 @@
{
"version": 2,
"builds": [
{
"src": "/src/main.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "src/main.py"
}
],
"env": {
"APP_MODULE": "src.main:app"
}
}