diff --git a/.drone.yml b/.drone.yml index 68035f6..0a701c3 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,6 +9,10 @@ globals: password: from_secret: REGISTRY_PASSWORD steps: + - name: brand commit before build + image: bash + commands: + - echo ${DRONE_COMMIT_SHA:0:7} > app/__commit__ - name: build app-testing image: plugins/docker settings: @@ -35,6 +39,10 @@ globals: password: from_secret: REGISTRY_PASSWORD steps: + - name: brand commit before build + image: bash + commands: + - echo ${DRONE_COMMIT_SHA:0:7} > app/__commit__ - name: build-app-prod image: plugins/docker settings: @@ -43,7 +51,6 @@ steps: dockerfile: ./Dockerfile tags: ["${DRONE_COMMIT_SHA:0:7}", "latest-prod"] <<: *docker_creds - trigger: branch: - master diff --git a/.gitignore b/.gitignore index 87fe0d8..6f9de4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ ### Database file database.db +database_mysql/ ### Python template # Byte-compiled / optimized / DLL files diff --git a/Dockerfile b/Dockerfile index bc2d72d..95e5a63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.11.0-alpine3.16 COPY ./app /app WORKDIR /app +RUN apk add gcc musl-dev mariadb-connector-c-dev RUN pip3 install -r requirements.txt ENV FLASK_APP=app.py -CMD ["python3", "-m", "flask", "run", "--host=0.0.0.0"] \ No newline at end of file +CMD ["gunicorn", "-b", "0.0.0.0:80", "-w", "4", "app:app"] \ No newline at end of file diff --git a/app/__commit__ b/app/__commit__ new file mode 100644 index 0000000..87edf79 --- /dev/null +++ b/app/__commit__ @@ -0,0 +1 @@ +unknown \ No newline at end of file diff --git a/app/__version__ b/app/__version__ new file mode 100644 index 0000000..7f20734 --- /dev/null +++ b/app/__version__ @@ -0,0 +1 @@ +1.0.1 \ No newline at end of file diff --git a/app/app.py b/app/app.py index a7421dd..79351ef 100644 --- a/app/app.py +++ b/app/app.py @@ -3,17 +3,21 @@ from flask import Flask, render_template, redirect, url_for, request, flash from flask_migrate import Migrate from werkzeug.security import generate_password_hash, check_password_hash from flask_login import (LoginManager, login_user, login_required, logout_user, current_user) -from misc import datetime, date, time, currDay +from misc import datetime, date, time, currDay, prevDay, ZoneInfo, currVersion, currCommit from db import (db, Period, Task, Event, User) -from forms import (TaskForm, EventForm, PeriodForm, SignupForm, LoginForm) +from forms import (TaskForm, EventForm, PeriodForm, SignupForm, LoginForm, SettingsForm) from create_events import createEvents basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) -app.config['SECRET_KEY'] = 'HwG55rpe83jcaglifXm8NuF4WEeXyJV4' +app.config['SECRET_KEY'] = os.environ['SECRET_KEY'] app.config['SQLALCHEMY_DATABASE_URI'] =\ - 'sqlite:///' + os.path.join(basedir, os.environ['SQLITE_DB']) + 'mysql://' + os.environ['MYSQL_USER'] + \ + ':' + os.environ['MYSQL_PASSWORD'] + \ + '@' + os.environ['MYSQL_HOST'] + \ + ':' + os.environ['MYSQL_PORT'] + \ + '/' + os.environ['MYSQL_DB'] app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) @@ -21,14 +25,21 @@ db.init_app(app) migrate = Migrate() migrate.init_app(app, db) +# Schedule creation of events every hour +#with app.app_context(): +# scheduleCreateEvents(app, db, currDay, Period, Event, createEvents) + # Authentication stuff login_manager = LoginManager() login_manager.login_view = 'login' login_manager.init_app(app) -if os.environ['SIGNUP_ENABLED'] == "YES": - signup_enabled = True +if 'SIGNUP_ENABLED' in os.environ: + if os.environ['SIGNUP_ENABLED'] == "YES": + signup_enabled = True + else: + signup_enabled = False else: signup_enabled = False @@ -36,10 +47,32 @@ else: def load_user(user_id): return User.query.get(int(user_id)) +# Context processor injects current version and commit +@app.context_processor +def injectVerCommit(): + return dict(currVersion=currVersion, currCommit=currCommit, datetime=datetime, ZoneInfo=ZoneInfo) + +# Error handling +# Pass env variables for debugging in prod +NODE_NAME = os.environ['NODE_NAME'] +POD_NAME = os.environ['POD_NAME'] + +# Error Routes +@app.errorhandler(404) +def notFound(e): + return render_template('errors/404.html', NODE_NAME=NODE_NAME, POD_NAME=POD_NAME), 404 + +@app.errorhandler(403) +def forbidden(e): + return render_template('errors/403.html', NODE_NAME=NODE_NAME, POD_NAME=POD_NAME), 403 + +@app.errorhandler(500) +def ISEerror(e): + return render_template('errors/500.html', NODE_NAME=NODE_NAME, POD_NAME=POD_NAME), 500 + # Index route @app.route('/') def index(): - createEvents(db, currDay, Period, Event) return redirect('/events') # Authentication routes @@ -49,12 +82,13 @@ def login(): if form.validate_on_submit(): userName = form.userName.data password = form.password.data + remember = form.rememberMe.data user = User.query.filter_by(userName=userName).first() if not user or not check_password_hash(user.password, password): flash('Credentials incorrect! Please try again') return redirect(url_for('login')) - login_user(user) + login_user(user, remember=remember) return redirect(url_for('events')) return render_template('login.html', form=form) @@ -82,6 +116,19 @@ def logout(): logout_user() return redirect(url_for('index')) +@app.route('/settings', methods=('GET', 'POST')) +@login_required +def settings(): + user = User.query.get_or_404(current_user.id) + form = SettingsForm(obj=user) + if form.validate_on_submit(): + user.realName = form.realName.data + user.timezone = form.timezone.data + if form.password.data != '': + user.password = generate_password_hash(form.password.data, method='sha256') + db.session.commit() + return render_template('settings.html', form=form) + # Periods routes @app.route('/periods') @login_required @@ -99,6 +146,7 @@ def newPeriod(): ) db.session.add(period) db.session.commit() + # Run createEvents upon adding new period createEvents(db, currDay, Period, Event) return redirect(f'/period/edit/{period.period}') return render_template('newPeriod.html', form=form) @@ -131,9 +179,8 @@ def delete_period(periodNum): def events(): events = Event.query.all() periods = Period.query.all() - createEvents(db, currDay, Period, Event) - return render_template('events.html', events=events, periods=periods, datetime=datetime, date=date) + return render_template('events.html', events=events, periods=periods, datetime=datetime, date=date, ZoneInfo=ZoneInfo) @app.route('/event/edit//', methods=('GET', 'POST')) @login_required diff --git a/app/create_events.py b/app/create_events.py index 19bfc2c..2033c0d 100644 --- a/app/create_events.py +++ b/app/create_events.py @@ -9,3 +9,5 @@ def createEvents(db, currDay, Period, Event): ) db.session.add(event) db.session.commit() + + print("createEvents script ran successfully") \ No newline at end of file diff --git a/app/db.py b/app/db.py index 6d380b0..4bb6bff 100644 --- a/app/db.py +++ b/app/db.py @@ -43,3 +43,4 @@ class User(UserMixin, db.Model): email = db.Column(db.String(100), unique=True) password = db.Column(db.String(100)) realName = db.Column(db.String(1000)) + timezone = db.Column(db.String(20), default='UTC') diff --git a/app/forms.py b/app/forms.py index 928c5fb..31a44b6 100644 --- a/app/forms.py +++ b/app/forms.py @@ -1,6 +1,7 @@ +import pytz from db import Task from flask_wtf import FlaskForm -from wtforms import (StringField, DateField, TimeField, TextAreaField, IntegerField, BooleanField, +from wtforms import (StringField, DateField, TimeField, TextAreaField, IntegerField, SelectField, BooleanField, RadioField, EmailField, PasswordField) from wtforms.validators import InputRequired, Length from wtforms_sqlalchemy.orm import QuerySelectField @@ -10,8 +11,7 @@ def get_tasks(): class TaskForm(FlaskForm): title = StringField('Title', validators=[InputRequired(), Length(min=5, max=100)]) - description = TextAreaField('Description', validators=[InputRequired(), - Length(max=200)]) + description = TextAreaField('Description', validators=[Length(max=200)]) class EventForm(FlaskForm): # eventDate = DateField('Date', validators=[InputRequired()], format='m-%d-%Y') # period_num = IntegerField(validators=[InputRequired()]) @@ -21,6 +21,11 @@ class PeriodForm(FlaskForm): weekendSchedule = BooleanField(label='Include on Weekends?', false_values=None) periodTime = TimeField('Time', format="%H:%M") +class SettingsForm(FlaskForm): + password = PasswordField('Password') + realName = StringField('Real Name') + timezone = SelectField('Time Zone', choices=pytz.all_timezones) + class SignupForm(FlaskForm): userName = StringField('Username', validators=[InputRequired()]) password = PasswordField('Password', validators=[InputRequired()]) @@ -29,4 +34,5 @@ class SignupForm(FlaskForm): class LoginForm(FlaskForm): userName = StringField('Username', validators=[InputRequired()]) - password = PasswordField('Password', validators=[InputRequired()]) \ No newline at end of file + password = PasswordField('Password', validators=[InputRequired()]) + rememberMe = BooleanField(label='Remember me?') \ No newline at end of file diff --git a/app/init_db.py b/app/init_db.py index ece185e..3e47332 100644 --- a/app/init_db.py +++ b/app/init_db.py @@ -16,49 +16,49 @@ period9 = Period(period=9, periodTime='15:30:00', weekendSchedule=False) task1 = Task(id=1, title="Sexy ERP time", description="Be the dominant partner and fuck so much XD", - created_timestamp='1668278862', due_timestamp='') + created_timestamp=1668278862, due_timestamp=None) task2 = Task(id=2, title="Test task", description="Test", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task3 = Task(id=3, title="La Nager", description="Francis stuff", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task4 = Task(id=4, title="Ops/Tech Meeting", description="HEIL GEORGE!", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task5 = Task(id=5, title="Tech Team Meeting", description="Awkward AF", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task6 = Task(id=6, title="Write BellScheduler", description="heh", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task7 = Task(id=7, title="Fap to cunny porn", description="FBI OPEN UP!", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task8 = Task(id=8, title="Go on vrchat", description="Mmm... virtual headpats!", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) task9 = Task(id=9, title="Brush teeth", description="Ya dont do that more often, ya gross fuck", - created_timestamp='1668278862', - due_timestamp='') + created_timestamp=1668278862, + due_timestamp=None) -event1 = Event(id=1, scheduled_date='11-12-2022', period_num=1, task_id=4) -event2 = Event(id=2, scheduled_date='11-12-2022', period_num=2, task_id=2) -event3 = Event(id=3, scheduled_date='11-12-2022', period_num=3, task_id=5) -event4 = Event(id=4, scheduled_date='11-12-2022', period_num=4, task_id=6) -event5 = Event(id=5, scheduled_date='11-12-2022', period_num=5, task_id=1) -event6 = Event(id=6, scheduled_date='11-12-2022', period_num=6, task_id=3) -event7 = Event(id=7, scheduled_date='11-12-2022', period_num=7, task_id=7) -event8 = Event(id=8, scheduled_date='11-12-2022', period_num=8, task_id=8) -event9 = Event(id=9, scheduled_date='11-12-2022', period_num=9, task_id=9) +event1 = Event(id=1, scheduled_date='03-17-2023', period_num=1, task_id=4) +event2 = Event(id=2, scheduled_date='03-17-2023', period_num=2, task_id=2) +event3 = Event(id=3, scheduled_date='03-17-2023', period_num=3, task_id=5) +event4 = Event(id=4, scheduled_date='03-17-2023', period_num=4, task_id=6) +event5 = Event(id=5, scheduled_date='03-17-2023', period_num=5, task_id=1) +event6 = Event(id=6, scheduled_date='03-17-2023', period_num=6, task_id=3) +event7 = Event(id=7, scheduled_date='03-17-2023', period_num=7, task_id=7) +event8 = Event(id=8, scheduled_date='03-17-2023', period_num=8, task_id=8) +event9 = Event(id=9, scheduled_date='03-17-2023', period_num=9, task_id=9) db.session.add_all([period1, period2, period3, period4, period5, period6, period7, period8, period9]) db.session.add_all([task1, task2, task3, task4, task5, task6, task7, task8, task9]) diff --git a/app/migrations/versions/bf65c9f77f9f_.py b/app/migrations/versions/bf65c9f77f9f_.py deleted file mode 100644 index ed45c69..0000000 --- a/app/migrations/versions/bf65c9f77f9f_.py +++ /dev/null @@ -1,36 +0,0 @@ -"""empty message - -Revision ID: bf65c9f77f9f -Revises: -Create Date: 2022-11-19 09:49:20.565127 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'bf65c9f77f9f' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('userName', sa.String(length=1000), nullable=True), - sa.Column('email', sa.String(length=100), nullable=True), - sa.Column('password', sa.String(length=100), nullable=True), - sa.Column('realName', sa.String(length=1000), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('user') - # ### end Alembic commands ### diff --git a/app/misc.py b/app/misc.py index 9124938..f4667bb 100644 --- a/app/misc.py +++ b/app/misc.py @@ -1,4 +1,17 @@ import time -from datetime import datetime, date +from datetime import datetime, date, timedelta +from zoneinfo import ZoneInfo + +# Get current day in UTC and put it in str format currDay = datetime.now() -currDay = currDay.strftime('%m-%d-%Y') \ No newline at end of file +currDay = currDay.strftime('%m-%d-%Y') + +# Get previous day in UTC and put it in str format +prevDay = datetime.now() + timedelta(days=-1) +prevDay = prevDay.strftime('%m-%d-%Y') + + +with open('__version__','r') as file: + currVersion = file.read() +with open('__commit__','r') as file: + currCommit = file.read() \ No newline at end of file diff --git a/app/requirements.txt b/app/requirements.txt index 8ed3ceb..bd4eaad 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -1,6 +1,9 @@ # This file is used by pip to install required python packages # Usage: pip install -r requirements.txt +# Gunicorn WSGI Server +gunicorn==20.1.0 + # Flask Framework click==8.1.3 Flask==2.2.2 @@ -20,6 +23,15 @@ Flask-User==1.0.2.2 # WTForms Extensions WTForms-SQLAlchemy==0.3.0 +# APScheduler automated scheduler +APScheduler==3.9.1.post1 + +# Python Time packages +pytz==2022.6 + # Automated tests pytest==7.2.0 pytest-cov==4.0.0 + +# MySQL Package +mysqlclient==2.1.1 \ No newline at end of file diff --git a/app/static/android-chrome-192x192.png b/app/static/android-chrome-192x192.png new file mode 100644 index 0000000..9726959 Binary files /dev/null and b/app/static/android-chrome-192x192.png differ diff --git a/app/static/android-chrome-512x512.png b/app/static/android-chrome-512x512.png new file mode 100644 index 0000000..6f88dcd Binary files /dev/null and b/app/static/android-chrome-512x512.png differ diff --git a/app/static/apple-touch-icon.png b/app/static/apple-touch-icon.png new file mode 100644 index 0000000..b2ef51c Binary files /dev/null and b/app/static/apple-touch-icon.png differ diff --git a/app/static/favicon-16x16.png b/app/static/favicon-16x16.png new file mode 100644 index 0000000..f959ccc Binary files /dev/null and b/app/static/favicon-16x16.png differ diff --git a/app/static/favicon-32x32.png b/app/static/favicon-32x32.png new file mode 100644 index 0000000..c6a069f Binary files /dev/null and b/app/static/favicon-32x32.png differ diff --git a/app/static/favicon.ico b/app/static/favicon.ico new file mode 100644 index 0000000..f044edd Binary files /dev/null and b/app/static/favicon.ico differ diff --git a/app/static/manifest.json b/app/static/manifest.json new file mode 100644 index 0000000..258ecd0 --- /dev/null +++ b/app/static/manifest.json @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/static/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/static/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/app/templates/base.html b/app/templates/base.html index ba71787..85b67fc 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -1,6 +1,10 @@ + + + + @@ -10,14 +14,14 @@ {% block title %} {% endblock %} - BellScheduler - + @@ -42,7 +49,9 @@
{% block content %} {% endblock %}
- + diff --git a/app/templates/editEvent.html b/app/templates/editEvent.html index cb48cb5..2c5b78e 100644 --- a/app/templates/editEvent.html +++ b/app/templates/editEvent.html @@ -9,7 +9,10 @@

