Repository: mr-teslaa/valentine-ai Branch: main Commit: 6c0ab822390f Files: 49 Total size: 137.0 KB Directory structure: gitextract_nl_bb119/ ├── .github/ │ └── workflows/ │ └── deploy.yml ├── .gitignore ├── application/ │ ├── CohereAI/ │ │ ├── GenerateBlog.py │ │ └── Utils.py │ ├── __init__.py │ ├── auth/ │ │ ├── __init__.py │ │ ├── forms.py │ │ └── views.py │ ├── config.py │ ├── models.py │ ├── public/ │ │ ├── __init__.py │ │ └── views.py │ ├── static/ │ │ └── assets/ │ │ ├── css/ │ │ │ └── custom.css │ │ ├── js/ │ │ │ ├── clock.js │ │ │ └── theme.js │ │ └── vendor/ │ │ └── prismjs/ │ │ ├── plugins/ │ │ │ ├── line-numbers/ │ │ │ │ └── prism-line-numbers.css │ │ │ └── toolbar/ │ │ │ └── prism-toolbar.css │ │ └── themes/ │ │ └── prism.css │ ├── superadmin/ │ │ ├── __init__.py │ │ ├── forms.py │ │ └── views.py │ ├── templates/ │ │ ├── auth/ │ │ │ ├── activation_link_email.html │ │ │ ├── forgetpassword.html │ │ │ ├── join.html │ │ │ ├── login.html │ │ │ ├── password_reset_link_email.html │ │ │ └── reset_token.html │ │ ├── helpers/ │ │ │ ├── _global_footer.html │ │ │ ├── _nav_top_landing.html │ │ │ └── _side_navbar_dashboard.html │ │ ├── layout/ │ │ │ └── root.html │ │ ├── public/ │ │ │ ├── landing.html │ │ │ └── letter.html │ │ └── user/ │ │ ├── account.html │ │ ├── account_update_password.html │ │ ├── dashboard.html │ │ ├── letter_sent.html │ │ ├── letters.html │ │ └── send_letter_email.html │ ├── user/ │ │ ├── __init__.py │ │ ├── forms.py │ │ └── views.py │ └── utils/ │ ├── CutomAuth.py │ ├── Location.py │ ├── SendEmail.py │ ├── Utils.py │ └── __init__.py ├── requirements.txt └── run.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/deploy.yml ================================================ on: push: branches: - main name: 🚀 Deploy website on push jobs: web-deploy: name: 🎉 Deploy runs-on: ubuntu-latest steps: - name: 🚚 Get latest code uses: actions/checkout@v2 - name: 📂 Sync files uses: SamKirkland/FTP-Deploy-Action@4.3.0 with: server: ${{ secrets.ftp_server }} username: ${{ secrets.ftp_username }} password: ${{ secrets.ftp_password }} ================================================ FILE: .gitignore ================================================ # Created by https://www.toptal.com/developers/gitignore/api/flask # Edit at https://www.toptal.com/developers/gitignore?templates=flask migrations/ __pycache__/ application/__pycache__/ application/public/__pycache__/ */*/__pycache__/ */*/*/__pycache__/ */*/*/*/__pycache__/ */*/*/*/*/__pycache__/ .idea/ venv/ env/ .code/ .vscode/ .pytest_cache/ tempCodeRunnerFile.py ### Flask ### instance/* !instance/.gitignore .webassets-cache .env ### Flask.Python Stack ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/#use-with-ide .pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ # End of https://www.toptal.com/developers/gitignore/api/flask ================================================ FILE: application/CohereAI/GenerateBlog.py ================================================ import os import time import cohere from dotenv import find_dotenv, load_dotenv load_dotenv(find_dotenv()) # Cohere AI API setup co = cohere.Client(os.getenv('API_KEY')) def max_likely(prediction): output = prediction.generations[0].text return output # Generate blog posts for each keyword def generate_letter(gender): letter_generate = co.generate( model='command', prompt= "You are a poet, you are known for your unique romantic, flirting words and today is valentines day. Write one very short sentence within 65 character romantic, loving, caring message for my " + gender, max_tokens=70, temperature=0.9, stop_sequences=["---"] ) letter = max_likely(letter_generate) return letter ================================================ FILE: application/CohereAI/Utils.py ================================================ import uuid def linkid(): link = uuid.uuid4().hex[:8] return link ================================================ FILE: application/__init__.py ================================================ from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt from flask_login import LoginManager from flask_migrate import Migrate from flask_moment import Moment from application.config import Config from flask_mail import Mail db = SQLAlchemy() bcrypt = Bcrypt() login_manager = LoginManager() migrate = Migrate() moment = Moment() mail = Mail() login_manager.login_view = 'auth.login' login_manager.login_message_category = 'info' def create_app(config_class=Config): app = Flask(__name__) app.config.from_object(Config) db.init_app(app) bcrypt.init_app(app) login_manager.init_app(app) moment.init_app(app) migrate.init_app(app, db) mail.init_app(app) from application.models import User from application.models import Visitor from application.auth.views import auth app.register_blueprint(auth) from application.public.views import public app.register_blueprint(public) from application.superadmin.views import superadmin app.register_blueprint(superadmin) from application.user.views import user app.register_blueprint(user) return app ================================================ FILE: application/auth/__init__.py ================================================ ================================================ FILE: application/auth/forms.py ================================================ from flask_wtf import FlaskForm from wtforms import StringField from wtforms import PasswordField from wtforms import IntegerField from wtforms import SubmitField from wtforms import BooleanField from wtforms import TextAreaField from wtforms import SelectField from wtforms import DateField from flask_wtf.file import FileField from flask_wtf.file import FileAllowed from wtforms.validators import DataRequired from wtforms.validators import NumberRange from wtforms.validators import Optional from wtforms.validators import Length from wtforms.validators import Email from wtforms.validators import EqualTo from wtforms.validators import ValidationError from flask_login import current_user from application.models import User class RegistrationForm(FlaskForm): name = StringField( 'Your Name', validators = [ DataRequired(), Length(2, 50) ] ) phone = StringField( 'Phone', validators=[ DataRequired(), Length(min=5, max=15, message='Phone number must be between 5 and 15.') ] ) email = StringField( 'E-mail', validators = [ DataRequired(), Email() ] ) password = PasswordField( 'Password', validators = [ DataRequired() ] ) confirm_password = PasswordField( 'Confirm Password', validators = [ DataRequired(), EqualTo('password') ] ) submit = SubmitField('Join Now') def validate_phone(self, phone): user_phone = User.query.filter_by(phone=phone.data).first() if user_phone: raise ValidationError('This Phone is alredy registerd. Please choose a different one.') def validate_email(self, email): user_email = User.query.filter_by(email=email.data).first() if user_email: raise ValidationError('That email is taken/already registered. Please choose a different one.') class LoginForm(FlaskForm): phone = StringField( 'Phone', validators=[ DataRequired(), Length(min=5, max=15, message='Phone number must be between 5 and 15.') ] ) password = PasswordField( 'Password', validators = [DataRequired()] ) remember = BooleanField('Remember Me') submit = SubmitField('Login') # UPDATE PASSWORD FORM class UpdatePasswordForm(FlaskForm): currentPassword = PasswordField( 'Current Password', validators=[ DataRequired() ] ) newPassword = PasswordField( 'New Password', # validators=[ DataRequired() ] ) confirmnewPassword = PasswordField( 'Confirm New Password', # validators=[ DataRequired() ] ) submit = SubmitField('Save') # FORGET PASSWORD FORM class ForgetPasswordForm(FlaskForm): email = StringField( 'Email', validators = [ Email() ] ) submit = SubmitField('Get Password Reset Link') # CHANGE PASSWORD TOKEN class ResetPasswordForm(FlaskForm): password = PasswordField( 'Password', validators=[ DataRequired() ] ) confirm_password = PasswordField( 'Confirm Password', validators = [ DataRequired(), EqualTo('password') ] ) submit = SubmitField('Reset Password') ================================================ FILE: application/auth/views.py ================================================ # importing basic flask module from flask import Blueprint from flask import redirect from flask import render_template from flask import request from flask import url_for from flask import flash from flask import abort from flask import jsonify from flask import make_response from flask import current_app # importing module from flask login from flask_login import current_user from flask_login import login_required from flask_login import login_user from flask_login import logout_user from application import db from application import bcrypt from application.models import User from application.auth.forms import LoginForm from application.auth.forms import RegistrationForm from application.auth.forms import UpdatePasswordForm from application.auth.forms import ForgetPasswordForm from application.auth.forms import ResetPasswordForm from application.utils.SendEmail import send_reset_email auth = Blueprint('auth', __name__) # @auth.route('/join/admin/', methods=['GET', 'POST']) # def join_superadmin(): # current_ip = request.remote_addr # if current_user.is_authenticated: # current_user.ip = current_ip # db.session.commit() # return redirect(url_for('user.dashboard')) # form = RegistrationForm() # if form.validate_on_submit(): # hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') # if form.middle_name.data: # user = User( # first_name=form.first_name.data.strip(), # middle_name=form.middle_name.data.strip(), # last_name=form.last_name.data.strip(), # phone=form.phone.data, # password=hashed_password, # email=form.email.data.strip(), address=form.address.data.strip(), # user_role='superadmin', is_active=True # ) # else: # user = User( # first_name=form.first_name.data.strip(), # last_name=form.last_name.data.strip(), # phone=form.phone.data, # password=hashed_password, # email=form.email.data.strip(), address=form.address.data.strip(), # user_role='superadmin', is_active=True # ) # db.session.add(user) # db.session.commit() # send_activation_email(user) # send_admin_contact_alert_email(user) # flash('Check your email, we have sent you a confirmation link to activate your account', 'info') # return redirect(url_for('auth.login')) # return render_template('auth/join.html', form=form) # NEW USER JOIN PAGE @auth.route('/join/', methods=['GET', 'POST']) def join(): current_ip = request.remote_addr if current_user.is_authenticated: current_user.ip = current_ip db.session.commit() return redirect(url_for('user.dashboard')) form = RegistrationForm() if form.validate_on_submit(): hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') user = User( name=form.name.data.strip(), phone=form.phone.data, password=hashed_password, email=form.email.data.strip(), user_role='user', is_active=True ) db.session.add(user) db.session.commit() flash('Account created successfully', 'info') return redirect(url_for('auth.login')) return render_template('auth/join.html', form=form) # Activate account route @auth.route('/activate/') def activate(token): # Activate a user's account user = User.query.filter_by(activation_token=token, is_active=False).first() if user: user_verified = user.verify_reset_token(token) if user_verified: user.is_active = True db.session.commit() flash('Your account has been activated! You are now able to log in ✅', 'success') return redirect(url_for('auth.login')) else: flash('The activation link is invalid or has expired.', 'warning') return redirect(url_for('auth.join')) # USER LOGIN PAGE @auth.route('/login/', methods=['GET', 'POST']) def login(): form = LoginForm() current_ip = request.remote_addr if current_user.is_authenticated: current_user.ip = current_ip db.session.commit() return redirect(url_for('user.dashboard')) if form.validate_on_submit(): user = User.query.filter_by(phone=form.phone.data).first_or_404() if user and user.is_active and bcrypt.check_password_hash(user.password, form.password.data): login_user(user, remember=form.remember.data) next_page = request.args.get('next') flash('✅ Login success', 'success') return redirect(next_page) if next_page else redirect(url_for('user.dashboard')) elif user and not user.is_active: flash('⚠️ Please check your email and activate your account, untill you can not login', 'info') else: flash('⚠️ Login Unsuccessful. Please check phone number and password', 'danger') return render_template('auth/login.html', form=form) # USER LOGOUT @auth.route("/logout/") @login_required def logout(): logout_user() flash('Logout successfully ✅', 'success') return redirect(url_for('auth.login')) # RESET PASSWORD FOR USER @auth.route('/user/resetpassword/', methods=['GET', 'POST']) @login_required def user_resetpassword(): form = UpdatePasswordForm() if form.validate_on_submit(): newpass = form.newPassword.data confirmpass = form.confirmnewPassword.data currentpass_hash = bcrypt.check_password_hash(current_user.password, form.currentPassword.data) if currentpass_hash and newpass==confirmpass: hashed_password = bcrypt.generate_password_hash(newpass).decode('utf-8') current_user.password = hashed_password db.session.commit() flash('Your password has been updated!', 'success') return redirect(url_for('user.dashboard')) else: flash('Password Not Matched', 'danger') return redirect(url_for('user.user_resetpassword')) return render_template('user/change_password.html', title='Change Password', form=form) # VERIFY USER EMAIL IS REGISTERED IN OUR SYSTEM @auth.route('/password/recover/', methods=['GET', 'POST']) def forgetpassword(): form = ForgetPasswordForm() if current_user.is_authenticated: return redirect(url_for('user.dashboard')) if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() send_reset_email(user) flash('If you have an account with this email, an email has been sent with instructions to reset your password.', 'info') return redirect(url_for('auth.login')) return render_template('auth/forgetpassword.html', title='Reset Password', form=form) # PASSWORD RESET TOKEN @auth.route("/reset-password/", methods=['GET', 'POST']) def reset_token(token): if current_user.is_authenticated: return redirect(url_for('user.index')) user = User.verify_reset_token(token) if user is None: flash('That is an invalid or expired token', 'warning') return redirect(url_for('user.reset_request')) form = ResetPasswordForm() if form.validate_on_submit(): hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') user.password = hashed_password db.session.commit() flash('Your password has been updated! You are now able to log in', 'success') return redirect(url_for('auth.login')) return render_template('auth/reset_token.html', title='Reset Password', form=form) ================================================ FILE: application/config.py ================================================ import os from dotenv import find_dotenv, load_dotenv load_dotenv(find_dotenv()) production=True # production=False class Config: SECRET_KEY='248fb9a5bdffa13c0bc136504ebf75c2' if production is True: SQLALCHEMY_DATABASE_URI=os.getenv('SQLALCHEMY_DATABASE_URI') else: SQLALCHEMY_DATABASE_URI='sqlite:///valentine.db' # SQLALCHEMY_TRACK_MODIFICATIONS=True MAIL_SERVER = os.getenv('SMTP_SERVER') MAIL_DEFAULT_SENDER = 'amazonkdp@binomatrix.com' MAIL_PORT = 465 MAIL_USE_SSL = True MAIL_USERNAME = os.getenv('EMAIL_USERNAME') MAIL_PASSWORD = os.getenv('EMAIL_PASSWORD') ================================================ FILE: application/models.py ================================================ import secrets # importing necessary module from datetime import datetime from flask import current_app # importing dataase from application import db # importing login manager from application import login_manager from flask_login import UserMixin from itsdangerous import TimedJSONWebSignatureSerializer as Serializer # making sure that the user is logged in @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) class User(db.Model, UserMixin): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(300)) phone = db.Column(db.String(15), unique=True) email = db.Column(db.String(120), unique=True) img = db.Column(db.String(500), default='default.jpg') password = db.Column(db.String(800), nullable=False) address = db.Column(db.String(900)) user_role = db.Column(db.String(60), default="user") letter_sender = db.relationship('Letter', backref='sender', lazy=True) join_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) ip = db.Column(db.String(60)) # ACCOUNT ACTIVATION activation_token = db.Column(db.String(500), unique=True) is_active = db.Column(db.Boolean(), default=False) # GENERATE ACTIVATION TOKEN def generate_activation_token(self, expires_sec=3600): s = Serializer(current_app.config['SECRET_KEY'], expires_sec) return s.dumps({'user_id': self.id}).decode('utf-8') # GENERATING PASSWORD RESET TOKEN def get_reset_token(self, expires_sec=1800): s = Serializer(current_app.config['SECRET_KEY'], expires_sec) return s.dumps({'user_id': self.id}).decode('utf-8') # verify the token if the token has exprired or invalid @staticmethod def verify_reset_token(token): s = Serializer(current_app.config['SECRET_KEY']) try: user_id = s.loads(token)['user_id'] except: return None return User.query.get(user_id) # verify the token if the token has exprired or invalid @staticmethod def verify_activation_token(token): s = Serializer(current_app.config['SECRET_KEY']) try: user_id = s.loads(token)['user_id'] except: return None return User.query.get(user_id) class Letter(db.Model): id = db.Column(db.Integer, primary_key=True) receiver_name = db.Column(db.String(100), nullable=False) email=db.Column(db.String(100), nullable=False) gender=db.Column(db.String(100), nullable=False) message=db.Column(db.String(900)) link=db.Column(db.String(100), unique=True) is_hidden = db.Column(db.Boolean(), default=False) created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) sender_id = db.Column(db.Integer, db.ForeignKey('user.id')) class Visitor(db.Model): id = db.Column(db.Integer, primary_key=True) ip = db.Column(db.String(100), nullable=False) first_name=db.Column(db.String(100)) middle_name=db.Column(db.String(100)) last_name=db.Column(db.String(100)) email=db.Column(db.String(100)) phone=db.Column(db.String(100)) message=db.Column(db.String(100)) date_visit = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) ================================================ FILE: application/public/__init__.py ================================================ ================================================ FILE: application/public/views.py ================================================ # importing basic flask module from flask import Blueprint from flask import redirect from flask import render_template from flask import request from flask import url_for from flask import flash from flask import abort from flask import jsonify from flask import make_response from flask import current_app from datetime import date from datetime import datetime from application import db from application.models import User from application.models import Letter from application.models import Visitor from application.utils.Location import getLocation public = Blueprint('public', __name__) # LANDING PAGE @public.route('/') def index(): # GETTING IP OF USER ip_request = request.remote_addr # GET TODAY today = datetime.utcnow().date() # GET VISITORS visitor = Visitor.query.filter_by(ip=ip_request).filter(Visitor.date_visit.like(f'{today}%')).first() if visitor: # visitor has already visited today, don't count as a new visit pass else: visitor = Visitor(ip=ip_request) db.session.add(visitor) db.session.commit() return render_template( 'public/landing.html' ) # LETTER PAGE @public.route('/letter//') def letter(link): letter = Letter.query.filter_by(link=link).order_by(Letter.created_at.desc()).first_or_404() return render_template('public/letter.html', letter=letter) ================================================ FILE: application/static/assets/css/custom.css ================================================ /* ================ CLOCK ================ */ .clock-container h4, .clock-container h5, .clock-container p { margin-bottom: 0; color: #fff !important; } .clock-container .clock { color: var(--bs-white); text-align: center; position: fixed; bottom: 0; padding: 0.2rem 1.5rem; margin: 0.5rem; border-radius: 16px; background-color: var(--bs-light); z-index: 1025; } .clock-container .clock h4, .clock-container .clock h5 { color: var(--bs-white); } .clock-container .clock-right { right: 0; background: linear-gradient(131deg, rgb(252, 171, 1), rgb(254, 33, 79) 100%); } .clock-container .clock-left { left: 0; background: linear-gradient(117deg, rgb(30, 42, 120), rgb(255, 46, 76) 100%); } /* ================ TEXT ================ */ .text__justify { text-align: justify; } /* ================ END TEXT ================ */ ================================================ FILE: application/static/assets/js/clock.js ================================================ function updateClock1() { let date = new Date(); let nyWeekday = date.toLocaleString("en-US", { timeZone: "America/New_York", weekday: "long", }); let nyTime = date.toLocaleString("en-US", { timeZone: "America/New_York", hour: "numeric", minute: "numeric", second: "numeric", hour12: true, }); document.getElementById("nyWeekday").innerHTML = nyWeekday; document.getElementById("nytime").innerHTML = nyTime; } function updateClock2() { let date = new Date(); let bdWeekday = date.toLocaleString("en-US", { timeZone: "Asia/Dhaka", weekday: "long", }); let bdTime = date.toLocaleString("en-US", { timeZone: "Asia/Dhaka", hour: "numeric", minute: "numeric", second: "numeric", hour12: true, }); document.getElementById("bdWeekday").innerHTML = bdWeekday; document.getElementById("bdtime").innerHTML = bdTime; } setInterval(updateClock1, 1000); setInterval(updateClock2, 1000); ================================================ FILE: application/static/assets/js/theme.js ================================================ function _typeof(e) { return (_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { return typeof e; } : function (e) { return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e; })(e); } function ownKeys(t, e) { var r, a = Object.keys(t); return ( Object.getOwnPropertySymbols && ((r = Object.getOwnPropertySymbols(t)), e && (r = r.filter(function (e) { return Object.getOwnPropertyDescriptor(t, e).enumerable; })), a.push.apply(a, r)), a ); } function _objectSpread(t) { for (var e = 1; e < arguments.length; e++) { var r = null != arguments[e] ? arguments[e] : {}; e % 2 ? ownKeys(Object(r), !0).forEach(function (e) { _defineProperty(t, e, r[e]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(t, Object.getOwnPropertyDescriptors(r)) : ownKeys(Object(r)).forEach(function (e) { Object.defineProperty( t, e, Object.getOwnPropertyDescriptor(r, e) ); }); } return t; } function _defineProperty(e, t, r) { return ( (t = _toPropertyKey(t)) in e ? Object.defineProperty(e, t, { value: r, enumerable: !0, configurable: !0, writable: !0, }) : (e[t] = r), e ); } function _toPropertyKey(e) { e = _toPrimitive(e, "string"); return "symbol" === _typeof(e) ? e : String(e); } function _toPrimitive(e, t) { if ("object" !== _typeof(e) || null === e) return e; var r = e[Symbol.toPrimitive]; if (void 0 === r) return ("string" === t ? String : Number)(e); t = r.call(e, t || "default"); if ("object" !== _typeof(t)) return t; throw new TypeError("@@toPrimitive must return a primitive value."); } /** * Silicon | Multipurpose Bootstrap 5 Template & UI Kit * Copyright 2023 Createx Studio * Theme core scripts * * @author Createx Studio * @version 1.5.0 */ !(function () { "use strict"; var t, e, r, a, n, o; null !== (e = document.querySelector('[data-bs-toggle="mode"]')) && ((t = e.querySelector(".form-check-input")), "dark" === mode ? (root.classList.add("dark-mode"), (t.checked = !0)) : (root.classList.remove("dark-mode"), (t.checked = !1)), e.addEventListener("click", function (e) { t.checked ? (root.classList.add("dark-mode"), window.localStorage.setItem("mode", "dark")) : (root.classList.remove("dark-mode"), window.localStorage.setItem("mode", "light")); })), null != (a = document.querySelector(".navbar-sticky")) && ((e = a.classList), (r = a.offsetHeight), e.contains("position-absolute") ? window.addEventListener("scroll", function (e) { 500 < e.currentTarget.pageYOffset ? a.classList.add("navbar-stuck") : a.classList.remove("navbar-stuck"); }) : window.addEventListener("scroll", function (e) { 500 < e.currentTarget.pageYOffset ? ((document.body.style.paddingTop = r + "px"), a.classList.add("navbar-stuck")) : ((document.body.style.paddingTop = ""), a.classList.remove("navbar-stuck")); })), new SmoothScroll("[data-scroll]", { speed: 800, speedAsDuration: !0, offset: function (e, t) { return t.dataset.scrollOffset || 40; }, header: "[data-scroll-header]", updateURL: !1, }), null != (o = document.querySelector(".btn-scroll-top")) && ((n = parseInt(600, 10)), window.addEventListener("scroll", function (e) { e.currentTarget.pageYOffset > n ? o.classList.add("show") : o.classList.remove("show"); })), (function () { for ( var e = document.querySelectorAll(".password-toggle"), r = 0; r < e.length; r++ ) !(function () { var t = e[r].querySelector(".form-control"); e[r].querySelector(".password-toggle-btn").addEventListener( "click", function (e) { "checkbox" === e.target.type && (e.target.checked ? (t.type = "text") : (t.type = "password")); }, !1 ); })(); })(), null !== document.querySelector(".rellax") && new Rellax(".rellax", { horizontal: !0 }), (function () { for ( var e = document.querySelectorAll(".parallax"), t = 0; t < e.length; t++ ) new Parallax(e[t]); })(), (function (e, t, r) { for (var a = 0; a < e.length; a++) t.call(r, a, e[a]); })(document.querySelectorAll(".swiper"), function (e, t) { var r; (r = null != t.dataset.swiperOptions ? JSON.parse(t.dataset.swiperOptions) : r).pager && (a = { pagination: { el: ".pagination .list-unstyled", clickable: !0, bulletActiveClass: "active", bulletClass: "page-item", renderBullet: function (e, t) { return ( '
  • ' + (e + 1) + "
  • " ); }, }, }); var a = _objectSpread(_objectSpread({}, r), a), a = new Swiper(t, a); r.tabs && a.on("activeIndexChange", function (e) { var t = document.querySelector( e.slides[e.activeIndex].dataset.swiperTab ); document .querySelector( e.slides[e.previousIndex].dataset.swiperTab ) .classList.remove("active"), t.classList.add("active"); }); }), (function () { var e = document.querySelectorAll(".gallery"); if (e.length) for (var t = 0; t < e.length; t++) { var r = !!e[t].dataset.thumbnails, a = !!e[t].dataset.video, n = [lgZoom, lgFullscreen], a = a ? [lgVideo] : [], r = r ? [lgThumbnail] : [], r = [].concat(n, a, r); lightGallery(e[t], { selector: ".gallery-item", plugins: r, licenseKey: "D4194FDD-48924833-A54AECA3-D6F8E646", download: !1, autoplayVideoOnSlide: !0, zoomFromOrigin: !1, youtubePlayerParams: { modestbranding: 1, showinfo: 0, rel: 0, }, vimeoPlayerParams: { byline: 0, portrait: 0, color: "6366f1", }, }); } })(), (function () { for ( var n = document.querySelectorAll(".range-slider"), o = 0; o < n.length; o++ ) !(function () { var e = n[o].querySelector(".range-slider-ui"), r = n[o].querySelector(".range-slider-value-min"), a = n[o].querySelector(".range-slider-value-max"), t = { dataStartMin: parseInt(n[o].dataset.startMin, 10), dataStartMax: parseInt(n[o].dataset.startMax, 10), dataMin: parseInt(n[o].dataset.min, 10), dataMax: parseInt(n[o].dataset.max, 10), dataStep: parseInt(n[o].dataset.step, 10), dataPips: n[o].dataset.pips, }; noUiSlider.create(e, { start: t.dataStartMax ? [t.dataStartMin, t.dataStartMax] : [t.dataStartMin], connect: !!t.dataStartMax || "lower", step: t.dataStep, pips: !!t.dataPips && { mode: "count", values: 5 }, tooltips: !0, range: { min: t.dataMin, max: t.dataMax }, format: { to: function (e) { return "$" + parseInt(e, 10); }, from: function (e) { return Number(e); }, }, }), e.noUiSlider.on("update", function (e, t) { e = (e = e[t]).replace(/\D/g, ""); t ? a && (a.value = Math.round(e)) : r && (r.value = Math.round(e)); }), r && r.addEventListener("change", function () { e.noUiSlider.set([this.value, null]); }), a && a.addEventListener("change", function () { e.noUiSlider.set([null, this.value]); }); })(); })(), window.addEventListener( "load", function () { var e = document.getElementsByClassName("needs-validation"); Array.prototype.filter.call(e, function (t) { t.addEventListener( "submit", function (e) { !1 === t.checkValidity() && (e.preventDefault(), e.stopPropagation()), t.classList.add("was-validated"); }, !1 ); }); }, !1 ), (function () { var a = document.querySelectorAll("[data-format]"); if (0 !== a.length) for (var n = 0; n < a.length; n++) !(function () { var e, t = a[n], r = t.parentNode.querySelector(".credit-card-icon"); null != t.dataset.format && (e = JSON.parse(t.dataset.format)), r ? new Cleave( t, _objectSpread( _objectSpread({}, e), {}, { onCreditCardTypeChanged: function (e) { r.className = "credit-card-icon " + e; }, } ) ) : new Cleave(t, e); })(); })(), [].slice .call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) .map(function (e) { return new bootstrap.Tooltip(e, { trigger: "hover" }); }), [].slice .call(document.querySelectorAll('[data-bs-toggle="popover"]')) .map(function (e) { return new bootstrap.Popover(e); }), [].slice.call(document.querySelectorAll(".toast")).map(function (e) { return new bootstrap.Toast(e); }), (function () { var e = document.querySelectorAll('[data-bs-toggle="video"]'); if (e.length) for (var t = 0; t < e.length; t++) lightGallery(e[t], { selector: "this", plugins: [lgVideo], licenseKey: "D4194FDD-48924833-A54AECA3-D6F8E646", download: !1, youtubePlayerParams: { modestbranding: 1, showinfo: 0, rel: 0, }, vimeoPlayerParams: { byline: 0, portrait: 0, color: "6366f1", }, }); })(), (function () { var e = document.querySelectorAll(".price-switch-wrapper"); if (!(e.length <= 0)) for (var t = 0; t < e.length; t++) e[t] .querySelector('[data-bs-toggle="price"]') .addEventListener("change", function (e) { for ( var t = e.currentTarget.querySelector( 'input[type="checkbox"]' ), r = e.currentTarget .closest(".price-switch-wrapper") .querySelectorAll( "[data-monthly-price]" ), a = e.currentTarget .closest(".price-switch-wrapper") .querySelectorAll( "[data-annual-price]" ), n = 0; n < r.length; n++ ) 1 == t.checked ? r[n].classList.add("d-none") : r[n].classList.remove("d-none"); for (var o = 0; o < r.length; o++) 1 == t.checked ? a[o].classList.remove("d-none") : a[o].classList.add("d-none"); }); })(), (function () { var n, r = document.querySelectorAll(".masonry-grid"); if (null !== r) for (var o = 0; o < r.length; o++) { var e = (function () { (n = new Shuffle(r[o], { itemSelector: ".masonry-grid-item", sizer: ".masonry-grid-item", })), imagesLoaded(r[o]).on("progress", function () { n.layout(); }); var a = r[o].closest(".masonry-filterable"); if (null === a) return { v: void 0 }; for ( var e = a.querySelectorAll( ".masonry-filters [data-group]" ), t = 0; t < e.length; t++ ) e[t].addEventListener("click", function (e) { var t = a.querySelector( ".masonry-filters .active" ), r = this.dataset.group; null !== t && t.classList.remove("active"), this.classList.add("active"), n.filter(r), e.preventDefault(); }); })(); if ("object" === _typeof(e)) return e.v; } })(), (function () { var e = document.querySelectorAll(".subscription-form"); if (null !== e) { for (var l = 0; l < e.length; l++) !(function () { var t = e[l].querySelector('button[type="submit"]'), r = t.innerHTML, a = e[l].querySelector(".form-control"), n = e[l].querySelector( ".subscription-form-antispam" ), o = e[l].querySelector(".subscription-status"); e[l].addEventListener("submit", function (e) { e && e.preventDefault(), "" === n.value && i(this, t, a, r, o); }); })(); var i = function (e, t, r, a, n) { t.innerHTML = "Sending..."; var o = e.action.replace("/post?", "/post-json?"), e = "&" + r.name + "=" + encodeURIComponent(r.value), l = document.createElement("script"); (l.src = o + "&c=callback" + e), document.body.appendChild(l); var i = "callback"; window[i] = function (e) { delete window[i], document.body.removeChild(l), (t.innerHTML = a), "success" == e.result ? (r.classList.remove("is-invalid"), r.classList.add("is-valid"), n.classList.remove("status-error"), n.classList.add("status-success"), (n.innerHTML = e.msg), setTimeout(function () { r.classList.remove("is-valid"), (n.innerHTML = ""), n.classList.remove( "status-success" ); }, 6e3)) : (r.classList.remove("is-valid"), r.classList.add("is-invalid"), n.classList.remove("status-success"), n.classList.add("status-error"), (n.innerHTML = e.msg.substring(4)), setTimeout(function () { r.classList.remove("is-invalid"), (n.innerHTML = ""), n.classList.remove("status-error"); }, 6e3)); }; }; } })(), document.querySelectorAll(".animation-on-hover").forEach(function (e) { e.addEventListener("mouseover", function () { e.querySelectorAll("lottie-player").forEach(function (e) { e.setDirection(1), e.play(); }); }), e.addEventListener("mouseleave", function () { e.querySelectorAll("lottie-player").forEach(function (e) { e.setDirection(-1), e.play(); }); }); }), (function () { var v = document.querySelectorAll(".audio-player"); if (0 !== v.length) for ( var e = function () { var t = v[y], r = t.querySelector("audio"), e = t.querySelector(".ap-play-button"), a = t.querySelector(".ap-seek-slider"), n = t.querySelector(".ap-volume-slider"), o = t.querySelector(".ap-duration"), l = t.querySelector(".ap-current-time"), i = "play", s = null; e.addEventListener("click", function (e) { i = "play" === i ? (e.currentTarget.classList.add( "ap-pause" ), r.play(), requestAnimationFrame(m), "pause") : (e.currentTarget.classList.remove( "ap-pause" ), r.pause(), cancelAnimationFrame(s), "play"); }); function c(e) { e === a ? t.style.setProperty( "--seek-before-width", (e.value / e.max) * 100 + "%" ) : t.style.setProperty( "--volume-before-width", (e.value / e.max) * 100 + "%" ); } a.addEventListener("input", function (e) { c(e.target); }), n.addEventListener("input", function (e) { c(e.target); }); function u(e) { var t = Math.floor(e / 60), e = ( (e = Math.floor(e % 60)) < 10 ? "0" : "" ).concat(e); return "".concat(t, ":").concat(e); } function d() { o.textContent = u(r.duration); } function p() { a.max = Math.floor(r.duration); } function f() { var e = Math.floor( r.buffered.end(r.buffered.length - 1) ); t.style.setProperty( "--buffered-width", "".concat((e / a.max) * 100, "%") ); } var m = function e() { (a.value = Math.floor(r.currentTime)), (l.textContent = u(a.value)), t.style.setProperty( "--seek-before-width", "".concat((a.value / a.max) * 100, "%") ), (s = requestAnimationFrame(e)); }; 0 < r.readyState ? (d(), p(), f()) : r.addEventListener( "loadedmetadata", function () { d(), p(), f(); } ), r.addEventListener("progress", f), a.addEventListener("input", function () { (l.textContent = u(a.value)), r.paused || cancelAnimationFrame(s); }), a.addEventListener("change", function () { (r.currentTime = a.value), r.paused || requestAnimationFrame(m); }), n.addEventListener("input", function (e) { e = e.target.value; r.volume = e / 100; }); }, y = 0; y < v.length; y++ ) e(); })(); })(); ================================================ FILE: application/static/assets/vendor/prismjs/plugins/line-numbers/prism-line-numbers.css ================================================ pre[class*="language-"].line-numbers { position: relative; padding-left: 3.8em; counter-reset: linenumber; } pre[class*="language-"].line-numbers > code { position: relative; white-space: inherit; } .line-numbers .line-numbers-rows { position: absolute; pointer-events: none; top: 0; font-size: 100%; left: -3.8em; width: 3em; /* works for line-numbers below 1000 lines */ letter-spacing: -1px; border-right: 1px solid #999; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .line-numbers-rows > span { display: block; counter-increment: linenumber; } .line-numbers-rows > span:before { content: counter(linenumber); color: #999; display: block; padding-right: 0.8em; text-align: right; } ================================================ FILE: application/static/assets/vendor/prismjs/plugins/toolbar/prism-toolbar.css ================================================ div.code-toolbar { position: relative; } div.code-toolbar > .toolbar { position: absolute; z-index: 10; top: .3em; right: .2em; transition: opacity 0.3s ease-in-out; opacity: 0; } div.code-toolbar:hover > .toolbar { opacity: 1; } /* Separate line b/c rules are thrown out if selector is invalid. IE11 and old Edge versions don't support :focus-within. */ div.code-toolbar:focus-within > .toolbar { opacity: 1; } div.code-toolbar > .toolbar > .toolbar-item { display: inline-block; } div.code-toolbar > .toolbar > .toolbar-item > a { cursor: pointer; } div.code-toolbar > .toolbar > .toolbar-item > button { background: none; border: 0; color: inherit; font: inherit; line-height: normal; overflow: visible; padding: 0; -webkit-user-select: none; /* for button */ -moz-user-select: none; -ms-user-select: none; } div.code-toolbar > .toolbar > .toolbar-item > a, div.code-toolbar > .toolbar > .toolbar-item > button, div.code-toolbar > .toolbar > .toolbar-item > span { color: #bbb; font-size: .8em; padding: 0 .5em; background: #f5f2f0; background: rgba(224, 224, 224, 0.2); box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); border-radius: .5em; } div.code-toolbar > .toolbar > .toolbar-item > a:hover, div.code-toolbar > .toolbar > .toolbar-item > a:focus, div.code-toolbar > .toolbar > .toolbar-item > button:hover, div.code-toolbar > .toolbar > .toolbar-item > button:focus, div.code-toolbar > .toolbar > .toolbar-item > span:hover, div.code-toolbar > .toolbar > .toolbar-item > span:focus { color: inherit; text-decoration: none; } ================================================ FILE: application/static/assets/vendor/prismjs/themes/prism.css ================================================ /** * prism.js default theme for JavaScript, CSS and HTML * Based on dabblet (http://dabblet.com) * @author Lea Verou */ code[class*="language-"], pre[class*="language-"] { color: black; background: none; text-shadow: 0 1px white; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { text-shadow: none; background: #b3d4fc; } pre[class*="language-"]::selection, pre[class*="language-"] ::selection, code[class*="language-"]::selection, code[class*="language-"] ::selection { text-shadow: none; background: #b3d4fc; } @media print { code[class*="language-"], pre[class*="language-"] { text-shadow: none; } } /* Code blocks */ pre[class*="language-"] { padding: 1em; margin: .5em 0; overflow: auto; } :not(pre) > code[class*="language-"], pre[class*="language-"] { background: #f5f2f0; } /* Inline code */ :not(pre) > code[class*="language-"] { padding: .1em; border-radius: .3em; white-space: normal; } .token.comment, .token.prolog, .token.doctype, .token.cdata { color: slategray; } .token.punctuation { color: #999; } .token.namespace { opacity: .7; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: #905; } .token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: #690; } .token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string { color: #9a6e3a; /* This background color was intended by the author of this theme. */ background: hsla(0, 0%, 100%, .5); } .token.atrule, .token.attr-value, .token.keyword { color: #07a; } .token.function, .token.class-name { color: #DD4A68; } .token.regex, .token.important, .token.variable { color: #e90; } .token.important, .token.bold { font-weight: bold; } .token.italic { font-style: italic; } .token.entity { cursor: help; } ================================================ FILE: application/superadmin/__init__.py ================================================ ================================================ FILE: application/superadmin/forms.py ================================================ from flask_wtf import FlaskForm from wtforms import StringField from wtforms import PasswordField from wtforms import IntegerField from wtforms import SubmitField from wtforms import BooleanField from wtforms import TextAreaField from wtforms import SelectField from wtforms import DateField from flask_wtf.file import FileField from flask_wtf.file import FileAllowed from wtforms.validators import DataRequired from wtforms.validators import Optional from wtforms.validators import NumberRange from wtforms.validators import Length from wtforms.validators import Email from wtforms.validators import EqualTo from wtforms.validators import ValidationError from flask_login import current_user from application.models import User # FUNDS ANALYTICS DATE RANGE # class FundsAnalyticsDateRangeForm(FlaskForm): # submit = SubmitField('Submit') ================================================ FILE: application/superadmin/views.py ================================================ import os from datetime import datetime # importing basic flask module from flask import Blueprint from flask import redirect from flask import render_template from flask import request from flask import url_for from flask import flash from flask import abort from flask import jsonify from flask import make_response from flask import current_app from sqlalchemy import func # importing module from flask login from flask_login import current_user from flask_login import login_required from flask_login import login_user from flask_login import logout_user from application import db from application import bcrypt # from application.superadmin.forms import aksjdlkf from application.models import User from application.utils.Utils import applicationID from application.utils.CutomAuth import superadmin_required superadmin = Blueprint('superadmin', __name__) # USER PROFILE @superadmin.route('/superadmin/dashboard/', methods=['GET', 'POST']) @login_required @superadmin_required def superadmin_dashboard(): return render_template( 'superadmin/dashboard.html', title='Admin Dashboard', ) ================================================ FILE: application/templates/auth/activation_link_email.html ================================================ Reset Your Password
    Rabeya Baten Foundation Rabeya Baten Foundation

    As Salamu Alaikum, Thank you for registering with the Rabeya Baten Foundation. This email confirms that we have received your registration and the information provided by you.

    Activate your account

    If you are unable to click the link, please copy and paste it into your browser's address bar.
    {{ activation_link }}


    Your account has been created successfully, and you can now access our website and start exploring our services. If you have any questions or need further assistance, please contact us at rabeyabatenfoundation@gmail.com.

    Zazak Allahu Khairan and Thank you for joining our community and supporting our mission to make a positive impact on society.

    Best Regards,
    Rabeya Baten Foundation Team

    Mobile: +8801765-914159
    Address: Rabeya Monjil, Padmapukur Par, Saiyadpur,
    Post Office: Duttapara. Thana: Chandraganj,
    District: Lakshmipur, Country: Bangladesh.
    Email: rabeyabatenfoundation@gmail.com
    YouTube: @RabeyaBatenFoundation
    Facebook: @rabeyabatenfoundation

    ================================================ FILE: application/templates/auth/forgetpassword.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}

    Forget your password?

    {{ form.hidden_tag() }}
    {{ form.email.label(class="form-label fs-base") }} {{ form.email( class="form-control form-control-lg", placeholder="Email" ) }}
    {% if form.email.errors %} {% for error in form.email.errors %} {{ error }} {% endfor %} {% else %} Please enter valid Email! {% endif %}
    {{ form.submit(class="btn btn-primary shadow-primary btn-lg w-100") }}
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/auth/join.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}

    Create Account

    Already have an account? Login here.

    {% for field in [form.name, form.phone, form.email, form.password, form.confirm_password] %} {% if field.errors %}
    {% endif %} {% endfor %}
    {{ form.hidden_tag() }}
    {{ form.name.label(class="form-label fs-base") }} {{ form.name( class="form-control form-control-lg", placeholder="Your Name" ) }}
    {% if form.name.errors %} {% for error in form.name.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid first name! {% endif %}
    {{ form.email.label(class="form-label fs-base") }} {{ form.email( class="form-control form-control-lg", placeholder="Email" ) }}
    {% if form.email.errors %} {% for error in form.email.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid Email! {% endif %}
    {{ form.phone.label(class="form-label fs-base") }} {{ form.phone( class="form-control form-control-lg", placeholder="Phone number" ) }}
    {% if form.phone.errors %} {% for error in form.phone.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid phone number! {% endif %}
    {{ form.password.label(class="form-label fs-base") }}
    {{ form.password( class="form-control form-control-lg", placeholder="Password" ) }}
    {% if form.password.errors %} {% for error in form.password.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid password! {% endif %}
    {{ form.confirm_password.label(class="form-label fs-base") }}
    {{ form.confirm_password( class="form-control form-control-lg", placeholder="Confirm Password" ) }}
    {% if form.confirm_password.errors %} {% for error in form.confirm_password.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid password! {% endif %}
    {{ form.submit(class="btn btn-primary shadow-primary btn-lg w-100") }}
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/auth/login.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}

    Welcome Back

    Don’t have an account yet? Register here.

    {% for field in [form.phone, form.password] %} {% if field.errors %}
    {% endif %} {% endfor %}
    {{ form.hidden_tag() }}
    {{ form.phone.label(class="form-label fs-base") }} {{ form.phone( class="form-control form-control-lg", placeholder="Phone number" ) }}
    {% if form.phone.errors %} {% for error in form.phone.errors %} {{ error }} {% endfor %} {% else %} Please enter valid phone number! {% endif %}
    {{ form.password.label(class="form-label fs-base") }}
    {{ form.password( class="form-control form-control-lg", placeholder="Password" ) }}
    {% if form.password.errors %} {% for error in form.password.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid password {% endif %}
    {{ form.remember(class="form-check-input") }} {{ form.remember.label(class="form-check-label fs-base") }}
    {{ form.submit(class="btn btn-primary shadow-primary btn-lg w-100") }}
    Forgot your password?
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/auth/password_reset_link_email.html ================================================ Reset Your Password
    ValentineAI

    We received a request to reset the password for your account with the Valentine application. To reset your password, please click on the link below

    Reset your Password

    If you are unable to click the link, please copy and paste it into your browser's address bar.

    {{ password_reset_link }}


    Please note that this link is only valid for the next 24 hours. If you do not reset your password within this time frame, you will need to submit a new request.

    If you have any questions or need further assistance, please contact us at sayhi@hossainfoysal.com.
    If you did not make this request then simply ignore this email and no changes will be made.

    Best Regards,
    Valentine AI

    It's a fun project. Made by HossainFoysal.com
    Hosted on BinoMatrix. Fastest growing software company in Bangladesh.
    ================================================ FILE: application/templates/auth/reset_token.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}

    Type new password

    {% for field in [form.password, form.confirm_password] %} {% if field.errors %}
    {% endif %} {% endfor %}
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/helpers/_global_footer.html ================================================ ================================================ FILE: application/templates/helpers/_nav_top_landing.html ================================================ ================================================ FILE: application/templates/helpers/_side_navbar_dashboard.html ================================================ ================================================ FILE: application/templates/layout/root.html ================================================ {% if title %} {{ title }} | Valentines Letter Sender {% else %} Valentines Letter Sender {% endif %} {% block head %} {% endblock %} {{ moment.include_moment() }} {% block nav %} {% endblock %} {% with messages=get_flashed_messages(with_categories=true)%} {% if messages %} {% for category, message in messages %} {% endfor %} {% endif %} {% endwith %} {% block body %} {% endblock %} {% block footer %} {% endblock %} {% block script %} {% endblock %} ================================================ FILE: application/templates/public/landing.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}

    Send your loved person a letter digitally 💌

    Powered by ValentineAI
    Hosted on BinoMatrix

    Write your valentine letter
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/public/letter.html ================================================ Letter
    Happy Valentine's Day!
    {{ letter.receiver_name }}
    {% if letter.is_hidden %}

    - Your well wisher -

    {% else %}

    - Your {{ letter.sender.name }} -

    {% endif %}
    ================================================ FILE: application/templates/user/account.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}
    {% include 'helpers/_side_navbar_dashboard.html' %}

    Profile Details

    {% for field in [form.name, form.email, form.phone] %} {% if field.errors %}
    {% endif %} {% endfor %}

    Edit info

    {{ form.hidden_tag() }}
    {{ form.name.label(class="form-label fs-base") }} {{ form.name( class="form-control form-control-lg", placeholder="Your First Name" ) }}
    {% if form.name.errors %} {% for error in form.name.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid name! {% endif %}
    {{ form.email.label(class="form-label fs-base") }} {{ form.email( class="form-control form-control-lg", placeholder="Email" ) }}
    {% if form.email.errors %} {% for error in form.email.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid Email! {% endif %}
    {{ form.phone.label(class="form-label fs-base") }} {{ form.phone( class="form-control form-control-lg", placeholder="Phone number" ) }}
    {% if form.phone.errors %} {% for error in form.phone.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid phone number! {% endif %}
    {{ form.submit(class="btn btn-primary shadow-primary btn-lg w-100") }}
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/user/account_update_password.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}
    {% include 'helpers/_side_navbar_dashboard.html' %}

    Account Password

    {% for field in [form.current_password, form.confirm_password, form.new_password] %} {% if field.errors %}
    {% endif %} {% endfor %}

    Update Password

    {{ form.hidden_tag() }}
    {{ form.current_password.label(class="form-label fs-base") }}
    {{ form.current_password( class="form-control form-control-lg", placeholder="Current Password" ) }}
    Please enter a valid password!
    {{ form.new_password.label(class="form-label fs-base") }}
    {{ form.new_password( class="form-control form-control-lg", placeholder="New Password" ) }}
    Please enter a valid password!
    {{ form.confirm_password.label(class="form-label fs-base") }}
    {{ form.confirm_password( class="form-control form-control-lg", placeholder="Confirm New Password" ) }}
    Please enter a valid password!
    {{ form.submit(class="btn btn-primary shadow-primary btn-lg w-100") }}
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/user/dashboard.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}
    {% include 'helpers/_side_navbar_dashboard.html' %}

    Send a letter to your loving person 💌

    {% for field in [form.name, form.email, form.gender, form.letter] %} {% if field.errors %}
    {% endif %} {% endfor %}
    Loading...

    Loading..

    {{ form.hidden_tag() }}
    {{ form.name.label(class="form-label fs-base") }} {{ form.name( class="form-control form-control-lg", placeholder="" ) }}
    {% if form.name.errors %} {% for error in form.name.errors %} {{ error }} {% endfor %} {% else %} Please enter valid name! {% endif %}
    {{ form.email.label(class="form-label fs-base") }} {{ form.email( class="form-control form-control-lg", placeholder="" ) }}
    {% if form.email.errors %} {% for error in form.email.errors %} {{ error }} {% endfor %} {% else %} Please enter valid email! {% endif %}
    {{ form.gender.label(class="form-label fs-base") }} {{ form.gender( class="form-select form-select-lg", placeholder="" ) }}
    {% if form.gender.errors %} {% for error in form.gender.errors %} {{ error }} {% endfor %} {% else %} Select a valid gender! {% endif %}
    {{ form.letter.label(class="form-label fs-base") }} {{ form.letter( class="form-control form-control-lg", placeholder="", style="height: 120px", ) }}
    {% if form.letter.errors %} {% for error in form.letter.errors %} {{ error }} {% endfor %} {% else %} Please enter a valid letter! {% endif %}
    {{ form.is_hidden(class="form-check-input") }} {{ form.is_hidden.label(class="form-check-label") }}
    {{ form.submit(class="btn btn-primary shadow-primary btn-lg w-100") }}
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/user/letter_sent.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}
    {% include 'helpers/_side_navbar_dashboard.html' %}

    💌 Message sent to your love 💝 ✈️

    View all letters
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/user/letters.html ================================================ {% extends 'layout/root.html' %} {% block nav %} {% include 'helpers/_nav_top_landing.html' %} {% endblock %} {% block body %}
    {% include 'helpers/_side_navbar_dashboard.html' %}

    💌 Letters you have sent

    {% for letter in letters.items %} {% endfor %}
    # Receiver Email Gender Message Action
    {{ loop.index }} {{ letter.receiver_name | title }} {{ letter.email }} {{ letter.gender | title }} {{ letter.message }} View Letter
    {% endblock %} {% block footer %} {% include 'helpers/_global_footer.html' %} {% endblock %} ================================================ FILE: application/templates/user/send_letter_email.html ================================================ 💌 You received a letter to read - ValentineAI
    ValentineAI

    You have received a new letter from your loved person who really want to surprise you. Check his messages below

    💌 Read the message

    If you are unable to click the link, please copy and paste it into your browser's address bar.

    {{ letter_link }}


    If you have any questions, please contact us at sayhi@hossainfoysal.com. We would love to help answer your question.

    Best Regards,
    Valentine AI

    It's a fun project. Made by HossainFoysal.com
    Hosted on BinoMatrix. Fastest growing software company in Bangladesh.
    ================================================ FILE: application/user/__init__.py ================================================ ================================================ FILE: application/user/forms.py ================================================ from flask_wtf import FlaskForm from wtforms import StringField from wtforms import PasswordField from wtforms import IntegerField from wtforms import SubmitField from wtforms import BooleanField from wtforms import TextAreaField from wtforms import SelectField from wtforms import DateField from flask_wtf.file import FileField from flask_wtf.file import FileAllowed from wtforms.validators import DataRequired from wtforms.validators import Optional from wtforms.validators import NumberRange from wtforms.validators import Length from wtforms.validators import Email from wtforms.validators import EqualTo from wtforms.validators import ValidationError from flask_login import current_user from application.models import User # LETTER FORM class LetterForm(FlaskForm): name = StringField( 'Receiver Name', validators = [ DataRequired(), Length(2, 50) ] ) email = StringField( 'Receiver Email', validators = [ DataRequired(), Email() ] ) gender = SelectField( 'To your', choices = [ ('girlfriend', 'Girlfriend'), ('boyfriend', 'Boyfriend') ] ) letter = TextAreaField( 'Your message', validators = [ DataRequired(), Length(10, 100) ] ) is_hidden = BooleanField( 'No, I don\'t want to display my name', validators = [DataRequired()] ) submit = SubmitField('Send your surprise message') # UPDATE PROFILE FORM class UpdateProfileForm(FlaskForm): name = StringField( 'Your Name', validators = [ DataRequired(), Length(2, 50) ] ) email = StringField( 'E-mail', validators = [ DataRequired(), Email() ] ) phone = StringField( 'Phone', validators=[ DataRequired(), ] ) picture = FileField( 'Update Profile Picture', validators = [ FileAllowed(['jpg','jpeg','png']) ] ) address = StringField( 'Address', validators = [ DataRequired(), Length(min=5, max=50) ] ) submit = SubmitField('Save') def validate_phone(self, phone): if phone.data and phone.data != current_user.phone: user_phone = User.query.filter_by(phone=phone.data).first() if user_phone: raise ValidationError('This phone number is already registered. Please choose a different one.') def validate_email(self, email): if email.data and email.data != current_user.email: user_email = User.query.filter_by(email=email.data).first() if user_email: raise ValidationError('That email is already registered. Please choose a different one.') # UPDATE PASSWORD class UpdatePasswordForm(FlaskForm): current_password = PasswordField( 'Current Password' ) new_password = PasswordField( 'New Password' ) confirm_password = PasswordField( 'Confirm New Password', validators = [ DataRequired(), EqualTo('new_password') ] ) submit = SubmitField('Save') ================================================ FILE: application/user/views.py ================================================ import os # importing basic flask module from flask import Blueprint from flask import redirect from flask import render_template from flask import request from flask import url_for from flask import flash from flask import abort from flask import jsonify from flask import make_response from flask import current_app # importing module from flask login from flask_login import current_user from flask_login import login_required from flask_login import login_user from flask_login import logout_user from application import db from application import bcrypt from application.user.forms import UpdateProfileForm from application.user.forms import UpdatePasswordForm from application.user.forms import LetterForm from application.models import User from application.models import Letter from application.CohereAI.Utils import linkid from application.utils.SendEmail import send_letter_email # from application.CohereAI.GenerateBlog import generate_letter user = Blueprint('user', __name__) # USER PROFILE @user.route('/dashboard/', methods=['GET', 'POST']) @login_required def dashboard(): if current_user.user_role == 'superadmin': return redirect(url_for('superadmin.dashboard')) # letter = generate_letter(gender='girlfriend') form = LetterForm() if form.validate_on_submit(): letter_link = linkid() letter = Letter( receiver_name=form.name.data.strip(), email=form.email.data.strip(), gender=form.gender.data, message=form.letter.data.strip(), link=letter_link, is_hidden=form.is_hidden.data, sender=current_user ) db.session.add(letter) db.session.commit() send_letter_email(letter) flash('Message generated', 'success') return redirect(url_for('user.letter_sent')) # if request.method == 'GET': # form.letter.data = letter return render_template( 'user/dashboard.html', title='Dashboard', form=form ) # USER PROFILE # @user.route('/dashboard/letter/regenerate/', methods=['GET', 'POST']) # @login_required # def regenerate_message(): # data = request.get_json() # gender = data['gender'] # letter = generate_letter(gender) # res = make_response(jsonify(letter), 200) # return res # USER LETTERS @user.route('/dashboard/letter/sent/', methods=['GET', 'POST']) @login_required def letter_sent(): letter = Letter.query.order_by(Letter.created_at.desc()).first_or_404() return render_template('user/letter_sent.html', letter=letter) # USER PROFILE @user.route('/dashboard/letters/', methods=['GET', 'POST']) @login_required def letters(): page = request.args.get('page', 1, type=int) letters = Letter.query.order_by(Letter.created_at.desc()).paginate(page=page, per_page=10) return render_template('user/letters.html', letters=letters) # USER PROFILE @user.route('/dashboard/account/', methods=['GET', 'POST']) @login_required def account(): form = UpdateProfileForm() if form.validate_on_submit(): # if form.picture.data: # picture_file = save_profile(form.picture.data) # current_user.image_file = picture_file current_user.name = form.name.data.strip() current_user.phone = form.phone.data current_user.email = form.email.data db.session.commit() flash('Your account has been updated!', 'success') return redirect(url_for('user.dashboard')) if request.method == 'GET': form.name.data = current_user.name form.email.data = current_user.email form.phone.data = current_user.phone # image_file = url_for('static', filename='profile/' + current_user.img) return render_template('user/account.html', title='Profile', form=form) # USER PROFILE @user.route('/dashboard/account/password/', methods=['GET', 'POST']) @login_required def account_password(): form = UpdatePasswordForm() if form.validate_on_submit(): # Get form data new_password = form.new_password.data confirm_new_password = form.confirm_password.data current_password = form.current_password.data # Check if current password is correct current_password_hash = bcrypt.check_password_hash(current_user.password, current_password) if current_password_hash and new_password == confirm_new_password: # Hash and set new password hashed_password = bcrypt.generate_password_hash(new_password).decode('utf-8') current_user.password = hashed_password db.session.commit() elif current_password_hash and new_password != confirm_new_password: flash('New Password and Confirm Password Doesn\'t Matched ⚠️', 'danger') return redirect(url_for('dashboard.user_profile_edit')) elif current_password and current_password_hash == False: flash('Your current password is incorrect', 'danger') return redirect(url_for('user.account_password')) db.session.commit() return redirect(url_for('user.dashboard')) return render_template('user/account_update_password.html', title='Password', form=form) ================================================ FILE: application/utils/CutomAuth.py ================================================ from functools import wraps from flask import abort from flask_login import current_user def superadmin_required(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated or current_user.user_role not in ["superadmin"]: abort(404) # Or redirect to an unauthorized page return f(*args, **kwargs) return decorated_function ================================================ FILE: application/utils/Location.py ================================================ import requests def getLocation(ip_address): url = 'https://get.geojs.io/v1/ip/geo/'+ip_address+'.json' geo_request = requests.get(url) geo_data = geo_request.json() return geo_data ================================================ FILE: application/utils/SendEmail.py ================================================ # importing necessary module import os import random import string from flask import url_for from flask import render_template from flask import current_app from flask import request from flask_mail import Message from application import db from application import bcrypt from application import mail from application.utils.Location import getLocation # Create an email message with an activation link # def send_activation_email(user): # token = generate_otp() # user.activation_token = bcrypt.generate_password_hash(token).decode('utf-8') # db.session.commit() # activation_link = url_for('auth.activate_account', token=user.activation_token, _external=True) # msg = Message('Activate Your Account', # sender=current_app.config['MAIL_DEFAULT_SENDER'], # recipients=[user.email]) # msg.html = render_template('auth/activation_email.html', activation_link=activation_link) # mail.send(msg) # def send_activation_email(user): # otp = generate_otp() # print(f'====== GET THE OTP -> {otp}') # token = bcrypt.generate_password_hash(otp).decode('utf-8') # print(f'====== GET THE TOKEN -> {token}') # user.activation_token = token # print(f'====== GET THE user activation token -> {user.activation_token}') # db.session.commit() # activation_link = url_for('auth.activate_account', token=token, _external=True) # msg = Message('Activate Your Account', # sender=current_app.config['MAIL_DEFAULT_SENDER'], # recipients=[user.email]) # msg.html = render_template('auth/activation_email.html', activation_link=activation_link) # mail.send(msg) # =================================== # SEND ACCOUNT ACTIVATION EMAIL # =================================== # def send_activation_email(user): # token = user.generate_activation_token() # user.activation_token = token # db.session.commit() # activation_url = url_for('auth.activate', token=token, _external=True) # msg = Message('Activate Your Account - Rabeya Baten Foundation', # sender=current_app.config['MAIL_DEFAULT_SENDER'], # recipients=[user.email]) # msg.html = render_template('auth/activation_link_email.html', activation_link=activation_url) # mail.send(msg) # =================================== # SEND PASSWORD RESET EMAIL # =================================== def send_reset_email(user): token = user.get_reset_token() reset_link = url_for('auth.reset_token', token=token, _external=True) msg = Message('Password Reset Request - Valentine', sender=current_app.config['MAIL_DEFAULT_SENDER'], recipients=[user.email]) msg.html = render_template('auth/password_reset_link_email.html', password_reset_link=reset_link) mail.send(msg) # =================================== # SEND EMAIL TO RECEIVER # =================================== def send_letter_email(letter): letter_link = url_for('public.letter', link=letter.link, _external=True) msg = Message('💌 You received a letter to read - ValentineAI', sender=current_app.config['MAIL_DEFAULT_SENDER'], recipients=[letter.email]) msg.html = render_template('user/send_letter_email.html', letter_link=letter_link) mail.send(msg) ================================================ FILE: application/utils/Utils.py ================================================ import os import uuid import secrets import datetime def applicationID(): now = datetime.datetime.now() timestamp = now.strftime("%Y%m%d%H%M%S") return timestamp + str(uuid.uuid4().int)[:10] ================================================ FILE: application/utils/__init__.py ================================================ ================================================ FILE: requirements.txt ================================================ alembic==1.7.7 bcrypt==3.2.2 blinker==1.4 certifi==2022.5.18.1 cffi==1.15.0 charset-normalizer==2.0.12 click==8.0.1 colorama==0.4.4 cssbeautifier==1.14.7 dnspython==2.1.0 EditorConfig==0.12.3 email-validator==1.1.3 Faker==18.9.0 Flask==2.0.1 Flask-Admin==1.6.0 Flask-Bcrypt==0.7.1 Flask-CKEditor==0.4.6 Flask-Login==0.5.0 Flask-Mail==0.9.1 Flask-Migrate==3.1.0 Flask-Moment==1.0.5 Flask-SQLAlchemy==2.5.1 Flask-WTF==0.15.1 greenlet==1.1.1 html-tag-names==0.1.2 html-void-elements==0.1.0 idna==3.2 itsdangerous==2.0.1 Jinja2==3.0.1 jsbeautifier==1.14.7 Mako==1.2.0 MarkupSafe==2.0.1 mysqlclient==2.1.0 packaging==23.1 pathspec==0.11.1 Pillow==8.3.1 pycparser==2.20 python-dateutil==2.8.2 python-dotenv==0.21.1 python-slugify==8.0.1 PyYAML==6.0 regex==2023.5.5 requests==2.27.1 six==1.16.0 SQLAlchemy==1.4.23 text-unidecode==1.3 tomli==2.0.1 tqdm==4.65.0 urllib3==1.26.9 Werkzeug==2.0.1 WTForms==2.3.3 ================================================ FILE: run.py ================================================ from application import create_app app = create_app() # production = False production = True if production is False: if __name__ == '__main__': app.run(debug=True) else: if __name__ == '__main__': app.run()