initial commit

main
Tylan Tyson 1 year ago
commit 8e7cefdab1

2
.gitignore vendored

@ -0,0 +1,2 @@
.DS_STORE
venv/

@ -0,0 +1,19 @@
# Imports
from flask_sqlalchemy import SQLAlchemy
# Database
database = SQLAlchemy()
# User
class User ( database.Model ):
id = database.Column(database.Integer, primary_key = True)
username = database.Column(database.String, nullable = False, unique = True)
password = database.Column(database.String, nullable = False)
memes = database.relationship("Meme", lazy = "dynamic")
# Meme
class Meme ( database.Model ):
id = database.Column(database.Integer, primary_key = True)
user = database.Column(database.String, database.ForeignKey("user.username"), nullable = False)
title = database.Column(database.String, nullable = False)
image = database.Column(database.String, nullable = False, unique = True)

Binary file not shown.

@ -0,0 +1,132 @@
from flask import Flask, render_template, request, redirect, session
from flask_bcrypt import Bcrypt
from database import database, User, Meme
import os
app = Flask(__name__)
app.secret_key = "secret"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + os.path.join(os.path.abspath(os.path.dirname(__file__)), 'db.sqlite')
database.init_app(app)
bcrypt = Bcrypt(app)
with app.app_context():
database.create_all()
def usernameValid ( username ):
# Allowed Characters
characters = "abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"
if len(username) < 4:
return False
for char in username:
if not char in characters:
return False
return True
def passwordValid ( password ):
if len(password) < 1:
return False
return True
@app.route("/")
def root ():
memes = database.session.execute(database.Select(Meme).order_by(Meme.id.desc())).all()
if session.get("username"):
return render_template("index.html", memes = memes, loggedIn = True)
else:
return render_template("index.html", memes = memes, loggedIn = False)
@app.route("/sign-up", methods = [ "GET", "POST"])
def signUp ():
if session.get("username"):
return redirect("/")
if request.method == "GET":
return render_template("sign-up.html", loggedIn = False)
else:
if usernameValid(request.form.get("username")) and passwordValid(request.form.get("password")) and request.form.get("password") == request.form.get("repeatPassword"):
users = database.session.execute(database.select(User).filter_by(username=request.form.get("username"))).first()
if users == None:
database.session.add(User(username = request.form.get("username"), password = bcrypt.generate_password_hash(request.form.get("password"))))
database.session.commit()
return redirect("/sign-in")
return "Username taken"
else:
return "Invalid username and / or password"
@app.route("/sign-in", methods = [ "GET", "POST"])
def signIn ():
if session.get("username"):
return redirect("/")
if request.method == "GET":
return render_template("sign-in.html", loggedIn = False)
else:
if usernameValid(request.form.get("username")) and passwordValid(request.form.get("password")):
print("val")
user = database.session.execute(database.select(User).filter_by(username=request.form.get("username"))).first()
if user != None:
if bcrypt.check_password_hash(user[0].password, request.form.get("password")):
session["username"] = request.form.get("username")
return redirect("/")
return render_template("sign-in.html", loggedIn = False)
@app.route("/sign-out")
def signOut():
if session.get("username"):
session.pop("username")
return redirect("/")
@app.route("/upload", methods = ["GET", "POST"])
def upload ():
if session.get("username") == None:
return redirect("/")
if request.method == "GET":
return render_template("upload.html", loggedIn = True)
else:
if request.files.get("image").filename.split(".")[-1] in ["png", "jpg", "jpeg", "webp"]:
meme = database.session.execute(database.select(Meme).order_by(Meme.id.desc())).first()
if meme == None:
image_num = 1
else:
image_num = meme[0].id + 1
database.session.add(Meme( user = session.get("username") ,title = request.form.get("title"), image = str(image_num) + ".png"))
database.session.commit()
request.files.get("image").save(os.path.join("./static/memes", str(image_num) + ".png"))
return redirect("/upload")
return "oof"
@app.route("/user/<name>")
def user ( name ):
user = database.session.execute(database.select(User).filter_by(username = name )).first()
if user != None:
memes = database.session.execute(database.select(Meme).filter_by(user=name).order_by(Meme.id.desc())).all()
if session.get("username"):
return render_template("user.html", username = user[0].username, memes = memes, loggedIn = True)
else:
return render_template("user.html", username = user[0].username, memes = memes, loggedIn = False)
else:
return "no user"
app.run(debug=True)

