mirror of
https://github.com/jwinterm/tubbymemes.git
synced 2026-10-17 05:21:28 +02:00
setup db models and redoing pages
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
setup:
|
||||
python3 -m venv .venv
|
||||
.venv/bin/pip install -r requirements.txt
|
||||
mkdir -p data/uploads
|
||||
|
||||
shell:
|
||||
bash manage.sh shell
|
||||
|
||||
init:
|
||||
bash manage.sh init
|
||||
|
||||
dev:
|
||||
bash manage.sh run
|
||||
|
||||
@@ -16,10 +20,5 @@ install-ipfs:
|
||||
tar -xvzf go-ipfs_v0.10.0_linux-amd64.tar.gz
|
||||
cd go-ipfs && bash install.sh
|
||||
|
||||
huey:
|
||||
mkdir -p data/
|
||||
.venv/bin/huey_consumer suchwowx.tasks.huey -w 1 -v | tee -a data/huey.log
|
||||
|
||||
kill:
|
||||
pkill -e -f huey
|
||||
pkill -e -f suchwowx
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from flask import Blueprint
|
||||
|
||||
from suchwowx.factory import db
|
||||
|
||||
|
||||
bp = Blueprint('cli', 'cli', cli_group=None)
|
||||
|
||||
@bp.cli.command('init')
|
||||
def init():
|
||||
import suchwowx.models
|
||||
db.create_all()
|
||||
+3
-2
@@ -11,7 +11,7 @@ db = SQLAlchemy()
|
||||
|
||||
|
||||
def setup_db(app: Flask, db:SQLAlchemy=db):
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite://{config.DATA_FOLDER}/sqlite.db' # noqa
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{config.DATA_FOLDER}/sqlite.db' # noqa
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
db.init_app(app)
|
||||
return db
|
||||
@@ -30,7 +30,8 @@ def create_app():
|
||||
Mobility(app)
|
||||
|
||||
with app.app_context():
|
||||
from suchwowx import filters, routes
|
||||
from suchwowx import filters, routes, cli
|
||||
app.register_blueprint(filters.bp)
|
||||
app.register_blueprint(routes.bp)
|
||||
app.register_blueprint(cli.bp)
|
||||
return app
|
||||
|
||||
+14
-3
@@ -1,4 +1,5 @@
|
||||
from uuid import uuid4
|
||||
from datetime import datetime
|
||||
|
||||
from suchwowx.factory import db
|
||||
|
||||
@@ -7,7 +8,17 @@ def rand_id():
|
||||
return uuid4().hex
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
__tablename__ = 'users'
|
||||
class Meme(db.Model):
|
||||
__tablename__ = 'memes'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
id = db.Column(db.String(80), default=rand_id, primary_key=True)
|
||||
create_date = db.Column(db.DateTime, default=datetime.utcnow())
|
||||
upload_path = db.Column(db.String(200), unique=True)
|
||||
meta_ipfs_hash = db.Column(db.String(100), unique=True)
|
||||
meme_ipfs_hash = db.Column(db.String(100), unique=True)
|
||||
title = db.Column(db.String(50))
|
||||
description = db.Column(db.String(400))
|
||||
creator_handle = db.Column(db.String(50))
|
||||
|
||||
def __repr__(self):
|
||||
return str(f'meme-{self.id}')
|
||||
|
||||
+35
-12
@@ -3,13 +3,18 @@ from os import path
|
||||
from secrets import token_urlsafe
|
||||
from json import loads, dumps
|
||||
|
||||
from flask import Blueprint, render_template, request, current_app
|
||||
from flask import Blueprint, render_template, request, current_app, redirect
|
||||
|
||||
from suchwowx.models import Meme
|
||||
from suchwowx.factory import db
|
||||
from suchwowx import config
|
||||
|
||||
|
||||
bp = Blueprint('meta', 'meta')
|
||||
|
||||
@bp.route('/', methods=['GET', 'POST'])
|
||||
def index():
|
||||
@bp.route('/new', methods=['GET', 'POST'])
|
||||
def new():
|
||||
meme = None
|
||||
if "file" in request.files:
|
||||
title = request.form.get('title')
|
||||
description = request.form.get('description')
|
||||
@@ -19,11 +24,15 @@ def index():
|
||||
token_urlsafe(24),
|
||||
path.splitext(file.filename)[1]
|
||||
)
|
||||
file.save(filename)
|
||||
full_path = f'{config.DATA_FOLDER}/uploads/{filename}'
|
||||
file.save(full_path)
|
||||
try:
|
||||
client = ipfsApi.Client('127.0.0.1', 5001)
|
||||
artwork_hash = client.add(filename)['Hash']
|
||||
client.pin_add(artwork_hash)
|
||||
artwork_hashes = client.add(full_path)
|
||||
print(artwork_hashes)
|
||||
artwork_hash = artwork_hashes[0]['Hash']
|
||||
print(artwork_hash)
|
||||
# client.pin_add(artwork_hash)
|
||||
print(f'[+] Uploaded artwork to IPFS: {artwork_hash}')
|
||||
# Create meta json
|
||||
meta = {
|
||||
@@ -35,16 +44,30 @@ def index():
|
||||
'creator': creator
|
||||
}
|
||||
}
|
||||
print(meta)
|
||||
meta_hash = client.add_json(meta)
|
||||
client.pin_add(meta_hash)
|
||||
# client.pin_add(meta_hash)
|
||||
print(f'[+] Uploaded metadata to IPFS: {meta_hash}')
|
||||
meme = Meme(
|
||||
upload_path=filename,
|
||||
meta_ipfs_hash=meta_hash,
|
||||
meme_ipfs_hash=artwork_hash,
|
||||
title=title,
|
||||
description=description,
|
||||
creator_handle=creator
|
||||
)
|
||||
db.session.add(meme)
|
||||
db.session.commit()
|
||||
return redirect('/')
|
||||
except ConnectionError:
|
||||
print('[!] Unable to connect to local ipfs')
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return render_template('index.html')
|
||||
return render_template(
|
||||
'new.html',
|
||||
meme=meme
|
||||
)
|
||||
|
||||
@bp.route('/next')
|
||||
def next():
|
||||
return render_template('next.html')
|
||||
@bp.route('/')
|
||||
def index():
|
||||
memes = Meme.query.filter().order_by(Meme.create_date.desc())
|
||||
return render_template('index.html', memes=memes)
|
||||
|
||||
@@ -13,65 +13,29 @@
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
SuchwowX. <br/>
|
||||
SuchWowX. <br/>
|
||||
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Memes. <strong>Interplanetary</strong>!
|
||||
</p>
|
||||
<a class="button is-primary" href="{{ url_for('meta.new') }}" up-target=".container">New Meme</a>
|
||||
|
||||
<!-- <a href="/next" class="one" up-target=".one">
|
||||
Flip
|
||||
</a>
|
||||
|
||||
<a href="/next" class="two" up-target=".two">
|
||||
Flip
|
||||
</a> -->
|
||||
|
||||
<form method="POST" enctype="multipart/form-data" class="site-form" id="memeUpload">
|
||||
<div class="field">
|
||||
<label class="label">File</label>
|
||||
<div class="control">
|
||||
<input class="filestyle" id="file" name="file" required type="file">
|
||||
{% if memes %}
|
||||
<div id="memes">
|
||||
{% for meme in memes %}
|
||||
<div class="meme" style="padding-top:1em;">
|
||||
<p>Meme: {{ meme }}</p>
|
||||
<p>Upload path: {{ meme.upload_path }}</p>
|
||||
<p>Meta IPFS: {{ meme.meta_ipfs_hash }}</p>
|
||||
<p>Meme IPFS: {{ meme.meme_ipfs_hash }}</p>
|
||||
<p>Title: {{ meme.title }}</p>
|
||||
<p>Description: {{ meme.description }}</p>
|
||||
<p>Creator handle: {{ meme.creator_handle }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Title</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="Title of your meme" name="title">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Creator</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="Your handle" name="creator">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Description</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea" placeholder="Description..." name="description"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox">
|
||||
I agree to support the ongoing funding of exploratory meme missions
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-primary">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>SuchWowX!</title>
|
||||
<script src="https://unpkg.com/unpoly@2.5.0/unpoly.min.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/unpoly@2.5.0/unpoly.min.css">
|
||||
<link rel="stylesheet" href="/static/css/bulma.min.css">
|
||||
<link rel="stylesheet" href="/static/css/bulma.css.map">
|
||||
</head>
|
||||
<body>
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
SuchWowX. <br/>
|
||||
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Memes. <strong>Interplanetary</strong>!
|
||||
</p>
|
||||
<a class="button" href="{{ url_for('meta.index') }}" up-target=".container">Go Back</a>
|
||||
|
||||
<form method="POST" enctype="multipart/form-data" class="site-form" id="memeUpload" action="{{ url_for('meta.new') }}">
|
||||
<div class="field">
|
||||
<label class="label">File</label>
|
||||
<div class="control">
|
||||
<input class="filestyle" id="file" name="file" required type="file">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Title</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="Title of your meme" name="title">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Creator</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="Your handle" name="creator">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Description</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea" placeholder="Description..." name="description"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox">
|
||||
I agree to support the ongoing funding of exploratory meme missions
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-primary" up-target=".container">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user