Spaces:
Runtime error
Runtime error
CaesarCloudSync commited on
Commit ·
211843b
0
Parent(s):
CaesarAI Change Card Improve 1
Browse files- .gitignore +13 -0
- Aptfile +3 -0
- Dockerfile +29 -0
- README.md +9 -0
- RevisionBankModels.py +13 -0
- Subjects.md +23 -0
- __pycache__/RevisionBankModels.cpython-310.pyc +0 -0
- __pycache__/config.cpython-310.pyc +0 -0
- __pycache__/csv_to_db.cpython-310.pyc +0 -0
- __pycache__/forgotpassemail.cpython-310.pyc +0 -0
- __pycache__/main.cpython-310.pyc +0 -0
- __pycache__/models.cpython-310.pyc +0 -0
- __pycache__/physicsaqa.cpython-310.pyc +0 -0
- __pycache__/raspsendemail.cpython-310.pyc +0 -0
- __pycache__/revisionbankscheduler.cpython-310.pyc +0 -0
- app.py +1457 -0
- config.py +15 -0
- configuration +5 -0
- csv_to_db.py +27 -0
- forgotpassemail.py +20 -0
- image.png +0 -0
- main.py +1414 -0
- maintest.py +76 -0
- models.py +38 -0
- physics.py +18 -0
- physicsaqa.py +44 -0
- raspsendemail.py +95 -0
- requirements.txt +77 -0
- revisionbankscheduler +1 -0
- revisionbankscheduler.py +138 -0
- revisionbankunit.py +22 -0
- runtime.txt +1 -0
- secrets.md +1 -0
- storerevisioncards.py +74 -0
- stripetest.py +17 -0
.gitignore
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.json
|
| 2 |
+
revisionbankenv
|
| 3 |
+
exampleimage.json
|
| 4 |
+
Procfile
|
| 5 |
+
yes
|
| 6 |
+
yes.pub
|
| 7 |
+
test.js
|
| 8 |
+
test.py
|
| 9 |
+
test3.py
|
| 10 |
+
test4.py
|
| 11 |
+
mydata.json
|
| 12 |
+
.space
|
| 13 |
+
revisionbankscheduler
|
Aptfile
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
tesseract-ocr
|
| 2 |
+
tesseract-ocr-eng
|
| 3 |
+
libtesseract-dev
|
Dockerfile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Use the official Python 3.9 image
|
| 2 |
+
FROM python:3.10
|
| 3 |
+
RUN export PYTHONPATH=$PWD
|
| 4 |
+
RUN apt-get update && apt-get install curl ffmpeg libsm6 libxext6 uvicorn libopencv-dev python3-opencv tesseract-ocr -y
|
| 5 |
+
RUN pip install uvicorn
|
| 6 |
+
# Set the working directory to /code
|
| 7 |
+
WORKDIR /code
|
| 8 |
+
#VOLUME /home/amari/Desktop/CaesarAI/CaesarFastAPI /code
|
| 9 |
+
# Copy the current directory contents into the container at /code
|
| 10 |
+
COPY ./requirements.txt /code/requirements.txt
|
| 11 |
+
|
| 12 |
+
# Install requirements.txt
|
| 13 |
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
| 14 |
+
|
| 15 |
+
# Set up a new user named "user" with user ID 1000
|
| 16 |
+
RUN useradd -m -u 1000 user
|
| 17 |
+
# Switch to the "user" user
|
| 18 |
+
USER user
|
| 19 |
+
# Set home to the user's home directory
|
| 20 |
+
ENV HOME=/home/user \
|
| 21 |
+
PATH=/home/user/.local/bin:$PATH
|
| 22 |
+
|
| 23 |
+
# Set the working directory to the user's home directory
|
| 24 |
+
WORKDIR $HOME/app
|
| 25 |
+
|
| 26 |
+
# Copy the current directory contents into the container at $HOME/app setting the owner to the user
|
| 27 |
+
COPY --chown=user . $HOME/app
|
| 28 |
+
|
| 29 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860","--reload"]
|
README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: RevisionBank
|
| 3 |
+
emoji: 📖
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: gray
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: apache-2.0
|
| 9 |
+
---
|
RevisionBankModels.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Generic, TypeVar,Dict,List,AnyStr,Any,Union
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
from pydantic.generics import GenericModel
|
| 4 |
+
|
| 5 |
+
M = TypeVar("M", bound=BaseModel)
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class GenericSingleObject(GenericModel, Generic[M]):
|
| 9 |
+
object: M
|
| 10 |
+
class RevisionBankAuth(BaseModel):
|
| 11 |
+
email:str
|
| 12 |
+
password:str
|
| 13 |
+
|
Subjects.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
## Subjects
|
| 2 |
+
# Done = $, Pending = % , Not Done = /
|
| 3 |
+
# A level Exam Boards = Edexcel,AQA,CIE,OCR, WJEC
|
| 4 |
+
# GCSE
|
| 5 |
+
# 1. Further Maths $
|
| 6 |
+
# 2. Physics OCR ans $
|
| 7 |
+
# 3. Computer science OCR ans $
|
| 8 |
+
# 4. Chemistry OCR ans $
|
| 9 |
+
# 5. Biology OCR ans $
|
| 10 |
+
# 6. History
|
| 11 |
+
# 7. Extended Project Qualification
|
| 12 |
+
# 8. Economics
|
| 13 |
+
# 9. Business
|
| 14 |
+
|
| 15 |
+
# 10. Geography
|
| 16 |
+
# 11. Art
|
| 17 |
+
# 12. Geology
|
| 18 |
+
# 13. Modern Languages
|
| 19 |
+
# 14. Music
|
| 20 |
+
# 15. RS
|
| 21 |
+
# 16. Psycology
|
| 22 |
+
# 17. Drama
|
| 23 |
+
# 18. Geology
|
__pycache__/RevisionBankModels.cpython-310.pyc
ADDED
|
Binary file (799 Bytes). View file
|
|
|
__pycache__/config.cpython-310.pyc
ADDED
|
Binary file (723 Bytes). View file
|
|
|
__pycache__/csv_to_db.cpython-310.pyc
ADDED
|
Binary file (1.45 kB). View file
|
|
|
__pycache__/forgotpassemail.cpython-310.pyc
ADDED
|
Binary file (815 Bytes). View file
|
|
|
__pycache__/main.cpython-310.pyc
ADDED
|
Binary file (42.1 kB). View file
|
|
|
__pycache__/models.cpython-310.pyc
ADDED
|
Binary file (1.68 kB). View file
|
|
|
__pycache__/physicsaqa.cpython-310.pyc
ADDED
|
Binary file (1.43 kB). View file
|
|
|
__pycache__/raspsendemail.cpython-310.pyc
ADDED
|
Binary file (2.31 kB). View file
|
|
|
__pycache__/revisionbankscheduler.cpython-310.pyc
ADDED
|
Binary file (3.49 kB). View file
|
|
|
app.py
ADDED
|
@@ -0,0 +1,1457 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import base64
|
| 2 |
+
import concurrent
|
| 3 |
+
import os
|
| 4 |
+
from concurrent.futures import thread
|
| 5 |
+
from datetime import datetime
|
| 6 |
+
import datetime as dt
|
| 7 |
+
import requests
|
| 8 |
+
from bs4 import BeautifulSoup
|
| 9 |
+
from flask import Flask, app, jsonify, request
|
| 10 |
+
from flask_cors import CORS, cross_origin
|
| 11 |
+
from flask_mail import Mail, Message
|
| 12 |
+
from physicsaqa import PhysicsAQA
|
| 13 |
+
from config import Config
|
| 14 |
+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt_identity
|
| 15 |
+
from csv_to_db import ImportCSV
|
| 16 |
+
from models import Users
|
| 17 |
+
from bson.objectid import ObjectId #
|
| 18 |
+
import hashlib
|
| 19 |
+
import random
|
| 20 |
+
from datetime import datetime
|
| 21 |
+
from PIL import Image, ImageOps
|
| 22 |
+
from io import BytesIO
|
| 23 |
+
import base64
|
| 24 |
+
import json
|
| 25 |
+
import stripe
|
| 26 |
+
#import cv2
|
| 27 |
+
import re
|
| 28 |
+
import pytesseract
|
| 29 |
+
from forgotpassemail import forgotpasswordemail
|
| 30 |
+
app = Flask(__name__)
|
| 31 |
+
app.config.from_object(Config)
|
| 32 |
+
mail = Mail(app)
|
| 33 |
+
jwt = JWTManager(app)
|
| 34 |
+
importcsv = ImportCSV("RevisionBankDB",maindb=0)
|
| 35 |
+
importcsvqp = ImportCSV("RevisionBankDB",maindb= 1)
|
| 36 |
+
importcsvqp1 = ImportCSV("RevisionBankQPs1",maindb=2)
|
| 37 |
+
app.config['JWT_SECRET_KEY'] = "Peter Piper picked a peck of pickled peppers, A peck of pickled peppers Peter Piper picked, If Peter Piper picked a peck of pickled peppers,Where's the peck of pickled peppers Peter Piper picked" #'super-secret'
|
| 38 |
+
|
| 39 |
+
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = dt.timedelta(days=1)
|
| 40 |
+
|
| 41 |
+
def getendsubscription(current_user):
|
| 42 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 43 |
+
end_date = user_from_db["end_date_subscription"]
|
| 44 |
+
return end_date
|
| 45 |
+
# Sending Emails from Heroku: https://blairconrad.com/2020/03/05/libraryhippo-2020-sending-email-from-heroku/
|
| 46 |
+
# Send Email API: https://app.sendgrid.com/
|
| 47 |
+
# Signin and Signup page: https://shayff.medium.com/building-your-first-flask-rest-api-with-mongodb-and-jwt-e03f2d317f04
|
| 48 |
+
# SetUp Tesseract: https://towardsdatascience.com/deploy-python-tesseract-ocr-on-heroku-bbcc39391a8d
|
| 49 |
+
def check_user_from_db(current_user): #test
|
| 50 |
+
email_exists = importcsv.db.users.find_one({"email":current_user})
|
| 51 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 52 |
+
if email_exists:
|
| 53 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 54 |
+
return user_from_db
|
| 55 |
+
elif student_email_exists:
|
| 56 |
+
user_from_db = list(importcsv.db.studentsubscriptions.find({"email": current_user}))[0]
|
| 57 |
+
return user_from_db
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
@app.route('/',methods=['GET'])
|
| 61 |
+
@cross_origin() # allow all origins all methods.
|
| 62 |
+
def index():
|
| 63 |
+
return "Hello World"
|
| 64 |
+
@app.route('/test',methods=['POST'])
|
| 65 |
+
@cross_origin() # allow all origins all methods.
|
| 66 |
+
def test():
|
| 67 |
+
data = request.get_json()
|
| 68 |
+
databack = data['data'] + ' from backend'
|
| 69 |
+
return {"result":databack }
|
| 70 |
+
|
| 71 |
+
@app.route("/sendmail",methods=["POST"])
|
| 72 |
+
@cross_origin()
|
| 73 |
+
def sendmail():
|
| 74 |
+
data = request.get_json()
|
| 75 |
+
now = datetime.now().strftime("%c")
|
| 76 |
+
msg = Message("Mail from LibraryHippo", recipients=["amari.lawal@gmail.com"])
|
| 77 |
+
msg.body = f"test mail from LibraryHippo at {now}"
|
| 78 |
+
msg.html = f"<h1>Test mail from LibraryHippo</h1><p>It's now {now}."
|
| 79 |
+
mail.send(msg)
|
| 80 |
+
return f"Sent mail at {now}"
|
| 81 |
+
@app.route("/revisionbankstripepayment",methods=["POST"])
|
| 82 |
+
@cross_origin() # allow all origins all methods.
|
| 83 |
+
@jwt_required()
|
| 84 |
+
def revisionbankstripepayment():
|
| 85 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 86 |
+
if current_user:
|
| 87 |
+
try:
|
| 88 |
+
data = request.get_json()
|
| 89 |
+
price = data["price"]
|
| 90 |
+
stripe.api_key = "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"
|
| 91 |
+
#"sk_test_51La4WnLpfbhhIhYRjP1w036wUwBoatAgqNRYEoj9u6jMd7GvSmBioKgmwJsabjgAY8V5W8i2r3QdelOPe5VNOueB00zDxeXtDQ"
|
| 92 |
+
|
| 93 |
+
striperesponse = stripe.PaymentIntent.create(
|
| 94 |
+
amount=round(price*100),
|
| 95 |
+
currency="gbp",
|
| 96 |
+
payment_method_types=["card"],
|
| 97 |
+
)
|
| 98 |
+
clientsecret= striperesponse["client_secret"]
|
| 99 |
+
#print(clientsecret)
|
| 100 |
+
return {"clientsecret":clientsecret}
|
| 101 |
+
except Exception as ex:
|
| 102 |
+
return {"error":f"{type(ex)}-{ex}"}
|
| 103 |
+
|
| 104 |
+
@app.route('/revisionbanktranslate',methods=['POST'])
|
| 105 |
+
@cross_origin() # allow all origins all methods.
|
| 106 |
+
def revisionbanktranslate():
|
| 107 |
+
def read_img(img):
|
| 108 |
+
pytesseract.pytesseract.tesseract_cmd = "/app/.apt/usr/bin/tesseract"
|
| 109 |
+
text = pytesseract.image_to_string(img,
|
| 110 |
+
lang="eng",
|
| 111 |
+
config='--dpi 300 --psm 6 --oem 2 -c tessedit_char_blacklist=][|~_}{=!#%&«§><:;—?¢°*@,')
|
| 112 |
+
|
| 113 |
+
return(text)
|
| 114 |
+
try:
|
| 115 |
+
# TODO Use Tesseract OCR to get the text from the image hello
|
| 116 |
+
data = request.get_json()
|
| 117 |
+
img = data["revisioncardscreenshot"].replace("data:image/png;base64,","").replace("data:image/jpeg;base64,","")
|
| 118 |
+
# TODO Next Remove Blurriness and Noise from the image with cv2
|
| 119 |
+
#https://pyimagesearch.com/2017/07/10/using-tesseract-ocr-python/
|
| 120 |
+
img_obj =ImageOps.grayscale(Image.open(BytesIO(base64.b64decode(img))))
|
| 121 |
+
text = read_img(img_obj)
|
| 122 |
+
|
| 123 |
+
return {"revisioncardscreenshotext":text }
|
| 124 |
+
#return {"result":data}
|
| 125 |
+
except Exception as e:
|
| 126 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
@app.route('/getedexcelqp',methods=['POST'])
|
| 130 |
+
@cross_origin() # allow all origins all methods.
|
| 131 |
+
@jwt_required()
|
| 132 |
+
def getedexcelqp():
|
| 133 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 134 |
+
if current_user:
|
| 135 |
+
try:
|
| 136 |
+
data = request.get_json()
|
| 137 |
+
edexcelpapers = list(importcsvqp.db.edexcelpapers.find({data["edexcelpaper"]:{"$exists":"true"}}))[0]
|
| 138 |
+
del edexcelpapers["_id"]
|
| 139 |
+
return {"edexcelpaper":edexcelpapers}
|
| 140 |
+
except Exception as e:
|
| 141 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 142 |
+
@app.route('/getcomputerscienceqp',methods=['POST'])
|
| 143 |
+
@cross_origin() # allow all origins all methods.
|
| 144 |
+
@jwt_required()
|
| 145 |
+
def getcomputerscienceqp():
|
| 146 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 147 |
+
if current_user:
|
| 148 |
+
try:
|
| 149 |
+
data = request.get_json()
|
| 150 |
+
edexcelpapers = list(importcsvqp1.db.computerscienceqp.find({data["aqacomputerscience"]:{"$exists":"true"}}))[0]
|
| 151 |
+
del edexcelpapers["_id"]
|
| 152 |
+
return edexcelpapers # {"aqacomputerscience":edexcelpapers}
|
| 153 |
+
except Exception as e:
|
| 154 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 155 |
+
@app.route('/getcomputersciencems',methods=['POST'])
|
| 156 |
+
@cross_origin() # allow all origins all methods.
|
| 157 |
+
@jwt_required()
|
| 158 |
+
def getcomputersciencems():
|
| 159 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 160 |
+
if current_user:
|
| 161 |
+
try:
|
| 162 |
+
data = request.get_json()
|
| 163 |
+
edexcelpapers = list(importcsvqp1.db.computersciencems.find({data["aqacomputerscience"]:{"$exists":"true"}}))[0]
|
| 164 |
+
del edexcelpapers["_id"]
|
| 165 |
+
return edexcelpapers # {"aqacomputerscience":edexcelpapers}
|
| 166 |
+
except Exception as e:
|
| 167 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 168 |
+
@app.route('/getphysicsocrqp',methods=['POST'])
|
| 169 |
+
@cross_origin() # allow all origins all methods.
|
| 170 |
+
@jwt_required()
|
| 171 |
+
def getphysicsocrqp():
|
| 172 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 173 |
+
if current_user:
|
| 174 |
+
try:
|
| 175 |
+
data = request.get_json()
|
| 176 |
+
if data["subject"] == "physics":
|
| 177 |
+
edexcelpapers = list(importcsvqp1.db.physicsocrqp.find({data["questionpapersubject"]:{"$exists":"true"}}))[0]
|
| 178 |
+
elif data["subject"] == "chemistry":
|
| 179 |
+
edexcelpapers = list(importcsvqp.db.chemistryaqaqp.find({data["questionpapersubject"]:{"$exists":"true"}}))[0]
|
| 180 |
+
elif data["subject"] == "biology":
|
| 181 |
+
edexcelpapers = list(importcsvqp.db.biologyaqaqp.find({data["questionpapersubject"]:{"$exists":"true"}}))[0]
|
| 182 |
+
|
| 183 |
+
del edexcelpapers["_id"]
|
| 184 |
+
#print(edexcelpapers)
|
| 185 |
+
if data["scheme"] == "qp":
|
| 186 |
+
return {"questionpapersubject":edexcelpapers[data["questionpapersubject"]]["questionpaper"]}
|
| 187 |
+
elif data["scheme"] == "ms":
|
| 188 |
+
return {"questionpapersubject":edexcelpapers[data["questionpapersubject"]]["markscheme"]}
|
| 189 |
+
except Exception as e:
|
| 190 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
@app.route('/storeocrrevisioncards',methods=['POST'])
|
| 194 |
+
@jwt_required()
|
| 195 |
+
@cross_origin() # allow all origins all methods.
|
| 196 |
+
def storeocrrevisioncards():
|
| 197 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 198 |
+
if current_user:
|
| 199 |
+
try:
|
| 200 |
+
data_json = request.get_json()
|
| 201 |
+
data = data_json["revisioncardscheduler"]
|
| 202 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 203 |
+
if email_exists: # Checks if email exists
|
| 204 |
+
cards_not_exist = []
|
| 205 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0] # Gets the email.
|
| 206 |
+
|
| 207 |
+
#print(user_revision_cards)
|
| 208 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 209 |
+
if card not in user_revision_cards["revisioncards"]:
|
| 210 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 211 |
+
#cards_that_exist.append(card)
|
| 212 |
+
if cards_not_exist != []:
|
| 213 |
+
new_cards = cards_not_exist + user_revision_cards["revisioncards"] # adds new cards to the list.
|
| 214 |
+
user_revision_cards["revisioncards"] = new_cards # Updates the list.
|
| 215 |
+
del user_revision_cards["_id"]
|
| 216 |
+
user_revision_cards["email"] = current_user # Sets the email to the current user.
|
| 217 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user}) # Allows data to be updated.
|
| 218 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards) # Inserts the new data.
|
| 219 |
+
return {"message":"revision cards updated"}
|
| 220 |
+
elif cards_not_exist == []: # If the cards are already in the database, return a message.
|
| 221 |
+
return {"message":"No new cards"}
|
| 222 |
+
|
| 223 |
+
elif not email_exists:
|
| 224 |
+
return {"message": "account doesn't exist"}
|
| 225 |
+
except Exception as ex:
|
| 226 |
+
print(type(ex),ex)
|
| 227 |
+
@app.route('/storerevisioncards',methods=['POST'])
|
| 228 |
+
@cross_origin() # allow all origins all methods.
|
| 229 |
+
@jwt_required()
|
| 230 |
+
def storerevisioncards():
|
| 231 |
+
try:
|
| 232 |
+
current_user = get_jwt_identity()
|
| 233 |
+
if current_user:
|
| 234 |
+
data_json = request.get_json() # test
|
| 235 |
+
data = data_json["revisioncardscheduler"]
|
| 236 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 237 |
+
if email_exists: # Checks if email exists
|
| 238 |
+
cards_not_exist = []
|
| 239 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0] # Gets the email.
|
| 240 |
+
|
| 241 |
+
#print(user_revision_cards)
|
| 242 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 243 |
+
if card not in user_revision_cards["revisioncards"]:
|
| 244 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 245 |
+
#cards_that_exist.append(card)
|
| 246 |
+
if cards_not_exist != []:
|
| 247 |
+
new_cards = cards_not_exist + user_revision_cards["revisioncards"] # adds new cards to the list.
|
| 248 |
+
user_revision_cards["revisioncards"] = new_cards # Updates the list.
|
| 249 |
+
del user_revision_cards["_id"]
|
| 250 |
+
user_revision_cards["email"] = current_user # Sets the email to the current user.
|
| 251 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user}) # Allows data to be updated.
|
| 252 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards) # Inserts the new data.
|
| 253 |
+
return {"message":"revision cards updated"}
|
| 254 |
+
elif cards_not_exist == []: # If the cards are already in the database, return a message.
|
| 255 |
+
return {"message":"No new cards"}
|
| 256 |
+
|
| 257 |
+
elif not email_exists:
|
| 258 |
+
data["email"] = current_user
|
| 259 |
+
importcsv.db.accountrevisioncards.insert_one(data)
|
| 260 |
+
|
| 261 |
+
return {"message": "revision card stored"}
|
| 262 |
+
except Exception as ex:
|
| 263 |
+
print(type(ex),ex)
|
| 264 |
+
@app.route('/changesendtoemail',methods=['PUT'])
|
| 265 |
+
@cross_origin() # allow all origins all methods.
|
| 266 |
+
@jwt_required()
|
| 267 |
+
def changesendtoemail(): # TODO
|
| 268 |
+
current_user = get_jwt_identity()
|
| 269 |
+
if current_user:
|
| 270 |
+
try:
|
| 271 |
+
data = request.get_json()
|
| 272 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 273 |
+
if email_exists:
|
| 274 |
+
scheduled_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 275 |
+
if scheduled_exists:
|
| 276 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 277 |
+
importcsv.db.scheduledcards.delete_many(user_scheduled_cards)
|
| 278 |
+
del user_scheduled_cards["sendtoemail"]
|
| 279 |
+
sendtoemailscheduled = user_scheduled_cards["sendtoemail"]
|
| 280 |
+
user_scheduled_cards.update({"sendtoemail": sendtoemailscheduled})
|
| 281 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards)
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 285 |
+
importcsv.db.accountrevisioncards.delete_many(user_revision_cards)
|
| 286 |
+
del user_revision_cards["sendtoemail"]
|
| 287 |
+
sendtoemail = data["sendtoemail"]
|
| 288 |
+
user_revision_cards.update({"sendtoemail": sendtoemail})
|
| 289 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards)
|
| 290 |
+
return jsonify({"message": "Send to email changed."})
|
| 291 |
+
elif not email_exists:
|
| 292 |
+
return {"message":"email does not exist"}
|
| 293 |
+
except Exception as ex:
|
| 294 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 295 |
+
@app.route('/changerevisioncard',methods=['POST'])
|
| 296 |
+
@cross_origin() # allow all origins all methods.
|
| 297 |
+
@jwt_required()
|
| 298 |
+
def changerevisioncard():
|
| 299 |
+
current_user = get_jwt_identity()
|
| 300 |
+
if current_user:
|
| 301 |
+
try:
|
| 302 |
+
data = request.get_json()
|
| 303 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 304 |
+
if email_exists: # Checks if email exists
|
| 305 |
+
# TODO Slightly buggy here - removes old schedule from the database.
|
| 306 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 307 |
+
for card in user_scheduled_cards["revisioncards"]:
|
| 308 |
+
oldcard = {i:data[i] for i in data if i!='newrevisioncard'}
|
| 309 |
+
if card == oldcard:
|
| 310 |
+
user_scheduled_cards["revisioncards"].remove(card)
|
| 311 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 312 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards)
|
| 313 |
+
|
| 314 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 315 |
+
for card in user_revision_cards["revisioncards"]:
|
| 316 |
+
oldcard = {i:data[i] for i in data if i!='newrevisioncard'}
|
| 317 |
+
if card == oldcard:
|
| 318 |
+
user_revision_cards["revisioncards"].remove(card)
|
| 319 |
+
del data["revisioncard"]
|
| 320 |
+
data["revisioncard"] = data["newrevisioncard"]
|
| 321 |
+
del data["newrevisioncard"]
|
| 322 |
+
user_revision_cards["revisioncards"].append(data)
|
| 323 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user})
|
| 324 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards)
|
| 325 |
+
return {"message":"revision card changed."}
|
| 326 |
+
except Exception as ex:
|
| 327 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
@app.route('/getrevisioncards',methods=['GET'])
|
| 332 |
+
@cross_origin() # allow all origins all methods.
|
| 333 |
+
@jwt_required()
|
| 334 |
+
def getrevisioncards():
|
| 335 |
+
current_user = get_jwt_identity()
|
| 336 |
+
if current_user:
|
| 337 |
+
try:
|
| 338 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 339 |
+
if email_exists: # Checks if email exists
|
| 340 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 341 |
+
del user_revision_cards["_id"],user_revision_cards["email"]
|
| 342 |
+
return user_revision_cards
|
| 343 |
+
elif not email_exists:
|
| 344 |
+
return {"message":"No revision cards"} # Send in shape of data
|
| 345 |
+
except Exception as ex:
|
| 346 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 347 |
+
@app.route('/uploadrevisioncardtxtfile',methods=['POST'])
|
| 348 |
+
@cross_origin() # allow all origins all methods.
|
| 349 |
+
@jwt_required()
|
| 350 |
+
def uploadrevisioncardtxtfile():
|
| 351 |
+
try:
|
| 352 |
+
current_user = get_jwt_identity()
|
| 353 |
+
if current_user:
|
| 354 |
+
file = request.files["file"]
|
| 355 |
+
if file:
|
| 356 |
+
return {"message":file}
|
| 357 |
+
elif not file:
|
| 358 |
+
{"message":"No file"}
|
| 359 |
+
except Exception as ex:
|
| 360 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 361 |
+
|
| 362 |
+
|
| 363 |
+
@app.route('/removerevisioncard',methods=['POST'])
|
| 364 |
+
@cross_origin() # allow all origins all methods.
|
| 365 |
+
@jwt_required()
|
| 366 |
+
def removerevisioncard():
|
| 367 |
+
current_user = get_jwt_identity()
|
| 368 |
+
if current_user:
|
| 369 |
+
try:
|
| 370 |
+
data = request.get_json()
|
| 371 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 372 |
+
if email_exists: # Checks if email exists
|
| 373 |
+
# Remove the revision card from the database.
|
| 374 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 375 |
+
for card in user_revision_cards["revisioncards"]:
|
| 376 |
+
if card == data:
|
| 377 |
+
user_revision_cards["revisioncards"].remove(card)
|
| 378 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user})
|
| 379 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards)
|
| 380 |
+
# Remove the revision card from the scheduled cards
|
| 381 |
+
try:
|
| 382 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 383 |
+
for card in user_scheduled_cards["revisioncards"]:
|
| 384 |
+
if card == data:
|
| 385 |
+
user_scheduled_cards["revisioncards"].remove(card)
|
| 386 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 387 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards)
|
| 388 |
+
return {"message":"revision card removed"}
|
| 389 |
+
except IndexError as iex:
|
| 390 |
+
return {"message":"revision card removed"}
|
| 391 |
+
|
| 392 |
+
except Exception as ex:
|
| 393 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 394 |
+
@app.route('/schedulerevisioncard',methods=['POST'])
|
| 395 |
+
@cross_origin() # allow all origins all methods.
|
| 396 |
+
@jwt_required()
|
| 397 |
+
def schedulerevisioncard():
|
| 398 |
+
try:
|
| 399 |
+
current_user = get_jwt_identity()
|
| 400 |
+
if current_user:
|
| 401 |
+
data = request.get_json() # test
|
| 402 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 403 |
+
if email_exists: # Checks if email exists
|
| 404 |
+
cards_not_exist = []
|
| 405 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0] # Gets the email.
|
| 406 |
+
|
| 407 |
+
#print(user_revision_cards)
|
| 408 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 409 |
+
if card not in user_scheduled_cards["revisioncards"]:
|
| 410 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 411 |
+
#cards_that_exist.append(card)
|
| 412 |
+
if cards_not_exist != []:
|
| 413 |
+
new_cards = cards_not_exist + user_scheduled_cards["revisioncards"] # adds new cards to the list.
|
| 414 |
+
user_scheduled_cards["revisioncards"] = new_cards # Updates the list.
|
| 415 |
+
del user_scheduled_cards["_id"]
|
| 416 |
+
user_scheduled_cards["email"] = current_user # Sets the email to the current user.
|
| 417 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user}) # Allows data to be updated.
|
| 418 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards) # Inserts the new data.
|
| 419 |
+
return {"message":"revision cards scheduled"}
|
| 420 |
+
elif cards_not_exist == []: # If the cards are already in the database, return a message.
|
| 421 |
+
return {"message":"revision cards already scheduled"}
|
| 422 |
+
|
| 423 |
+
elif not email_exists:
|
| 424 |
+
data["email"] = current_user
|
| 425 |
+
importcsv.db.scheduledcards.insert_one(data)
|
| 426 |
+
|
| 427 |
+
return {"message": "revision card scheduled"}
|
| 428 |
+
except Exception as ex:
|
| 429 |
+
print(type(ex),ex)
|
| 430 |
+
@app.route('/unscheduleallrevisioncard',methods=['DELETE'])
|
| 431 |
+
@cross_origin() # allow all origins all methods.
|
| 432 |
+
@jwt_required()
|
| 433 |
+
def unscheduleallrevisioncard():
|
| 434 |
+
current_user = get_jwt_identity()
|
| 435 |
+
if current_user:
|
| 436 |
+
try:
|
| 437 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 438 |
+
if email_exists: # Checks if email exists
|
| 439 |
+
user_revision_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 440 |
+
user_revision_cards["revisioncards"] = []
|
| 441 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 442 |
+
importcsv.db.scheduledcards.insert_one(user_revision_cards)
|
| 443 |
+
return {"message":"Allrevision card unscheduled"}
|
| 444 |
+
except Exception as ex:
|
| 445 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 446 |
+
@app.route('/unschedulerevisioncard',methods=['POST'])
|
| 447 |
+
@cross_origin() # allow all origins all methods.
|
| 448 |
+
@jwt_required()
|
| 449 |
+
def unschedulerevisioncard():
|
| 450 |
+
current_user = get_jwt_identity()
|
| 451 |
+
if current_user:
|
| 452 |
+
try:
|
| 453 |
+
data = request.get_json()
|
| 454 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 455 |
+
if email_exists: # Checks if email exists
|
| 456 |
+
|
| 457 |
+
user_revision_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 458 |
+
for card in user_revision_cards["revisioncards"]:
|
| 459 |
+
if card == data:
|
| 460 |
+
user_revision_cards["revisioncards"].remove(card)
|
| 461 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 462 |
+
importcsv.db.scheduledcards.insert_one(user_revision_cards)
|
| 463 |
+
return {"message":"revision card unscheduled"}
|
| 464 |
+
except Exception as ex:
|
| 465 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 466 |
+
@app.route('/sendnowrevisioncard',methods=['POST'])
|
| 467 |
+
@cross_origin() # allow all origins all methods.
|
| 468 |
+
@jwt_required()
|
| 469 |
+
def sendnowrevisioncard():
|
| 470 |
+
try:
|
| 471 |
+
current_user = get_jwt_identity()
|
| 472 |
+
if current_user:
|
| 473 |
+
data = request.get_json()
|
| 474 |
+
now = datetime.now().strftime("%c")
|
| 475 |
+
message = f"""{data['revisioncards'][0]['revisioncardtitle']}{data["revisioncards"][0]["revisioncard"]}"""
|
| 476 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":data["sendtoemail"],"message":message,"subject":f"{data['revisioncards'][0]['subject']} Send Now"}})
|
| 477 |
+
#print(response.text)
|
| 478 |
+
#msg = Message(f"{data['revisioncards'][0]['subject']} Send Now", recipients=[data["sendtoemail"]]) # "amari.lawal@gmail.com"
|
| 479 |
+
#msg.body = f"Mail from RevisionCard Send Now at {now}"
|
| 480 |
+
#if "!DOCTYPE" not in data["revisioncards"][0]["revisioncard"] or "h1" not in data["revisioncards"][0]["revisioncard"]:
|
| 481 |
+
# msg.html = f"""<pre>{data['revisioncards'][0]['revisioncardtitle']}
|
| 482 |
+
# {data["revisioncards"][0]["revisioncard"]}</pre>"""
|
| 483 |
+
#elif "!DOCTYPE" in data["revisioncards"][0]["revisioncard"] or "h1" in data["revisioncards"][0]["revisioncard"]:
|
| 484 |
+
# msg.html = f"""
|
| 485 |
+
# {data['revisioncards'][0]['revisioncardtitle']}
|
| 486 |
+
# {data["revisioncards"][0]["revisioncard"]}
|
| 487 |
+
# """
|
| 488 |
+
#print(msg)
|
| 489 |
+
#mail.send(msg)
|
| 490 |
+
return {"message":"revision card sent"}
|
| 491 |
+
except Exception as ex:
|
| 492 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 493 |
+
@app.route('/checkschedulerevisioncard',methods=['GET'])
|
| 494 |
+
@cross_origin() # allow all origins all methods.
|
| 495 |
+
@jwt_required()
|
| 496 |
+
def checkschedulerevisioncard():
|
| 497 |
+
current_user = get_jwt_identity()
|
| 498 |
+
if current_user:
|
| 499 |
+
try:
|
| 500 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 501 |
+
if email_exists: # Checks if email exists
|
| 502 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 503 |
+
del user_scheduled_cards["_id"],user_scheduled_cards["email"],user_scheduled_cards["revisionscheduleinterval"],user_scheduled_cards["sendtoemail"]
|
| 504 |
+
return user_scheduled_cards
|
| 505 |
+
elif not email_exists:
|
| 506 |
+
return {"message":"revision cards not scheduled"} # Send in shape of data
|
| 507 |
+
except Exception as ex:
|
| 508 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 509 |
+
|
| 510 |
+
@app.route('/fmathsqp',methods=['POST'])
|
| 511 |
+
@cross_origin() # allow all origins all methods.
|
| 512 |
+
@jwt_required()
|
| 513 |
+
def fmathsqp():
|
| 514 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 515 |
+
if current_user:
|
| 516 |
+
datajson = request.get_json()
|
| 517 |
+
try:
|
| 518 |
+
main_qp_url = "https://www.physicsandmathstutor.com/a-level-maths-papers/"
|
| 519 |
+
data = datajson["furthermaths"]
|
| 520 |
+
email = data["email"]
|
| 521 |
+
book_inp = data["furthermathsbook"]
|
| 522 |
+
topic_inp = data["furthermathstopic"]
|
| 523 |
+
platform = data["platform"]
|
| 524 |
+
qp_sections = {"Core":["c1",'c2','c3','c4'],"Mechanics":['m1','m2','m3','m4','m5'],"Statistics":['s1','s2','s3','s4'],'Further Pure':['fp1','fp2','fp3'],'Decision Maths':['d1','d2']}
|
| 525 |
+
if "c".lower() in book_inp.lower():
|
| 526 |
+
book_choice = "c"
|
| 527 |
+
elif "m".lower() in book_inp.lower():
|
| 528 |
+
book_choice = "m"
|
| 529 |
+
elif "s".lower() in book_inp.lower():
|
| 530 |
+
book_choice = "s"
|
| 531 |
+
elif "fp".lower() in book_inp.lower():
|
| 532 |
+
book_choice = "fp"
|
| 533 |
+
elif "d".lower() in book_inp.lower():
|
| 534 |
+
book_choice = "d"
|
| 535 |
+
elif "a".lower() in book_inp.lower():
|
| 536 |
+
book_choice = "a"
|
| 537 |
+
else:
|
| 538 |
+
return {"result": "doesn't exist"}
|
| 539 |
+
if book_choice != "a":
|
| 540 |
+
endpoints = [endpoint for val in qp_sections.values() for endpoint in val if book_choice in endpoint]
|
| 541 |
+
elif book_choice == "a":
|
| 542 |
+
endpoints = [endpoint for val in qp_sections.values() for endpoint in val]
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
pdf_result = []
|
| 546 |
+
pdf_titles = []
|
| 547 |
+
def qp_extraction(qp_url,end):
|
| 548 |
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0","Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
|
| 549 |
+
response_topic = requests.get(f"{qp_url}/{end}-by-topic/",headers=headers).text
|
| 550 |
+
#if "This site is currently under going scheduled maintenance." in response_topic:
|
| 551 |
+
# return {"error":"Physics maths tutor is in maintenance mode."}
|
| 552 |
+
soup = BeautifulSoup(response_topic,features='lxml')
|
| 553 |
+
for child in soup.find_all(['a'],href=True):
|
| 554 |
+
if topic_inp.lower() in str(child.text).lower():
|
| 555 |
+
pdf_url = child['href']
|
| 556 |
+
#print(pdf_url)
|
| 557 |
+
#print(f'{str(child.text).capitalize()}.pdf')
|
| 558 |
+
pdf_titles.append(f'{str(child.text).capitalize()}.pdf')
|
| 559 |
+
pdf_result.append(pdf_url)
|
| 560 |
+
#response = requests.get(pdf_url)
|
| 561 |
+
#pdf_result.append(str(response.content).replace("b'","").replace("'",""))
|
| 562 |
+
|
| 563 |
+
|
| 564 |
+
|
| 565 |
+
|
| 566 |
+
#print(endpoints)
|
| 567 |
+
def topic_extraction(end):
|
| 568 |
+
qp_extraction(main_qp_url,end)
|
| 569 |
+
|
| 570 |
+
def threads_url():
|
| 571 |
+
#threads = 60 # 20 # TODO Number of threads may be blowing up the router.
|
| 572 |
+
threads = 4
|
| 573 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor: #max_workers=threads
|
| 574 |
+
executor.map(topic_extraction,endpoints)
|
| 575 |
+
threads_url()
|
| 576 |
+
message = """
|
| 577 |
+
The Further Maths question papers, email has been sent to you:
|
| 578 |
+
"""
|
| 579 |
+
linkmessage = """
|
| 580 |
+
The Further Maths question papers links:
|
| 581 |
+
"""
|
| 582 |
+
|
| 583 |
+
#random.shuffle(pdf_result)
|
| 584 |
+
#random.shuffle(pdf_titles)
|
| 585 |
+
if pdf_result != []:
|
| 586 |
+
if len(pdf_result) > 5:
|
| 587 |
+
pdf_slice = round(len(pdf_result) * (100/100))
|
| 588 |
+
else:
|
| 589 |
+
pdf_slice = round(len(pdf_result) * (100/100))
|
| 590 |
+
for link,title in zip(pdf_result[:pdf_slice],pdf_titles[:pdf_slice]):
|
| 591 |
+
linkmessage += "<br>"
|
| 592 |
+
linkmessage += f"{title}" + "<br>"
|
| 593 |
+
linkmessage += link.replace(" ",'%20') + "<br>"
|
| 594 |
+
for i in pdf_titles:
|
| 595 |
+
message += "\n"
|
| 596 |
+
message += i + "\n"
|
| 597 |
+
|
| 598 |
+
|
| 599 |
+
|
| 600 |
+
user_from_db = check_user_from_db(current_user)
|
| 601 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 602 |
+
if "end_date_subscription" in user_from_db:
|
| 603 |
+
end_date = getendsubscription(current_user)
|
| 604 |
+
if user_from_db["emailsleft"] <= 0:
|
| 605 |
+
if platform == "app":
|
| 606 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 607 |
+
elif platform == "web":
|
| 608 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 609 |
+
return pdf_response
|
| 610 |
+
|
| 611 |
+
elif user_from_db["emailsleft"] > 0:
|
| 612 |
+
now = datetime.now().strftime("%c")
|
| 613 |
+
message = f"""
|
| 614 |
+
<h1>The Further Maths question papers links:</h1>
|
| 615 |
+
<p>{linkmessage}</p>.
|
| 616 |
+
"""
|
| 617 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathqp PDFs"}})
|
| 618 |
+
|
| 619 |
+
#msg = Message("FMathqp PDFs", recipients=[email]) # "amari.lawal@gmail.com"
|
| 620 |
+
#msg.body = f"Mail from FMathqp at {now}"
|
| 621 |
+
#msg.html = f"""
|
| 622 |
+
#<h1>The Further Maths question papers links:</h1>
|
| 623 |
+
#<p>{linkmessage}</p>.
|
| 624 |
+
#"""
|
| 625 |
+
|
| 626 |
+
#mail.send(msg)
|
| 627 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 628 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 629 |
+
if platform == "app":
|
| 630 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 631 |
+
elif platform == "web":
|
| 632 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":end_date}}
|
| 633 |
+
|
| 634 |
+
return pdf_response
|
| 635 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 636 |
+
if platform == "app":
|
| 637 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 638 |
+
elif platform == "web":
|
| 639 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":99999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 640 |
+
return pdf_response
|
| 641 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 642 |
+
if user_from_db["emailsleft"] <= 0:
|
| 643 |
+
if platform == "app":
|
| 644 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 645 |
+
elif platform == "web":
|
| 646 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 647 |
+
return pdf_response
|
| 648 |
+
|
| 649 |
+
elif user_from_db["emailsleft"] > 0:
|
| 650 |
+
now = datetime.now().strftime("%c")
|
| 651 |
+
message = f"""
|
| 652 |
+
<h1>The Further Maths question papers links:</h1>
|
| 653 |
+
<p>{linkmessage}</p>.
|
| 654 |
+
"""
|
| 655 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathqp PDFs"}})
|
| 656 |
+
|
| 657 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 658 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 659 |
+
if platform == "app":
|
| 660 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 661 |
+
elif platform == "web":
|
| 662 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":99999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 663 |
+
return pdf_response
|
| 664 |
+
elif pdf_result == []:
|
| 665 |
+
return {"error":"No further maths question papers available"}
|
| 666 |
+
except Exception as e:
|
| 667 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 668 |
+
else:
|
| 669 |
+
return jsonify({"message": "Login first please."})
|
| 670 |
+
|
| 671 |
+
|
| 672 |
+
@app.route('/fmathsb',methods=['POST'])
|
| 673 |
+
@cross_origin() # allow all origins all methods.
|
| 674 |
+
@jwt_required()
|
| 675 |
+
def fmathsb():
|
| 676 |
+
#pure maths: 0, statistics mechanics: 1, core pure maths: 2, further pure maths: 3, further statistics: 4, further mechanics: 5, decision maths: 6"
|
| 677 |
+
# year/book: 1, year/book: 2
|
| 678 |
+
# {"furthermathsb":{"email":"amari.lawal@gmail.com","furthermathsbbook": 0,"furthermathsbyear":2}}
|
| 679 |
+
# Output PureMaths Book 2
|
| 680 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 681 |
+
if current_user:
|
| 682 |
+
try:
|
| 683 |
+
sb_books_list = {"0":"pure-maths","1":"statistics-mechanics","2":"core-pure-maths","3":"further-pure-maths","4":"further-statistics","5":"further-mechanics","6":"decision-maths"}
|
| 684 |
+
datajson = request.get_json()
|
| 685 |
+
data = datajson["furthermathsb"]
|
| 686 |
+
email = data["email"]
|
| 687 |
+
sb_book_inp = str(data["furthermathsbbook"])
|
| 688 |
+
sb_year_inp = str(data["furthermathsbyear"])
|
| 689 |
+
sb_exercise = str(data["furthermathsbexercise"])
|
| 690 |
+
platform = data["platform"]
|
| 691 |
+
|
| 692 |
+
sb_book = sb_books_list[str(sb_book_inp)]
|
| 693 |
+
sb_year = str(sb_year_inp)
|
| 694 |
+
|
| 695 |
+
if sb_book == "pure-maths" or sb_book == "statistics-mechanics":
|
| 696 |
+
sb_url = f"https://www.physicsandmathstutor.com/maths-revision/solutionbanks/edexcel-{sb_book}-year-{sb_year}/"
|
| 697 |
+
#print(sb_url)
|
| 698 |
+
else:
|
| 699 |
+
sb_url = f"https://www.physicsandmathstutor.com/maths-revision/solutionbanks/edexcel-{sb_book}-{sb_year}/"
|
| 700 |
+
|
| 701 |
+
book_dir_name = f"{sb_book}{str(sb_year)}".capitalize()
|
| 702 |
+
|
| 703 |
+
response = requests.get(sb_url).text
|
| 704 |
+
soup = BeautifulSoup(response,features='lxml')
|
| 705 |
+
soup_a_tags = soup.find_all(['a'],href=True)
|
| 706 |
+
sb_result = []
|
| 707 |
+
sb_titles = []
|
| 708 |
+
def sb_extraction(child):
|
| 709 |
+
if "Exercise" in child.text and sb_exercise.upper() in child.text:
|
| 710 |
+
print(child.text)
|
| 711 |
+
pdf_url = child['href']
|
| 712 |
+
#response = requests.get(pdf_url)
|
| 713 |
+
sb_titles.append(f'{book_dir_name}-{str(child.text).capitalize()}.pdf')
|
| 714 |
+
sb_result.append(pdf_url)
|
| 715 |
+
def threads_url():
|
| 716 |
+
#threads = 60 # 20 # TODO Number of threads may be blowing up the router.
|
| 717 |
+
threads = 4
|
| 718 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor: #max_workers=threads
|
| 719 |
+
executor.map(sb_extraction,soup_a_tags)
|
| 720 |
+
threads_url()
|
| 721 |
+
if sb_result != []:
|
| 722 |
+
message = """
|
| 723 |
+
The Further Maths solution bank, email has been sent to you:
|
| 724 |
+
"""
|
| 725 |
+
linkmessage = """
|
| 726 |
+
The Further Maths question papers links:
|
| 727 |
+
"""
|
| 728 |
+
for link,title in zip(sb_result,sb_titles):
|
| 729 |
+
linkmessage += "<br>"
|
| 730 |
+
linkmessage += f"{title}" + "<br>"
|
| 731 |
+
linkmessage += link.replace(" ",'%20') + "<br>"
|
| 732 |
+
for i in sb_titles:
|
| 733 |
+
message += "\n"
|
| 734 |
+
message += i + "\n"
|
| 735 |
+
user_from_db = check_user_from_db(current_user)
|
| 736 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 737 |
+
if "end_date_subscription" in user_from_db:
|
| 738 |
+
end_date = getendsubscription(current_user)
|
| 739 |
+
if user_from_db["emailsleft"] <= 0:
|
| 740 |
+
if platform == "app":
|
| 741 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 742 |
+
elif platform == "web":
|
| 743 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 744 |
+
return pdf_response
|
| 745 |
+
|
| 746 |
+
elif user_from_db["emailsleft"] > 0:
|
| 747 |
+
now = datetime.now().strftime("%c")
|
| 748 |
+
message = f"""
|
| 749 |
+
<h1>The Further Maths Solution Bank links:</h1>
|
| 750 |
+
<p>{linkmessage}</p>.
|
| 751 |
+
"""
|
| 752 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathSB PDFs"}})
|
| 753 |
+
|
| 754 |
+
#msg = Message("FMathSB PDFs", recipients=[email]) # "amari.lawal@gmail.com"
|
| 755 |
+
#msg.body = f"Mail from FMathsb at {now}"
|
| 756 |
+
#msg.html = f"""
|
| 757 |
+
#<h1>The Further Maths Solution Bank links:</h1>
|
| 758 |
+
#<p>{linkmessage}</p>.
|
| 759 |
+
#"""
|
| 760 |
+
|
| 761 |
+
#mail.send(msg)
|
| 762 |
+
emailcount = int(user_from_db["emailsleft"])-1
|
| 763 |
+
user_from_db.update({"emailsleft":emailcount})
|
| 764 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 765 |
+
|
| 766 |
+
if platform == "app":
|
| 767 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 768 |
+
elif platform == "web":
|
| 769 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":emailcount,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 770 |
+
return pdf_response
|
| 771 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 772 |
+
if platform == "app":
|
| 773 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 774 |
+
elif platform == "web":
|
| 775 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":9999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 776 |
+
return pdf_response
|
| 777 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 778 |
+
if user_from_db["emailsleft"] <= 0:
|
| 779 |
+
if platform == "app":
|
| 780 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 781 |
+
elif platform == "web":
|
| 782 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 783 |
+
return pdf_response
|
| 784 |
+
|
| 785 |
+
elif user_from_db["emailsleft"] > 0:
|
| 786 |
+
now = datetime.now().strftime("%c")
|
| 787 |
+
message = f"""
|
| 788 |
+
<h1>The Further Maths Solution Bank links:</h1>
|
| 789 |
+
<p>{linkmessage}</p>.
|
| 790 |
+
"""
|
| 791 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathSB PDFs"}})
|
| 792 |
+
|
| 793 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 794 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 795 |
+
if platform == "app":
|
| 796 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 797 |
+
elif platform == "web":
|
| 798 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":9999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 799 |
+
return pdf_response
|
| 800 |
+
|
| 801 |
+
elif sb_result == []:
|
| 802 |
+
return {f"error":f"No further maths solution bank for {sb_book} {sb_year}"}
|
| 803 |
+
except Exception as e:
|
| 804 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 805 |
+
else:
|
| 806 |
+
return jsonify({"message": "Login first please."})
|
| 807 |
+
@app.route('/ocrsciencebookanswers',methods=['POST'])
|
| 808 |
+
@cross_origin() # allow all origins all methods.
|
| 809 |
+
@jwt_required()
|
| 810 |
+
def scienceocranswers():
|
| 811 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 812 |
+
if current_user:
|
| 813 |
+
datajson = request.get_json()
|
| 814 |
+
|
| 815 |
+
def ocrscienceanswers(querydata):
|
| 816 |
+
examboards = "OCR"
|
| 817 |
+
url = "https://global.oup.com/education/content/secondary/series/ocr-a-level-sciences/a-level-sciences-for-ocr-student-book-answers/?region=uk"
|
| 818 |
+
physicsanswerspdf = {}
|
| 819 |
+
|
| 820 |
+
response= requests.get(url).text
|
| 821 |
+
soup = BeautifulSoup(response,features='lxml')
|
| 822 |
+
for divele in soup.find_all('div',{'class':'content_block half_width enclosed'}): # inner_block text_only_single ##
|
| 823 |
+
if querydata in divele.text:
|
| 824 |
+
for a in divele.find_all("a",href=True):
|
| 825 |
+
if a["href"] != "?region=uk":
|
| 826 |
+
physicsanswerspdf.update({a.text.replace("\xa0",' '): a["href"].replace("?region=uk",'')})
|
| 827 |
+
|
| 828 |
+
result = {querydata:{examboards:physicsanswerspdf}}
|
| 829 |
+
return result
|
| 830 |
+
try:
|
| 831 |
+
data = datajson["physicsocr"]
|
| 832 |
+
email = data["email"]
|
| 833 |
+
subject = data["subject"] # physics, chemistry, biology
|
| 834 |
+
physicsocralph = data["physicsocralph"] # A or B
|
| 835 |
+
chapter = data["chapter"] # Chapter 1
|
| 836 |
+
year = data["year"] # AS/Year 1, A Level
|
| 837 |
+
platform = data["platform"] # web or app
|
| 838 |
+
|
| 839 |
+
query = f"{subject.capitalize()} {physicsocralph} {year}"
|
| 840 |
+
papers = ocrscienceanswers(query)
|
| 841 |
+
answerlink = papers[query]["OCR"][f"{chapter.capitalize()} (PDF)"].replace(" ",'%20')
|
| 842 |
+
|
| 843 |
+
user_from_db = check_user_from_db(current_user)
|
| 844 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 845 |
+
if "end_date_subscription" in user_from_db:
|
| 846 |
+
end_date = getendsubscription(current_user)
|
| 847 |
+
if user_from_db["emailsleft"] <= 0:
|
| 848 |
+
result = {"scienceocranswers": answerlink,"emailcount":0,"end_date_subscription":end_date}
|
| 849 |
+
return result
|
| 850 |
+
elif user_from_db["emailsleft"] > 0:
|
| 851 |
+
now = datetime.now().strftime("%c")
|
| 852 |
+
message = f"""
|
| 853 |
+
<h1>OCR Science {query} Answers:</h1>
|
| 854 |
+
<p>{answerlink}</p>.
|
| 855 |
+
"""
|
| 856 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"OCR {query} Answers"}})
|
| 857 |
+
|
| 858 |
+
#msg = Message(f"OCR {query} Answers", recipients=[email]) # "amari.lawal@gmail.com"
|
| 859 |
+
#msg.body = f"Mail from {query} at {now}"
|
| 860 |
+
#msg.html = f"""
|
| 861 |
+
#<h1>OCR Science {query} Answers:</h1>
|
| 862 |
+
#<p>{answerlink}</p>.
|
| 863 |
+
#"""
|
| 864 |
+
|
| 865 |
+
#mail.send(msg)
|
| 866 |
+
emailcount = int(user_from_db["emailsleft"])-1
|
| 867 |
+
user_from_db.update({"emailsleft":emailcount})
|
| 868 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 869 |
+
result = {"scienceocranswers": answerlink,"emailcount":emailcount,"end_date_subscription":end_date}
|
| 870 |
+
return result
|
| 871 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 872 |
+
result = {"scienceocranswers": answerlink,"emailcount":0,"end_date_subscription":9999999}
|
| 873 |
+
return result
|
| 874 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 875 |
+
if user_from_db["emailsleft"] <= 0:
|
| 876 |
+
result = {"scienceocranswers": answerlink,"emailcount":0,"end_date_subscription":end_date}
|
| 877 |
+
return result
|
| 878 |
+
elif user_from_db["emailsleft"] > 0:
|
| 879 |
+
now = datetime.now().strftime("%c")
|
| 880 |
+
message = f"""
|
| 881 |
+
<h1>OCR Science {query} Answers:</h1>
|
| 882 |
+
<p>{answerlink}</p>.
|
| 883 |
+
"""
|
| 884 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"OCR {query} Answers"}})
|
| 885 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 886 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 887 |
+
result = {"scienceocranswers": answerlink,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":9999999}
|
| 888 |
+
return result
|
| 889 |
+
except Exception as e:
|
| 890 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 891 |
+
else:
|
| 892 |
+
return jsonify({"message": "Login first please."})
|
| 893 |
+
@app.route('/physicsaqa',methods=['POST'])
|
| 894 |
+
@cross_origin() # allow all origins all methods.
|
| 895 |
+
@jwt_required()
|
| 896 |
+
def physicsaqa():
|
| 897 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 898 |
+
if current_user:
|
| 899 |
+
try:
|
| 900 |
+
datajson = request.get_json()
|
| 901 |
+
topicquestions = PhysicsAQA().collectdata()
|
| 902 |
+
data = datajson["physicsaqa"]
|
| 903 |
+
email = data["email"]
|
| 904 |
+
chapter = data["chapter"] # Section 1: Measurement & Their Errors
|
| 905 |
+
topic = data["topic"] # Constituents of the Atom or The Law of the Atom
|
| 906 |
+
platform = data["platform"] # web or app
|
| 907 |
+
try:
|
| 908 |
+
questionpaper = topicquestions[chapter][topic]
|
| 909 |
+
except Exception as ex:
|
| 910 |
+
return {"error":"chapter or topic not found"}
|
| 911 |
+
try:
|
| 912 |
+
markscheme = topicquestions[chapter][f"{topic} MS"]
|
| 913 |
+
except Exception as ex:
|
| 914 |
+
return {"error":"chapter or topic mark scheme not found"}
|
| 915 |
+
|
| 916 |
+
|
| 917 |
+
user_from_db = check_user_from_db(current_user)
|
| 918 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 919 |
+
if "end_date_subscription" in user_from_db:
|
| 920 |
+
end_date = getendsubscription(current_user)
|
| 921 |
+
if user_from_db["emailsleft"] <= 0:
|
| 922 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":emailcount,"end_date_subscription":end_date}}
|
| 923 |
+
elif user_from_db["emailsleft"] > 0:
|
| 924 |
+
now = datetime.now().strftime("%c")
|
| 925 |
+
message = f"""
|
| 926 |
+
<h1>PhysicsAqa Question Papers:</h1>
|
| 927 |
+
<p>{questionpaper}</p>
|
| 928 |
+
<p>{markscheme}</p>.
|
| 929 |
+
"""
|
| 930 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"PhysicsAqa Papers"}})
|
| 931 |
+
#msg = Message(f"PhysicsAqa Papers", recipients=[email]) # "amari.lawal@gmail.com"
|
| 932 |
+
#msg.body = f"Mail from physicsaqaApi at {now}"
|
| 933 |
+
#msg.html = f"""
|
| 934 |
+
#<h1>PhysicsAqa Question Papers:</h1>
|
| 935 |
+
#<p>{questionpaper}</p>
|
| 936 |
+
#<p>{markscheme}</p>.
|
| 937 |
+
#"""
|
| 938 |
+
#mail.send(msg)
|
| 939 |
+
emailcount = int(user_from_db["emailsleft"])-1
|
| 940 |
+
user_from_db.update({"emailsleft":emailcount})
|
| 941 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 942 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":emailcount,"end_date_subscription":end_date}}
|
| 943 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 944 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":0,"end_date_subscription":9999999}}
|
| 945 |
+
# If it is a student account
|
| 946 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 947 |
+
# Check number of emails left
|
| 948 |
+
if user_from_db["emailsleft"] <= 0:
|
| 949 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":emailcount,"end_date_subscription":end_date}}
|
| 950 |
+
elif user_from_db["emailsleft"] > 0:
|
| 951 |
+
now = datetime.now().strftime("%c")
|
| 952 |
+
message = f"""
|
| 953 |
+
<h1>PhysicsAqa Question Papers:</h1>
|
| 954 |
+
<p>{questionpaper}</p>
|
| 955 |
+
<p>{markscheme}</p>.
|
| 956 |
+
"""
|
| 957 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"PhysicsAqa Papers"}})
|
| 958 |
+
|
| 959 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 960 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 961 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":9999999}}
|
| 962 |
+
|
| 963 |
+
except TypeError as tex:
|
| 964 |
+
return {f"error":f"request is wrong shape {tex}"}
|
| 965 |
+
except Exception as ex:
|
| 966 |
+
return {f"error":f"{type(ex)} {str(ex)}"}
|
| 967 |
+
else:
|
| 968 |
+
return jsonify({"message": "Login first please."})
|
| 969 |
+
|
| 970 |
+
|
| 971 |
+
@app.route('/signupapi', methods=['POST'])
|
| 972 |
+
@cross_origin()
|
| 973 |
+
def signup():
|
| 974 |
+
try:
|
| 975 |
+
data = request.get_json()
|
| 976 |
+
data["id"] = ObjectId()
|
| 977 |
+
data["access"] = True
|
| 978 |
+
user = Users(**data)
|
| 979 |
+
signupdata = user.to_bson()
|
| 980 |
+
#print(signupdata)
|
| 981 |
+
email_exists = importcsv.db.users.find_one({"email": signupdata["email"]})
|
| 982 |
+
email_exists_student = importcsv.db.studentsubscriptions.find_one({"email": signupdata["email"]}) # Checks if student account exists
|
| 983 |
+
if email_exists or email_exists_student:
|
| 984 |
+
return jsonify({"message": "Email already exists"}) # , 400
|
| 985 |
+
elif not email_exists:
|
| 986 |
+
# Notifies who are the beta testers
|
| 987 |
+
#if datetime.now() < "2022-05-19T21:37:00.057084":
|
| 988 |
+
# signupdata.update({"betatest":"true"})
|
| 989 |
+
importcsv.db.users.insert_one(signupdata)
|
| 990 |
+
access_token = create_access_token(identity=signupdata["email"])
|
| 991 |
+
callback = {"status": "success","id": str(signupdata["_id"]),"access_token":access_token}
|
| 992 |
+
return callback
|
| 993 |
+
except Exception as ex:
|
| 994 |
+
error_detected = {"error": "error occured","errortype":type(ex), "error": str(ex)}
|
| 995 |
+
return error_detected
|
| 996 |
+
@app.route('/loginapi', methods=['POST'])
|
| 997 |
+
@cross_origin()
|
| 998 |
+
def login():
|
| 999 |
+
# Login API
|
| 1000 |
+
try:
|
| 1001 |
+
def provide_access_token(login_details,student=0):
|
| 1002 |
+
if student == 0:
|
| 1003 |
+
email_exists = list(importcsv.db.users.find({"email": login_details["email"]}))[0]
|
| 1004 |
+
elif student == 1:
|
| 1005 |
+
email_exists = list(importcsv.db.studentsubscriptions.find({"email": login_details["email"]}))[0]
|
| 1006 |
+
encrypted_password = hashlib.sha256(login_details["password"].encode('utf-8')).hexdigest()
|
| 1007 |
+
if email_exists["password"] == encrypted_password:
|
| 1008 |
+
access_token = create_access_token(identity=email_exists["email"])
|
| 1009 |
+
return access_token
|
| 1010 |
+
else:
|
| 1011 |
+
return "Wrong password"
|
| 1012 |
+
|
| 1013 |
+
|
| 1014 |
+
login_details = request.get_json()
|
| 1015 |
+
email_exists = importcsv.db.users.find_one({"email": login_details["email"]})
|
| 1016 |
+
email_exists_student = importcsv.db.studentsubscriptions.find_one({"email": login_details["email"]}) # Checks if student account exists
|
| 1017 |
+
if email_exists:
|
| 1018 |
+
access_token = provide_access_token(login_details,student=0)
|
| 1019 |
+
if access_token == "Wrong password":
|
| 1020 |
+
return jsonify({"message": "The username or password is incorrect."})
|
| 1021 |
+
else:
|
| 1022 |
+
return jsonify({"access_token": access_token}), 200
|
| 1023 |
+
elif email_exists_student:
|
| 1024 |
+
access_token = provide_access_token(login_details,student=1)
|
| 1025 |
+
if access_token == "Wrong password":
|
| 1026 |
+
return jsonify({"message": "The username or password is incorrect."})
|
| 1027 |
+
else:
|
| 1028 |
+
return jsonify({"access_token": access_token}), 200
|
| 1029 |
+
return jsonify({"message": "The username or password is incorrect."})
|
| 1030 |
+
except Exception as ex:
|
| 1031 |
+
return jsonify({"error": f"{type(ex)} {str(ex)}"})
|
| 1032 |
+
#
|
| 1033 |
+
@app.route('/forgotpassword', methods=['POST'])
|
| 1034 |
+
@cross_origin()
|
| 1035 |
+
def forgotpassword():
|
| 1036 |
+
# Login API
|
| 1037 |
+
data = request.get_json()
|
| 1038 |
+
try:
|
| 1039 |
+
#print(data["email"])
|
| 1040 |
+
access_token = create_access_token(identity=data["email"])
|
| 1041 |
+
# store token in database temporarily
|
| 1042 |
+
now = datetime.now().strftime("%c")
|
| 1043 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":data["email"],"message":forgotpasswordemail(data["email"],access_token),"subject":f"RevsionBank Password Reset"}})
|
| 1044 |
+
#msg = Message(f"RevsionBank Password Reset", recipients=[data["email"]]) # "amari.lawal@gmail.com"
|
| 1045 |
+
#msg.body = f"Mail from RevisionBank at {now}"
|
| 1046 |
+
#msg.html = forgotpasswordemail(data["email"],access_token)
|
| 1047 |
+
#mail.send(msg)
|
| 1048 |
+
return jsonify({"message": "Reset Email sent"})
|
| 1049 |
+
except Exception as ex:
|
| 1050 |
+
return {"error": f"{type(ex)} {str(ex)}"}
|
| 1051 |
+
|
| 1052 |
+
@app.route('/resetpassword', methods=['PUT'])
|
| 1053 |
+
@cross_origin()
|
| 1054 |
+
@jwt_required()
|
| 1055 |
+
def resetpassword():
|
| 1056 |
+
current_user = get_jwt_identity()
|
| 1057 |
+
if current_user:
|
| 1058 |
+
try:
|
| 1059 |
+
data = request.get_json()
|
| 1060 |
+
email_exists = importcsv.db.users.find_one({"email": current_user})
|
| 1061 |
+
#print(email_exists)
|
| 1062 |
+
if email_exists:
|
| 1063 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1064 |
+
#print(user_from_db)
|
| 1065 |
+
# TODO Delete password from here and replace.
|
| 1066 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1067 |
+
del user_from_db["password"]
|
| 1068 |
+
encrypted_password = hashlib.sha256(data["password"].encode('utf-8')).hexdigest()
|
| 1069 |
+
user_from_db.update({"password": encrypted_password})
|
| 1070 |
+
importcsv.db.users.insert_one(user_from_db)
|
| 1071 |
+
return jsonify({"message": "Password reset successful."})
|
| 1072 |
+
elif not email_exists:
|
| 1073 |
+
return {"message": "Email Doesn't exist."}
|
| 1074 |
+
except Exception as ex:
|
| 1075 |
+
return {"error": f"{type(ex)} {str(ex)}"}
|
| 1076 |
+
|
| 1077 |
+
|
| 1078 |
+
|
| 1079 |
+
@app.route('/storesubscription', methods=['POST'])
|
| 1080 |
+
@cross_origin()
|
| 1081 |
+
@jwt_required()
|
| 1082 |
+
def storesubscription():
|
| 1083 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1084 |
+
if current_user:
|
| 1085 |
+
try:
|
| 1086 |
+
data = request.get_json()
|
| 1087 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1088 |
+
if data["subscription"] == 'basic':
|
| 1089 |
+
emailsleft = {'emailsleft': 0}
|
| 1090 |
+
elif data["subscription"] == 'standard':
|
| 1091 |
+
emailsleft = {'emailsleft': 40}
|
| 1092 |
+
elif data["subscription"] == 'premium' or data["subscription"] == 'educational':
|
| 1093 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1094 |
+
if data["subscription"] == "educational":
|
| 1095 |
+
user_from_db.update({"numofaccounts": 200}) # TODO Constant Value needs to be changed when frontend is changed
|
| 1096 |
+
user_from_db.update({"start_date_subscription": data["start_date_subscription"]})
|
| 1097 |
+
user_from_db.update({"end_date_subscription": data["end_date_subscription"]})
|
| 1098 |
+
user_from_db.update({"subscription": data["subscription"]}) # Updates the user with the new subscription
|
| 1099 |
+
user_from_db.update(emailsleft)
|
| 1100 |
+
importcsv.db.users.update_one( { "email": current_user}, {"$set": user_from_db}, upsert = True )
|
| 1101 |
+
|
| 1102 |
+
importcsv.db.subscriptionlog.insert_one({"email": user_from_db["email"],"start_date_subscription": data["start_date_subscription"], "end_date_subscription": data["end_date_subscription"], "subscription": data["subscription"], "emailsleft": emailsleft["emailsleft"]})
|
| 1103 |
+
return jsonify({"message": "Subscription Completed."})
|
| 1104 |
+
except Exception as ex:
|
| 1105 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1106 |
+
|
| 1107 |
+
else:
|
| 1108 |
+
return jsonify({"message": "User not found"})
|
| 1109 |
+
@app.route('/storebetatester', methods=['POST']) # @jwt_required()
|
| 1110 |
+
@cross_origin()
|
| 1111 |
+
def storebetatester():
|
| 1112 |
+
data = request.get_json()
|
| 1113 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1114 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1115 |
+
if email_exists:
|
| 1116 |
+
user_from_db = list(importcsv.db.users.find({"email": data["email"]}))[0] # Gets wanted data for user
|
| 1117 |
+
#user_from_db.update({"numofaccounts": 200}) # TODO Constant Value needs to be changed when frontend is changed
|
| 1118 |
+
date_now = datetime.now()
|
| 1119 |
+
datetime_delta = dt.timedelta(weeks=2)
|
| 1120 |
+
user_from_db.update({"start_date_subscription": date_now.isoformat()})
|
| 1121 |
+
|
| 1122 |
+
user_from_db.update({"end_date_subscription": (datetime_delta + date_now).isoformat()})
|
| 1123 |
+
user_from_db.update({"subscription": "premium"}) # Updates the user with the new subscription
|
| 1124 |
+
user_from_db.update(emailsleft)
|
| 1125 |
+
user_from_db.update({"betatester": "true"})
|
| 1126 |
+
importcsv.db.users.update_one( { "email": data["email"]}, {"$set": user_from_db}, upsert = True )
|
| 1127 |
+
|
| 1128 |
+
#importcsv.db.subscriptionlog.insert_one({"email": user_from_db["email"],"start_date_subscription": data["start_date_subscription"], "end_date_subscription": data["end_date_subscription"], "subscription": data["subscription"], "emailsleft": emailsleft["emailsleft"]})
|
| 1129 |
+
return jsonify({"message": "Beta Tester Subscription Completed."})
|
| 1130 |
+
elif not email_exists:
|
| 1131 |
+
return jsonify({"message": "User not found"})
|
| 1132 |
+
@app.route('/storeeducationalfreetrial', methods=['POST']) # @jwt_required()
|
| 1133 |
+
@cross_origin()
|
| 1134 |
+
def storeeducationalfreetrial():
|
| 1135 |
+
data = request.get_json()
|
| 1136 |
+
try:
|
| 1137 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1138 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1139 |
+
if email_exists:
|
| 1140 |
+
user_from_db = list(importcsv.db.users.find({"email": data["email"]}))[0] # Gets wanted data for user
|
| 1141 |
+
#user_from_db.update({"numofaccounts": 200}) # TODO Constant Value needs to be changed when frontend is changed
|
| 1142 |
+
date_now = datetime.now()
|
| 1143 |
+
decimal_part = float(3 / 7)
|
| 1144 |
+
datetime_delta = dt.timedelta(weeks=4 + decimal_part)
|
| 1145 |
+
user_from_db.update({"start_date_subscription": date_now.isoformat()})
|
| 1146 |
+
user_from_db.update({"numofaccounts": 200})
|
| 1147 |
+
|
| 1148 |
+
user_from_db.update({"end_date_subscription": (datetime_delta + date_now).isoformat()})
|
| 1149 |
+
user_from_db.update({"subscription": "educational"}) # Updates the user with the new subscription
|
| 1150 |
+
user_from_db.update(emailsleft)
|
| 1151 |
+
importcsv.db.users.update_one( { "email": data["email"]}, {"$set": user_from_db}, upsert = True )
|
| 1152 |
+
|
| 1153 |
+
#importcsv.db.subscriptionlog.insert_one({"email": user_from_db["email"],"start_date_subscription": data["start_date_subscription"], "end_date_subscription": data["end_date_subscription"], "subscription": data["subscription"], "emailsleft": emailsleft["emailsleft"]})
|
| 1154 |
+
return jsonify({"message": "Educational Freetrial Subscription Completed."})
|
| 1155 |
+
elif not email_exists:
|
| 1156 |
+
return jsonify({"message": "User not found"})
|
| 1157 |
+
except Exception as ex:
|
| 1158 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1159 |
+
@app.route('/scheduleeducationalfreetrial', methods=['POST']) # @jwt_required()
|
| 1160 |
+
@cross_origin()
|
| 1161 |
+
def scheduleeducationalfreetrial():
|
| 1162 |
+
data = request.get_json()
|
| 1163 |
+
try:
|
| 1164 |
+
regexdatetime = re.compile(r'\d\d\d\d-\d\d-\d\d')
|
| 1165 |
+
mo = regexdatetime.search(data["educationalfreetrialdate"])
|
| 1166 |
+
educationalfreetrialdate = mo.group()
|
| 1167 |
+
except AttributeError as aex:
|
| 1168 |
+
return {"error":r"Datetime shape is %Y-%m-%d"}
|
| 1169 |
+
try:
|
| 1170 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1171 |
+
if email_exists:
|
| 1172 |
+
importcsv.db.schedulededucationalfreetrial.insert_one({"email": data["email"],"educationalfreetrialdate":educationalfreetrialdate})
|
| 1173 |
+
return jsonify({"message": "Educational Freetrial Scheduled."})
|
| 1174 |
+
elif not email_exists:
|
| 1175 |
+
return jsonify({"message": "User not found"})
|
| 1176 |
+
except Exception as ex:
|
| 1177 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1178 |
+
@app.route('/deletescheduleeducationalfreetrial', methods=['POST']) # @jwt_required()
|
| 1179 |
+
@cross_origin()
|
| 1180 |
+
def deletescheduleeducationalfreetrial():
|
| 1181 |
+
data = request.get_json()
|
| 1182 |
+
current_user = data["email"]
|
| 1183 |
+
current_user = importcsv.db.users.find_one({"email": data["email"]})
|
| 1184 |
+
if current_user:
|
| 1185 |
+
try:
|
| 1186 |
+
user_from_db = list(importcsv.db.schedulededucationalfreetrial.find({"email": data["email"]}))[0]
|
| 1187 |
+
importcsv.db.schedulededucationalfreetrial.delete_many(user_from_db)
|
| 1188 |
+
return jsonify({"message":"Educational Freetrial Unscheduled."})
|
| 1189 |
+
except Exception as ex:
|
| 1190 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1191 |
+
@app.route('/removebetatester', methods=['POST']) # @jwt_required()
|
| 1192 |
+
@cross_origin()
|
| 1193 |
+
def removebetatester():
|
| 1194 |
+
data = request.get_json()
|
| 1195 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1196 |
+
if email_exists:
|
| 1197 |
+
user_from_db = list(importcsv.db.users.find({"email": data["email"]}))[0] # Gets wanted data for user
|
| 1198 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1199 |
+
del user_from_db["end_date_subscription"], user_from_db["start_date_subscription"],user_from_db["subscription"],user_from_db["emailsleft"], user_from_db["betatester"]
|
| 1200 |
+
importcsv.db.users.update_one( { "email": data["email"]}, {"$set": user_from_db}, upsert = True )
|
| 1201 |
+
return jsonify({"message": "Beta Tester Subscription Deleted."})
|
| 1202 |
+
elif not email_exists:
|
| 1203 |
+
return jsonify({"message": "User not found"})
|
| 1204 |
+
@app.route('/getsubscription', methods=['GET'])
|
| 1205 |
+
@cross_origin()
|
| 1206 |
+
@jwt_required()
|
| 1207 |
+
def getsubscription():
|
| 1208 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1209 |
+
if current_user:
|
| 1210 |
+
try:
|
| 1211 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1212 |
+
end_date = user_from_db["end_date_subscription"]
|
| 1213 |
+
end_date_subscription = {"end_date_subscription": end_date}
|
| 1214 |
+
return jsonify(end_date_subscription)
|
| 1215 |
+
except Exception as ex:
|
| 1216 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1217 |
+
@app.route('/getemailcount', methods=['GET'])
|
| 1218 |
+
@cross_origin()
|
| 1219 |
+
@jwt_required()
|
| 1220 |
+
def getemailcount():
|
| 1221 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1222 |
+
if current_user:
|
| 1223 |
+
try:
|
| 1224 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1225 |
+
emailcount = user_from_db["emailsleft"]
|
| 1226 |
+
emailcountres = {"emailcount": emailcount}
|
| 1227 |
+
return jsonify(emailcountres)
|
| 1228 |
+
except Exception as ex:
|
| 1229 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1230 |
+
@app.route('/storefreetrial', methods=['POST'])
|
| 1231 |
+
@cross_origin()
|
| 1232 |
+
@jwt_required()
|
| 1233 |
+
def storefreetrial():
|
| 1234 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1235 |
+
if current_user:
|
| 1236 |
+
try:
|
| 1237 |
+
data = request.get_json()
|
| 1238 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1239 |
+
if 'freetrial' not in user_from_db:
|
| 1240 |
+
user_from_db.update({"freetrial": "true"})
|
| 1241 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1242 |
+
user_from_db.update({"start_date_subscription": data["start_date_subscription"]})
|
| 1243 |
+
user_from_db.update({"end_date_subscription": data["end_date_subscription"]})
|
| 1244 |
+
user_from_db.update({"subscription": data["subscription"]}) # Updates the user with the new subscription
|
| 1245 |
+
user_from_db.update(emailsleft)
|
| 1246 |
+
importcsv.db.users.update_one( { "email": current_user}, {"$set": user_from_db}, upsert = True )
|
| 1247 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db}, upsert = True)
|
| 1248 |
+
importcsv.db.freetrialhistory.insert_one({"email": user_from_db["email"],"freetrial":"true"})
|
| 1249 |
+
return jsonify({"message": "Freetrial Redeemed."})
|
| 1250 |
+
elif 'freetrial' in user_from_db:
|
| 1251 |
+
return jsonify({"error": "Freetrial has already used."})
|
| 1252 |
+
except Exception as ex:
|
| 1253 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1254 |
+
@app.route('/setstudentsubscriptions', methods=['POST'])
|
| 1255 |
+
@cross_origin()
|
| 1256 |
+
@jwt_required()
|
| 1257 |
+
def setstudentsubscriptions():
|
| 1258 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1259 |
+
if current_user:
|
| 1260 |
+
# Hostemail is the primary key for the studentsubscription collection
|
| 1261 |
+
try:
|
| 1262 |
+
data = request.get_json()
|
| 1263 |
+
# {"hostemail": "amari.lawal05@gmail.com","hostnumofaccounts": 198,"studentemails": [{"email": "6Lawala@truroschool.com","password": "mann35"},{"email": "Bola.lawal@hotmail.co.uk","password": "billy45"},{"email": "amari.lawal@gmail.com","password": "bobby46"}],"studentemailsleft": 20,"studentsubscription": "student educational"}
|
| 1264 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Host emails data
|
| 1265 |
+
studentsnotexist = []
|
| 1266 |
+
for student in data["studentemails"]: # data["studentemails"] is a list of dictionaries [{"email":"example@gmail.com","password":"password"},{"email":"example@gmail.com","password":"password"}]
|
| 1267 |
+
student_user_from_db = importcsv.db.studentsubscriptions.find_one({"email": student["email"]}) # Checks if any of the emails added are in the database
|
| 1268 |
+
if not student_user_from_db: # If the email is not in the database, then we need to store the data into the database
|
| 1269 |
+
studentsnotexist.append(student) # Adds the email to the list of emails that do not exist in the database
|
| 1270 |
+
|
| 1271 |
+
if studentsnotexist == []: # If all data is already in the database, no need to store it.
|
| 1272 |
+
return jsonify({"message": "all students exist."})
|
| 1273 |
+
elif studentsnotexist != []: # If there are emails that are not in the database, we need to store the data into the database
|
| 1274 |
+
if user_from_db["numofaccounts"] > 0:
|
| 1275 |
+
for student in studentsnotexist: # Goes through the emails not in the database
|
| 1276 |
+
encrypted_password = hashlib.sha256(student["password"].encode('utf-8')).hexdigest()# Encrypts the password
|
| 1277 |
+
# Then stores data into the studentsubscriptions collection
|
| 1278 |
+
importcsv.db.studentsubscriptions.insert_one({"hostemail":current_user,"email": student["email"],"password": encrypted_password,"emailsleft": 20,"subscription": "student educational"})
|
| 1279 |
+
|
| 1280 |
+
return {"message": "student subscriptions Set."}
|
| 1281 |
+
elif user_from_db["numofaccounts"] <= 0:
|
| 1282 |
+
return {"error": "No more student accounts left."}
|
| 1283 |
+
except Exception as ex:
|
| 1284 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1285 |
+
@app.route('/getstudentsubscriptions', methods=['GET'])
|
| 1286 |
+
@cross_origin()
|
| 1287 |
+
@jwt_required()
|
| 1288 |
+
def getstudentsubscriptions():
|
| 1289 |
+
current_user = get_jwt_identity()
|
| 1290 |
+
if current_user:
|
| 1291 |
+
try:
|
| 1292 |
+
student_user_from_db = list(importcsv.db.studentsubscriptions.find({"hostemail": current_user})) # [0]
|
| 1293 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1294 |
+
for student in student_user_from_db:
|
| 1295 |
+
del student["_id"], student["password"],student["hostemail"],student['subscription']
|
| 1296 |
+
|
| 1297 |
+
importcsv.db.users.delete_many(user_from_db) # Deletes the data in order to update it.
|
| 1298 |
+
del user_from_db["numofaccounts"] # Deletes the numofaccounts to update it.
|
| 1299 |
+
user_from_db.update({"numofaccounts": 200 - len(student_user_from_db)}) # Updates the number of accounts
|
| 1300 |
+
importcsv.db.users.insert_one(user_from_db) # inserts updated data into the host emails account
|
| 1301 |
+
return jsonify({"result":student_user_from_db})
|
| 1302 |
+
except Exception as ex:
|
| 1303 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1304 |
+
@app.route('/checkstudentsubscriptions', methods=['GET'])
|
| 1305 |
+
@cross_origin()
|
| 1306 |
+
@jwt_required()
|
| 1307 |
+
def checkstudentsubscriptions():
|
| 1308 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1309 |
+
if current_user:
|
| 1310 |
+
try:
|
| 1311 |
+
student_from_db = list(importcsv.db.studentsubscriptions.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1312 |
+
student_subscription = student_from_db["subscription"]
|
| 1313 |
+
student_subscription_json = {"student_subscription": student_subscription}
|
| 1314 |
+
return jsonify(student_subscription_json)
|
| 1315 |
+
except Exception as ex:
|
| 1316 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1317 |
+
@app.route('/deletestudentaccount', methods=['POST'])
|
| 1318 |
+
@cross_origin()
|
| 1319 |
+
@jwt_required()
|
| 1320 |
+
def deletestudentaccount():
|
| 1321 |
+
current_user = get_jwt_identity()
|
| 1322 |
+
if current_user:
|
| 1323 |
+
data = request.get_json()
|
| 1324 |
+
try:
|
| 1325 |
+
hostkey = importcsv.db.studentsubscriptions.find_one({"hostemail": current_user})
|
| 1326 |
+
studentkey = importcsv.db.studentsubscriptions.find_one({"email": data["studentemail"]})
|
| 1327 |
+
if hostkey and studentkey:
|
| 1328 |
+
importcsv.db.studentsubscriptions.delete_one({"email": data["studentemail"]})
|
| 1329 |
+
return jsonify({"message": "Student account deleted."})
|
| 1330 |
+
else:
|
| 1331 |
+
return jsonify({"error": "Student account does not exist."})
|
| 1332 |
+
except Exception as ex:
|
| 1333 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1334 |
+
@app.route('/changestudentpassword', methods=['PUT'])
|
| 1335 |
+
@cross_origin()
|
| 1336 |
+
@jwt_required()
|
| 1337 |
+
def changestudentpassword():
|
| 1338 |
+
current_user = get_jwt_identity()
|
| 1339 |
+
if current_user:
|
| 1340 |
+
data = request.get_json()
|
| 1341 |
+
try:
|
| 1342 |
+
hostkey = importcsv.db.studentsubscriptions.find_one({"hostemail": current_user})
|
| 1343 |
+
studentkey = importcsv.db.studentsubscriptions.find_one({"email": data["studentemail"]})
|
| 1344 |
+
if hostkey and studentkey:
|
| 1345 |
+
student_user_from_db = list(importcsv.db.studentsubscriptions.find({"email": data["studentemail"]}))[0]
|
| 1346 |
+
# TODO Delete password from here and replace.
|
| 1347 |
+
importcsv.db.studentsubscriptions.delete_many(student_user_from_db)
|
| 1348 |
+
del student_user_from_db["password"]
|
| 1349 |
+
encrypted_password = hashlib.sha256(data["password"].encode('utf-8')).hexdigest()
|
| 1350 |
+
student_user_from_db.update({"password": encrypted_password})
|
| 1351 |
+
importcsv.db.studentsubscriptions.insert_one(student_user_from_db)
|
| 1352 |
+
return jsonify({"message": "Password reset successful."})
|
| 1353 |
+
else:
|
| 1354 |
+
return jsonify({"error": "Student account does not exist."})
|
| 1355 |
+
except Exception as ex:
|
| 1356 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1357 |
+
|
| 1358 |
+
|
| 1359 |
+
|
| 1360 |
+
@app.route('/getfreetrial', methods=['GET'])
|
| 1361 |
+
@cross_origin()
|
| 1362 |
+
@jwt_required()
|
| 1363 |
+
def getfreetrial():
|
| 1364 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1365 |
+
if current_user:
|
| 1366 |
+
try:
|
| 1367 |
+
freetrialhistory = list(importcsv.db.freetrialhistory.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1368 |
+
freetrial = freetrialhistory["freetrial"]
|
| 1369 |
+
freetrial_subscription = {"freetrial": freetrial} # check freetrial
|
| 1370 |
+
return jsonify(freetrial_subscription)
|
| 1371 |
+
except Exception as ex:
|
| 1372 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1373 |
+
@app.route('/getemail', methods=['GET'])
|
| 1374 |
+
@cross_origin()
|
| 1375 |
+
@jwt_required()
|
| 1376 |
+
def getemail():
|
| 1377 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1378 |
+
if current_user:
|
| 1379 |
+
try:
|
| 1380 |
+
user_from_db = check_user_from_db(current_user)
|
| 1381 |
+
return {"email":user_from_db["email"]}
|
| 1382 |
+
except Exception as ex:
|
| 1383 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1384 |
+
|
| 1385 |
+
@app.route('/deletesubscription', methods=['DELETE'])
|
| 1386 |
+
@cross_origin()
|
| 1387 |
+
@jwt_required()
|
| 1388 |
+
def deletesubscription():
|
| 1389 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1390 |
+
if current_user:
|
| 1391 |
+
try:
|
| 1392 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1393 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1394 |
+
if "end_date_subscription" in user_from_db:
|
| 1395 |
+
del user_from_db["end_date_subscription"]
|
| 1396 |
+
if "start_date_subscription" in user_from_db:
|
| 1397 |
+
del user_from_db["start_date_subscription"]
|
| 1398 |
+
if "subscription" in user_from_db:
|
| 1399 |
+
del user_from_db["subscription"]
|
| 1400 |
+
if "emailsleft" in user_from_db:
|
| 1401 |
+
del user_from_db["emailsleft"]
|
| 1402 |
+
if "numofaccounts" in user_from_db:
|
| 1403 |
+
del user_from_db["numofaccounts"]
|
| 1404 |
+
importcsv.db.users.update_one( { "email": current_user}, {"$set": user_from_db}, upsert = True )
|
| 1405 |
+
|
| 1406 |
+
return jsonify({"message":"Subscription deleted from expiration"})
|
| 1407 |
+
except Exception as ex:
|
| 1408 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1409 |
+
@app.route('/getaccountinfo', methods=['GET'])
|
| 1410 |
+
@cross_origin()
|
| 1411 |
+
@jwt_required()
|
| 1412 |
+
def getaccountinfo():
|
| 1413 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1414 |
+
if current_user:
|
| 1415 |
+
try:
|
| 1416 |
+
email_exists = importcsv.db.users.find_one({"email": current_user})
|
| 1417 |
+
email_exists_student = importcsv.db.studentsubscriptions.find_one({"email": current_user})
|
| 1418 |
+
if email_exists:
|
| 1419 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1420 |
+
del user_from_db["password"], user_from_db["_id"]
|
| 1421 |
+
return jsonify(user_from_db)
|
| 1422 |
+
elif email_exists_student:
|
| 1423 |
+
student_user_from_db = list(importcsv.db.studentsubscriptions.find({"email": current_user}))[0]
|
| 1424 |
+
host_from_db = list(importcsv.db.users.find({"email": student_user_from_db["hostemail"]}))[0]
|
| 1425 |
+
student_user_from_db.update({"start_date_subscription":host_from_db["start_date_subscription"]})
|
| 1426 |
+
student_user_from_db.update({"end_date_subscription":host_from_db["end_date_subscription"]})
|
| 1427 |
+
del student_user_from_db["password"], student_user_from_db["_id"]
|
| 1428 |
+
return jsonify(student_user_from_db)
|
| 1429 |
+
#return {"error": f"account not found"}
|
| 1430 |
+
except Exception as ex:
|
| 1431 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1432 |
+
@app.route('/deleteaccount', methods=['DELETE'])
|
| 1433 |
+
@cross_origin()
|
| 1434 |
+
@jwt_required()
|
| 1435 |
+
def deleteaccount():
|
| 1436 |
+
current_user = get_jwt_identity() # outputs the email of the user example@gmail.com
|
| 1437 |
+
if current_user:
|
| 1438 |
+
try:
|
| 1439 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1440 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1441 |
+
return jsonify({"message":"Account Deleted"})
|
| 1442 |
+
except Exception as ex:
|
| 1443 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1444 |
+
@app.route('/getedexcelpapers',methods=['GET'])
|
| 1445 |
+
@cross_origin() # allow all origins all methods.
|
| 1446 |
+
def getedexcelpapers():
|
| 1447 |
+
try:
|
| 1448 |
+
data = request.get_json()
|
| 1449 |
+
dataedexcel = list(importcsv.db.edexcelpapers.find({"year":"AS Level"}))
|
| 1450 |
+
return {"result":dataedexcel}
|
| 1451 |
+
except Exception as ex:
|
| 1452 |
+
return {"error":f"{type(ex)},ex"}
|
| 1453 |
+
|
| 1454 |
+
if __name__ == "__main__":
|
| 1455 |
+
app.run(debug=True,host="0.0.0.0",port=5000)
|
| 1456 |
+
#app.run(debug=True)
|
| 1457 |
+
|
config.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
|
| 4 |
+
basedir = os.path.abspath(os.path.dirname(__file__))
|
| 5 |
+
load_dotenv(os.path.join(basedir, "secrets"))
|
| 6 |
+
load_dotenv(os.path.join(basedir, "configuration"))
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Config(object):
|
| 10 |
+
MAIL_DEFAULT_SENDER = os.environ.get("MAIL_DEFAULT_SENDER")
|
| 11 |
+
MAIL_PASSWORD = os.environ.get("MAIL_PASSWORD")
|
| 12 |
+
MAIL_PORT = int(os.environ.get("MAIL_PORT") or 25)
|
| 13 |
+
MAIL_SERVER = os.environ.get("MAIL_SERVER")
|
| 14 |
+
MAIL_USE_TLS = os.environ.get("MAIL_USE_TLS") != "False"
|
| 15 |
+
MAIL_USERNAME = os.environ.get("MAIL_USERNAME")
|
configuration
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MAIL_DEFAULT_SENDER=revisionbankedu@gmail.com
|
| 2 |
+
MAIL_PORT=587
|
| 3 |
+
MAIL_SERVER=smtp.sendgrid.net
|
| 4 |
+
MAIL_USE_TLS=True
|
| 5 |
+
MAIL_USERNAME=apikey
|
csv_to_db.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pymongo
|
| 2 |
+
import json
|
| 3 |
+
import certifi
|
| 4 |
+
# Mongo client Debugging:
|
| 5 |
+
# Tsl error :https://stackoverflow.com/questions/54484890/ssl-handshake-issue-with-pymongo-on-python3
|
| 6 |
+
# Ip address whilisting mongo atlas..
|
| 7 |
+
class ImportCSV:
|
| 8 |
+
def __init__(self,database,maindb=0) -> None:
|
| 9 |
+
ca = certifi.where()
|
| 10 |
+
# This tells python to specifically send a tls certificate for the connection.
|
| 11 |
+
if maindb == 0: # User Accounts Database
|
| 12 |
+
client = pymongo.MongoClient(f"mongodb+srv://palondrome:kya63amari@roadmaptestcluster0.avksy.mongodb.net/roadmaptestdb?retryWrites=true&w=majority",tlsCAFile=ca)
|
| 13 |
+
self.db = client[database]
|
| 14 |
+
elif maindb == 1:# Question Paper 1 Database
|
| 15 |
+
client = pymongo.MongoClient(f"mongodb+srv://palondrome2:kya63amari@cluster0.rxqjf.mongodb.net/chemistryqp?retryWrites=true&w=majority",tlsCAFile=ca)
|
| 16 |
+
self.db = client[database]
|
| 17 |
+
elif maindb == 2:# Question Paper 1 Database
|
| 18 |
+
client = pymongo.MongoClient(f"mongodb+srv://palondrome3:kya63amari@qpcluster1.iplrmml.mongodb.net/?retryWrites=true&w=majority",tlsCAFile=ca)
|
| 19 |
+
self.db = client[database]
|
| 20 |
+
def load_data(self,collection_name,init_data):
|
| 21 |
+
# Initialises collection
|
| 22 |
+
db_cm = self.db[collection_name]
|
| 23 |
+
def load_n_insert(data):
|
| 24 |
+
# Input is Dataframe
|
| 25 |
+
data_json = json.loads(data.to_json(orient='records'))
|
| 26 |
+
db_cm.insert_many(data_json)
|
| 27 |
+
load_n_insert(init_data)
|
forgotpassemail.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
def forgotpasswordemail(email,access_token):
|
| 3 |
+
emailtext = f"""
|
| 4 |
+
<h1 style="color:#264BE4;">RevisionBank</h1>
|
| 5 |
+
<strong>
|
| 6 |
+
Reset Password
|
| 7 |
+
</strong>
|
| 8 |
+
<p >
|
| 9 |
+
Hello {email}
|
| 10 |
+
</p>
|
| 11 |
+
<p>
|
| 12 |
+
A request has been received to change the password for your RevisionBank account.
|
| 13 |
+
</p>
|
| 14 |
+
<a href="https://revisionbank.org/resetpassword?token={access_token}" target="_blank" rel="noopener noreferrer">
|
| 15 |
+
<button style="width:40%;background-color: #264BE4;border: 1px solid #264BE4;border-radius: 10px;">
|
| 16 |
+
<p style="color:white">Reset Password</p>
|
| 17 |
+
</button>
|
| 18 |
+
</a>
|
| 19 |
+
"""
|
| 20 |
+
return emailtext
|
image.png
ADDED
|
main.py
ADDED
|
@@ -0,0 +1,1414 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import base64
|
| 2 |
+
import concurrent
|
| 3 |
+
import os
|
| 4 |
+
from concurrent.futures import thread
|
| 5 |
+
from datetime import datetime
|
| 6 |
+
import datetime as dt
|
| 7 |
+
import requests
|
| 8 |
+
from bs4 import BeautifulSoup
|
| 9 |
+
from flask import Flask, app, jsonify, request
|
| 10 |
+
from flask_cors import CORS, cross_origin
|
| 11 |
+
from flask_mail import Mail, Message
|
| 12 |
+
from physicsaqa import PhysicsAQA
|
| 13 |
+
from config import Config
|
| 14 |
+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt_identity
|
| 15 |
+
from csv_to_db import ImportCSV
|
| 16 |
+
from models import Users
|
| 17 |
+
from bson.objectid import ObjectId #
|
| 18 |
+
import hashlib
|
| 19 |
+
import random
|
| 20 |
+
from datetime import datetime
|
| 21 |
+
from PIL import Image, ImageOps
|
| 22 |
+
from io import BytesIO
|
| 23 |
+
import base64
|
| 24 |
+
import json
|
| 25 |
+
import stripe
|
| 26 |
+
import jwt
|
| 27 |
+
#import cv2
|
| 28 |
+
import re
|
| 29 |
+
import jwt
|
| 30 |
+
from fastapi import FastAPI, Header
|
| 31 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 32 |
+
from pydantic import BaseModel
|
| 33 |
+
from typing import Optional
|
| 34 |
+
from typing import Generic, TypeVar,Dict,List,AnyStr,Any,Union
|
| 35 |
+
import asyncio
|
| 36 |
+
import uvicorn
|
| 37 |
+
import pytesseract
|
| 38 |
+
from forgotpassemail import forgotpasswordemail
|
| 39 |
+
from RevisionBankModels import *
|
| 40 |
+
from fastapi_utils.tasks import repeat_every
|
| 41 |
+
from revisionbankscheduler import RevisionBankScheduler
|
| 42 |
+
app = FastAPI()
|
| 43 |
+
app.add_middleware(
|
| 44 |
+
CORSMiddleware,
|
| 45 |
+
allow_origins=["*"],
|
| 46 |
+
allow_credentials=True,
|
| 47 |
+
allow_methods=["*"],
|
| 48 |
+
allow_headers=["*"],
|
| 49 |
+
)
|
| 50 |
+
importcsv = ImportCSV("RevisionBankDB",maindb=0)
|
| 51 |
+
importcsvqp = ImportCSV("RevisionBankDB",maindb= 1)
|
| 52 |
+
importcsvqp1 = ImportCSV("RevisionBankQPs1",maindb=2)
|
| 53 |
+
revisionbankschedule = RevisionBankScheduler(importcsv)
|
| 54 |
+
JWT_SECRET = "Peter Piper picked a peck of pickled peppers, A peck of pickled peppers Peter Piper picked, If Peter Piper picked a peck of pickled peppers,Where's the peck of pickled peppers Peter Piper picked" #'super-secret'
|
| 55 |
+
# IRL we should NEVER hardcode the secret: it should be an evironment variable!!!
|
| 56 |
+
JWT_ALGORITHM = "HS256"
|
| 57 |
+
|
| 58 |
+
JSONObject = Dict[Any, Any]
|
| 59 |
+
JSONArray = List[Any]
|
| 60 |
+
JSONStructure = Union[JSONArray, JSONObject]
|
| 61 |
+
time_hour = 60 * 60 # 1 hour,
|
| 62 |
+
def secure_encode(token):
|
| 63 |
+
# if we want to sign/encrypt the JSON object: {"hello": "world"}, we can do it as follows
|
| 64 |
+
# encoded = jwt.encode({"hello": "world"}, JWT_SECRET, algorithm=JWT_ALGORITHM)
|
| 65 |
+
encoded_token = jwt.encode(token, JWT_SECRET, algorithm=JWT_ALGORITHM)
|
| 66 |
+
# this is often used on the client side to encode the user's email address or other properties
|
| 67 |
+
return encoded_token
|
| 68 |
+
|
| 69 |
+
def secure_decode(token):
|
| 70 |
+
# if we want to sign/encrypt the JSON object: {"hello": "world"}, we can do it as follows
|
| 71 |
+
# encoded = jwt.encode({"hello": "world"}, JWT_SECRET, algorithm=JWT_ALGORITHM)
|
| 72 |
+
decoded_token = jwt.decode(token, JWT_SECRET, algorithms=JWT_ALGORITHM)
|
| 73 |
+
# this is often used on the client side to encode the user's email address or other properties
|
| 74 |
+
return decoded_token
|
| 75 |
+
def getendsubscription(current_user):
|
| 76 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 77 |
+
end_date = user_from_db["end_date_subscription"]
|
| 78 |
+
return end_date
|
| 79 |
+
# Sending Emails from Heroku: https://blairconrad.com/2020/03/05/libraryhippo-2020-sending-email-from-heroku/
|
| 80 |
+
# Send Email API: https://app.sendgrid.com/
|
| 81 |
+
# Signin and Signup page: https://shayff.medium.com/building-your-first-flask-rest-api-with-mongodb-and-jwt-e03f2d317f04
|
| 82 |
+
# SetUp Tesseract: https://towardsdatascience.com/deploy-python-tesseract-ocr-on-heroku-bbcc39391a8d
|
| 83 |
+
def check_user_from_db(current_user): #test
|
| 84 |
+
email_exists = importcsv.db.users.find_one({"email":current_user})
|
| 85 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 86 |
+
if email_exists:
|
| 87 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 88 |
+
return user_from_db
|
| 89 |
+
elif student_email_exists:
|
| 90 |
+
user_from_db = list(importcsv.db.studentsubscriptions.find({"email": current_user}))[0]
|
| 91 |
+
return user_from_db
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@app.get('/')# GET # allow all origins all methods.
|
| 95 |
+
async def index():
|
| 96 |
+
return "Hello World"
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
@app.on_event("startup")
|
| 100 |
+
@repeat_every(seconds= time_hour * 24) # 24 hours
|
| 101 |
+
async def revisionbankschedulerevisioncardsrepeat() -> None:
|
| 102 |
+
revisionbankschedule.runschedule()
|
| 103 |
+
print("All Cards sent.")
|
| 104 |
+
|
| 105 |
+
@app.post("/revisionbankstripepayment") # POST # allow all origins all methods.
|
| 106 |
+
async def revisionbankstripepayment(data : JSONStructure = None, authorization: str = Header(None)):
|
| 107 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 108 |
+
if current_user:
|
| 109 |
+
try:
|
| 110 |
+
data = dict(data)#request.get_json()
|
| 111 |
+
price = data["price"]
|
| 112 |
+
stripe.api_key = "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"
|
| 113 |
+
#"sk_test_51La4WnLpfbhhIhYRjP1w036wUwBoatAgqNRYEoj9u6jMd7GvSmBioKgmwJsabjgAY8V5W8i2r3QdelOPe5VNOueB00zDxeXtDQ"
|
| 114 |
+
|
| 115 |
+
striperesponse = stripe.PaymentIntent.create(
|
| 116 |
+
amount=round(price*100),
|
| 117 |
+
currency="gbp",
|
| 118 |
+
payment_method_types=["card"],
|
| 119 |
+
)
|
| 120 |
+
clientsecret= striperesponse["client_secret"]
|
| 121 |
+
#print(clientsecret)
|
| 122 |
+
return {"clientsecret":clientsecret}
|
| 123 |
+
except Exception as ex:
|
| 124 |
+
return {"error":f"{type(ex)}-{ex}"}
|
| 125 |
+
|
| 126 |
+
@app.post('/revisionbanktranslate') # POST # allow all origins all methods.
|
| 127 |
+
async def revisionbanktranslate(data : JSONStructure = None, authorization: str = Header(None)):
|
| 128 |
+
async def read_img(img):
|
| 129 |
+
pytesseract.pytesseract.tesseract_cmd = "/app/.apt/usr/bin/tesseract"
|
| 130 |
+
text = pytesseract.image_to_string(img,
|
| 131 |
+
lang="eng",
|
| 132 |
+
config='--dpi 300 --psm 6 --oem 2 -c tessedit_char_blacklist=][|~_}{=!#%&«§><:;—?¢°*@,')
|
| 133 |
+
|
| 134 |
+
return(text)
|
| 135 |
+
try:
|
| 136 |
+
# TODO Use Tesseract OCR to get the text from the image hello
|
| 137 |
+
data = dict(data)#request.get_json()
|
| 138 |
+
img = data["revisioncardscreenshot"].replace("data:image/png;base64,","").replace("data:image/jpeg;base64,","")
|
| 139 |
+
# TODO Next Remove Blurriness and Noise from the image with cv2
|
| 140 |
+
#https://pyimagesearch.com/2017/07/10/using-tesseract-ocr-python/
|
| 141 |
+
img_obj =ImageOps.grayscale(Image.open(BytesIO(base64.b64decode(img))))
|
| 142 |
+
text = read_img(img_obj)
|
| 143 |
+
|
| 144 |
+
return {"revisioncardscreenshotext":text }
|
| 145 |
+
#return {"result":data}
|
| 146 |
+
except Exception as e:
|
| 147 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
@app.post('/getedexcelqp') # POST # allow all origins all methods.
|
| 151 |
+
async def getedexcelqp(data : JSONStructure = None, authorization: str = Header(None)):
|
| 152 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 153 |
+
if current_user:
|
| 154 |
+
try:
|
| 155 |
+
data = dict(data)#request.get_json()
|
| 156 |
+
edexcelpapers = list(importcsvqp.db.edexcelpapers.find({data["edexcelpaper"]:{"$exists":"true"}}))[0]
|
| 157 |
+
del edexcelpapers["_id"]
|
| 158 |
+
return {"edexcelpaper":edexcelpapers}
|
| 159 |
+
except Exception as e:
|
| 160 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 161 |
+
@app.post('/getcomputerscienceqp') # POST # allow all origins all methods.
|
| 162 |
+
async def getcomputerscienceqp(data : JSONStructure = None, authorization: str = Header(None)):
|
| 163 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 164 |
+
if current_user:
|
| 165 |
+
try:
|
| 166 |
+
data = dict(data)#request.get_json()
|
| 167 |
+
edexcelpapers = list(importcsvqp1.db.computerscienceqp.find({data["aqacomputerscience"]:{"$exists":"true"}}))[0]
|
| 168 |
+
del edexcelpapers["_id"]
|
| 169 |
+
return edexcelpapers # {"aqacomputerscience":edexcelpapers}
|
| 170 |
+
except Exception as e:
|
| 171 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 172 |
+
@app.post('/getcomputersciencems') # POST # allow all origins all methods.
|
| 173 |
+
async def getcomputersciencems(data : JSONStructure = None, authorization: str = Header(None)):
|
| 174 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 175 |
+
if current_user:
|
| 176 |
+
try:
|
| 177 |
+
data = dict(data)#request.get_json()
|
| 178 |
+
edexcelpapers = list(importcsvqp1.db.computersciencems.find({data["aqacomputerscience"]:{"$exists":"true"}}))[0]
|
| 179 |
+
del edexcelpapers["_id"]
|
| 180 |
+
return edexcelpapers # {"aqacomputerscience":edexcelpapers}
|
| 181 |
+
except Exception as e:
|
| 182 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 183 |
+
@app.post('/getphysicsocrqp') # POST # allow all origins all methods.
|
| 184 |
+
async def getphysicsocrqp(data : JSONStructure = None, authorization: str = Header(None)):
|
| 185 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 186 |
+
if current_user:
|
| 187 |
+
try:
|
| 188 |
+
data = dict(data)#request.get_json()
|
| 189 |
+
if data["subject"] == "physics":
|
| 190 |
+
edexcelpapers = list(importcsvqp1.db.physicsocrqp.find({data["questionpapersubject"]:{"$exists":"true"}}))[0]
|
| 191 |
+
elif data["subject"] == "chemistry":
|
| 192 |
+
edexcelpapers = list(importcsvqp.db.chemistryaqaqp.find({data["questionpapersubject"]:{"$exists":"true"}}))[0]
|
| 193 |
+
elif data["subject"] == "biology":
|
| 194 |
+
edexcelpapers = list(importcsvqp.db.biologyaqaqp.find({data["questionpapersubject"]:{"$exists":"true"}}))[0]
|
| 195 |
+
|
| 196 |
+
del edexcelpapers["_id"]
|
| 197 |
+
#print(edexcelpapers)
|
| 198 |
+
if data["scheme"] == "qp":
|
| 199 |
+
return {"questionpapersubject":edexcelpapers[data["questionpapersubject"]]["questionpaper"]}
|
| 200 |
+
elif data["scheme"] == "ms":
|
| 201 |
+
return {"questionpapersubject":edexcelpapers[data["questionpapersubject"]]["markscheme"]}
|
| 202 |
+
except Exception as e:
|
| 203 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
@app.post('/storeocrrevisioncards') # POST # allow all origins all methods.
|
| 207 |
+
async def storeocrrevisioncards(data : JSONStructure = None, authorization: str = Header(None)):
|
| 208 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 209 |
+
if current_user:
|
| 210 |
+
try:
|
| 211 |
+
data_json = dict(data)#request.get_json()
|
| 212 |
+
print(data_json)
|
| 213 |
+
data = data_json["revisioncardscheduler"]
|
| 214 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 215 |
+
if email_exists: # Checks if email exists
|
| 216 |
+
cards_not_exist = []
|
| 217 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0] # Gets the email.
|
| 218 |
+
|
| 219 |
+
#print(user_revision_cards)
|
| 220 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 221 |
+
if card not in user_revision_cards["revisioncards"]:
|
| 222 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 223 |
+
#cards_that_exist.append(card)
|
| 224 |
+
if cards_not_exist != []:
|
| 225 |
+
new_cards = cards_not_exist + user_revision_cards["revisioncards"] # adds new cards to the list.
|
| 226 |
+
user_revision_cards["revisioncards"] = new_cards # Updates the list.
|
| 227 |
+
del user_revision_cards["_id"]
|
| 228 |
+
user_revision_cards["email"] = current_user # Sets the email to the current user.
|
| 229 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user}) # Allows data to be updated.
|
| 230 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards) # Inserts the new data.
|
| 231 |
+
return {"message":"revision cards updated"}
|
| 232 |
+
elif cards_not_exist == []: # If the cards are already in the database, return a message.
|
| 233 |
+
return {"message":"No new cards"}
|
| 234 |
+
|
| 235 |
+
elif not email_exists:
|
| 236 |
+
return {"message": "account doesn't exist"}
|
| 237 |
+
except Exception as ex:
|
| 238 |
+
print(type(ex),ex)
|
| 239 |
+
@app.post('/storerevisioncards') # POST # allow all origins all methods.
|
| 240 |
+
async def storerevisioncards(data : JSONStructure = None, authorization: str = Header(None)):
|
| 241 |
+
try:
|
| 242 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 243 |
+
if current_user:
|
| 244 |
+
data_json = dict(data)#request.get_json() # test
|
| 245 |
+
data = data_json["revisioncardscheduler"]
|
| 246 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 247 |
+
if email_exists: # Checks if email exists
|
| 248 |
+
cards_not_exist = []
|
| 249 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0] # Gets the email.
|
| 250 |
+
|
| 251 |
+
#print(user_revision_cards)
|
| 252 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 253 |
+
if card not in user_revision_cards["revisioncards"]:
|
| 254 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 255 |
+
#cards_that_exist.append(card)
|
| 256 |
+
if cards_not_exist != []:
|
| 257 |
+
new_cards = cards_not_exist + user_revision_cards["revisioncards"] # adds new cards to the list.
|
| 258 |
+
user_revision_cards["revisioncards"] = new_cards # Updates the list.
|
| 259 |
+
del user_revision_cards["_id"]
|
| 260 |
+
user_revision_cards["email"] = current_user # Sets the email to the current user.
|
| 261 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user}) # Allows data to be updated.
|
| 262 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards) # Inserts the new data.
|
| 263 |
+
return {"message":"revision cards updated"}
|
| 264 |
+
elif cards_not_exist == []: # If the cards are already in the database, return a message.
|
| 265 |
+
return {"message":"No new cards"}
|
| 266 |
+
|
| 267 |
+
elif not email_exists:
|
| 268 |
+
data["email"] = current_user
|
| 269 |
+
importcsv.db.accountrevisioncards.insert_one(data)
|
| 270 |
+
|
| 271 |
+
return {"message": "revision card stored"}
|
| 272 |
+
except Exception as ex:
|
| 273 |
+
print(type(ex),ex)
|
| 274 |
+
@app.put('/changesendtoemail')# PUT # allow all origins all methods.
|
| 275 |
+
async def changesendtoemail(data : JSONStructure = None, authorization: str = Header(None)): # TODO
|
| 276 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 277 |
+
if current_user:
|
| 278 |
+
try:
|
| 279 |
+
data = dict(data)#request.get_json()
|
| 280 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 281 |
+
if email_exists:
|
| 282 |
+
scheduled_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 283 |
+
if scheduled_exists:
|
| 284 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 285 |
+
importcsv.db.scheduledcards.delete_many(user_scheduled_cards)
|
| 286 |
+
del user_scheduled_cards["sendtoemail"]
|
| 287 |
+
sendtoemailscheduled = user_scheduled_cards["sendtoemail"]
|
| 288 |
+
user_scheduled_cards.update({"sendtoemail": sendtoemailscheduled})
|
| 289 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards)
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 293 |
+
importcsv.db.accountrevisioncards.delete_many(user_revision_cards)
|
| 294 |
+
del user_revision_cards["sendtoemail"]
|
| 295 |
+
sendtoemail = data["sendtoemail"]
|
| 296 |
+
user_revision_cards.update({"sendtoemail": sendtoemail})
|
| 297 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards)
|
| 298 |
+
return {"message": "Send to email changed."}
|
| 299 |
+
elif not email_exists:
|
| 300 |
+
return {"message":"email does not exist"}
|
| 301 |
+
except Exception as ex:
|
| 302 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 303 |
+
@app.post('/changerevisioncard') # POST # allow all origins all methods.
|
| 304 |
+
async def changerevisioncard(data : JSONStructure = None, authorization: str = Header(None)):
|
| 305 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 306 |
+
if current_user:
|
| 307 |
+
try:
|
| 308 |
+
data = dict(data)#request.get_json()
|
| 309 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 310 |
+
if email_exists: # Checks if email exists
|
| 311 |
+
# TODO Slightly buggy here - removes old schedule from the database.
|
| 312 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 313 |
+
if user_scheduled_cards:
|
| 314 |
+
for card in user_scheduled_cards["revisioncards"]:
|
| 315 |
+
oldcard = {i:data[i] for i in data if i!='newrevisioncard'}
|
| 316 |
+
if card == oldcard:
|
| 317 |
+
user_scheduled_cards["revisioncards"].remove(card)
|
| 318 |
+
#importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 319 |
+
#importcsv.db.scheduledcards.insert_one(user_scheduled_cards)
|
| 320 |
+
importcsv.db.scheduledcards.replace_one(
|
| 321 |
+
{"email":current_user},user_scheduled_cards
|
| 322 |
+
)
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 326 |
+
for card in user_revision_cards["revisioncards"]:
|
| 327 |
+
oldcard = {i:data[i] for i in data if i!='newrevisioncard'}
|
| 328 |
+
if card == oldcard:
|
| 329 |
+
user_revision_cards["revisioncards"].remove(card)
|
| 330 |
+
del data["revisioncard"]
|
| 331 |
+
data["revisioncard"] = data["newrevisioncard"]
|
| 332 |
+
del data["newrevisioncard"]
|
| 333 |
+
user_revision_cards["revisioncards"].append(data)
|
| 334 |
+
importcsv.db.accountrevisioncards.replace_one(
|
| 335 |
+
{"email":current_user},user_revision_cards
|
| 336 |
+
)
|
| 337 |
+
#importcsv.db.accountrevisioncards.delete_many({"email":current_user})
|
| 338 |
+
#importcsv.db.accountrevisioncards.insert_one(user_revision_cards)
|
| 339 |
+
return {"message":"revision card changed."}
|
| 340 |
+
except Exception as ex:
|
| 341 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 342 |
+
|
| 343 |
+
|
| 344 |
+
|
| 345 |
+
@app.get('/getrevisioncards')# GET # allow all origins all methods.
|
| 346 |
+
async def getrevisioncards(authorization: str = Header(None)):
|
| 347 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 348 |
+
if current_user:
|
| 349 |
+
try:
|
| 350 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 351 |
+
if email_exists: # Checks if email exists
|
| 352 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 353 |
+
del user_revision_cards["_id"],user_revision_cards["email"]
|
| 354 |
+
return user_revision_cards
|
| 355 |
+
elif not email_exists:
|
| 356 |
+
return {"message":"No revision cards"} # Send in shape of data
|
| 357 |
+
except Exception as ex:
|
| 358 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 359 |
+
@app.post('/uploadrevisioncardtxtfile') # POST # allow all origins all methods.
|
| 360 |
+
async def uploadrevisioncardtxtfile(data : JSONStructure = None, authorization: str = Header(None)):
|
| 361 |
+
try:
|
| 362 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 363 |
+
if current_user:
|
| 364 |
+
file = request.files["file"]
|
| 365 |
+
if file:
|
| 366 |
+
return {"message":file}
|
| 367 |
+
elif not file:
|
| 368 |
+
{"message":"No file"}
|
| 369 |
+
except Exception as ex:
|
| 370 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
@app.post('/removerevisioncard') # POST # allow all origins all methods.
|
| 374 |
+
async def removerevisioncard(data : JSONStructure = None, authorization: str = Header(None)):
|
| 375 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 376 |
+
if current_user:
|
| 377 |
+
try:
|
| 378 |
+
data = dict(data)#request.get_json()
|
| 379 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":current_user})
|
| 380 |
+
if email_exists: # Checks if email exists
|
| 381 |
+
# Remove the revision card from the database.
|
| 382 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": current_user}))[0]
|
| 383 |
+
for card in user_revision_cards["revisioncards"]:
|
| 384 |
+
if card == data:
|
| 385 |
+
user_revision_cards["revisioncards"].remove(card)
|
| 386 |
+
importcsv.db.accountrevisioncards.delete_many({"email":current_user})
|
| 387 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards)
|
| 388 |
+
# Remove the revision card from the scheduled cards
|
| 389 |
+
try:
|
| 390 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 391 |
+
for card in user_scheduled_cards["revisioncards"]:
|
| 392 |
+
if card == data:
|
| 393 |
+
user_scheduled_cards["revisioncards"].remove(card)
|
| 394 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 395 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards)
|
| 396 |
+
return {"message":"revision card removed"}
|
| 397 |
+
except IndexError as iex:
|
| 398 |
+
return {"message":"revision card removed"}
|
| 399 |
+
|
| 400 |
+
except Exception as ex:
|
| 401 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 402 |
+
@app.post('/schedulerevisioncard') # POST # allow all origins all methods.
|
| 403 |
+
async def schedulerevisioncard(data : JSONStructure = None, authorization: str = Header(None)):
|
| 404 |
+
try:
|
| 405 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 406 |
+
if current_user:
|
| 407 |
+
data = dict(data)#request.get_json() # test
|
| 408 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 409 |
+
if email_exists: # Checks if email exists
|
| 410 |
+
cards_not_exist = []
|
| 411 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0] # Gets the email.
|
| 412 |
+
|
| 413 |
+
#print(user_revision_cards)
|
| 414 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 415 |
+
if card not in user_scheduled_cards["revisioncards"]:
|
| 416 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 417 |
+
#cards_that_exist.append(card)
|
| 418 |
+
if cards_not_exist != []:
|
| 419 |
+
new_cards = cards_not_exist + user_scheduled_cards["revisioncards"] # adds new cards to the list.
|
| 420 |
+
user_scheduled_cards["revisioncards"] = new_cards # Updates the list.
|
| 421 |
+
del user_scheduled_cards["_id"]
|
| 422 |
+
user_scheduled_cards["email"] = current_user # Sets the email to the current user.
|
| 423 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user}) # Allows data to be updated.
|
| 424 |
+
importcsv.db.scheduledcards.insert_one(user_scheduled_cards) # Inserts the new data.
|
| 425 |
+
return {"message":"revision cards scheduled"}
|
| 426 |
+
elif cards_not_exist == []: # If the cards are already in the database, return a message.
|
| 427 |
+
return {"message":"revision cards already scheduled"}
|
| 428 |
+
|
| 429 |
+
elif not email_exists:
|
| 430 |
+
data["email"] = current_user
|
| 431 |
+
importcsv.db.scheduledcards.insert_one(data)
|
| 432 |
+
|
| 433 |
+
return {"message": "revision card scheduled"}
|
| 434 |
+
except Exception as ex:
|
| 435 |
+
print(type(ex),ex)
|
| 436 |
+
@app.delete('/unscheduleallrevisioncard') # DELETE # allow all origins all methods.
|
| 437 |
+
async def unscheduleallrevisioncard(authorization: str = Header(None)):
|
| 438 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 439 |
+
if current_user:
|
| 440 |
+
try:
|
| 441 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 442 |
+
if email_exists: # Checks if email exists
|
| 443 |
+
user_revision_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 444 |
+
user_revision_cards["revisioncards"] = []
|
| 445 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 446 |
+
importcsv.db.scheduledcards.insert_one(user_revision_cards)
|
| 447 |
+
return {"message":"Allrevision card unscheduled"}
|
| 448 |
+
except Exception as ex:
|
| 449 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 450 |
+
@app.post('/unschedulerevisioncard') # POST # allow all origins all methods.
|
| 451 |
+
async def unschedulerevisioncard(data : JSONStructure = None, authorization: str = Header(None)):
|
| 452 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 453 |
+
if current_user:
|
| 454 |
+
try:
|
| 455 |
+
data = dict(data)#request.get_json()
|
| 456 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 457 |
+
if email_exists: # Checks if email exists
|
| 458 |
+
|
| 459 |
+
user_revision_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 460 |
+
for card in user_revision_cards["revisioncards"]:
|
| 461 |
+
if card == data:
|
| 462 |
+
user_revision_cards["revisioncards"].remove(card)
|
| 463 |
+
importcsv.db.scheduledcards.delete_many({"email":current_user})
|
| 464 |
+
importcsv.db.scheduledcards.insert_one(user_revision_cards)
|
| 465 |
+
return {"message":"revision card unscheduled"}
|
| 466 |
+
except Exception as ex:
|
| 467 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 468 |
+
@app.post('/sendnowrevisioncard') # POST # allow all origins all methods.
|
| 469 |
+
async def sendnowrevisioncard(data : JSONStructure = None, authorization: str = Header(None)):
|
| 470 |
+
try:
|
| 471 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 472 |
+
if current_user:
|
| 473 |
+
data = dict(data)#request.get_json()
|
| 474 |
+
now = datetime.now().strftime("%c")
|
| 475 |
+
message = f"""{data['revisioncards'][0]['revisioncardtitle']}{data["revisioncards"][0]["revisioncard"]}"""
|
| 476 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":data["sendtoemail"],"message":message,"subject":f"{data['revisioncards'][0]['subject']} Send Now"}})
|
| 477 |
+
#print(response.text)
|
| 478 |
+
#msg = Message(f"{data['revisioncards'][0]['subject']} Send Now", recipients=[data["sendtoemail"]]) # "amari.lawal@gmail.com"
|
| 479 |
+
#msg.body = f"Mail from RevisionCard Send Now at {now}"
|
| 480 |
+
#if "!DOCTYPE" not in data["revisioncards"][0]["revisioncard"] or "h1" not in data["revisioncards"][0]["revisioncard"]:
|
| 481 |
+
# msg.html = f"""<pre>{data['revisioncards'][0]['revisioncardtitle']}
|
| 482 |
+
# {data["revisioncards"][0]["revisioncard"]}</pre>"""
|
| 483 |
+
#elif "!DOCTYPE" in data["revisioncards"][0]["revisioncard"] or "h1" in data["revisioncards"][0]["revisioncard"]:
|
| 484 |
+
# msg.html = f"""
|
| 485 |
+
# {data['revisioncards'][0]['revisioncardtitle']}
|
| 486 |
+
# {data["revisioncards"][0]["revisioncard"]}
|
| 487 |
+
# """
|
| 488 |
+
#print(msg)
|
| 489 |
+
#mail.send(msg)
|
| 490 |
+
return {"message":"revision card sent"}
|
| 491 |
+
except Exception as ex:
|
| 492 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 493 |
+
@app.get('/checkschedulerevisioncard')# GET # allow all origins all methods.
|
| 494 |
+
async def checkschedulerevisioncard(authorization: str = Header(None)):
|
| 495 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 496 |
+
if current_user:
|
| 497 |
+
try:
|
| 498 |
+
email_exists = importcsv.db.scheduledcards.find_one({"email":current_user})
|
| 499 |
+
if email_exists: # Checks if email exists
|
| 500 |
+
user_scheduled_cards = list(importcsv.db.scheduledcards.find({"email": current_user}))[0]
|
| 501 |
+
del user_scheduled_cards["_id"],user_scheduled_cards["email"],user_scheduled_cards["revisionscheduleinterval"],user_scheduled_cards["sendtoemail"]
|
| 502 |
+
return user_scheduled_cards
|
| 503 |
+
elif not email_exists:
|
| 504 |
+
return {"message":"revision cards not scheduled"} # Send in shape of data
|
| 505 |
+
except Exception as ex:
|
| 506 |
+
return {f"error":f"{type(ex)},{str(ex)}"}
|
| 507 |
+
|
| 508 |
+
@app.post('/fmathsqp') # POST # allow all origins all methods.
|
| 509 |
+
async def fmathsqp(data : JSONStructure = None, authorization: str = Header(None)):
|
| 510 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 511 |
+
if current_user:
|
| 512 |
+
datajson = dict(data)#request.get_json()
|
| 513 |
+
try:
|
| 514 |
+
main_qp_url = "https://www.physicsandmathstutor.com/a-level-maths-papers/"
|
| 515 |
+
data = datajson["furthermaths"]
|
| 516 |
+
email = data["email"]
|
| 517 |
+
book_inp = data["furthermathsbook"]
|
| 518 |
+
topic_inp = data["furthermathstopic"]
|
| 519 |
+
platform = data["platform"]
|
| 520 |
+
qp_sections = {"Core":["c1",'c2','c3','c4'],"Mechanics":['m1','m2','m3','m4','m5'],"Statistics":['s1','s2','s3','s4'],'Further Pure':['fp1','fp2','fp3'],'Decision Maths':['d1','d2']}
|
| 521 |
+
if "c".lower() in book_inp.lower():
|
| 522 |
+
book_choice = "c"
|
| 523 |
+
elif "m".lower() in book_inp.lower():
|
| 524 |
+
book_choice = "m"
|
| 525 |
+
elif "s".lower() in book_inp.lower():
|
| 526 |
+
book_choice = "s"
|
| 527 |
+
elif "fp".lower() in book_inp.lower():
|
| 528 |
+
book_choice = "fp"
|
| 529 |
+
elif "d".lower() in book_inp.lower():
|
| 530 |
+
book_choice = "d"
|
| 531 |
+
elif "a".lower() in book_inp.lower():
|
| 532 |
+
book_choice = "a"
|
| 533 |
+
else:
|
| 534 |
+
return {"result": "doesn't exist"}
|
| 535 |
+
if book_choice != "a":
|
| 536 |
+
endpoints = [endpoint for val in qp_sections.values() for endpoint in val if book_choice in endpoint]
|
| 537 |
+
elif book_choice == "a":
|
| 538 |
+
endpoints = [endpoint for val in qp_sections.values() for endpoint in val]
|
| 539 |
+
|
| 540 |
+
|
| 541 |
+
pdf_result = []
|
| 542 |
+
pdf_titles = []
|
| 543 |
+
def qp_extraction(qp_url,end):
|
| 544 |
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0","Accept-Encoding": "gzip, async deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
|
| 545 |
+
response_topic = requests.get(f"{qp_url}/{end}-by-topic/",headers=headers).text
|
| 546 |
+
#if "This site is currently under going scheduled maintenance." in response_topic:
|
| 547 |
+
# return {"error":"Physics maths tutor is in maintenance mode."}
|
| 548 |
+
soup = BeautifulSoup(response_topic,features='lxml')
|
| 549 |
+
for child in soup.find_all(['a'],href=True):
|
| 550 |
+
if topic_inp.lower() in str(child.text).lower():
|
| 551 |
+
pdf_url = child['href']
|
| 552 |
+
#print(pdf_url)
|
| 553 |
+
#print(f'{str(child.text).capitalize()}.pdf')
|
| 554 |
+
pdf_titles.append(f'{str(child.text).capitalize()}.pdf')
|
| 555 |
+
pdf_result.append(pdf_url)
|
| 556 |
+
#response = requests.get(pdf_url)
|
| 557 |
+
#pdf_result.append(str(response.content).replace("b'","").replace("'",""))
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
|
| 561 |
+
|
| 562 |
+
#print(endpoints)
|
| 563 |
+
def topic_extraction(end):
|
| 564 |
+
qp_extraction(main_qp_url,end)
|
| 565 |
+
|
| 566 |
+
def threads_url(data : JSONStructure = None, authorization: str = Header(None)):
|
| 567 |
+
#threads = 60 # 20 # TODO Number of threads may be blowing up the router.
|
| 568 |
+
threads = 4
|
| 569 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor: #max_workers=threads
|
| 570 |
+
executor.map(topic_extraction,endpoints)
|
| 571 |
+
threads_url()
|
| 572 |
+
message = """
|
| 573 |
+
The Further Maths question papers, email has been sent to you:
|
| 574 |
+
"""
|
| 575 |
+
linkmessage = """
|
| 576 |
+
The Further Maths question papers links:
|
| 577 |
+
"""
|
| 578 |
+
|
| 579 |
+
#random.shuffle(pdf_result)
|
| 580 |
+
#random.shuffle(pdf_titles)
|
| 581 |
+
if pdf_result != []:
|
| 582 |
+
if len(pdf_result) > 5:
|
| 583 |
+
pdf_slice = round(len(pdf_result) * (100/100))
|
| 584 |
+
else:
|
| 585 |
+
pdf_slice = round(len(pdf_result) * (100/100))
|
| 586 |
+
for link,title in zip(pdf_result[:pdf_slice],pdf_titles[:pdf_slice]):
|
| 587 |
+
linkmessage += "<br>"
|
| 588 |
+
linkmessage += f"{title}" + "<br>"
|
| 589 |
+
linkmessage += link.replace(" ",'%20') + "<br>"
|
| 590 |
+
for i in pdf_titles:
|
| 591 |
+
message += "\n"
|
| 592 |
+
message += i + "\n"
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
|
| 596 |
+
user_from_db = check_user_from_db(current_user)
|
| 597 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 598 |
+
if "end_date_subscription" in user_from_db:
|
| 599 |
+
end_date = getendsubscription(current_user)
|
| 600 |
+
if user_from_db["emailsleft"] <= 0:
|
| 601 |
+
if platform == "app":
|
| 602 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 603 |
+
elif platform == "web":
|
| 604 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 605 |
+
return pdf_response
|
| 606 |
+
|
| 607 |
+
elif user_from_db["emailsleft"] > 0:
|
| 608 |
+
now = datetime.now().strftime("%c")
|
| 609 |
+
message = f"""
|
| 610 |
+
<h1>The Further Maths question papers links:</h1>
|
| 611 |
+
<p>{linkmessage}</p>.
|
| 612 |
+
"""
|
| 613 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathqp PDFs"}})
|
| 614 |
+
|
| 615 |
+
#msg = Message("FMathqp PDFs", recipients=[email]) # "amari.lawal@gmail.com"
|
| 616 |
+
#msg.body = f"Mail from FMathqp at {now}"
|
| 617 |
+
#msg.html = f"""
|
| 618 |
+
#<h1>The Further Maths question papers links:</h1>
|
| 619 |
+
#<p>{linkmessage}</p>.
|
| 620 |
+
#"""
|
| 621 |
+
|
| 622 |
+
#mail.send(msg)
|
| 623 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 624 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 625 |
+
if platform == "app":
|
| 626 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 627 |
+
elif platform == "web":
|
| 628 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":end_date}}
|
| 629 |
+
|
| 630 |
+
return pdf_response
|
| 631 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 632 |
+
if platform == "app":
|
| 633 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 634 |
+
elif platform == "web":
|
| 635 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":99999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 636 |
+
return pdf_response
|
| 637 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 638 |
+
if user_from_db["emailsleft"] <= 0:
|
| 639 |
+
if platform == "app":
|
| 640 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 641 |
+
elif platform == "web":
|
| 642 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 643 |
+
return pdf_response
|
| 644 |
+
|
| 645 |
+
elif user_from_db["emailsleft"] > 0:
|
| 646 |
+
now = datetime.now().strftime("%c")
|
| 647 |
+
message = f"""
|
| 648 |
+
<h1>The Further Maths question papers links:</h1>
|
| 649 |
+
<p>{linkmessage}</p>.
|
| 650 |
+
"""
|
| 651 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathqp PDFs"}})
|
| 652 |
+
|
| 653 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 654 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 655 |
+
if platform == "app":
|
| 656 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 657 |
+
elif platform == "web":
|
| 658 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":99999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 659 |
+
return pdf_response
|
| 660 |
+
elif pdf_result == []:
|
| 661 |
+
return {"error":"No further maths question papers available"}
|
| 662 |
+
except Exception as e:
|
| 663 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 664 |
+
else:
|
| 665 |
+
return {"message": "Login first please."}
|
| 666 |
+
|
| 667 |
+
|
| 668 |
+
@app.post('/fmathsb') # POST # allow all origins all methods.
|
| 669 |
+
async def fmathsb(data : JSONStructure = None, authorization: str = Header(None)):
|
| 670 |
+
#pure maths: 0, statistics mechanics: 1, core pure maths: 2, further pure maths: 3, further statistics: 4, further mechanics: 5, decision maths: 6"
|
| 671 |
+
# year/book: 1, year/book: 2
|
| 672 |
+
# {"furthermathsb":{"email":"amari.lawal@gmail.com","furthermathsbbook": 0,"furthermathsbyear":2}}
|
| 673 |
+
# Output PureMaths Book 2
|
| 674 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 675 |
+
if current_user:
|
| 676 |
+
try:
|
| 677 |
+
sb_books_list = {"0":"pure-maths","1":"statistics-mechanics","2":"core-pure-maths","3":"further-pure-maths","4":"further-statistics","5":"further-mechanics","6":"decision-maths"}
|
| 678 |
+
datajson = dict(data)#request.get_json()
|
| 679 |
+
data = datajson["furthermathsb"]
|
| 680 |
+
email = data["email"]
|
| 681 |
+
sb_book_inp = str(data["furthermathsbbook"])
|
| 682 |
+
sb_year_inp = str(data["furthermathsbyear"])
|
| 683 |
+
sb_exercise = str(data["furthermathsbexercise"])
|
| 684 |
+
platform = data["platform"]
|
| 685 |
+
|
| 686 |
+
sb_book = sb_books_list[str(sb_book_inp)]
|
| 687 |
+
sb_year = str(sb_year_inp)
|
| 688 |
+
|
| 689 |
+
if sb_book == "pure-maths" or sb_book == "statistics-mechanics":
|
| 690 |
+
sb_url = f"https://www.physicsandmathstutor.com/maths-revision/solutionbanks/edexcel-{sb_book}-year-{sb_year}/"
|
| 691 |
+
#print(sb_url)
|
| 692 |
+
else:
|
| 693 |
+
sb_url = f"https://www.physicsandmathstutor.com/maths-revision/solutionbanks/edexcel-{sb_book}-{sb_year}/"
|
| 694 |
+
|
| 695 |
+
book_dir_name = f"{sb_book}{str(sb_year)}".capitalize()
|
| 696 |
+
|
| 697 |
+
response = requests.get(sb_url).text
|
| 698 |
+
soup = BeautifulSoup(response,features='lxml')
|
| 699 |
+
soup_a_tags = soup.find_all(['a'],href=True)
|
| 700 |
+
sb_result = []
|
| 701 |
+
sb_titles = []
|
| 702 |
+
async def sb_extraction(child):
|
| 703 |
+
if "Exercise" in child.text and sb_exercise.upper() in child.text:
|
| 704 |
+
print(child.text)
|
| 705 |
+
pdf_url = child['href']
|
| 706 |
+
#response = requests.get(pdf_url)
|
| 707 |
+
sb_titles.append(f'{book_dir_name}-{str(child.text).capitalize()}.pdf')
|
| 708 |
+
sb_result.append(pdf_url)
|
| 709 |
+
async def threads_url(data : JSONStructure = None, authorization: str = Header(None)):
|
| 710 |
+
#threads = 60 # 20 # TODO Number of threads may be blowing up the router.
|
| 711 |
+
threads = 4
|
| 712 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor: #max_workers=threads
|
| 713 |
+
executor.map(sb_extraction,soup_a_tags)
|
| 714 |
+
threads_url()
|
| 715 |
+
if sb_result != []:
|
| 716 |
+
message = """
|
| 717 |
+
The Further Maths solution bank, email has been sent to you:
|
| 718 |
+
"""
|
| 719 |
+
linkmessage = """
|
| 720 |
+
The Further Maths question papers links:
|
| 721 |
+
"""
|
| 722 |
+
for link,title in zip(sb_result,sb_titles):
|
| 723 |
+
linkmessage += "<br>"
|
| 724 |
+
linkmessage += f"{title}" + "<br>"
|
| 725 |
+
linkmessage += link.replace(" ",'%20') + "<br>"
|
| 726 |
+
for i in sb_titles:
|
| 727 |
+
message += "\n"
|
| 728 |
+
message += i + "\n"
|
| 729 |
+
user_from_db = check_user_from_db(current_user)
|
| 730 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 731 |
+
if "end_date_subscription" in user_from_db:
|
| 732 |
+
end_date = getendsubscription(current_user)
|
| 733 |
+
if user_from_db["emailsleft"] <= 0:
|
| 734 |
+
if platform == "app":
|
| 735 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 736 |
+
elif platform == "web":
|
| 737 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 738 |
+
return pdf_response
|
| 739 |
+
|
| 740 |
+
elif user_from_db["emailsleft"] > 0:
|
| 741 |
+
now = datetime.now().strftime("%c")
|
| 742 |
+
message = f"""
|
| 743 |
+
<h1>The Further Maths Solution Bank links:</h1>
|
| 744 |
+
<p>{linkmessage}</p>.
|
| 745 |
+
"""
|
| 746 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathSB PDFs"}})
|
| 747 |
+
|
| 748 |
+
#msg = Message("FMathSB PDFs", recipients=[email]) # "amari.lawal@gmail.com"
|
| 749 |
+
#msg.body = f"Mail from FMathsb at {now}"
|
| 750 |
+
#msg.html = f"""
|
| 751 |
+
#<h1>The Further Maths Solution Bank links:</h1>
|
| 752 |
+
#<p>{linkmessage}</p>.
|
| 753 |
+
#"""
|
| 754 |
+
|
| 755 |
+
#mail.send(msg)
|
| 756 |
+
emailcount = int(user_from_db["emailsleft"])-1
|
| 757 |
+
user_from_db.update({"emailsleft":emailcount})
|
| 758 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 759 |
+
|
| 760 |
+
if platform == "app":
|
| 761 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 762 |
+
elif platform == "web":
|
| 763 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":emailcount,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 764 |
+
return pdf_response
|
| 765 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 766 |
+
if platform == "app":
|
| 767 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 768 |
+
elif platform == "web":
|
| 769 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":9999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 770 |
+
return pdf_response
|
| 771 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 772 |
+
if user_from_db["emailsleft"] <= 0:
|
| 773 |
+
if platform == "app":
|
| 774 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 775 |
+
elif platform == "web":
|
| 776 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":0,"end_date_subscription":end_date}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 777 |
+
return pdf_response
|
| 778 |
+
|
| 779 |
+
elif user_from_db["emailsleft"] > 0:
|
| 780 |
+
now = datetime.now().strftime("%c")
|
| 781 |
+
message = f"""
|
| 782 |
+
<h1>The Further Maths Solution Bank links:</h1>
|
| 783 |
+
<p>{linkmessage}</p>.
|
| 784 |
+
"""
|
| 785 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":"FMathSB PDFs"}})
|
| 786 |
+
|
| 787 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 788 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 789 |
+
if platform == "app":
|
| 790 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":message}} # "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 791 |
+
elif platform == "web":
|
| 792 |
+
pdf_response = {"furthermathsresult":{"furthermathsmessage":linkmessage,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":9999999}}# "furthermathslinks":pdf_result,"furthermathstitles":pdf_titles,"furthermathslinkmessage":linkmessage
|
| 793 |
+
return pdf_response
|
| 794 |
+
|
| 795 |
+
elif sb_result == []:
|
| 796 |
+
return {f"error":f"No further maths solution bank for {sb_book} {sb_year}"}
|
| 797 |
+
except Exception as e:
|
| 798 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 799 |
+
else:
|
| 800 |
+
return {"message": "Login first please."}
|
| 801 |
+
@app.post('/ocrsciencebookanswers') # POST # allow all origins all methods.
|
| 802 |
+
async def scienceocranswers(data : JSONStructure = None, authorization: str = Header(None)):
|
| 803 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 804 |
+
if current_user:
|
| 805 |
+
datajson = dict(data)#request.get_json()
|
| 806 |
+
|
| 807 |
+
async def ocrscienceanswers(querydata):
|
| 808 |
+
examboards = "OCR"
|
| 809 |
+
url = "https://global.oup.com/education/content/secondary/series/ocr-a-level-sciences/a-level-sciences-for-ocr-student-book-answers/?region=uk"
|
| 810 |
+
physicsanswerspdf = {}
|
| 811 |
+
|
| 812 |
+
response= requests.get(url).text
|
| 813 |
+
soup = BeautifulSoup(response,features='lxml')
|
| 814 |
+
for divele in soup.find_all('div',{'class':'content_block half_width enclosed'}): # inner_block text_only_single ##
|
| 815 |
+
if querydata in divele.text:
|
| 816 |
+
for a in divele.find_all("a",href=True):
|
| 817 |
+
if a["href"] != "?region=uk":
|
| 818 |
+
physicsanswerspdf.update({a.text.replace("\xa0",' '): a["href"].replace("?region=uk",'')})
|
| 819 |
+
|
| 820 |
+
result = {querydata:{examboards:physicsanswerspdf}}
|
| 821 |
+
return result
|
| 822 |
+
try:
|
| 823 |
+
data = datajson["physicsocr"]
|
| 824 |
+
email = data["email"]
|
| 825 |
+
subject = data["subject"] # physics, chemistry, biology
|
| 826 |
+
physicsocralph = data["physicsocralph"] # A or B
|
| 827 |
+
chapter = data["chapter"] # Chapter 1
|
| 828 |
+
year = data["year"] # AS/Year 1, A Level
|
| 829 |
+
platform = data["platform"] # web or app
|
| 830 |
+
|
| 831 |
+
query = f"{subject.capitalize()} {physicsocralph} {year}"
|
| 832 |
+
papers = ocrscienceanswers(query)
|
| 833 |
+
answerlink = papers[query]["OCR"][f"{chapter.capitalize()} (PDF)"].replace(" ",'%20')
|
| 834 |
+
|
| 835 |
+
user_from_db = check_user_from_db(current_user)
|
| 836 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 837 |
+
if "end_date_subscription" in user_from_db:
|
| 838 |
+
end_date = getendsubscription(current_user)
|
| 839 |
+
if user_from_db["emailsleft"] <= 0:
|
| 840 |
+
result = {"scienceocranswers": answerlink,"emailcount":0,"end_date_subscription":end_date}
|
| 841 |
+
return result
|
| 842 |
+
elif user_from_db["emailsleft"] > 0:
|
| 843 |
+
now = datetime.now().strftime("%c")
|
| 844 |
+
message = f"""
|
| 845 |
+
<h1>OCR Science {query} Answers:</h1>
|
| 846 |
+
<p>{answerlink}</p>.
|
| 847 |
+
"""
|
| 848 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"OCR {query} Answers"}})
|
| 849 |
+
|
| 850 |
+
#msg = Message(f"OCR {query} Answers", recipients=[email]) # "amari.lawal@gmail.com"
|
| 851 |
+
#msg.body = f"Mail from {query} at {now}"
|
| 852 |
+
#msg.html = f"""
|
| 853 |
+
#<h1>OCR Science {query} Answers:</h1>
|
| 854 |
+
#<p>{answerlink}</p>.
|
| 855 |
+
#"""
|
| 856 |
+
|
| 857 |
+
#mail.send(msg)
|
| 858 |
+
emailcount = int(user_from_db["emailsleft"])-1
|
| 859 |
+
user_from_db.update({"emailsleft":emailcount})
|
| 860 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 861 |
+
result = {"scienceocranswers": answerlink,"emailcount":emailcount,"end_date_subscription":end_date}
|
| 862 |
+
return result
|
| 863 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 864 |
+
result = {"scienceocranswers": answerlink,"emailcount":0,"end_date_subscription":9999999}
|
| 865 |
+
return result
|
| 866 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 867 |
+
if user_from_db["emailsleft"] <= 0:
|
| 868 |
+
result = {"scienceocranswers": answerlink,"emailcount":0,"end_date_subscription":end_date}
|
| 869 |
+
return result
|
| 870 |
+
elif user_from_db["emailsleft"] > 0:
|
| 871 |
+
now = datetime.now().strftime("%c")
|
| 872 |
+
message = f"""
|
| 873 |
+
<h1>OCR Science {query} Answers:</h1>
|
| 874 |
+
<p>{answerlink}</p>.
|
| 875 |
+
"""
|
| 876 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"OCR {query} Answers"}})
|
| 877 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 878 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 879 |
+
result = {"scienceocranswers": answerlink,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":9999999}
|
| 880 |
+
return result
|
| 881 |
+
except Exception as e:
|
| 882 |
+
return {f"error":f"{type(e)},{str(e)}"}
|
| 883 |
+
else:
|
| 884 |
+
return {"message": "Login first please."}
|
| 885 |
+
@app.post('/physicsaqa') # POST # allow all origins all methods.
|
| 886 |
+
async def physicsaqa(data : JSONStructure = None, authorization: str = Header(None)):
|
| 887 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 888 |
+
if current_user:
|
| 889 |
+
try:
|
| 890 |
+
datajson = dict(data)#request.get_json()
|
| 891 |
+
topicquestions = PhysicsAQA().collectdata()
|
| 892 |
+
data = datajson["physicsaqa"]
|
| 893 |
+
email = data["email"]
|
| 894 |
+
chapter = data["chapter"] # Section 1: Measurement & Their Errors
|
| 895 |
+
topic = data["topic"] # Constituents of the Atom or The Law of the Atom
|
| 896 |
+
platform = data["platform"] # web or app
|
| 897 |
+
try:
|
| 898 |
+
questionpaper = topicquestions[chapter][topic]
|
| 899 |
+
except Exception as ex:
|
| 900 |
+
return {"error":"chapter or topic not found"}
|
| 901 |
+
try:
|
| 902 |
+
markscheme = topicquestions[chapter][f"{topic} MS"]
|
| 903 |
+
except Exception as ex:
|
| 904 |
+
return {"error":"chapter or topic mark scheme not found"}
|
| 905 |
+
|
| 906 |
+
|
| 907 |
+
user_from_db = check_user_from_db(current_user)
|
| 908 |
+
student_email_exists = importcsv.db.studentsubscriptions.find_one({"email":current_user})
|
| 909 |
+
if "end_date_subscription" in user_from_db:
|
| 910 |
+
end_date = getendsubscription(current_user)
|
| 911 |
+
if user_from_db["emailsleft"] <= 0:
|
| 912 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":emailcount,"end_date_subscription":end_date}}
|
| 913 |
+
elif user_from_db["emailsleft"] > 0:
|
| 914 |
+
now = datetime.now().strftime("%c")
|
| 915 |
+
message = f"""
|
| 916 |
+
<h1>PhysicsAqa Question Papers:</h1>
|
| 917 |
+
<p>{questionpaper}</p>
|
| 918 |
+
<p>{markscheme}</p>.
|
| 919 |
+
"""
|
| 920 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"PhysicsAqa Papers"}})
|
| 921 |
+
#msg = Message(f"PhysicsAqa Papers", recipients=[email]) # "amari.lawal@gmail.com"
|
| 922 |
+
#msg.body = f"Mail from physicsaqaApi at {now}"
|
| 923 |
+
#msg.html = f"""
|
| 924 |
+
#<h1>PhysicsAqa Question Papers:</h1>
|
| 925 |
+
#<p>{questionpaper}</p>
|
| 926 |
+
#<p>{markscheme}</p>.
|
| 927 |
+
#"""
|
| 928 |
+
#mail.send(msg)
|
| 929 |
+
emailcount = int(user_from_db["emailsleft"])-1
|
| 930 |
+
user_from_db.update({"emailsleft":emailcount})
|
| 931 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 932 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":emailcount,"end_date_subscription":end_date}}
|
| 933 |
+
elif "end_date_subscription" not in user_from_db and not student_email_exists:
|
| 934 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":0,"end_date_subscription":9999999}}
|
| 935 |
+
# If it is a student account
|
| 936 |
+
elif "end_date_subscription" not in user_from_db and student_email_exists:
|
| 937 |
+
# Check number of emails left
|
| 938 |
+
if user_from_db["emailsleft"] <= 0:
|
| 939 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":emailcount,"end_date_subscription":end_date}}
|
| 940 |
+
elif user_from_db["emailsleft"] > 0:
|
| 941 |
+
now = datetime.now().strftime("%c")
|
| 942 |
+
message = f"""
|
| 943 |
+
<h1>PhysicsAqa Question Papers:</h1>
|
| 944 |
+
<p>{questionpaper}</p>
|
| 945 |
+
<p>{markscheme}</p>.
|
| 946 |
+
"""
|
| 947 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":email,"message":message,"subject":f"PhysicsAqa Papers"}})
|
| 948 |
+
|
| 949 |
+
user_from_db.update({"emailsleft":int(user_from_db["emailsleft"])-1})
|
| 950 |
+
importcsv.db.studentsubscriptions.update_one({"email": current_user}, {"$set": user_from_db},upsert=True)
|
| 951 |
+
return {"physicsaqa":{"chapter":chapter,"topic":topic,"question paper":questionpaper,"markscheme":markscheme,"emailcount":int(user_from_db["emailsleft"])-1,"end_date_subscription":9999999}}
|
| 952 |
+
|
| 953 |
+
except TypeError as tex:
|
| 954 |
+
return {f"error":f"request is wrong shape {tex}"}
|
| 955 |
+
except Exception as ex:
|
| 956 |
+
return {f"error":f"{type(ex)} {str(ex)}"}
|
| 957 |
+
else:
|
| 958 |
+
return {"message": "Login first please."}
|
| 959 |
+
|
| 960 |
+
|
| 961 |
+
@app.post('/signupapi') # POST
|
| 962 |
+
async def signup(data: RevisionBankAuth):
|
| 963 |
+
try:
|
| 964 |
+
data = dict(data)
|
| 965 |
+
print(data)
|
| 966 |
+
data["id"] = ObjectId()
|
| 967 |
+
data["access"] = True
|
| 968 |
+
user = Users(**data)
|
| 969 |
+
signupdata = user.to_bson()
|
| 970 |
+
|
| 971 |
+
print(signupdata["email"])
|
| 972 |
+
email_exists = importcsv.db.users.find_one({"email": signupdata["email"]})
|
| 973 |
+
email_exists_student = importcsv.db.studentsubscriptions.find_one({"email": signupdata["email"]}) # Checks if student account exists
|
| 974 |
+
if email_exists or email_exists_student:
|
| 975 |
+
return {"message": "Email already exists"} # , 400
|
| 976 |
+
elif not email_exists:
|
| 977 |
+
# Notifies who are the beta testers
|
| 978 |
+
#if datetime.now() < "2022-05-19T21:37:00.057084":
|
| 979 |
+
# signupdata.update({"betatest":"true"})
|
| 980 |
+
importcsv.db.users.insert_one(signupdata)
|
| 981 |
+
access_token = secure_encode({{"email":signupdata["email"]}})#create_access_token(identity=signupdata["email"])
|
| 982 |
+
callback = {"status": "success","id": str(signupdata["_id"]),"access_token":access_token}
|
| 983 |
+
return callback
|
| 984 |
+
except Exception as ex:
|
| 985 |
+
error_detected = {"error": "error occured","errortype":type(ex), "error": str(ex)}
|
| 986 |
+
return error_detected
|
| 987 |
+
@app.post('/loginapi') # POST
|
| 988 |
+
async def login(login_details: RevisionBankAuth): # ,authorization: str = Header(None)
|
| 989 |
+
# Login API
|
| 990 |
+
try:
|
| 991 |
+
def provide_access_token(login_details,student=0):
|
| 992 |
+
if student == 0:
|
| 993 |
+
email_exists = list(importcsv.db.users.find({"email": login_details["email"]}))[0]
|
| 994 |
+
elif student == 1:
|
| 995 |
+
email_exists = list(importcsv.db.studentsubscriptions.find({"email": login_details["email"]}))[0]
|
| 996 |
+
encrypted_password = hashlib.sha256(login_details["password"].encode('utf-8')).hexdigest()
|
| 997 |
+
if email_exists["password"] == encrypted_password:
|
| 998 |
+
access_token = secure_encode({"email":email_exists["email"]}) #create_access_token(identity=email_exists["email"])
|
| 999 |
+
return access_token
|
| 1000 |
+
else:
|
| 1001 |
+
return "Wrong password"
|
| 1002 |
+
|
| 1003 |
+
|
| 1004 |
+
login_details = dict(login_details)
|
| 1005 |
+
#print(login_details)
|
| 1006 |
+
email_exists = importcsv.db.users.find_one({"email": login_details["email"]})
|
| 1007 |
+
email_exists_student = importcsv.db.studentsubscriptions.find_one({"email": login_details["email"]}) # Checks if student account exists
|
| 1008 |
+
if email_exists:
|
| 1009 |
+
access_token = provide_access_token(login_details,student=0)
|
| 1010 |
+
if access_token == "Wrong password":
|
| 1011 |
+
return {"message": "The username or password is incorrect."}
|
| 1012 |
+
else:
|
| 1013 |
+
return {"access_token": access_token}
|
| 1014 |
+
elif email_exists_student:
|
| 1015 |
+
access_token = provide_access_token(login_details,student=1)
|
| 1016 |
+
if access_token == "Wrong password":
|
| 1017 |
+
return {"message": "The username or password is incorrect."}
|
| 1018 |
+
else:
|
| 1019 |
+
return {"access_token": access_token}
|
| 1020 |
+
return {"message": "The username or password is incorrect."}
|
| 1021 |
+
except Exception as ex:
|
| 1022 |
+
return {"error": f"{type(ex)} {str(ex)}"}
|
| 1023 |
+
#
|
| 1024 |
+
@app.post('/forgotpassword') # POST
|
| 1025 |
+
async def forgotpassword(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1026 |
+
# Login API
|
| 1027 |
+
data = dict(data)#request.get_json()
|
| 1028 |
+
try:
|
| 1029 |
+
#print(data["email"])
|
| 1030 |
+
access_token = secure_decode(data["email"]) #create_access_token(identity=data["email"])
|
| 1031 |
+
# store token in database temporarily
|
| 1032 |
+
now = datetime.now().strftime("%c")
|
| 1033 |
+
response = requests.post("http://0.0.0.0:7860/raspsendemail",json={"raspsendemail":{"email":data["email"],"message":forgotpasswordemail(data["email"],access_token),"subject":f"RevsionBank Password Reset"}})
|
| 1034 |
+
#msg = Message(f"RevsionBank Password Reset", recipients=[data["email"]]) # "amari.lawal@gmail.com"
|
| 1035 |
+
#msg.body = f"Mail from RevisionBank at {now}"
|
| 1036 |
+
#msg.html = forgotpasswordemail(data["email"],access_token)
|
| 1037 |
+
#mail.send(msg)
|
| 1038 |
+
return {"message": "Reset Email sent"}
|
| 1039 |
+
except Exception as ex:
|
| 1040 |
+
return {"error": f"{type(ex)} {str(ex)}"}
|
| 1041 |
+
|
| 1042 |
+
@app.put('/resetpassword') # PUT
|
| 1043 |
+
async def resetpassword(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1044 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 1045 |
+
if current_user:
|
| 1046 |
+
try:
|
| 1047 |
+
data = dict(data)#request.get_json()
|
| 1048 |
+
email_exists = importcsv.db.users.find_one({"email": current_user})
|
| 1049 |
+
#print(email_exists)
|
| 1050 |
+
if email_exists:
|
| 1051 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1052 |
+
#print(user_from_db)
|
| 1053 |
+
# TODO Delete password from here and replace.
|
| 1054 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1055 |
+
del user_from_db["password"]
|
| 1056 |
+
encrypted_password = hashlib.sha256(data["password"].encode('utf-8')).hexdigest()
|
| 1057 |
+
user_from_db.update({"password": encrypted_password})
|
| 1058 |
+
importcsv.db.users.insert_one(user_from_db)
|
| 1059 |
+
return {"message": "Password reset successful."}
|
| 1060 |
+
elif not email_exists:
|
| 1061 |
+
return {"message": "Email Doesn't exist."}
|
| 1062 |
+
except Exception as ex:
|
| 1063 |
+
return {"error": f"{type(ex)} {str(ex)}"}
|
| 1064 |
+
|
| 1065 |
+
|
| 1066 |
+
|
| 1067 |
+
@app.post('/storesubscription') # POST
|
| 1068 |
+
async def storesubscription(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1069 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1070 |
+
if current_user:
|
| 1071 |
+
try:
|
| 1072 |
+
data = dict(data)#request.get_json()
|
| 1073 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1074 |
+
if data["subscription"] == 'basic':
|
| 1075 |
+
emailsleft = {'emailsleft': 0}
|
| 1076 |
+
elif data["subscription"] == 'standard':
|
| 1077 |
+
emailsleft = {'emailsleft': 40}
|
| 1078 |
+
elif data["subscription"] == 'premium' or data["subscription"] == 'educational':
|
| 1079 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1080 |
+
if data["subscription"] == "educational":
|
| 1081 |
+
user_from_db.update({"numofaccounts": 200}) # TODO Constant Value needs to be changed when frontend is changed
|
| 1082 |
+
user_from_db.update({"start_date_subscription": data["start_date_subscription"]})
|
| 1083 |
+
user_from_db.update({"end_date_subscription": data["end_date_subscription"]})
|
| 1084 |
+
user_from_db.update({"subscription": data["subscription"]}) # Updates the user with the new subscription
|
| 1085 |
+
user_from_db.update(emailsleft)
|
| 1086 |
+
importcsv.db.users.update_one( { "email": current_user}, {"$set": user_from_db}, upsert = True )
|
| 1087 |
+
|
| 1088 |
+
importcsv.db.subscriptionlog.insert_one({"email": user_from_db["email"],"start_date_subscription": data["start_date_subscription"], "end_date_subscription": data["end_date_subscription"], "subscription": data["subscription"], "emailsleft": emailsleft["emailsleft"]})
|
| 1089 |
+
return {"message": "Subscription Completed."}
|
| 1090 |
+
except Exception as ex:
|
| 1091 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1092 |
+
|
| 1093 |
+
else:
|
| 1094 |
+
return {"message": "User not found"}
|
| 1095 |
+
@app.post('/storebetatester') # POST #
|
| 1096 |
+
async def storebetatester(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1097 |
+
data = dict(data)#request.get_json()
|
| 1098 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1099 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1100 |
+
if email_exists:
|
| 1101 |
+
user_from_db = list(importcsv.db.users.find({"email": data["email"]}))[0] # Gets wanted data for user
|
| 1102 |
+
#user_from_db.update({"numofaccounts": 200}) # TODO Constant Value needs to be changed when frontend is changed
|
| 1103 |
+
date_now = datetime.now()
|
| 1104 |
+
datetime_delta = dt.timedelta(weeks=2)
|
| 1105 |
+
user_from_db.update({"start_date_subscription": date_now.isoformat()})
|
| 1106 |
+
|
| 1107 |
+
user_from_db.update({"end_date_subscription": (datetime_delta + date_now).isoformat()})
|
| 1108 |
+
user_from_db.update({"subscription": "premium"}) # Updates the user with the new subscription
|
| 1109 |
+
user_from_db.update(emailsleft)
|
| 1110 |
+
user_from_db.update({"betatester": "true"})
|
| 1111 |
+
importcsv.db.users.update_one( { "email": data["email"]}, {"$set": user_from_db}, upsert = True )
|
| 1112 |
+
|
| 1113 |
+
#importcsv.db.subscriptionlog.insert_one({"email": user_from_db["email"],"start_date_subscription": data["start_date_subscription"], "end_date_subscription": data["end_date_subscription"], "subscription": data["subscription"], "emailsleft": emailsleft["emailsleft"]})
|
| 1114 |
+
return {"message": "Beta Tester Subscription Completed."}
|
| 1115 |
+
elif not email_exists:
|
| 1116 |
+
return {"message": "User not found"}
|
| 1117 |
+
@app.post('/storeeducationalfreetrial') # POST #
|
| 1118 |
+
async def storeeducationalfreetrial(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1119 |
+
data = dict(data)#request.get_json()
|
| 1120 |
+
try:
|
| 1121 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1122 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1123 |
+
if email_exists:
|
| 1124 |
+
user_from_db = list(importcsv.db.users.find({"email": data["email"]}))[0] # Gets wanted data for user
|
| 1125 |
+
#user_from_db.update({"numofaccounts": 200}) # TODO Constant Value needs to be changed when frontend is changed
|
| 1126 |
+
date_now = datetime.now()
|
| 1127 |
+
decimal_part = float(3 / 7)
|
| 1128 |
+
datetime_delta = dt.timedelta(weeks=4 + decimal_part)
|
| 1129 |
+
user_from_db.update({"start_date_subscription": date_now.isoformat()})
|
| 1130 |
+
user_from_db.update({"numofaccounts": 200})
|
| 1131 |
+
|
| 1132 |
+
user_from_db.update({"end_date_subscription": (datetime_delta + date_now).isoformat()})
|
| 1133 |
+
user_from_db.update({"subscription": "educational"}) # Updates the user with the new subscription
|
| 1134 |
+
user_from_db.update(emailsleft)
|
| 1135 |
+
importcsv.db.users.update_one( { "email": data["email"]}, {"$set": user_from_db}, upsert = True )
|
| 1136 |
+
|
| 1137 |
+
#importcsv.db.subscriptionlog.insert_one({"email": user_from_db["email"],"start_date_subscription": data["start_date_subscription"], "end_date_subscription": data["end_date_subscription"], "subscription": data["subscription"], "emailsleft": emailsleft["emailsleft"]})
|
| 1138 |
+
return {"message": "Educational Freetrial Subscription Completed."}
|
| 1139 |
+
elif not email_exists:
|
| 1140 |
+
return {"message": "User not found"}
|
| 1141 |
+
except Exception as ex:
|
| 1142 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1143 |
+
@app.post('/scheduleeducationalfreetrial') # POST #
|
| 1144 |
+
async def scheduleeducationalfreetrial(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1145 |
+
data = dict(data)#request.get_json()
|
| 1146 |
+
try:
|
| 1147 |
+
regexdatetime = re.compile(r'\d\d\d\d-\d\d-\d\d')
|
| 1148 |
+
mo = regexdatetime.search(data["educationalfreetrialdate"])
|
| 1149 |
+
educationalfreetrialdate = mo.group()
|
| 1150 |
+
except AttributeError as aex:
|
| 1151 |
+
return {"error":r"Datetime shape is %Y-%m-%d"}
|
| 1152 |
+
try:
|
| 1153 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1154 |
+
if email_exists:
|
| 1155 |
+
importcsv.db.schedulededucationalfreetrial.insert_one({"email": data["email"],"educationalfreetrialdate":educationalfreetrialdate})
|
| 1156 |
+
return {"message": "Educational Freetrial Scheduled."}
|
| 1157 |
+
elif not email_exists:
|
| 1158 |
+
return {"message": "User not found"}
|
| 1159 |
+
except Exception as ex:
|
| 1160 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1161 |
+
@app.post('/deletescheduleeducationalfreetrial') # POST #
|
| 1162 |
+
async def deletescheduleeducationalfreetrial(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1163 |
+
data = dict(data)#request.get_json()
|
| 1164 |
+
current_user = data["email"]
|
| 1165 |
+
current_user = importcsv.db.users.find_one({"email": data["email"]})
|
| 1166 |
+
if current_user:
|
| 1167 |
+
try:
|
| 1168 |
+
user_from_db = list(importcsv.db.schedulededucationalfreetrial.find({"email": data["email"]}))[0]
|
| 1169 |
+
importcsv.db.schedulededucationalfreetrial.delete_many(user_from_db)
|
| 1170 |
+
return {"message":"Educational Freetrial Unscheduled."}
|
| 1171 |
+
except Exception as ex:
|
| 1172 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1173 |
+
@app.post('/removebetatester') # POST #
|
| 1174 |
+
async def removebetatester(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1175 |
+
data = dict(data)#request.get_json()
|
| 1176 |
+
email_exists = importcsv.db.users.find_one({"email": data["email"]})
|
| 1177 |
+
if email_exists:
|
| 1178 |
+
user_from_db = list(importcsv.db.users.find({"email": data["email"]}))[0] # Gets wanted data for user
|
| 1179 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1180 |
+
del user_from_db["end_date_subscription"], user_from_db["start_date_subscription"],user_from_db["subscription"],user_from_db["emailsleft"], user_from_db["betatester"]
|
| 1181 |
+
importcsv.db.users.update_one( { "email": data["email"]}, {"$set": user_from_db}, upsert = True )
|
| 1182 |
+
return {"message": "Beta Tester Subscription Deleted."}
|
| 1183 |
+
elif not email_exists:
|
| 1184 |
+
return {"message": "User not found"}
|
| 1185 |
+
@app.get('/getsubscription') # GET
|
| 1186 |
+
async def getsubscription(authorization: str = Header(None)):
|
| 1187 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1188 |
+
if current_user:
|
| 1189 |
+
try:
|
| 1190 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1191 |
+
end_date = user_from_db["end_date_subscription"]
|
| 1192 |
+
end_date_subscription = {"end_date_subscription": end_date}
|
| 1193 |
+
return end_date_subscription
|
| 1194 |
+
except Exception as ex:
|
| 1195 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1196 |
+
@app.get('/getemailcount') # GET
|
| 1197 |
+
async def getemailcount(authorization: str = Header(None)):
|
| 1198 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1199 |
+
if current_user:
|
| 1200 |
+
try:
|
| 1201 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1202 |
+
emailcount = user_from_db["emailsleft"]
|
| 1203 |
+
emailcountres = {"emailcount": emailcount}
|
| 1204 |
+
return emailcountres
|
| 1205 |
+
except Exception as ex:
|
| 1206 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1207 |
+
@app.post('/storefreetrial') # POST
|
| 1208 |
+
async def storefreetrial(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1209 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1210 |
+
if current_user:
|
| 1211 |
+
try:
|
| 1212 |
+
data = dict(data)#request.get_json()
|
| 1213 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1214 |
+
if 'freetrial' not in user_from_db:
|
| 1215 |
+
user_from_db.update({"freetrial": "true"})
|
| 1216 |
+
emailsleft = {'emailsleft': 10000000000}
|
| 1217 |
+
user_from_db.update({"start_date_subscription": data["start_date_subscription"]})
|
| 1218 |
+
user_from_db.update({"end_date_subscription": data["end_date_subscription"]})
|
| 1219 |
+
user_from_db.update({"subscription": data["subscription"]}) # Updates the user with the new subscription
|
| 1220 |
+
user_from_db.update(emailsleft)
|
| 1221 |
+
importcsv.db.users.update_one( { "email": current_user}, {"$set": user_from_db}, upsert = True )
|
| 1222 |
+
importcsv.db.users.update_one({"email": current_user}, {"$set": user_from_db}, upsert = True)
|
| 1223 |
+
importcsv.db.freetrialhistory.insert_one({"email": user_from_db["email"],"freetrial":"true"})
|
| 1224 |
+
return {"message": "Freetrial Redeemed."}
|
| 1225 |
+
elif 'freetrial' in user_from_db:
|
| 1226 |
+
return {"error": "Freetrial has already used."}
|
| 1227 |
+
except Exception as ex:
|
| 1228 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1229 |
+
@app.post('/setstudentsubscriptions') # POST
|
| 1230 |
+
async def setstudentsubscriptions(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1231 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1232 |
+
if current_user:
|
| 1233 |
+
# Hostemail is the primary key for the studentsubscription collection
|
| 1234 |
+
try:
|
| 1235 |
+
data = dict(data)#request.get_json()
|
| 1236 |
+
# {"hostemail": "amari.lawal05@gmail.com","hostnumofaccounts": 198,"studentemails": [{"email": "6Lawala@truroschool.com","password": "mann35"},{"email": "Bola.lawal@hotmail.co.uk","password": "billy45"},{"email": "amari.lawal@gmail.com","password": "bobby46"}],"studentemailsleft": 20,"studentsubscription": "student educational"}
|
| 1237 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0] # Host emails data
|
| 1238 |
+
studentsnotexist = []
|
| 1239 |
+
for student in data["studentemails"]: # data["studentemails"] is a list of dictionaries [{"email":"example@gmail.com","password":"password"},{"email":"example@gmail.com","password":"password"}]
|
| 1240 |
+
student_user_from_db = importcsv.db.studentsubscriptions.find_one({"email": student["email"]}) # Checks if any of the emails added are in the database
|
| 1241 |
+
if not student_user_from_db: # If the email is not in the database, then we need to store the data into the database
|
| 1242 |
+
studentsnotexist.append(student) # Adds the email to the list of emails that do not exist in the database
|
| 1243 |
+
|
| 1244 |
+
if studentsnotexist == []: # If all data is already in the database, no need to store it.
|
| 1245 |
+
return {"message": "all students exist."}
|
| 1246 |
+
elif studentsnotexist != []: # If there are emails that are not in the database, we need to store the data into the database
|
| 1247 |
+
if user_from_db["numofaccounts"] > 0:
|
| 1248 |
+
for student in studentsnotexist: # Goes through the emails not in the database
|
| 1249 |
+
encrypted_password = hashlib.sha256(student["password"].encode('utf-8')).hexdigest()# Encrypts the password
|
| 1250 |
+
# Then stores data into the studentsubscriptions collection
|
| 1251 |
+
importcsv.db.studentsubscriptions.insert_one({"hostemail":current_user,"email": student["email"],"password": encrypted_password,"emailsleft": 20,"subscription": "student educational"})
|
| 1252 |
+
|
| 1253 |
+
return {"message": "student subscriptions Set."}
|
| 1254 |
+
elif user_from_db["numofaccounts"] <= 0:
|
| 1255 |
+
return {"error": "No more student accounts left."}
|
| 1256 |
+
except Exception as ex:
|
| 1257 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1258 |
+
@app.get('/getstudentsubscriptions') # GET
|
| 1259 |
+
async def getstudentsubscriptions(authorization: str = Header(None)):
|
| 1260 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 1261 |
+
if current_user:
|
| 1262 |
+
try:
|
| 1263 |
+
student_user_from_db = list(importcsv.db.studentsubscriptions.find({"hostemail": current_user})) # [0]
|
| 1264 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1265 |
+
for student in student_user_from_db:
|
| 1266 |
+
del student["_id"], student["password"],student["hostemail"],student['subscription']
|
| 1267 |
+
|
| 1268 |
+
importcsv.db.users.delete_many(user_from_db) # Deletes the data in order to update it.
|
| 1269 |
+
del user_from_db["numofaccounts"] # Deletes the numofaccounts to update it.
|
| 1270 |
+
user_from_db.update({"numofaccounts": 200 - len(student_user_from_db)}) # Updates the number of accounts
|
| 1271 |
+
importcsv.db.users.insert_one(user_from_db) # inserts updated data into the host emails account
|
| 1272 |
+
return {"result":student_user_from_db}
|
| 1273 |
+
except Exception as ex:
|
| 1274 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1275 |
+
@app.get('/checkstudentsubscriptions') # GET
|
| 1276 |
+
async def checkstudentsubscriptions(authorization: str = Header(None)):
|
| 1277 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1278 |
+
if current_user:
|
| 1279 |
+
try:
|
| 1280 |
+
student_from_db = list(importcsv.db.studentsubscriptions.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1281 |
+
student_subscription = student_from_db["subscription"]
|
| 1282 |
+
student_subscription_json = {"student_subscription": student_subscription}
|
| 1283 |
+
return student_subscription_json
|
| 1284 |
+
except Exception as ex:
|
| 1285 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1286 |
+
@app.post('/deletestudentaccount') # POST
|
| 1287 |
+
async def deletestudentaccount(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1288 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 1289 |
+
if current_user:
|
| 1290 |
+
data = dict(data)#request.get_json()
|
| 1291 |
+
try:
|
| 1292 |
+
hostkey = importcsv.db.studentsubscriptions.find_one({"hostemail": current_user})
|
| 1293 |
+
studentkey = importcsv.db.studentsubscriptions.find_one({"email": data["studentemail"]})
|
| 1294 |
+
if hostkey and studentkey:
|
| 1295 |
+
importcsv.db.studentsubscriptions.delete_one({"email": data["studentemail"]})
|
| 1296 |
+
return {"message": "Student account deleted."}
|
| 1297 |
+
else:
|
| 1298 |
+
return {"error": "Student account does not exist."}
|
| 1299 |
+
except Exception as ex:
|
| 1300 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1301 |
+
@app.put('/changestudentpassword') # PUT
|
| 1302 |
+
async def changestudentpassword(data : JSONStructure = None, authorization: str = Header(None)):
|
| 1303 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"]
|
| 1304 |
+
if current_user:
|
| 1305 |
+
data = dict(data)#request.get_json()
|
| 1306 |
+
try:
|
| 1307 |
+
hostkey = importcsv.db.studentsubscriptions.find_one({"hostemail": current_user})
|
| 1308 |
+
studentkey = importcsv.db.studentsubscriptions.find_one({"email": data["studentemail"]})
|
| 1309 |
+
if hostkey and studentkey:
|
| 1310 |
+
student_user_from_db = list(importcsv.db.studentsubscriptions.find({"email": data["studentemail"]}))[0]
|
| 1311 |
+
# TODO Delete password from here and replace.
|
| 1312 |
+
importcsv.db.studentsubscriptions.delete_many(student_user_from_db)
|
| 1313 |
+
del student_user_from_db["password"]
|
| 1314 |
+
encrypted_password = hashlib.sha256(data["password"].encode('utf-8')).hexdigest()
|
| 1315 |
+
student_user_from_db.update({"password": encrypted_password})
|
| 1316 |
+
importcsv.db.studentsubscriptions.insert_one(student_user_from_db)
|
| 1317 |
+
return {"message": "Password reset successful."}
|
| 1318 |
+
else:
|
| 1319 |
+
return {"error": "Student account does not exist."}
|
| 1320 |
+
except Exception as ex:
|
| 1321 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1322 |
+
|
| 1323 |
+
|
| 1324 |
+
|
| 1325 |
+
@app.get('/getfreetrial') # GET
|
| 1326 |
+
async def getfreetrial(authorization: str = Header(None)):
|
| 1327 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1328 |
+
if current_user:
|
| 1329 |
+
try:
|
| 1330 |
+
freetrialhistory = list(importcsv.db.freetrialhistory.find({"email": current_user}))[0] # Gets wanted data for user
|
| 1331 |
+
freetrial = freetrialhistory["freetrial"]
|
| 1332 |
+
freetrial_subscription = {"freetrial": freetrial} # check freetrial
|
| 1333 |
+
return freetrial_subscription
|
| 1334 |
+
except Exception as ex:
|
| 1335 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1336 |
+
@app.get('/getemail') # GET
|
| 1337 |
+
async def getemail(authorization: str = Header(None)):
|
| 1338 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1339 |
+
if current_user:
|
| 1340 |
+
try:
|
| 1341 |
+
user_from_db = check_user_from_db(current_user)
|
| 1342 |
+
return {"email":user_from_db["email"]}
|
| 1343 |
+
except Exception as ex:
|
| 1344 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1345 |
+
|
| 1346 |
+
@app.delete('/deletesubscription') # DELETE
|
| 1347 |
+
async def deletesubscription(authorization: str = Header(None)):
|
| 1348 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1349 |
+
if current_user:
|
| 1350 |
+
try:
|
| 1351 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1352 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1353 |
+
if "end_date_subscription" in user_from_db:
|
| 1354 |
+
del user_from_db["end_date_subscription"]
|
| 1355 |
+
if "start_date_subscription" in user_from_db:
|
| 1356 |
+
del user_from_db["start_date_subscription"]
|
| 1357 |
+
if "subscription" in user_from_db:
|
| 1358 |
+
del user_from_db["subscription"]
|
| 1359 |
+
if "emailsleft" in user_from_db:
|
| 1360 |
+
del user_from_db["emailsleft"]
|
| 1361 |
+
if "numofaccounts" in user_from_db:
|
| 1362 |
+
del user_from_db["numofaccounts"]
|
| 1363 |
+
importcsv.db.users.update_one( { "email": current_user}, {"$set": user_from_db}, upsert = True )
|
| 1364 |
+
|
| 1365 |
+
return {"message":"Subscription deleted from expiration"}
|
| 1366 |
+
except Exception as ex:
|
| 1367 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1368 |
+
@app.get('/getaccountinfo') # GET
|
| 1369 |
+
async def getaccountinfo(authorization: str = Header(None)):
|
| 1370 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1371 |
+
if current_user:
|
| 1372 |
+
try:
|
| 1373 |
+
email_exists = importcsv.db.users.find_one({"email": current_user})
|
| 1374 |
+
email_exists_student = importcsv.db.studentsubscriptions.find_one({"email": current_user})
|
| 1375 |
+
if email_exists:
|
| 1376 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1377 |
+
del user_from_db["password"], user_from_db["_id"]
|
| 1378 |
+
return user_from_db
|
| 1379 |
+
elif email_exists_student:
|
| 1380 |
+
student_user_from_db = list(importcsv.db.studentsubscriptions.find({"email": current_user}))[0]
|
| 1381 |
+
host_from_db = list(importcsv.db.users.find({"email": student_user_from_db["hostemail"]}))[0]
|
| 1382 |
+
student_user_from_db.update({"start_date_subscription":host_from_db["start_date_subscription"]})
|
| 1383 |
+
student_user_from_db.update({"end_date_subscription":host_from_db["end_date_subscription"]})
|
| 1384 |
+
del student_user_from_db["password"], student_user_from_db["_id"]
|
| 1385 |
+
return student_user_from_db
|
| 1386 |
+
#return {"error": f"account not found"}
|
| 1387 |
+
except Exception as ex:
|
| 1388 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1389 |
+
@app.delete('/deleteaccount') # DELETE
|
| 1390 |
+
async def deleteaccount(authorization: str = Header(None)):
|
| 1391 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user example@gmail.com
|
| 1392 |
+
if current_user:
|
| 1393 |
+
try:
|
| 1394 |
+
user_from_db = list(importcsv.db.users.find({"email": current_user}))[0]
|
| 1395 |
+
importcsv.db.users.delete_many(user_from_db)
|
| 1396 |
+
return {"message":"Account Deleted"}
|
| 1397 |
+
except Exception as ex:
|
| 1398 |
+
return {"error": f"{type(ex)}-{ex}"}
|
| 1399 |
+
@app.get('/getedexcelpapers')# GET # allow all origins all methods.
|
| 1400 |
+
async def getedexcelpapers(authorization: str = Header(None)):
|
| 1401 |
+
try:
|
| 1402 |
+
data = dict(data)#request.get_json()
|
| 1403 |
+
dataedexcel = list(importcsv.db.edexcelpapers.find({"year":"AS Level"}))
|
| 1404 |
+
return {"result":dataedexcel}
|
| 1405 |
+
except Exception as ex:
|
| 1406 |
+
return {"error":f"{type(ex)},ex"}
|
| 1407 |
+
|
| 1408 |
+
async def main():
|
| 1409 |
+
config = uvicorn.Config("main:app", port=7860, log_level="info",host="0.0.0.0",reload=True)
|
| 1410 |
+
server = uvicorn.Server(config)
|
| 1411 |
+
await server.serve()
|
| 1412 |
+
|
| 1413 |
+
if __name__ == "__main__":
|
| 1414 |
+
asyncio.run(main())
|
maintest.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import jwt
|
| 2 |
+
from fastapi import FastAPI, Header
|
| 3 |
+
from pydantic import BaseModel
|
| 4 |
+
from typing import Optional
|
| 5 |
+
import asyncio
|
| 6 |
+
import uvicorn
|
| 7 |
+
from RevisionBankModels import *
|
| 8 |
+
JWT_SECRET = "secret" # IRL we should NEVER hardcode the secret: it should be an evironment variable!!!
|
| 9 |
+
JWT_ALGORITHM = "HS256"
|
| 10 |
+
|
| 11 |
+
app = FastAPI()
|
| 12 |
+
|
| 13 |
+
class Auth(BaseModel):
|
| 14 |
+
name: str
|
| 15 |
+
password: str
|
| 16 |
+
class Person(BaseModel):
|
| 17 |
+
name: str
|
| 18 |
+
gender: Optional[str] = None
|
| 19 |
+
age: float
|
| 20 |
+
checked: Optional[bool] = None
|
| 21 |
+
|
| 22 |
+
@app.post("/signup")
|
| 23 |
+
async def root(person: Auth):
|
| 24 |
+
try:
|
| 25 |
+
person = dict(person)
|
| 26 |
+
access_token = secure_encode({"name":person})
|
| 27 |
+
print(access_token)
|
| 28 |
+
# here we can add code to check the user (by email)
|
| 29 |
+
# e.g. select the user from the DB and see its permissions
|
| 30 |
+
return {"access_token":access_token}
|
| 31 |
+
except Exception as ex:
|
| 32 |
+
print(ex)
|
| 33 |
+
return "Unauthorized Access!"
|
| 34 |
+
# in this example we'll simply return the person entity from the request body
|
| 35 |
+
# after adding a "checked"
|
| 36 |
+
|
| 37 |
+
@app.post("/signin")
|
| 38 |
+
async def root(person: Person, authorization: str = Header(None)):
|
| 39 |
+
try:
|
| 40 |
+
decoded = secure_decode(authorization.replace("Bearer ",""))
|
| 41 |
+
# here we can add code to check the user (by email)
|
| 42 |
+
# e.g. select the user from the DB and see its permissions
|
| 43 |
+
print(decoded)
|
| 44 |
+
return {"message":"signed in"}
|
| 45 |
+
except:
|
| 46 |
+
return "Unauthorized Access!"
|
| 47 |
+
# in this example we'll simply return the person entity from the request body
|
| 48 |
+
# after adding a "checked"
|
| 49 |
+
|
| 50 |
+
@app.post('/forgotpassword') # POST
|
| 51 |
+
def forgotpassword(data : GenericSingleObject):
|
| 52 |
+
data = dict(data)
|
| 53 |
+
print(data)
|
| 54 |
+
return {"message":"hi"}
|
| 55 |
+
|
| 56 |
+
def secure_encode(token):
|
| 57 |
+
# if we want to sign/encrypt the JSON object: {"hello": "world"}, we can do it as follows
|
| 58 |
+
# encoded = jwt.encode({"hello": "world"}, JWT_SECRET, algorithm=JWT_ALGORITHM)
|
| 59 |
+
encoded_token = jwt.encode(token, JWT_SECRET, algorithm=JWT_ALGORITHM)
|
| 60 |
+
# this is often used on the client side to encode the user's email address or other properties
|
| 61 |
+
return encoded_token
|
| 62 |
+
|
| 63 |
+
def secure_decode(token):
|
| 64 |
+
# if we want to sign/encrypt the JSON object: {"hello": "world"}, we can do it as follows
|
| 65 |
+
# encoded = jwt.encode({"hello": "world"}, JWT_SECRET, algorithm=JWT_ALGORITHM)
|
| 66 |
+
decoded_token = jwt.decode(token, JWT_SECRET, algorithms=JWT_ALGORITHM)
|
| 67 |
+
# this is often used on the client side to encode the user's email address or other properties
|
| 68 |
+
return decoded_token
|
| 69 |
+
|
| 70 |
+
async def main():
|
| 71 |
+
config = uvicorn.Config("main:app", port=7860, log_level="info",host="0.0.0.0",reload=True)
|
| 72 |
+
server = uvicorn.Server(config)
|
| 73 |
+
await server.serve()
|
| 74 |
+
|
| 75 |
+
if __name__ == "__main__":
|
| 76 |
+
asyncio.run(main())
|
models.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import Optional
|
| 3 |
+
from bson.objectid import ObjectId
|
| 4 |
+
import bcrypt
|
| 5 |
+
import hashlib
|
| 6 |
+
# https://www.mongodb.com/developer/how-to/flask-python-mongodb/
|
| 7 |
+
# https://codehandbook.org/creating-rest-api-using-python-mongodb/
|
| 8 |
+
# https://zetcode.com/python/bcrypt/
|
| 9 |
+
class PydanticObjectID(ObjectId):
|
| 10 |
+
@classmethod
|
| 11 |
+
def __get_validators__(cls):
|
| 12 |
+
yield cls.validate
|
| 13 |
+
@classmethod
|
| 14 |
+
def validate(cls, v):
|
| 15 |
+
if not isinstance(v, ObjectId):
|
| 16 |
+
raise TypeError(f'Must be an ObjectId')
|
| 17 |
+
return str(v)
|
| 18 |
+
class Users(BaseModel):
|
| 19 |
+
id : PydanticObjectID # Sets MongoDB ID
|
| 20 |
+
email: str
|
| 21 |
+
password: str
|
| 22 |
+
access: bool
|
| 23 |
+
def generate_hash_pw(self):
|
| 24 |
+
salt = bcrypt.gensalt()
|
| 25 |
+
data = self.dict(by_alias=True, exclude_none=True)
|
| 26 |
+
hashed = bcrypt.hashpw(data["password"].encode('utf-8'), salt)
|
| 27 |
+
return hashed,str(salt).replace("b'","").replace("'","")
|
| 28 |
+
|
| 29 |
+
def to_bson(self):
|
| 30 |
+
data = self.dict(by_alias=True,exclude_none=True)
|
| 31 |
+
hashed = hashlib.sha256(data["password"].encode('utf-8')).hexdigest()
|
| 32 |
+
del data["password"]
|
| 33 |
+
data["password"] = hashed
|
| 34 |
+
data["_id"] = data["id"]
|
| 35 |
+
del data["id"]
|
| 36 |
+
return data
|
| 37 |
+
#data_val = json.loads(json_util.dumps(data))
|
| 38 |
+
|
physics.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from physicsaqa import PhysicsAQA
|
| 2 |
+
|
| 3 |
+
data = PhysicsAQA().collectdata()
|
| 4 |
+
#print(data.keys())
|
| 5 |
+
#chapt = list({"label":chapter,"value":ind}for ind,chapter in enumerate(list(data.keys())))
|
| 6 |
+
#print(chapt)
|
| 7 |
+
topic = list(top for dic in list(data.values()) for top in dic.keys() if "MS" not in top)
|
| 8 |
+
topicms = list(top for dic in list(data.values()) for top in dic.keys() if "MS" in top)
|
| 9 |
+
resulttop = [{"label":top,"value":ind} for ind,top in enumerate(topic)]
|
| 10 |
+
resulttopms = [{"label":top,"value":ind} for ind,top in enumerate(topicms)]
|
| 11 |
+
#print(resulttop)
|
| 12 |
+
dic = {}
|
| 13 |
+
dic["physicsaqadata"] = {}
|
| 14 |
+
for key,val in data.items():
|
| 15 |
+
dic["physicsaqadata"][key] = [{"label":val,"value":ind}for ind,val in enumerate(list(val.keys()))]
|
| 16 |
+
|
| 17 |
+
## = list(for key,val in data.items())
|
| 18 |
+
print(dic) #["physicsaqadata"]["Section 2: Particles & Radiation"]
|
physicsaqa.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import re
|
| 3 |
+
from bs4 import BeautifulSoup
|
| 4 |
+
class PhysicsAQA:
|
| 5 |
+
def __init__(self) -> None:
|
| 6 |
+
|
| 7 |
+
self.url = "https://www.savemyexams.co.uk/a-level/physics/aqa/-/pages/topic-questions-pdf/"
|
| 8 |
+
|
| 9 |
+
response= requests.get(self.url).text
|
| 10 |
+
self.soup = BeautifulSoup(response,features='lxml')#
|
| 11 |
+
|
| 12 |
+
def collectdata(self):
|
| 13 |
+
physicsaqa = {}
|
| 14 |
+
slice_indexes = []
|
| 15 |
+
data = []
|
| 16 |
+
data = self.soup.find_all(["td"])[2:]
|
| 17 |
+
for ind,td in enumerate(data):
|
| 18 |
+
if "." in td.text or "Section" in td.text:
|
| 19 |
+
#print(td.text,ind)
|
| 20 |
+
slice_indexes.append(ind)
|
| 21 |
+
|
| 22 |
+
#print(len(slice_indexes))
|
| 23 |
+
for ind in range(len(slice_indexes)+1):
|
| 24 |
+
if ind == len(slice_indexes) -1:
|
| 25 |
+
break
|
| 26 |
+
|
| 27 |
+
sliceone = slice_indexes[ind]
|
| 28 |
+
slicetwo = slice_indexes[ind + 1]
|
| 29 |
+
chapterdata = data[sliceone:slicetwo]
|
| 30 |
+
chapternum = data[sliceone:slicetwo][0].text.replace('\n','').replace('\xa0','')
|
| 31 |
+
#print(sliceone,slicetwo)
|
| 32 |
+
#print(data[sliceone:slicetwo])
|
| 33 |
+
physicsaqa[chapternum] = {}
|
| 34 |
+
for chapter in chapterdata:
|
| 35 |
+
#print(chapter)
|
| 36 |
+
if chapter.find("a",href=True) != None:
|
| 37 |
+
#print(chapter)
|
| 38 |
+
physicsaqa[chapternum][chapter.find("a",href=True).text.replace('\xa0','').replace('\n','').replace("\u200b","")] = chapter.find("a",href=True)["href"]
|
| 39 |
+
return physicsaqa
|
| 40 |
+
if __name__ == "__main__":
|
| 41 |
+
data = PhysicsAQA().collectdata()
|
| 42 |
+
|
| 43 |
+
print(data)
|
| 44 |
+
|
raspsendemail.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import smtplib, ssl
|
| 2 |
+
from email import encoders
|
| 3 |
+
from email.mime.base import MIMEBase
|
| 4 |
+
from email.mime.multipart import MIMEMultipart
|
| 5 |
+
from email.mime.text import MIMEText
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class RaspEmail:
|
| 9 |
+
@staticmethod
|
| 10 |
+
def send(receiver_email,subject,htmlmessage,attachment=None):
|
| 11 |
+
sender_email = "revisionbankedu@gmail.com"
|
| 12 |
+
message = MIMEMultipart("alternative")
|
| 13 |
+
message["Subject"] = subject
|
| 14 |
+
message["From"] = sender_email
|
| 15 |
+
message["To"] = receiver_email
|
| 16 |
+
password = "ktqgjfzgcbfacsve"
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
# Turn these into plain/html MIMEText objects
|
| 20 |
+
part1 = MIMEText(htmlmessage, "html")
|
| 21 |
+
|
| 22 |
+
# Add HTML/plain-text parts to MIMEMultipart message.
|
| 23 |
+
# The email client will try to render the last part first
|
| 24 |
+
|
| 25 |
+
message.attach(part1)
|
| 26 |
+
# files should be a dictionary of filenames & base64 content
|
| 27 |
+
#print(attachment)
|
| 28 |
+
if attachment != None:
|
| 29 |
+
for file in attachment:
|
| 30 |
+
for key,val in file.items():
|
| 31 |
+
if ".png" in key:
|
| 32 |
+
part2 = MIMEBase('image', 'png')
|
| 33 |
+
image = val.replace("data:image/png;base64,","")
|
| 34 |
+
part2.set_payload(image)
|
| 35 |
+
part2.add_header('Content-Transfer-Encoding', 'base64')
|
| 36 |
+
part2['Content-Disposition'] = 'attachment; filename="%s"' % key
|
| 37 |
+
message.attach(part2)
|
| 38 |
+
elif ".jpg" in key or "jpeg" in key:
|
| 39 |
+
part2 = MIMEBase('image', 'jpeg')
|
| 40 |
+
image = val.replace("data:image/jpeg;base64,","")
|
| 41 |
+
part2.set_payload(image)
|
| 42 |
+
part2.add_header('Content-Transfer-Encoding', 'base64')
|
| 43 |
+
part2['Content-Disposition'] = 'attachment; filename="%s"' % key
|
| 44 |
+
message.attach(part2)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
# Create secure connection with server and send email
|
| 49 |
+
context = ssl.create_default_context()
|
| 50 |
+
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
|
| 51 |
+
server.login(sender_email, password)
|
| 52 |
+
server.sendmail(
|
| 53 |
+
sender_email, receiver_email, message.as_string()
|
| 54 |
+
)
|
| 55 |
+
@staticmethod
|
| 56 |
+
def send_attachment(receiver_email,subject,filename,htmlmessage):
|
| 57 |
+
sender_email = "revisionbankedu@gmail.com"
|
| 58 |
+
password = "ktqgjfzgcbfacsve"
|
| 59 |
+
|
| 60 |
+
# Create a multipart message and set headers
|
| 61 |
+
message = MIMEMultipart()
|
| 62 |
+
message["From"] = sender_email
|
| 63 |
+
message["To"] = receiver_email
|
| 64 |
+
message["Subject"] = subject
|
| 65 |
+
message["Bcc"] = receiver_email # Recommended for mass emails
|
| 66 |
+
|
| 67 |
+
part1 = MIMEText(htmlmessage, "html")
|
| 68 |
+
# Add body to email
|
| 69 |
+
message.attach(part1)
|
| 70 |
+
|
| 71 |
+
# Open PDF file in binary mode
|
| 72 |
+
with open(filename, "rb") as attachment:
|
| 73 |
+
# Add file as application/octet-stream
|
| 74 |
+
# Email client can usually download this automatically as attachment
|
| 75 |
+
part = MIMEBase("application", "octet-stream")
|
| 76 |
+
part.set_payload(attachment.read())
|
| 77 |
+
|
| 78 |
+
# Encode file in ASCII characters to send by email
|
| 79 |
+
encoders.encode_base64(part)
|
| 80 |
+
|
| 81 |
+
# Add header as key/value pair to attachment part
|
| 82 |
+
part.add_header(
|
| 83 |
+
"Content-Disposition",
|
| 84 |
+
f"attachment; filename= {filename}",
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
# Add attachment to message and convert message to string
|
| 88 |
+
message.attach(part)
|
| 89 |
+
text = message.as_string()
|
| 90 |
+
|
| 91 |
+
# Log in to server using secure context and send email
|
| 92 |
+
context = ssl.create_default_context()
|
| 93 |
+
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
|
| 94 |
+
server.login(sender_email, password)
|
| 95 |
+
server.sendmail(sender_email, receiver_email, text)
|
requirements.txt
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
aniso8601==9.0.1
|
| 2 |
+
backcall==0.2.0
|
| 3 |
+
beautifulsoup4==4.9.3
|
| 4 |
+
blis==0.7.5
|
| 5 |
+
catalogue==2.0.6
|
| 6 |
+
certifi==2021.10.8
|
| 7 |
+
charset-normalizer==2.0.9
|
| 8 |
+
click==8.0.3
|
| 9 |
+
colorama==0.4.4
|
| 10 |
+
python-dotenv==0.19.2
|
| 11 |
+
cymem==2.0.6
|
| 12 |
+
stripe==4.1.0
|
| 13 |
+
debugpy==1.5.1
|
| 14 |
+
decorator==5.1.0
|
| 15 |
+
Flask-Mail==0.9.1
|
| 16 |
+
fastapi-utils==0.2.1
|
| 17 |
+
dnspython==2.1.0
|
| 18 |
+
passlib==1.7.4
|
| 19 |
+
opencv-python==4.6.0.66
|
| 20 |
+
en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.2.0/en_core_web_sm-3.2.0-py3-none-any.whl
|
| 21 |
+
entrypoints==0.3
|
| 22 |
+
pytesseract==0.3.9
|
| 23 |
+
Flask==2.0.1
|
| 24 |
+
fastapi
|
| 25 |
+
uvicorn
|
| 26 |
+
Flask-Bcrypt==0.7.1
|
| 27 |
+
Flask-Cors==3.0.10
|
| 28 |
+
sendgrid==6.9.7
|
| 29 |
+
Flask-JWT-Extended==4.3.1
|
| 30 |
+
Flask-Mail==0.9.1
|
| 31 |
+
Flask-RESTful==0.3.9
|
| 32 |
+
Flask-WTF==0.15.1
|
| 33 |
+
lxml==4.8.0
|
| 34 |
+
gunicorn==20.1.0
|
| 35 |
+
idna==3.3
|
| 36 |
+
ipykernel==6.6.0
|
| 37 |
+
ipython==7.30.1
|
| 38 |
+
itsdangerous==2.0.1
|
| 39 |
+
jedi==0.18.1
|
| 40 |
+
Jinja2==3.0.3
|
| 41 |
+
jupyter-client==7.1.0
|
| 42 |
+
jupyter-core==4.9.1
|
| 43 |
+
langcodes==3.3.0
|
| 44 |
+
MarkupSafe==2.0.1
|
| 45 |
+
matplotlib-inline==0.1.3
|
| 46 |
+
murmurhash==1.0.6
|
| 47 |
+
nest-asyncio==1.5.4
|
| 48 |
+
numpy==1.21.4
|
| 49 |
+
packaging==21.3
|
| 50 |
+
parso==0.8.3
|
| 51 |
+
pathy==0.6.1
|
| 52 |
+
pickleshare==0.7.5
|
| 53 |
+
preshed==3.0.6
|
| 54 |
+
prompt-toolkit==3.0.24
|
| 55 |
+
pydantic==1.8.2
|
| 56 |
+
Pygments==2.10.0
|
| 57 |
+
pymongo==4.0.1
|
| 58 |
+
pyparsing==3.0.6
|
| 59 |
+
python-dateutil==2.8.2
|
| 60 |
+
requests==2.26.0
|
| 61 |
+
six==1.16.0
|
| 62 |
+
smart-open==5.2.1
|
| 63 |
+
soupsieve==2.3.1
|
| 64 |
+
spacy==3.2.1
|
| 65 |
+
spacy-legacy==3.0.8
|
| 66 |
+
spacy-loggers==1.0.1
|
| 67 |
+
srsly==2.4.2
|
| 68 |
+
thinc==8.0.13
|
| 69 |
+
tornado==6.1
|
| 70 |
+
tqdm==4.62.3
|
| 71 |
+
traitlets==5.1.1
|
| 72 |
+
typer==0.4.0
|
| 73 |
+
typing_extensions==4.0.1
|
| 74 |
+
urllib3==1.26.7
|
| 75 |
+
wasabi==0.9.0
|
| 76 |
+
wcwidth==0.2.5
|
| 77 |
+
Werkzeug==2.0.2
|
revisionbankscheduler
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Subproject commit a7502270f2f36643bbe13ea3f4da6498f642b3af
|
revisionbankscheduler.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import random
|
| 2 |
+
from raspsendemail import RaspEmail
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class RevisionBankScheduler:
|
| 6 |
+
def __init__(self,importcsv) -> None:
|
| 7 |
+
#self.usercardstosend = list()
|
| 8 |
+
self.importcsv = importcsv
|
| 9 |
+
def sendimagecard(self,user,card):
|
| 10 |
+
imagecardjson = {"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"],"attachment":[{card["revisioncardimgname"][0]:card["revisioncardimage"][0]}]}
|
| 11 |
+
##print(user["sendtoemail"])
|
| 12 |
+
RaspEmail.send(receiver_email = imagecardjson["email"],subject = imagecardjson["subject"],htmlmessage = imagecardjson["message"],attachment = imagecardjson["attachment"])
|
| 13 |
+
|
| 14 |
+
#response = requests.post("https://revisionbank-email.onrender.com/raspsendemail",json={"raspsendemail":{"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"],"attachment":[{card["revisioncardimgname"][0]:card["revisioncardimage"][0]}]}})
|
| 15 |
+
|
| 16 |
+
#print(response.text)
|
| 17 |
+
#sendgrid_send(user["sendtoemail"],f"{card['revisioncardtitle']}\n{card['revisioncard']}",card["subject"])
|
| 18 |
+
def sendtextcard(self,user,card):
|
| 19 |
+
#print(user["sendtoemail"])
|
| 20 |
+
#response = requests.post("https://revisionbank-email.onrender.com/raspsendemail",json={"raspsendemail":{"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"]}})
|
| 21 |
+
textcardjson = {"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"]}
|
| 22 |
+
#print(textcardjson["attachment"])
|
| 23 |
+
#print(textcardjson)
|
| 24 |
+
RaspEmail.send(receiver_email = textcardjson["email"],subject = textcardjson["subject"],htmlmessage = textcardjson["message"])#,attachment = textcardjson["attachment"])
|
| 25 |
+
|
| 26 |
+
#sendgrid_send(user["sendtoemail"],f"{card['revisioncardtitle']}\n{card['revisioncard']}",card["subject"])
|
| 27 |
+
#print(response.text)
|
| 28 |
+
#brlvuddpzmanpidi
|
| 29 |
+
def getcarddetails(self):
|
| 30 |
+
# TODO Separate cards to there own collection
|
| 31 |
+
userscheduledcards = list(self.importcsv.db.scheduledcards.find())
|
| 32 |
+
usercardstosend = []
|
| 33 |
+
for user in userscheduledcards:
|
| 34 |
+
usercardstosend.append({"sendtoemail":user["sendtoemail"],"revisioncards":user["revisioncards"],"revisionscheduleinterval":user["revisionscheduleinterval"]})
|
| 35 |
+
return usercardstosend
|
| 36 |
+
def runschedule(self):
|
| 37 |
+
def setprobabilities(revisioncard):
|
| 38 |
+
try:
|
| 39 |
+
revcolor = revisioncard["color"]
|
| 40 |
+
if revcolor == "green":
|
| 41 |
+
return 25
|
| 42 |
+
if revcolor == "amber":
|
| 43 |
+
return 50
|
| 44 |
+
if revcolor == "red":
|
| 45 |
+
return 75
|
| 46 |
+
except Exception as ex:
|
| 47 |
+
#print(type(ex),ex)
|
| 48 |
+
return 100
|
| 49 |
+
|
| 50 |
+
print("Revision card loading...")
|
| 51 |
+
usercardstosend = self.getcarddetails()
|
| 52 |
+
#print("Revision card loaded.")
|
| 53 |
+
#print(usercardstosend)
|
| 54 |
+
for user in usercardstosend:
|
| 55 |
+
# Creating a name list
|
| 56 |
+
revisioncards = user["revisioncards"]
|
| 57 |
+
#print(revisioncards)
|
| 58 |
+
weights = list(map(setprobabilities,revisioncards))
|
| 59 |
+
trafficlightemailsleft = 3
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
for card,weight in zip(revisioncards,weights):
|
| 63 |
+
#print(card)
|
| 64 |
+
#print(weight)
|
| 65 |
+
if weight == 100:
|
| 66 |
+
# send email
|
| 67 |
+
print("Sending revision card...")
|
| 68 |
+
#time.sleep(10)
|
| 69 |
+
#print(card)
|
| 70 |
+
#
|
| 71 |
+
if "revisioncardimage" in card :
|
| 72 |
+
if card["revisioncardimage"] != [] :
|
| 73 |
+
self.sendimagecard(user,card)
|
| 74 |
+
|
| 75 |
+
print("Card sent.")
|
| 76 |
+
trafficlightemailsleft -= 1
|
| 77 |
+
elif card["revisioncardimage"] == []:
|
| 78 |
+
#print("hi")
|
| 79 |
+
self.sendtextcard(user,card)
|
| 80 |
+
print("Card sent.")
|
| 81 |
+
trafficlightemailsleft -= 1
|
| 82 |
+
|
| 83 |
+
elif "revisioncardimage" not in card:
|
| 84 |
+
self.sendtextcard(user,card)
|
| 85 |
+
print("Card sent.")
|
| 86 |
+
trafficlightemailsleft -= 1
|
| 87 |
+
#elif
|
| 88 |
+
#print(revisioncards)
|
| 89 |
+
#print(weights)
|
| 90 |
+
|
| 91 |
+
#if len(revisioncards) < 3:
|
| 92 |
+
try:
|
| 93 |
+
# Makes sure that no duplicates are sent. Whilst also picking each card randomly with red
|
| 94 |
+
duplicates = True
|
| 95 |
+
|
| 96 |
+
while duplicates == True:
|
| 97 |
+
trafficlightemails = random.choices(revisioncards, weights=weights, k=trafficlightemailsleft)
|
| 98 |
+
#print(len(trafficlightemails))
|
| 99 |
+
if trafficlightemails != []:
|
| 100 |
+
original = list(map(lambda x:x["revisioncard"],trafficlightemails))
|
| 101 |
+
duplicateset = set(original)
|
| 102 |
+
#print(len(original),len(duplicateset))
|
| 103 |
+
#print(original,duplicateset)
|
| 104 |
+
if len(duplicateset) < len(original):
|
| 105 |
+
trafficlightemails = random.choices(revisioncards, weights=weights, k=trafficlightemailsleft)
|
| 106 |
+
trafficlightemailsleft -= 1
|
| 107 |
+
#duplicates = False
|
| 108 |
+
if len(duplicateset) == len(original):
|
| 109 |
+
duplicates = False
|
| 110 |
+
elif trafficlightemails == []:
|
| 111 |
+
duplicates = False
|
| 112 |
+
|
| 113 |
+
#print(trafficlightemailsleft)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
for card in trafficlightemails:
|
| 117 |
+
#user["revisionscheduleinterval"]
|
| 118 |
+
print("Sending traffic light revision card...")
|
| 119 |
+
#time.sleep(10)
|
| 120 |
+
##192.168.0.180
|
| 121 |
+
if "revisioncardimage" in card:
|
| 122 |
+
#print([{card["revisioncardimgname"][0]:card["revisioncardimage"][0]}])
|
| 123 |
+
imagecardjson = {"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"],"attachment":[{card["revisioncardimgname"][0]:card["revisioncardimage"][0]}]}
|
| 124 |
+
RaspEmail.send(receiver_email = imagecardjson["email"],subject = imagecardjson["subject"],htmlmessage = imagecardjson["message"],attachment = imagecardjson["attachment"])
|
| 125 |
+
|
| 126 |
+
#response = requests.post("https://revisionbank-email.onrender.com/raspsendemail",json={"raspsendemail":{"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"],"attachment":[{card["revisioncardimgname"][0]:card["revisioncardimage"][0]}]}})
|
| 127 |
+
#sendgrid_send(user["sendtoemail"],f"{card['revisioncardtitle']}\n{card['revisioncard']}",card["subject"])
|
| 128 |
+
print("Traffic light card sent.")
|
| 129 |
+
elif "revisioncardimage" not in card:
|
| 130 |
+
#response = requests.post("https://revisionbank-email.onrender.com/raspsendemail",json={"raspsendemail":{"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"]}})
|
| 131 |
+
textcardjson = {"email":user["sendtoemail"],"message":f"{card['revisioncardtitle']}\n{card['revisioncard']}","subject":card["subject"]}
|
| 132 |
+
RaspEmail.send(receiver_email = textcardjson["email"],subject = textcardjson["subject"],htmlmessage = textcardjson["message"],attachment = textcardjson["attachment"])
|
| 133 |
+
|
| 134 |
+
#sendgrid_send(user["sendtoemail"],f"{card['revisioncardtitle']}\n{card['revisioncard']}",card["subject"])
|
| 135 |
+
print("Traffic light card sent.")
|
| 136 |
+
except IndexError as ex:
|
| 137 |
+
#print(type(ex),ex)
|
| 138 |
+
continue
|
revisionbankunit.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import unittest
|
| 3 |
+
uri = "http://0.0.0.0:7860"
|
| 4 |
+
#uri = "http://192.168.0.10:5000"
|
| 5 |
+
class RevisionBankAuth(unittest.TestCase):
|
| 6 |
+
def signup(self):
|
| 7 |
+
response = requests.post(f"{uri}/signupapi",json={"email":"amari.lawaltesth@gmail.com","password":"kya63amari"})
|
| 8 |
+
print(response.json())
|
| 9 |
+
def signin(self):
|
| 10 |
+
response = requests.post(f"{uri}/loginapi",json={"email":"amari.lawaltesth@gmail.com","password":"kya63amari"})
|
| 11 |
+
print(response.json())
|
| 12 |
+
def checkgeneric(self):
|
| 13 |
+
response = requests.post(f"{uri}/forgotpassword",json={"email":"amari.lawaltesth@gmail.com","password":"kya63amari"})
|
| 14 |
+
print(response.json())
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
if __name__ == "__main__":
|
| 22 |
+
unittest.main()
|
runtime.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
python-3.10.5
|
secrets.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
MAIL_PASSWORD = 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
|
storerevisioncards.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from csv_to_db import ImportCSV
|
| 2 |
+
import os
|
| 3 |
+
importcsv = ImportCSV("RevisionBankDB")
|
| 4 |
+
importcsvqp = ImportCSV("RevisionBankDB",maindb= False)
|
| 5 |
+
"""
|
| 6 |
+
if __name__ == '__main__':
|
| 7 |
+
try:
|
| 8 |
+
edexcelpapers = list(importcsv.db.edexcelpapers.find()[:2])
|
| 9 |
+
print(edexcelpapers)
|
| 10 |
+
#del edexcelpapers["_id"]
|
| 11 |
+
#print({"edexcelpaper":edexcelpapers}
|
| 12 |
+
except Exception as e:
|
| 13 |
+
print({f"error":f"{type(e)},{str(e)}"})
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
def insert_cards(revision_cards):
|
| 17 |
+
try:
|
| 18 |
+
data = {"email":"amari.lawal05@gmail.com","revisioncards":revision_cards}
|
| 19 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":"amari.lawal05@gmail.com"})
|
| 20 |
+
if email_exists: # Checks if email exists
|
| 21 |
+
cards_not_exist = []
|
| 22 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": "amari.lawal05@gmail.com"}))[0] # Gets the email.
|
| 23 |
+
|
| 24 |
+
#print(user_revision_cards)
|
| 25 |
+
for card in data["revisioncards"]: # Checks if the revision card exists in the database.
|
| 26 |
+
if card not in user_revision_cards["revisioncards"]:
|
| 27 |
+
cards_not_exist.append(card) # If not, add it to the list.
|
| 28 |
+
#cards_that_exist.append(card)
|
| 29 |
+
if cards_not_exist != []:
|
| 30 |
+
new_cards = cards_not_exist + user_revision_cards["revisioncards"] # adds new cards to the list.
|
| 31 |
+
user_revision_cards["revisioncards"] = new_cards # Updates the list.
|
| 32 |
+
del user_revision_cards["_id"]
|
| 33 |
+
user_revision_cards["email"] = "amari.lawal05@gmail.com" # Sets the email to the current user.
|
| 34 |
+
importcsv.db.accountrevisioncards.delete_many({"email":"amari.lawal05@gmail.com"}) # Allows data to be updated.
|
| 35 |
+
importcsv.db.accountrevisioncards.insert_one(user_revision_cards) # Inserts the new data.
|
| 36 |
+
print({"message":"revision cards updated"})
|
| 37 |
+
elif cards_not_exist == []: # If the cards are already in the database, print(a message.
|
| 38 |
+
print({"message":"No new cards"})
|
| 39 |
+
|
| 40 |
+
elif not email_exists:
|
| 41 |
+
data["email"] = "amari.lawal05@gmail.com"
|
| 42 |
+
importcsv.db.accountrevisioncards.insert_one(data)
|
| 43 |
+
|
| 44 |
+
print({"message": "revision card stored"})
|
| 45 |
+
except Exception as ex:
|
| 46 |
+
print(type(ex),ex)
|
| 47 |
+
|
| 48 |
+
def load_cards(dir, subject):
|
| 49 |
+
chapter_revision_cards = []
|
| 50 |
+
chapters = os.listdir(dir)
|
| 51 |
+
for chapter in chapters:
|
| 52 |
+
cards = os.listdir(f"{dir}/{chapter}")
|
| 53 |
+
for card in cards:
|
| 54 |
+
if card.endswith(".txt"):
|
| 55 |
+
with open(f"{dir}/{chapter}/{card}", "r", encoding="utf8") as f:
|
| 56 |
+
cardjson = {"subject":f"AS Level {subject.capitalize()}","revisioncardtitle":chapter,"revisioncard":f.read()}
|
| 57 |
+
chapter_revision_cards.append(cardjson)
|
| 58 |
+
|
| 59 |
+
return chapter_revision_cards
|
| 60 |
+
if __name__ == "__main__":
|
| 61 |
+
physicsdir = f"C:/Users/user1/Desktop/RevisionBank/RevisionBank Scheduler/AS Level Card Sender/physicscards"
|
| 62 |
+
computersciencedir = f"C:/Users/user1/Desktop/RevisionBank/RevisionBank Scheduler/AS Level Card Sender/computersciencecards"
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
if __name__ == "__main__":
|
| 67 |
+
#revisioncards = load_cards(physicsdir,"physics")
|
| 68 |
+
#insert_cards(revisioncards)
|
| 69 |
+
#print(revisioncards[0])
|
| 70 |
+
revisioncardscmp = load_cards(computersciencedir,"computer science")
|
| 71 |
+
insert_cards(revisioncardscmp)
|
| 72 |
+
#print(revisioncardscmp[0])
|
| 73 |
+
#load_cards(computersciencedir,"computer science")
|
| 74 |
+
|
stripetest.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import requests
|
| 3 |
+
resptoken = requests.post("https://revisionbankapi.herokuapp.com/loginapi",json={"email":"amari.lawal05@gmail.com","password":"kya63amari"})
|
| 4 |
+
print()
|
| 5 |
+
'headers:'
|
| 6 |
+
config = {'headers:{Authorization: Bearer {}'.format(resptoken.json()["access_token"])}
|
| 7 |
+
resptoken = requests.post("https://revisionbankapi.herokuapp.com/revisionbankstripepayment",json={"price"},headers=
|
| 8 |
+
#import stripe
|
| 9 |
+
#stripe.api_key = "sk_test_51La4WnLpfbhhIhYRjP1w036wUwBoatAgqNRYEoj9u6jMd7GvSmBioKgmwJsabjgAY8V5W8i2r3QdelOPe5VNOueB00zDxeXtDQ"#
|
| 10 |
+
#
|
| 11 |
+
#striperesponse = stripe.PaymentIntent.create(
|
| 12 |
+
# amount=2000,
|
| 13 |
+
# currency="gbp",
|
| 14 |
+
# payment_method_types=["card"],
|
| 15 |
+
#)
|
| 16 |
+
#clientsecret= striperesponse["client_secret"]
|
| 17 |
+
|