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 %}
+
+{% 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