@ -0,0 +1,13 @@
bcrypt==4.0.1
click==8.1.3
Flask==2.2.3
Flask-Bcrypt==1.0.1
Flask-SQLAlchemy==3.0.3
importlib-metadata==6.6.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
SQLAlchemy==2.0.10
typing_extensions==4.5.0
Werkzeug==2.2.3
zipp==3.15.0

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

@ -0,0 +1,143 @@
* {
margin: 0;
padding: 0;
text-decoration: none;
}
body {
background: rgb(33, 33, 33);
}
@font-face {
font-family: Writer-Regular;
src: url(/static/Writer-Regular.ttf);
}
nav {
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(17, 17, 17);
}
.navLogo {
width: 30%;
display: flex;
justify-content: center;
align-items: center;
}
.navLinks {
width: 30%;
display: flex;
justify-content: center;
align-items: center;
font-family: Writer-Regular;
font-size: 16px;
}
.navLinks a {
margin: 20px;
color: white;
}
.memes {
width: 100vw;
height: fit-content;
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
background: rgb(33, 33, 33);
}
.meme {
width: 90%;
max-width: 800px;
display: flex;
flex-direction: column;
background: linear-gradient(135deg, rgba(50, 50, 50, 0.4), rgba(55, 55, 55, 0.4));
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 20px;
border:1px solid rgba(255, 255, 255, 0.18);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
transition: linear 0.2s;
margin: 20px;
overflow: hidden;
font-family: Writer-Regular;
font-size: 18px;
}
.meme h1 {
color: white;
margin: 10px;
}
.meme h1 a {
color: white;
text-decoration: underline;
}
.meme img {
aspect-ratio: 1 / 1;
}
@media screen and (max-width: 1800px) {
nav {
flex-direction: column;
}
.navLogo, .navLinks {
width: 100%;
}
}
@media screen and (max-width: 600px) {
.navLinks {
flex-direction: column;
}
}
.userTitle {
width: 100vw;
background: rgb(33, 33, 33);
color: white;
font-family: Writer-Regular;
display: flex;
justify-content: center;
padding: 20px;
padding-bottom: 10px;
}
.uploadFormDiv {
padding: 10px;
background: rgb(33, 33, 33);
display: flex;
justify-content: center;
align-items: center;
}
.uploadFormDiv form {
display: flex;
flex-direction: column;
color: white;
width: 90%;
max-width: 600px;
}
.uploadFormDiv form input {
padding: 10px 20px;
}

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/static/main.css">
</head>
<body>
<nav>
<div class = "navLogo">
<img src="/static/logo.png" width = "300px">
</div>
{% if loggedIn == True %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/upload">Upload</a>
<a href="/sign-out">Sign Out</a>
</div>
{% else %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/sign-in">Sign In</a>
<a href="/sign-up">Sign Up</a>
</div>
{% endif %}
</nav>
<div class = "memes">
{% for meme in memes %}
<div class = "meme">
<h1>{{ meme[0].title }} by <a href="/user/{{ meme[0].user}}">{{ meme[0].user}}</a></h1>
<img src="/static/memes/{{ meme[0].image }}" class = "memeImage">
</div>
{% endfor %}
</div>
<script>
const items = document.querySelectorAll(".meme")
console.log(items)
items.forEach( item => {
item.addEventListener("mousemove", event => {
console.log(item)
item.style.transform = `perspective(500px) scale(1.02) rotateX(${ - 20 * (( item.getBoundingClientRect().bottom - event.clientY - item.clientHeight / 2 ) / item.clientHeight ) / 5 }deg) rotateY(${ 20 * (( item.getBoundingClientRect().right - event.clientX - item.clientWidth / 2) / item.clientWidth ) / 5 }deg)`;
})
item.addEventListener("mouseout", event => {
item.style.transform = "perspective(500px) scale(1) rotateX(0) rotateY(0)";
})
})
</script>
</body>
</html>

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/static/main.css">
</head>
<body>
<nav>
<div class = "navLogo">
<img src="/static/logo.png" width = "300px">
</div>
{% if loggedIn == True %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/upload">Upload</a>
<a href="/sign-out">Sign Out</a>
</div>
{% else %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/sign-in">Sign In</a>
<a href="/sign-up">Sign Up</a>
</div>
{% endif %}
</nav>
<h1 class = "userTitle">Sign In</h1>
<div class = "uploadFormDiv">
<form action="/sign-in" method = "POST">
<input type="text" name = "username" placeholder="Username">
<input type="password" name = "password" placeholder="Password">
<input type="submit" value="Sign Up">
</form>
</div>
</body>
</html>

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/static/main.css">
</head>
<body>
<nav>
<div class = "navLogo">
<img src="/static/logo.png" width = "300px">
</div>
{% if loggedIn == True %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/upload">Upload</a>
<a href="/sign-out">Sign Out</a>
</div>
{% else %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/sign-in">Sign In</a>
<a href="/sign-up">Sign Up</a>
</div>
{% endif %}
</nav>
<h1 class = "userTitle">Sign Up</h1>
<div class = "uploadFormDiv">
<form action="/sign-up" method = "POST">
<input type="text" name = "username" placeholder="Username">
<input type="password" name = "password" placeholder="Password">
<input type="password" name="repeatPassword" placeholder="Repeat Password">
<input type="submit" value="Sign Up">
</form>
</div>
</body>
</html>

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/static/main.css">
</head>
<body>
<nav>
<div class = "navLogo">
<img src="/static/logo.png" width = "300px">
</div>
{% if loggedIn == True %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/upload">Upload</a>
<a href="/sign-out">Sign Out</a>
</div>
{% else %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/sign-in">Sign In</a>
<a href="/sign-up">Sign Up</a>
</div>
{% endif %}
</nav>
<h1 class = "userTitle">Upload</h1>
<div class = "uploadFormDiv">
<form action="/upload" method = "POST" enctype="multipart/form-data">
<input type="text" name = "title" placeholder="Title">
<input type="file" name="image">
<input type="submit" value="Upload">
</form>
</div>
</body>
</html>

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/static/main.css">
</head>
<body>
<nav>
<div class = "navLogo">
<img src="/static/logo.png" width = "300px">
</div>
{% if loggedIn == True %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/upload">Upload</a>
<a href="/sign-out">Sign Out</a>
</div>
{% else %}
<div class = "navLinks">
<a href="/">Home</a>
<a href="/sign-in">Sign In</a>
<a href="/sign-up">Sign Up</a>
</div>
{% endif %}
</nav>
<h1 class = "userTitle">{{ username }}'s Memes</h1>
<div class = "memes">
{% for meme in memes %}
<div class = "meme">
<h1>{{ meme[0].title }}</h1>
<img src="/static/memes/{{ meme[0].image }}" class = "memeImage">
</div>
{% endfor %}
</div>
<script>
const items = document.querySelectorAll(".meme")
console.log(items)
items.forEach( item => {
item.addEventListener("mousemove", event => {
console.log(item)
item.style.transform = `perspective(500px) scale(1.02) rotateX(${ - 20 * (( item.getBoundingClientRect().bottom - event.clientY - item.clientHeight / 2 ) / item.clientHeight ) / 5 }deg) rotateY(${ 20 * (( item.getBoundingClientRect().right - event.clientX - item.clientWidth / 2) / item.clientWidth ) / 5 }deg)`;
})
item.addEventListener("mouseout", event => {
item.style.transform = "perspective(500px) scale(1) rotateX(0) rotateY(0)";
})
})
</script>
</body>
</html>
Loading…
Cancel
Save