{{ event.tasks.title }} -
{{ event.tasks.description }} + +
{% if event.tasks.description != None %} +

{{ event.tasks.description }}

+ {% endif %}

{% else %}

(no task assigned... yet)

diff --git a/app/templates/errors/403.html b/app/templates/errors/403.html new file mode 100644 index 0000000..5b703b1 --- /dev/null +++ b/app/templates/errors/403.html @@ -0,0 +1,22 @@ +{% extends 'base.html' %} +{% set currDay = datetime.now() %} +{% set currTime = currDay.strftime('%I:%M %p') %} +{% set currDay = currDay.strftime('%m-%d-%Y') %} + +{% block content %} +

{% block title %} Error 403 {% endblock %}

+
+
+

Forbidden

+
+ +
+ Date: {{ currDay }}
+ Time {{ currTime }} (UTC)

+
+
+ Node: {{ NODE_NAME }}
+ Pod: {{ POD_NAME }} +
+
+{% endblock %} \ No newline at end of file diff --git a/app/templates/errors/404.html b/app/templates/errors/404.html new file mode 100644 index 0000000..a6fa5f8 --- /dev/null +++ b/app/templates/errors/404.html @@ -0,0 +1,22 @@ +{% extends 'base.html' %} +{% set currDay = datetime.now() %} +{% set currTime = currDay.strftime('%I:%M %p') %} +{% set currDay = currDay.strftime('%m-%d-%Y') %} + +{% block content %} +

