Skip to content

Commit

Permalink
yep
Browse files Browse the repository at this point in the history
  • Loading branch information
chee committed Nov 16, 2020
1 parent 177550f commit 12da670
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 109 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Expand Up @@ -191,5 +191,5 @@ flycheck_*.el
# network security
/network-security.data



.flaskenv
app/app.db
15 changes: 15 additions & 0 deletions app/file.py
@@ -0,0 +1,15 @@
import mimetypes
from os.path import join, basename, dirname
from werkzeug.utils import secure_filename
from slugify import slugify
mimetypes.init()

def get_url_for(file, username, collection_slug, piece_slug):
name = f'{username}-{collection_slug}-{piece_slug}-{secure_filename(basename(file.filename))}'
path = join(dirname(__file__), "static", name)
file.save(path)

return f"/static/{name}"

def get_type_for(file):
return mimetypes.guess_type(file.filename)[0]
13 changes: 13 additions & 0 deletions app/forms.py
@@ -1,6 +1,8 @@
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, ValidationError, URL
from werkzeug.utils import secure_filename
from .models import CopyrightHolder

class LoginForm(FlaskForm):
Expand All @@ -9,6 +11,17 @@ class LoginForm(FlaskForm):
remember = BooleanField('🍪')
submit = SubmitField('login')

class CollectionForm(FlaskForm):
name = StringField('name', validators=[DataRequired()])
description = StringField('description', validators=[DataRequired()])
submit = SubmitField('make')

class PieceForm(FlaskForm):
name = StringField('name', validators=[DataRequired()])
description = StringField('description', validators=[DataRequired()])
file = FileField('file', validators=[FileRequired()])
submit = SubmitField('save')

class RegistrationForm(FlaskForm):
name = StringField('username', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
Expand Down
8 changes: 4 additions & 4 deletions app/models.py
Expand Up @@ -29,20 +29,20 @@ def is_admin(self):

class Collection(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, unique=True)
name = db.Column(db.String(128), index=True)
description = db.Column(db.String(256))
slug = db.Column(db.String(128), index=True)
copyright_holder_id = db.Column(db.Integer, db.ForeignKey('copyright_holder.id'))
password_hash = db.Column(db.String(128))
pieces = db.relationship('Piece', backref='collection', lazy='dynamic')
def __repr__(self):
return f'<Collection {self.name}>'

class Piece(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, unique=True)
name = db.Column(db.String(128), index=True)
slug = db.Column(db.String(128), index=True)
description = db.Column(db.String(256))
url = db.Column(db.String(128))
url = db.Column(db.String(256))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
type = db.Column(db.String(10), index=True)
collection_id = db.Column(db.Integer, db.ForeignKey('collection.id'))
Expand Down
116 changes: 106 additions & 10 deletions app/routes.py
@@ -1,22 +1,26 @@
from flask import render_template, flash, redirect, url_for
from flask_login import current_user, login_user
from flask_login import current_user, login_user, login_required
from . import app
from . import db
from .forms import LoginForm, RegistrationForm
from .forms import LoginForm, RegistrationForm, CollectionForm, PieceForm
from .models import CopyrightHolder, Collection, Piece

from .file import get_url_for, get_type_for
from slugify import slugify
from os import scandir
from os.path import join, dirname


@app.route('/')
def index():
return render_template("index.html",
collections=Collection.query.all())

@app.route('/logout/')
@app.route('/logout')
def logout():
return render_template("base.html")

@app.route('/register/', methods=['GET', 'POST'])
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
Expand All @@ -32,6 +36,7 @@ def register():
return redirect(url_for('index'))
return render_template('register.html', title="make user", form=form)

@app.route('/login/', methods=['GET', 'POST'])
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
Expand All @@ -47,26 +52,117 @@ def login():
return render_template('login.html', title="login", form=form)

@app.route('/<username>')
@app.route('/<username>/')
def copyright_holder(username):
ch = CopyrightHolder.query.filter_by(username=username).first()
if ch is None:
return "404"
flash("404")
return redirect(url_for('index'))
return render_template("copyright_holder.html",
copyright_holder=ch)

@app.route('/<username>/new')

@app.route('/<username>/new', methods=['GET', 'POST'])
@app.route('/<username>/new/', methods=['GET', 'POST'])
@login_required
def new_collection(username):
return render_template("base.html")
ch = CopyrightHolder.query.filter_by(username=username).first()
if ch is None:
flash("404")
return redirect(url_for('index'))
if current_user.id != ch.id:
flash("hey, that's not yours")
return redirect(url_for('index'))
form = CollectionForm()
if form.validate_on_submit():
slug = slugify(form.name.data)
existing = Collection.query.filter_by(slug=slug).first()
if existing is not None:
flash(f"that name would need the path {username}/{slug}, which is taken")
return redirect(url_for('new_collection',
username=username))
collection = Collection(name=form.name.data,
description=form.description.data,
slug=slug,
copyright_holder_id=current_user.id)

db.session.add(collection)
db.session.commit()

flash(f"{collection.name} created")
return redirect(url_for('collection', username=username, slug=slug))
return render_template('new_collection.html',
title="create new collection",
form=form)


@app.route('/<username>/<slug>')
@app.route('/<username>/<slug>/')
def collection(username, slug):
collection = Collection.query.filter_by(slug=slug).first()
ch = CopyrightHolder.query.filter_by(username=username).first()
collection = ch.collections.filter_by(slug=slug).first()
if collection is None:
return "404"
return render_template("collection.html",
copyright_holder=collection)
copyright_holder=ch,
collection=collection)

