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=["[email protected]"])
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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"]]) # "[email protected]"
|
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 [email protected]
|
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]) # "[email protected]"
|
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":"[email protected]","furthermathsbbook": 0,"furthermathsbyear":2}}
|
679 |
+
# Output PureMaths Book 2
|
680 |
+
current_user = get_jwt_identity() # outputs the email of the user [email protected]
|
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]) # "[email protected]"
|
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 [email protected]
|
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]) # "[email protected]"
|
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 [email protected]
|
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]) # "[email protected]"
|
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"]]) # "[email protected]"
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
1259 |
+
if current_user:
|
1260 |
+
# Hostemail is the primary key for the studentsubscription collection
|
1261 |
+
try:
|
1262 |
+
data = request.get_json()
|
1263 |
+
# {"hostemail": "[email protected]","hostnumofaccounts": 198,"studentemails": [{"email": "[email protected]","password": "mann35"},{"email": "[email protected]","password": "billy45"},{"email": "[email protected]","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":"[email protected]","password":"password"},{"email":"[email protected]","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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 | |
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:[email protected]/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:[email protected]/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:[email protected]/?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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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"]]) # "[email protected]"
|
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 [email protected]
|
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]) # "[email protected]"
|
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":"[email protected]","furthermathsbbook": 0,"furthermathsbyear":2}}
|
673 |
+
# Output PureMaths Book 2
|
674 |
+
current_user = secure_decode(authorization.replace("Bearer ",""))["email"] # outputs the email of the user [email protected]
|
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]) # "[email protected]"
|
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 [email protected]
|
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]) # "[email protected]"
|
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 [email protected]
|
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]) # "[email protected]"
|
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"]]) # "[email protected]"
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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": "[email protected]","hostnumofaccounts": 198,"studentemails": [{"email": "[email protected]","password": "mann35"},{"email": "[email protected]","password": "billy45"},{"email": "[email protected]","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":"[email protected]","password":"password"},{"email":"[email protected]","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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 [email protected]
|
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 = "[email protected]"
|
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 = "[email protected]"
|
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":"[email protected]","password":"kya63amari"})
|
8 |
+
print(response.json())
|
9 |
+
def signin(self):
|
10 |
+
response = requests.post(f"{uri}/loginapi",json={"email":"[email protected]","password":"kya63amari"})
|
11 |
+
print(response.json())
|
12 |
+
def checkgeneric(self):
|
13 |
+
response = requests.post(f"{uri}/forgotpassword",json={"email":"[email protected]","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":"[email protected]","revisioncards":revision_cards}
|
19 |
+
email_exists = importcsv.db.accountrevisioncards.find_one({"email":"[email protected]"})
|
20 |
+
if email_exists: # Checks if email exists
|
21 |
+
cards_not_exist = []
|
22 |
+
user_revision_cards = list(importcsv.db.accountrevisioncards.find({"email": "[email protected]"}))[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"] = "[email protected]" # Sets the email to the current user.
|
34 |
+
importcsv.db.accountrevisioncards.delete_many({"email":"[email protected]"}) # 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"] = "[email protected]"
|
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":"[email protected]","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 |
+
|