{% block title %} Error 404 {% endblock %}

+
+
+

Page Not Found

+
+ +
+ Date: {{ currDay }}
+ Time {{ currTime }} (UTC)

+
+
+ Node: {{ NODE_NAME }}
+ Pod: {{ POD_NAME }} +
+
+{% endblock %} \ No newline at end of file diff --git a/app/templates/errors/500.html b/app/templates/errors/500.html new file mode 100644 index 0000000..690f0d3 --- /dev/null +++ b/app/templates/errors/500.html @@ -0,0 +1,22 @@ +{% extends 'base.html' %} +{% set currDay = datetime.now() %} +{% set currTime = currDay.strftime('%I:%M %p') %} +{% set currDay = currDay.strftime('%m-%d-%Y') %} + +{% block content %} +

{% block title %} Error 500 {% endblock %}

+
+
+

Internal Server Error

+
+ +
+ Date: {{ currDay }}
+ Time {{ currTime }} (UTC)

+
+
+ Node: {{ NODE_NAME }}
+ Pod: {{ POD_NAME }} +
+
+{% endblock %} \ No newline at end of file diff --git a/app/templates/events.html b/app/templates/events.html index b4b1c0d..f0dea65 100644 --- a/app/templates/events.html +++ b/app/templates/events.html @@ -1,10 +1,12 @@ {% extends 'base.html' %} {% set currDay = datetime.now() %} +{% set currDay = currDay.astimezone(ZoneInfo(current_user.timezone)) %} +{% set currTime = currDay.strftime('%I:%M %p') %} {% set currDay = currDay.strftime('%m-%d-%Y') %} {% block content %}