@app.route('/<username>/<collection_slug>/<piece_slug>')
@app.route('/<username>/<collection_slug>/<piece_slug>/')
def piece(username, collection_slug, piece_slug):
ch = CopyrightHolder.query.filter_by(username=username).first()
collection = ch.collections.filter_by(slug=collection_slug).first()
piece = collection.pieces.filter_by(slug=piece_slug).first()
return render_template("_piece.html",
copyright_holder=ch,
collection=collection,
piece=piece)


@app.route('/<username>/<slug>/new')
@login_required
@app.route('/<username>/<slug>/new', methods=['GET', 'POST'])
@app.route('/<username>/<slug>/new/', methods=['GET', 'POST'])
def new_piece(username, slug):
return render_template("base.html")
ch = CopyrightHolder.query.filter_by(username=username).first()
if ch is None:
flash("404")
return redirect(url_for('index'))
if current_user.id != ch.id:
flash("hey, that's not yours")
return redirect(url_for('index'))
collection = Collection.query.filter_by(slug=slug).first()
if collection is None:
flash("404")
return redirect(url_for('copyright_holder', username=username))
form = PieceForm()
if form.validate_on_submit():
piece_slug = slugify(form.name.data)
existing = Piece.query.filter_by(slug=slug).first()
if existing is not None:
flash(f"that name would need the path {username}/{slug}/{piece_slug}, which is taken")
return redirect(url_for('new_piece',
username=username,
slug=slug))
file = form.file.data
url = get_url_for(file,
username=username,
collection_slug=slug,
piece_slug=piece_slug)
type = get_type_for(file)
piece = Piece(name=form.name.data,
description=form.description.data,
slug=piece_slug,
collection_id=collection.id,
type=type,
url=url)

db.session.add(piece)
db.session.commit()

flash(f"{piece.name} created")
return redirect(url_for('collection',
username=username,
slug=slug))
return render_template('new_piece.html',
title=f"add to '{collection.name}'",
form=form)
Binary file not shown.
Empty file added app/static/hoohoo
Empty file.
49 changes: 49 additions & 0 deletions app/templates/_piece.html
@@ -0,0 +1,49 @@
<h3>
<a href="/{{piece.collection.copyright_holder.username}}/{{piece.collection.slug}}/{{piece.slug}}">{{piece.name}}</a>
</h3>
{{piece.description}}
<a href="{{piece.url}}" download>download</a>
{% autoescape false %}
{{piece.html}}
{% endautoescape %}

{% if piece.type.startswith("audio/") %}
<audio controls src="{{piece.url}}"></audio>
{% endif %}

{% if piece.type.startswith("image/") %}
<img src="{{piece.url}}">
{% endif %}

{% if piece.type.startswith("video/") %}
<video controls src="{{piece.url}}"></video>
{% endif %}

