890 lines
24 KiB
Python
890 lines
24 KiB
Python
import datetime
|
|
import hashlib
|
|
import os
|
|
|
|
from PIL import Image, ImageSequence
|
|
import concurrent.futures
|
|
|
|
from flask import Flask, render_template, redirect, url_for, request, jsonify
|
|
from flask_login import login_required, LoginManager, login_user, logout_user, current_user
|
|
|
|
from models.Habit import Habit
|
|
from models.HabitList import HabitList
|
|
from models.HabitTracking import HabitTracking
|
|
from models.User import User
|
|
from utils import anonymous_required
|
|
|
|
# Create a new Flask instance
|
|
app = Flask(__name__)
|
|
app.secret_key = 'PSSSSSHHHT!'
|
|
UPLOAD_FOLDER = 'static/profile_images/' # Folder to store profile images
|
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
|
|
|
# Initialize the Flask-Login extension
|
|
login_manager = LoginManager()
|
|
login_manager.login_view = 'login'
|
|
login_manager.init_app(app)
|
|
|
|
@login_manager.user_loader
|
|
def load_user(user_id):
|
|
return User.get(user_id)
|
|
|
|
|
|
@app.context_processor
|
|
def inject_user():
|
|
return dict(user=current_user)
|
|
|
|
|
|
@app.context_processor
|
|
def inject_notifications():
|
|
if current_user.is_authenticated:
|
|
habit_lists = current_user.get_unaccepted_habitLists()
|
|
lists = []
|
|
for habit_list in habit_lists:
|
|
# Check if the user is the first user in the list
|
|
if habit_list.get_users()[0].id != current_user.id:
|
|
lists.append(habit_list)
|
|
|
|
return dict(notifications=lists)
|
|
return dict(notifications=[])
|
|
|
|
|
|
# Create a new route
|
|
@app.route('/')
|
|
def index():
|
|
if current_user.is_authenticated:
|
|
habit_lists = current_user.get_habitLists()
|
|
name = "Hallo " + current_user.name
|
|
heatmap_values, day = current_user.get_heatmap()
|
|
heatmap_color = current_user.heatmap_color
|
|
else:
|
|
habit_lists = []
|
|
name = "Bitte melde dich an."
|
|
heatmap_values = []
|
|
day = None
|
|
heatmap_color = None
|
|
|
|
# Sort habit_lists based on their order attribute
|
|
habit_lists = sorted(habit_lists, key=lambda habitList: habitList.slot)
|
|
|
|
# Sort habits within each habit_list by slot
|
|
for habit_list in habit_lists:
|
|
habit_list.habits = sorted(habit_list.get_habits(), key=lambda habit: (habit.checked, habit.slot))
|
|
for habit in habit_list.get_habits():
|
|
habit.load_statistics()
|
|
|
|
# Get active_list from query parameter
|
|
try:
|
|
active_list = int(request.args.get('list'))
|
|
except (ValueError, TypeError):
|
|
active_list = None
|
|
|
|
return render_template(
|
|
'index.html',
|
|
title=name,
|
|
habit_lists=habit_lists,
|
|
heatmap_values=heatmap_values,
|
|
day=day,
|
|
color=heatmap_color,
|
|
errors={},
|
|
active_list=active_list
|
|
)
|
|
|
|
|
|
###################### Login & Signup #####################
|
|
@app.route('/login')
|
|
@anonymous_required
|
|
def login():
|
|
return render_template('auth/login.html', errors={})
|
|
|
|
@app.route('/signup')
|
|
@anonymous_required
|
|
def signup():
|
|
return render_template('auth/signup.html', errors={})
|
|
|
|
@app.route('/login', methods=['POST'])
|
|
def login_post():
|
|
email = request.form.get('email')
|
|
password = request.form.get('password')
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not email:
|
|
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
|
|
if not password:
|
|
errors['password'] = 'Das Passwort ist erforderlich.'
|
|
|
|
# Check if user exists
|
|
user = User.get_by_email(email)
|
|
|
|
if not user:
|
|
errors['email'] = 'E-Mail Adresse nicht gefunden.'
|
|
elif user.password is None or hashlib.sha256(password.encode()).hexdigest() != user.password:
|
|
errors['password'] = 'Das Passwort ist falsch.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
'auth/login.html',
|
|
email=email,
|
|
password=password,
|
|
errors=errors
|
|
)
|
|
|
|
login_user(user)
|
|
|
|
# Redirect to login page
|
|
return redirect(url_for('index'))
|
|
|
|
@app.route('/signup', methods=['POST'])
|
|
def signup_post():
|
|
email = request.form.get('email')
|
|
name = request.form.get('name')
|
|
password = request.form.get('password')
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not email:
|
|
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
|
|
if not name:
|
|
errors['name'] = 'Der Name ist erforderlich.'
|
|
if not password:
|
|
errors['password'] = 'Das Passwort ist erforderlich.'
|
|
|
|
# Check if email is already in use
|
|
if User.get_by_email(email):
|
|
errors['email'] = 'E-Mail Adresse bereits in Benutzung.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
'auth/signup.html',
|
|
email=email,
|
|
name=name,
|
|
password=password,
|
|
errors=errors
|
|
)
|
|
|
|
# Save user to database. Maybe log the user in directly.
|
|
user = User.create(name, email, password)
|
|
login_user(user)
|
|
|
|
# Redirect to login page
|
|
return redirect(url_for('index'))
|
|
|
|
@app.route('/logout')
|
|
@login_required
|
|
def logout():
|
|
# Log out functionality
|
|
logout_user()
|
|
|
|
return redirect(url_for('index'))
|
|
###########################################################
|
|
|
|
|
|
|
|
########################## Habit ##########################
|
|
@app.route('/habit')
|
|
@login_required
|
|
def habit_creation():
|
|
return render_template(
|
|
'habit.html',
|
|
title='Erstelle ein Habit',
|
|
unit="Woche",
|
|
errors={},
|
|
)
|
|
|
|
@app.route('/habit', methods=['POST'])
|
|
@login_required
|
|
def habit_create():
|
|
name = request.form.get('name')
|
|
note = request.form.get('note')
|
|
times = request.form.get('times')
|
|
unit = request.form.get('unit')
|
|
list_id = request.form.get('list_query')
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not name:
|
|
errors['name'] = 'Der Name ist erforderlich.'
|
|
if not times:
|
|
errors['times'] = 'Die Anzahl ist erforderlich.'
|
|
if not note:
|
|
note = ''
|
|
if not unit:
|
|
errors['unit'] = 'Die Einheit ist erforderlich.'
|
|
if not list_id:
|
|
errors['list_query'] = 'Die Habitliste ist erforderlich.'
|
|
|
|
# Check if times is an integer
|
|
try:
|
|
times = int(times)
|
|
|
|
# Check that times is greater than 0
|
|
if times <= 0:
|
|
errors['times'] = 'Die Anzahl muss größer als 0 sein.'
|
|
except ValueError:
|
|
errors['times'] = 'Die Anzahl muss eine Zahl sein.'
|
|
|
|
# Check that unit is valid
|
|
if unit not in ['Tag', 'Woche', 'Monat', 'Jahr']:
|
|
errors['unit'] = 'Die Einheit ist ungültig.'
|
|
|
|
# check if list_id is an int
|
|
try:
|
|
list_id = int(list_id)
|
|
except ValueError:
|
|
errors['list_query'] = 'Die Anzahl muss eine Zahl sein.'
|
|
|
|
# Check if times is possible to achieve
|
|
if unit == 'Tag' and times != 1:
|
|
errors['times'] = 'Die Anzahl muss 1 sein, wenn das Habit täglich ist.'
|
|
if unit == 'Woche' and times > 7:
|
|
errors['times'] = 'Die Anzahl darf höchstens 7 sein, wenn das Habit wöchentlich ist.'
|
|
if unit == 'Monat' and times > 31:
|
|
errors['times'] = 'Die Anzahl darf höchstens 31 sein, wenn das Habit monatlich ist.'
|
|
if unit == 'Jahr' and times > 365:
|
|
errors['times'] = 'Die Anzahl darf höchstens 365 sein, wenn das Habit jährlich ist.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
'habit.html',
|
|
title='Erstelle ein Habit',
|
|
name=name,
|
|
note=note,
|
|
times=times,
|
|
unit=unit,
|
|
errors=errors,
|
|
list_id=list_id
|
|
)
|
|
|
|
# Map unit to integer
|
|
if unit == 'Tag':
|
|
unit = 0
|
|
elif unit == 'Woche':
|
|
unit = 1
|
|
elif unit == 'Monat':
|
|
unit = 2
|
|
elif unit == 'Jahr':
|
|
unit = 3
|
|
else:
|
|
unit = 1
|
|
|
|
# Save habit to database
|
|
Habit.create(list_id, name, times, note, unit)
|
|
|
|
# Back to index
|
|
return redirect(url_for('index'))
|
|
|
|
@app.route('/edit-habit')
|
|
@login_required
|
|
def edit_habit():
|
|
habit_id = int(request.args.get("habit"))
|
|
habit = Habit.get(habit_id)
|
|
|
|
|
|
units = ["Tag", "Woche", "Monat", "Jahr"]
|
|
|
|
return render_template(
|
|
"edit-habit.html",
|
|
title=habit.name,
|
|
habit=habit.id,
|
|
name=habit.name,
|
|
note=habit.note,
|
|
times=habit.times,
|
|
unit=units[habit.unit],
|
|
errors={}
|
|
)
|
|
|
|
@app.route('/edit-habit', methods=['POST'])
|
|
@login_required
|
|
def edit_habit_change():
|
|
|
|
units = ["Tag", "Woche", "Monat", "Jahr"]
|
|
name = request.form.get('name')
|
|
note = request.form.get('note')
|
|
times = request.form.get('times')
|
|
unit = request.form.get('unit')
|
|
list_id = request.form.get('habit')
|
|
|
|
habit = Habit.get(list_id)
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not name:
|
|
errors['name'] = 'Der Name ist erforderlich.'
|
|
if not times:
|
|
errors['times'] = 'Die Anzahl ist erforderlich.'
|
|
if not note:
|
|
note = ''
|
|
if not unit:
|
|
errors['unit'] = 'Die Einheit ist erforderlich.'
|
|
if not list_id:
|
|
errors['habit'] = 'Das Habit ist erforderlich.'
|
|
|
|
# Check if times is an integer
|
|
try:
|
|
print(times)
|
|
times = int(times)
|
|
|
|
|
|
# Check that times is greater than 0
|
|
if times <= 0:
|
|
errors['times'] = 'Die Anzahl muss größer als 0 sein.'
|
|
except ValueError:
|
|
errors['times'] = 'Die Anzahl muss eine Zahl sein.'
|
|
|
|
# Check that unit is valid
|
|
if unit not in ['Tag', 'Woche', 'Monat', 'Jahr']:
|
|
errors['unit'] = 'Die Einheit ist ungültig.'
|
|
|
|
# check if list_id is an int
|
|
try:
|
|
int(list_id)
|
|
except ValueError:
|
|
errors['list_query'] = 'Die Anzahl muss eine Zahl sein.'
|
|
|
|
# Check if times is possible to achieve
|
|
if unit == 'Tag' and times != 1:
|
|
errors['times'] = 'Die Anzahl muss 1 sein, wenn das Habit täglich ist.'
|
|
if unit == 'Woche' and times > 7:
|
|
errors['times'] = 'Die Anzahl darf höchstens 7 sein, wenn das Habit wöchentlich ist.'
|
|
if unit == 'Monat' and times > 31:
|
|
errors['times'] = 'Die Anzahl darf höchstens 31 sein, wenn das Habit monatlich ist.'
|
|
if unit == 'Jahr' and times > 365:
|
|
errors['times'] = 'Die Anzahl darf höchstens 365 sein, wenn das Habit jährlich ist.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
"edit-habit.html",
|
|
title=habit.name,
|
|
habit=habit.id,
|
|
name=habit.name,
|
|
note=habit.note,
|
|
times=habit.times,
|
|
unit=units[habit.unit],
|
|
errors=errors
|
|
)
|
|
|
|
# Map unit to integer
|
|
if unit == 'Tag':
|
|
unit = 0
|
|
elif unit == 'Woche':
|
|
unit = 1
|
|
elif unit == 'Monat':
|
|
unit = 2
|
|
elif unit == 'Jahr':
|
|
unit = 3
|
|
else:
|
|
unit = 1
|
|
|
|
# Save habit to database
|
|
print(name, note, times, unit)
|
|
habit.name, habit.note, habit.times, habit.unit = name, note, times, unit
|
|
|
|
habit.update()
|
|
# Back to index
|
|
return redirect(url_for('index'))
|
|
|
|
@app.route('/check', methods=['POST'])
|
|
@login_required
|
|
def check_habit():
|
|
habit_id = request.get_json()["habitId"]
|
|
habit = Habit.get(habit_id)
|
|
|
|
if habit is None:
|
|
return {"error": "Habit not found"}
|
|
|
|
# Check if habit belongs to user
|
|
users = habit.habit_list().get_users()
|
|
if current_user not in users:
|
|
return {"error": "Habit does not belong to user"}
|
|
|
|
trackings = habit.get_habitTrackings()
|
|
|
|
# Check if habit has been tracked today
|
|
delete_tracking = None
|
|
for tracking in trackings:
|
|
if tracking.created_at.date() == datetime.date.today():
|
|
delete_tracking = tracking
|
|
|
|
if not delete_tracking:
|
|
HabitTracking.create(habit_id)
|
|
habit.fill_statistics()
|
|
else:
|
|
delete_tracking.delete()
|
|
habit.reset_statistics()
|
|
|
|
habit.load_statistics()
|
|
heatmap_values, day = current_user.get_heatmap()
|
|
|
|
return {
|
|
"habitId": habit_id,
|
|
"unchecked": not delete_tracking,
|
|
"percentage": habit.percentage,
|
|
"streak": habit.streak,
|
|
"heatmap": heatmap_values,
|
|
"day": day,
|
|
}
|
|
|
|
@app.route('/delete', methods=['POST'])
|
|
@login_required
|
|
def delete_habit():
|
|
habit_id = request.get_json()["habitId"]
|
|
|
|
habit = Habit.get(habit_id)
|
|
|
|
if habit is None:
|
|
return {"error": "Habit not found"}
|
|
|
|
# Check if habit belongs to user
|
|
if current_user not in habit.habit_list().get_users():
|
|
return {"error": "Habit does not belong to user"}
|
|
|
|
habit.delete()
|
|
return {}
|
|
|
|
@app.route('/reorder-habit', methods=['POST'])
|
|
@login_required
|
|
def reorder_habits():
|
|
new_index = request.get_json()["newIndex"] + 1
|
|
habit = Habit.get(request.get_json()["habitId"])
|
|
|
|
if habit is None:
|
|
return {"error": "Habit not found"}
|
|
|
|
# Check if habit belongs to user
|
|
users = habit.habit_list().get_users()
|
|
if current_user not in users:
|
|
return {"error": "Habit does not belong to user"}
|
|
|
|
habit.update_slot(new_index)
|
|
|
|
return {}
|
|
###########################################################
|
|
|
|
|
|
|
|
######################## HabitList ########################
|
|
@app.route('/habit-list')
|
|
@login_required
|
|
def habit_list_creation():
|
|
return render_template(
|
|
'habit-list.html',
|
|
title='Erstelle eine Habitliste',
|
|
errors={},
|
|
)
|
|
|
|
@app.route('/habit-list', methods=['POST'])
|
|
@login_required
|
|
def habit_list_create():
|
|
name = request.form.get('name')
|
|
description = request.form.get('description')
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not name:
|
|
errors['name'] = 'Der Name ist erforderlich.'
|
|
if not description:
|
|
description = ''
|
|
|
|
if errors:
|
|
return render_template(
|
|
'habit-list.html',
|
|
title='Erstelle eine Habitliste',
|
|
name=name,
|
|
description=description,
|
|
errors=errors
|
|
)
|
|
|
|
# Save habit to database
|
|
HabitList.create(current_user.id, name, description)
|
|
|
|
# Back to index
|
|
return redirect(url_for('index'))
|
|
|
|
@app.route('/delete-list', methods=['POST'])
|
|
@login_required
|
|
def delete_list():
|
|
list_id = request.get_json()["listId"]
|
|
|
|
habit_list = HabitList.get(list_id)
|
|
|
|
if habit_list is None:
|
|
return {"error": "List not found"}
|
|
|
|
# Check if habit belongs to user
|
|
if current_user not in habit_list.get_users():
|
|
return {"error": "List does not belong to user"}
|
|
|
|
habit_list.delete(current_user.id)
|
|
return {}
|
|
|
|
@app.route('/users')
|
|
@login_required
|
|
def users():
|
|
habit_list_id = request.args.get('habit_list', current_user.get_habitLists()[0].id)
|
|
habit_list = HabitList.get(int(habit_list_id))
|
|
users = habit_list.get_users()
|
|
|
|
# Remove the current user from the list
|
|
users = [user for user in users if user.id != current_user.id]
|
|
|
|
return render_template(
|
|
'users.html',
|
|
title='Teilnehmer',
|
|
habit_list=habit_list,
|
|
users=users,
|
|
errors={},
|
|
)
|
|
|
|
@app.route('/users', methods=['POST'])
|
|
@login_required
|
|
def add_user():
|
|
email = request.form.get('email')
|
|
habit_list_id = request.form.get('habit_list_id')
|
|
habit_list = HabitList.get(int(habit_list_id))
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not email:
|
|
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
|
|
if not habit_list_id:
|
|
errors['habit_list'] = 'Die Habitliste ist erforderlich.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
'users.html',
|
|
title='Teilnehmer',
|
|
email=email,
|
|
habit_list=habit_list,
|
|
errors=errors,
|
|
users=habit_list.get_users(),
|
|
)
|
|
|
|
# Check if user exists
|
|
user = User.get_by_email(email)
|
|
if not user:
|
|
errors['email'] = 'E-Mail Adresse nicht gefunden.'
|
|
|
|
if user and user.id == current_user.id:
|
|
errors['email'] = 'Du kannst dich nicht selbst hinzufügen.'
|
|
|
|
# Check if user is already in the habit list
|
|
already = False
|
|
if user:
|
|
for u in habit_list.get_users():
|
|
if u.id == user.id:
|
|
already = True
|
|
break
|
|
|
|
if already:
|
|
errors['email'] = 'Teilnehmer ist bereits in der Liste.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
'users.html',
|
|
title='Teilnehmer',
|
|
email=email,
|
|
habit_list=habit_list,
|
|
errors=errors,
|
|
users=habit_list.get_users(),
|
|
)
|
|
|
|
# Add user to habit list
|
|
habit_list = HabitList.get(int(habit_list_id))
|
|
habit_list.add_user(user)
|
|
|
|
return redirect(url_for('index', habit_list=habit_list.id))
|
|
|
|
@app.route('/users-edit')
|
|
@login_required
|
|
def edit_users():
|
|
habit_list_id = request.args.get('habit_list', current_user.get_habitLists()[0].id)
|
|
habit_list = HabitList.get(int(habit_list_id))
|
|
users = habit_list.get_users()
|
|
|
|
# Remove the current user from the list
|
|
users = [user for user in users if user.id != current_user.id]
|
|
|
|
return render_template(
|
|
'users-edit.html',
|
|
title='Teilnehmer bearbeiten',
|
|
habit_list=habit_list,
|
|
users=users,
|
|
errors={},
|
|
)
|
|
|
|
@app.route('/user-delete', methods=['POST'])
|
|
@login_required
|
|
def delete_user_from_list():
|
|
habit_list_id = request.form.get('habit_list_id')
|
|
habit_list = HabitList.get(int(habit_list_id))
|
|
|
|
habit_user_id = request.form.get('habit_user_id')
|
|
users = habit_list.get_users()
|
|
|
|
# Remove the current user from the list
|
|
users = [user for user in users if user.id != current_user.id]
|
|
|
|
# Check for errors
|
|
errors = {}
|
|
if not habit_list_id:
|
|
errors['habit_list'] = 'Die Habitliste ist erforderlich.'
|
|
if not habit_list_id:
|
|
errors['habit_user'] = 'Ein User ist erforderlich.'
|
|
|
|
if errors:
|
|
return render_template(
|
|
'users-edit.html',
|
|
title='Teilnehmer bearbeiten',
|
|
habit_list=habit_list,
|
|
users=users,
|
|
errors={},
|
|
)
|
|
|
|
# delete user from habit list
|
|
id = int(habit_user_id)
|
|
habit_list.delete(id)
|
|
|
|
return redirect(url_for('index', habit_list=habit_list.id))
|
|
|
|
@app.route('/users-leave')
|
|
@login_required
|
|
def user_leave():
|
|
list_id = request.args.get('habit_list')
|
|
|
|
habit_list = HabitList.get(list_id)
|
|
|
|
if habit_list is None:
|
|
return {"error": "List not found"}
|
|
|
|
# Check if habit belongs to user
|
|
if current_user not in habit_list.get_users():
|
|
return {"error": "List does not belong to user"}
|
|
|
|
habit_list.remove_user(current_user.id)
|
|
return redirect(url_for("index"))
|
|
|
|
@app.route('/accept-list', methods=['POST'])
|
|
@login_required
|
|
def accept_list():
|
|
list_id = request.json.get('list_id')
|
|
habit_list = HabitList.get(int(list_id))
|
|
|
|
users = habit_list.get_users()
|
|
# Check if user is part of the list
|
|
found = False
|
|
for user in users:
|
|
if user.id == current_user.id:
|
|
found = True
|
|
break
|
|
|
|
if not found:
|
|
return {}
|
|
|
|
current_user.accept_List(habit_list.id)
|
|
return {}
|
|
|
|
@app.route('/deny-list', methods=['POST'])
|
|
@login_required
|
|
def deny_list():
|
|
list_id = request.json.get('list_id')
|
|
habit_list = HabitList.get(int(list_id))
|
|
|
|
users = habit_list.get_users()
|
|
# Check if user is part of the list
|
|
found = False
|
|
for user in users:
|
|
if user.id == current_user.id:
|
|
found = True
|
|
break
|
|
|
|
if not found:
|
|
return {}
|
|
|
|
habit_list.remove_user(current_user.id)
|
|
return {}
|
|
|
|
@app.route('/reorder-list', methods=['POST'])
|
|
@login_required
|
|
def reorder_habit_list():
|
|
new_index = request.get_json()["newIndex"] + 1
|
|
habitList = HabitList.get(request.get_json()["listId"])
|
|
|
|
if habitList is None:
|
|
return {"error": "HabitList not found"}
|
|
|
|
# Check if habit belongs to user
|
|
users = habitList.get_users()
|
|
if current_user not in users:
|
|
return {"error": "HabitList does not belong to user"}
|
|
|
|
habitList.update_slot(current_user.id, new_index)
|
|
|
|
return {}
|
|
###########################################################
|
|
|
|
|
|
|
|
######################### Profile #########################
|
|
@app.route('/profile')
|
|
@login_required
|
|
def profile():
|
|
return render_template(
|
|
"profile.html",
|
|
name=current_user.name,
|
|
email=current_user.email,
|
|
profile_image_url=current_user.profile_image,
|
|
color = current_user.heatmap_color,
|
|
title="Profil",
|
|
)
|
|
|
|
@app.route('/profile', methods=['POST'])
|
|
@login_required
|
|
def profile_change():
|
|
newName = request.form.get('newName')
|
|
newEmail = request.form.get('newEmail')
|
|
|
|
# Update user
|
|
current_user.name = newName
|
|
current_user.email = newEmail
|
|
current_user.update()
|
|
|
|
# Back to profile
|
|
return render_template(
|
|
"profile.html",
|
|
name=current_user.name,
|
|
email=current_user.email,
|
|
profile_image_url=current_user.profile_image,
|
|
color=current_user.heatmap_color,
|
|
)
|
|
|
|
@app.route('/check_password', methods=['POST'])
|
|
@login_required
|
|
def check_password():
|
|
# Get the password sent from the client
|
|
password = request.json.get('password')
|
|
|
|
if hashlib.sha256(password.encode()).hexdigest() == current_user.password:
|
|
return jsonify({"valid": True})
|
|
else:
|
|
return jsonify({"valid": False})
|
|
|
|
@app.route('/password', methods=['POST'])
|
|
@login_required
|
|
def password_change():
|
|
newPassword = request.form.get('newPassword')
|
|
|
|
# Update user
|
|
if newPassword:
|
|
current_user.password = hashlib.sha256(newPassword.encode()).hexdigest()
|
|
current_user.update()
|
|
|
|
# Back to profile
|
|
return render_template("profile.html",
|
|
name=current_user.name,
|
|
email=current_user.email,
|
|
profile_image_url=current_user.profile_image,
|
|
color=current_user.heatmap_color,
|
|
)
|
|
|
|
def save_profile_image(image_file):
|
|
filename = image_file.filename
|
|
if '.' not in filename:
|
|
# Ensure the filename has an extension
|
|
raise ValueError("Invalid filename")
|
|
|
|
# Check if the file extension is allowed
|
|
allowed_extensions = {'jpg', 'jpeg', 'png', 'gif'}
|
|
file_extension = filename.rsplit('.', 1)[1].lower()
|
|
if file_extension not in allowed_extensions:
|
|
raise ValueError("Invalid file extension")
|
|
|
|
# Get the filename from the image path saved in the user
|
|
filename = os.path.basename(current_user.profile_image)
|
|
|
|
# Open the uploaded image
|
|
image = Image.open(image_file)
|
|
|
|
# Function to crop and resize frames
|
|
def process_frame(frame, size):
|
|
new_size = min(frame.size)
|
|
left = (frame.width - new_size) // 2
|
|
top = (frame.height - new_size) // 2
|
|
right = left + new_size
|
|
bottom = top + new_size
|
|
cropped_frame = frame.crop((left, top, right, bottom))
|
|
return cropped_frame.resize(size)
|
|
|
|
# Function to process frames in parallel
|
|
def process_frames_parallel(frames, size):
|
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
resized_frames = list(executor.map(lambda f: process_frame(f, size), frames))
|
|
return resized_frames
|
|
|
|
# Check if the image is an animated gif
|
|
if file_extension == 'gif':
|
|
# Process frames
|
|
gif_frames = [frame.copy() for frame in ImageSequence.Iterator(image)]
|
|
processed_frames = process_frames_parallel(gif_frames, size=(128, 128))
|
|
|
|
# Save the modified frames as a new GIF
|
|
output_gif_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".jpg", ".gif"))
|
|
processed_frames[0].save(output_gif_path, save_all=True, append_images=processed_frames[1:], loop=0)
|
|
return output_gif_path
|
|
else:
|
|
# Process single image
|
|
processed_image = process_frame(image, size=(256, 256))
|
|
processed_image = processed_image.convert('RGB')
|
|
|
|
# Save the processed image
|
|
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".gif", ".jpg"))
|
|
processed_image.save(image_path, 'JPEG', quality=100)
|
|
return image_path
|
|
|
|
@app.route('/upload', methods=['POST'])
|
|
@login_required
|
|
def upload_profile_image():
|
|
if 'file' not in request.files:
|
|
return 'No file part'
|
|
|
|
file = request.files['file']
|
|
image_path = save_profile_image(file)
|
|
|
|
# Update the User
|
|
current_user.profile_image = image_path
|
|
current_user.update()
|
|
|
|
# Back to profile
|
|
return redirect(url_for('profile'))
|
|
|
|
@app.route('/save_color', methods=['POST'])
|
|
@login_required
|
|
def save_heatmap_color():
|
|
# Get the color value from the form
|
|
new_color = request.form['color']
|
|
current_user.heatmap_color = new_color
|
|
current_user.update()
|
|
|
|
# Back to profile
|
|
return render_template(
|
|
"profile.html",
|
|
name=current_user.name,
|
|
email=current_user.email,
|
|
profile_image_url=current_user.profile_image,
|
|
color=current_user.heatmap_color,
|
|
)
|
|
|
|
@app.route('/delete_account', methods=['POST'])
|
|
@login_required
|
|
def delete_account():
|
|
os.remove(current_user.profile_image)
|
|
current_user.delete()
|
|
|
|
return redirect(url_for('index'))
|
|
###########################################################
|
|
|
|
|
|
# Run the application
|
|
if __name__ == '__main__':
|
|
app.run(host="0.0.0.0", port=5000, debug=True)
|