{% block title %} Events {% endblock %}

- Current Date: {{ currDay }}

+ Current Date: {{ currDay }}
Current Time: {{ currTime }}

{% for period in periods %}
@@ -18,7 +20,9 @@
+ {% if event.tasks.description != None %}

{{ event.tasks.description }}

+ {% endif %}
{% else %}

(no task assigned... yet)

diff --git a/app/templates/login.html b/app/templates/login.html index ed2c19e..a2df10d 100644 --- a/app/templates/login.html +++ b/app/templates/login.html @@ -19,6 +19,9 @@ {{ form.password.label }} {{ form.password }}

+

+ {{ form.rememberMe.label}} {{ form.rememberMe }} +

diff --git a/app/templates/settings.html b/app/templates/settings.html new file mode 100644 index 0000000..04c0611 --- /dev/null +++ b/app/templates/settings.html @@ -0,0 +1,23 @@ +{% extends 'base.html' %} + +{% block content %} +

{% block title %} Settings {% endblock %}

+
+ {{ form.csrf_token }} +

+ User: {{ current_user.userName }} +

+ {{ form.realName.label }} {{ form.realName }} +

+
+ {{ form.password.label }} {{ form.password }} +

+
+ {{ form.timezone.label }} {{ form.timezone }} +
+

+