<p xmlns:dct="http://purl.org/dc/terms/"
xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#">
<a rel="license"
href="https://creativecommons.org/publicdomain/zero/1.0/">
<img src="https://i.creativecommons.org/p/zero/1.0/88x31.png"
style="border-style: none;"
alt="CC0" />
</a>
<br />
To the extent possible under law,
<a rel="dct:publisher"
href="https://cc0.snoot.club">
<span property="dct:title">
{{collection.copyright_holder.legal_name}}
</span>
</a>
has waived all copyright and related or neighboring rights to

<span property="dct:title">
{{piece.name}}
</span>.
This work is published from:
<span property="vcard:Country"
datatype="dct:ISO3166"
content="{{collection.country_code}}"
about="{{collection.country}}">
{{collection.country}}
</span>.
55 changes: 12 additions & 43 deletions app/templates/collection.html
@@ -1,45 +1,14 @@
{% extends "base.html" %}
{% if current_user.is_authenticated and current_user.id == collection.copyright_holder_id %}
<a href="{{url_for('new_piece', username=current_user.username, slug=collection.slug)}}">
new piece
</a>
{% endif %}
{% block nav %}
{% if current_user.is_authenticated and current_user.id == copyright_holder.id %}
<a href="{{url_for('new_piece', username=current_user.username, slug=collection.slug)}}">
new piece
</a>
{% endif %}
{% endblock %}
{% block content %}
<h2>pieces</h2>
{% for item in collection.pieces %}
<h3><a href="{{item.url}}"</a></h3>
{{item.description}}
{% autoescape false %}
{{item.html}}
{% endautoescape %}

<p xmlns:dct="http://purl.org/dc/terms/"
xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#">
<a rel="license"
href="https://creativecommons.org/publicdomain/zero/1.0/">
<img src="https://i.creativecommons.org/p/zero/1.0/88x31.png"
style="border-style: none;"
alt="CC0" />
</a>
<br />
To the extent possible under law,
<a rel="dct:publisher"
href="https://cc0.snoot.club">
<span property="dct:title">
{{collection.copyright_holder}}
</span>
</a>
has waived all copyright and related or neighboring rights to

<span property="dct:title">
{{item.name}}
</span>.
This work is published from:
<span property="vcard:Country"
datatype="dct:ISO3166"
content="{{collection.country_code}}"
about="{{collection.country}}">
{{collection.country}}
</span>.
{% endfor %}
{% endblock %}
<p>{{collection.description}}</p>
{% for piece in collection.pieces %}
{% include '_piece.html' %}
{% endfor %}
{% endblock %}
21 changes: 11 additions & 10 deletions app/templates/copyright_holder.html
@@ -1,21 +1,22 @@
{% extends "base.html" %}
{% block nav %}
{% if current_user.is_authenticated and current_user.id == copyright_holder.id %}
<a href="{{url_for('new_collection', username=copyright_holder.username)}}">
new collection
</a>
{% endif %}
{% if current_user.is_authenticated and current_user.id == copyright_holder.id %}
<a href="{{url_for('new_collection', username=copyright_holder.username)}}">
new collection
</a>
{% endif %}
{% endblock %}
{% block content %}
<h2>collections</h2>
{% for collection in copyright_holder.collections %}
<ul>
<ul>
{% for collection in copyright_holder.collections %}

<li>

<a href="{{url_for('collection', collection)}}">
<a href="{{url_for('collection', username=copyright_holder.username, slug=collection.slug)}}">
{{collection.name}}
</a><span class="collection-description">{{collection.description}}</span>
</li>
</ul>
{% endfor %}
{% endfor %}
</ul>
{% endblock %}
10 changes: 9 additions & 1 deletion app/templates/index.html
Expand Up @@ -4,7 +4,15 @@ <h2>collections</h2>
<ul>
{% for collection in collections %}
<li>
<a href="{{collection.path}}">{{collection.name}}</a>
<span class="collection-holder">
{{collection.copyright_holder.legal_name}}</span>:
<a href="{{url_for('collection', username=collection.copyright_holder.username, slug=collection.slug)}}">
{{collection.name}}
</a>
<span class="collection-description">
<q>{{collection.description}}</q>
</span>
</li>
{% endfor %}
</ul>
Expand Down

0 comments on commit 12da670

Please sign in to comment.