+ +

+
+{% endblock %} \ No newline at end of file diff --git a/app/templates/task.html b/app/templates/task.html index 71ff660..886659b 100644 --- a/app/templates/task.html +++ b/app/templates/task.html @@ -8,7 +8,9 @@

-

{{ task.description }}

+ {% if task.description != None %} +

{{ task.description }}

+ {% endif %}

Created: {{ createdTime.strftime('%Y-%m-%d %I:%M %p') }}

diff --git a/app/templates/tasks.html b/app/templates/tasks.html index 7a31ca7..e7f0db8 100644 --- a/app/templates/tasks.html +++ b/app/templates/tasks.html @@ -11,7 +11,9 @@

{{ task.title }}

- {{ task.description }} + {% if task.description != None %} + {{ task.description }} + {% endif %}

Created: {{ createdTime.strftime('%Y-%m-%d %I:%M %p') }}

@@ -19,4 +21,5 @@
{% endfor %} +
{% endblock %} \ No newline at end of file diff --git a/app/worker.py b/app/worker.py new file mode 100644 index 0000000..288a29e --- /dev/null +++ b/app/worker.py @@ -0,0 +1,35 @@ +import os +from flask import Flask +from misc import currDay, datetime, time, timedelta +from db import db, Period, Event +from create_events import createEvents +from apscheduler.schedulers.background import BlockingScheduler + +basedir = os.path.abspath(os.path.dirname(__file__)) + +app = Flask(__name__) +app.config['SECRET_KEY'] = os.environ['SECRET_KEY'] +app.config['SQLALCHEMY_DATABASE_URI'] =\ + 'mysql://' + os.environ['MYSQL_USER'] + \ + ':' + os.environ['MYSQL_PASSWORD'] + \ + '@' + os.environ['MYSQL_HOST'] + \ + ':' + os.environ['MYSQL_PORT'] + \ + '/' + os.environ['MYSQL_DB'] +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +db.init_app(app) + +# Define function to run create_events with app context +def run_create_events(): + with app.app_context(): + createEvents(db, currDay, Period, Event) + +# Call createEvents on initial launch of the script +run_create_events() + + +# Set up scheduler to run function at 59th minute of every hour +scheduler = BlockingScheduler() +scheduler.add_job(run_create_events, 'cron', minute=59) + +# Start scheduler +scheduler.start() \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index c98dbc7..c811c2a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,8 +4,42 @@ services: image: container-registry.infra.dubyatp.xyz/bellscheduler/app:latest-testing restart: always environment: - - SQLITE_DB=database.db - volumes: - - ./database.db:/app/database.db + - MYSQL_USER=root + - MYSQL_PASSWORD=notasecuresecretkeyonlyuseforlocaldevelopment + - MYSQL_HOST=db + - MYSQL_PORT=3306 + - MYSQL_DB=bellscheduler + - SECRET_KEY=notasecuresecretkeyonlyuseforlocaldevelopment + - NODE_NAME=local + - POD_NAME=local + - FLASK_ENV=development + - FLASK_DEBUG=1 + - PYTHONUNBUFFERED=1 ports: - - 127.0.0.1:5000:5000 \ No newline at end of file + - 127.0.0.1:80:80 + worker: + image: container-registry.infra.dubyatp.xyz/bellscheduler/app:latest-testing + restart: always + entrypoint: python3 + command: "-m worker" + environment: + - MYSQL_USER=root + - MYSQL_PASSWORD=notasecuresecretkeyonlyuseforlocaldevelopment + - MYSQL_HOST=db + - MYSQL_PORT=3306 + - MYSQL_DB=bellscheduler + - SECRET_KEY=notasecuresecretkeyonlyuseforlocaldevelopment + - NODE_NAME=local + - POD_NAME=local + - FLASK_ENV=development + - FLASK_DEBUG=1 + - PYTHONUNBUFFERED=1 + db: + image: mariadb:10.7.8-focal + restart: always + environment: + - MARIADB_ROOT_PASSWORD=notasecuresecretkeyonlyuseforlocaldevelopment + volumes: + - ./database_mysql:/var/lib/mysql + ports: + - 127.0.0.1:3306:3306 \ No newline at end of file