mirror of
https://github.com/jwinterm/tubbymemes.git
synced 2026-10-17 05:21:28 +02:00
reskinning for tubbycats
This commit is contained in:
@@ -7,6 +7,7 @@ shell:
|
||||
bash manage.sh shell
|
||||
|
||||
init:
|
||||
mkdir -p data
|
||||
.venv/bin/alembic upgrade head
|
||||
|
||||
dev:
|
||||
@@ -40,4 +41,4 @@ sync-remotes:
|
||||
./manage.sh sync-remotes
|
||||
|
||||
kill:
|
||||
pkill -e -f suchwowx
|
||||
pkill -e -f tubbymemes
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# SuchWowX
|
||||
# tubbymemes
|
||||
|
||||
This service is a continuation of SuchWow for the Wownero cryptocurrency project. It has been revamped to use Interplanetary Filesystem, server federation / content sharing, and optionally Avalanche network via a smart contract with some useful features (if you're into that). It's a decentralized application (dApp); it's preferred you run it locally and bootstrap the services on your own machine.
|
||||
Meme site dedicated to the best project on the Etherium network ;)
|
||||
|
||||
https://tubbycats.xyz/about
|
||||
|
||||
Memes are backed by Interplanetary Filesystem, server federation / content sharing, and optionally Avalanche network via a smart contract with some useful features (if you're into that). It's a decentralized application (dApp); it's preferred you run it locally and bootstrap the services on your own machine.
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -18,6 +22,9 @@ I have provided a `Makefile` with some helpful stuff...make sure to install `mak
|
||||
# install python virtual environment and install application dependencies
|
||||
make setup
|
||||
|
||||
# setup secrets
|
||||
cp env-example .env && vim .env
|
||||
|
||||
# install ipfs
|
||||
sudo make install-ipfs
|
||||
|
||||
@@ -64,7 +71,7 @@ openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
|
||||
cp conf/nginx-ssl.conf /etc/nginx/conf.d/ssl.conf
|
||||
|
||||
# setup nginx site config from this repo
|
||||
cp conf/nginx-site.conf /etc/nginx/sites-enabled/suchwowx.conf
|
||||
cp conf/nginx-site.conf /etc/nginx/sites-enabled/tubbymemes.conf
|
||||
|
||||
# generate TLS certificates
|
||||
service nginx stop
|
||||
@@ -82,24 +89,24 @@ systemctl daemon-reload
|
||||
systemctl enable ipfs
|
||||
systemctl start ipfs
|
||||
|
||||
# setup suchwowx service account and storage location
|
||||
useradd -m suchwowx
|
||||
mkdir -p /opt/suchwowx
|
||||
# setup tubbymemes service account and storage location
|
||||
useradd -m tubbymemes
|
||||
mkdir -p /opt/tubbymemes
|
||||
|
||||
# setup suchwowx application
|
||||
git clone https://github.com/lalanza808/suchwowx /opt/suchwowx
|
||||
cp /opt/suchwowx/env-example /opt/suchwowx/.env
|
||||
vim /opt/suchwowx/.env
|
||||
chown -R suchwowx:suchwowx /opt/suchwowx
|
||||
# setup tubbymemes application
|
||||
git clone https://github.com/lalanza808/tubbymemes /opt/tubbymemes
|
||||
cp /opt/tubbymemes/env-example /opt/tubbymemes/.env
|
||||
vim /opt/tubbymemes/.env
|
||||
chown -R tubbymemes:tubbymemes /opt/tubbymemes
|
||||
|
||||
# setup suchwowx service daemon
|
||||
cp conf/suchwowx.service /etc/systemd/system/suchwowx.service
|
||||
# setup tubbymemes service daemon
|
||||
cp conf/tubbymemes.service /etc/systemd/system/tubbymemes.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable suchwowx
|
||||
systemctl start suchwowx
|
||||
systemctl enable tubbymemes
|
||||
systemctl start tubbymemes
|
||||
|
||||
# setup ongoing syncing with remote servers and Avalanche network
|
||||
crontab -u suchwowx conf/crontab
|
||||
crontab -u tubbymemes conf/crontab
|
||||
```
|
||||
|
||||
At this point you should have Nginx web server running with TLS certificates generated with Letsencrypt/Certbot, Systemd services for IPFS daemon for serving files and Gunicorn for serving the Flask application.
|
||||
|
||||
+4
-4
@@ -4,9 +4,9 @@ from sqlalchemy import engine_from_config
|
||||
from sqlalchemy import pool
|
||||
from alembic import context
|
||||
|
||||
from suchwowx.factory import db
|
||||
from suchwowx.models import *
|
||||
from suchwowx import config as swx_config
|
||||
from tubbymemes.factory import db
|
||||
from tubbymemes.models import *
|
||||
from tubbymemes import config as c
|
||||
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
@@ -15,7 +15,7 @@ config = context.config
|
||||
|
||||
# this will overwrite the ini-file sqlalchemy.url path
|
||||
# with secrets from our .env file (pulled via config.py)
|
||||
sqlalchemy_url = f'sqlite:///{swx_config.DATA_FOLDER}/sqlite.db'
|
||||
sqlalchemy_url = f'sqlite:///{c.DATA_FOLDER}/sqlite.db'
|
||||
config.set_main_option('sqlalchemy.url', sqlalchemy_url)
|
||||
|
||||
# Interpret the config file for Python logging.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
"""init suchwowx
|
||||
"""init tubbymemes
|
||||
|
||||
Revision ID: 53c117fcef3f
|
||||
Revises:
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
# Sync with remote servers specified by operator
|
||||
0 * * * * sh -c "cd /opt/suchwowx; ./manage.sh sync-remotes"
|
||||
0 * * * * sh -c "cd /opt/tubbymemes; ./manage.sh sync-remotes"
|
||||
|
||||
# Sync with Avalanche blockchain to import minted memes
|
||||
30 * * * * sh -c "cd /opt/suchwowx; ./manage.sh sync-avax"
|
||||
30 * * * * sh -c "cd /opt/tubbymemes; ./manage.sh sync-avax"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Redirect inbound http to https
|
||||
server {
|
||||
listen 80;
|
||||
server_name suchwowx.xyz;
|
||||
return 301 https://suchwowx.xyz$request_uri;
|
||||
server_name tubbymemes.xyz;
|
||||
return 301 https://tubbymemes.xyz$request_uri;
|
||||
}
|
||||
|
||||
# Load SSL configs and serve SSL site
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name suchwowx.xyz;
|
||||
error_log /var/log/nginx/suchwowx.xyz-error.log warn;
|
||||
access_log /var/log/nginx/suchwowx.xyz-access.log;
|
||||
server_name tubbymemes.xyz;
|
||||
error_log /var/log/nginx/tubbymemes.xyz-error.log warn;
|
||||
access_log /var/log/nginx/tubbymemes.xyz-access.log;
|
||||
client_body_in_file_only clean;
|
||||
client_body_buffer_size 32K;
|
||||
# set max upload size
|
||||
@@ -39,6 +39,6 @@ server {
|
||||
}
|
||||
|
||||
include conf.d/ssl.conf;
|
||||
ssl_certificate /etc/letsencrypt/live/suchwowx.xyz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/suchwowx.xyz/privkey.pem;
|
||||
ssl_certificate /etc/letsencrypt/live/tubbymemes.xyz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/tubbymemes.xyz/privkey.pem;
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,24 +1,24 @@
|
||||
[Unit]
|
||||
Description=SuchWowX meme service
|
||||
Documentation=https://suchwowx.xyz
|
||||
Description=tubbymemes meme service
|
||||
Documentation=https://tubbymemes.xyz
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
PermissionsStartOnly = true
|
||||
PIDFile = /opt/suchwowx/data/gunicorn/suchwowx.pid
|
||||
User = suchwowx
|
||||
Group = suchwowx
|
||||
WorkingDirectory = /opt/suchwowx
|
||||
ExecStartPre = /bin/mkdir -p /opt/suchwowx/data/gunicorn
|
||||
ExecStartPre = /bin/chown -R suchwowx:suchwowx /opt/suchwowx/data/gunicorn
|
||||
Environment = FLASK_APP=suchwowx/app.py
|
||||
PIDFile = /opt/tubbymemes/data/gunicorn/tubbymemes.pid
|
||||
User = tubbymemes
|
||||
Group = tubbymemes
|
||||
WorkingDirectory = /opt/tubbymemes
|
||||
ExecStartPre = /bin/mkdir -p /opt/tubbymemes/data/gunicorn
|
||||
ExecStartPre = /bin/chown -R tubbymemes:tubbymemes /opt/tubbymemes/data/gunicorn
|
||||
Environment = FLASK_APP=tubbymemes/app.py
|
||||
Environment = FLASK_SECRETS=config.py
|
||||
Environment = FLASK_ENV=production
|
||||
Environment = FLASK_DEBUG=0
|
||||
ExecStart = /opt/suchwowx/.venv/bin/gunicorn --bind 127.0.0.1:4000 "suchwowx.app:app" --log-file /opt/suchwowx/data/gunicorn/gunicorn.log --pid /opt/suchwowx/data/gunicorn/suchwowx.pid --reload
|
||||
ExecReload = /bin/kill -s HUP /opt/suchwowx/data/gunicorn/suchwowx.pid
|
||||
ExecStop = /bin/kill -s TERM /opt/suchwowx/data/gunicorn/suchwowx.pid
|
||||
ExecStopPost = /bin/rm -rf /opt/suchwowx/data/gunicorn/suchwowx.pid
|
||||
ExecStart = /opt/tubbymemes/.venv/bin/gunicorn --bind 127.0.0.1:4000 "tubbymemes.app:app" --log-file /opt/tubbymemes/data/gunicorn/gunicorn.log --pid /opt/tubbymemes/data/gunicorn/tubbymemes.pid --reload
|
||||
ExecReload = /bin/kill -s HUP /opt/tubbymemes/data/gunicorn/tubbymemes.pid
|
||||
ExecStop = /bin/kill -s TERM /opt/tubbymemes/data/gunicorn/tubbymemes.pid
|
||||
ExecStopPost = /bin/rm -rf /opt/tubbymemes/data/gunicorn/tubbymemes.pid
|
||||
PrivateTmp = true
|
||||
|
||||
[Install]
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Production env - delete this line and unused config
|
||||
SECRET_KEY=vrBWMR2$nCdPuZ27
|
||||
DATA_FOLDER=/opt/suchwowx/data
|
||||
DATA_FOLDER=/opt/tubbymemes/data
|
||||
SERVER_NAME=myservername.com
|
||||
AVAX_RPC=https://api.avax.network/ext/bc/C/rpc
|
||||
TESTNET=0
|
||||
@@ -8,5 +8,5 @@ WEB3_PROVIDER_URI=https://api.avax.network/ext/bc/C/rpc
|
||||
|
||||
# Test env - delete this line and unused config
|
||||
SECRET_KEY=vrBWMR2$nCdPuZ27
|
||||
DATA_FOLDER=/opt/suchwowx/data
|
||||
DATA_FOLDER=/opt/tubbymemes/data
|
||||
WEB3_PROVIDER_URI=https://api.avax-test.network/ext/bc/C/rpc
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
source .venv/bin/activate
|
||||
export FLASK_APP=suchwowx/app.py
|
||||
export FLASK_APP=tubbymemes/app.py
|
||||
export FLASK_SECRETS=config.py
|
||||
export FLASK_DEBUG=1
|
||||
export FLASK_ENV=development
|
||||
@@ -18,7 +18,7 @@ then
|
||||
pgrep -F $BASE/gunicorn.pid
|
||||
if [[ $? != 0 ]]; then
|
||||
gunicorn \
|
||||
--bind 127.0.0.1:4000 "suchwowx.app:app" \
|
||||
--bind 127.0.0.1:4000 "tubbymemes.app:app" \
|
||||
--daemon \
|
||||
--log-file $BASE/gunicorn.log \
|
||||
--pid $BASE/gunicorn.pid \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from logging.config import dictConfig
|
||||
|
||||
from suchwowx.factory import create_app
|
||||
from suchwowx import config
|
||||
from tubbymemes.factory import create_app
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
app = create_app()
|
||||
@@ -3,10 +3,10 @@ from flask import Blueprint
|
||||
from secrets import token_urlsafe
|
||||
from datetime import datetime
|
||||
|
||||
from suchwowx.factory import db
|
||||
from suchwowx.helpers import get_eth_contract
|
||||
from suchwowx.models import Meme, User, Remote
|
||||
from suchwowx import config
|
||||
from tubbymemes.factory import db
|
||||
from tubbymemes.helpers import get_eth_contract
|
||||
from tubbymemes.models import Meme, User, Remote
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
bp = Blueprint('cli', 'cli', cli_group=None)
|
||||
@@ -1,8 +1,8 @@
|
||||
import click
|
||||
from flask import Blueprint
|
||||
|
||||
from suchwowx.models import Moderator, User
|
||||
from suchwowx.factory import db
|
||||
from tubbymemes.models import Moderator, User
|
||||
from tubbymemes.factory import db
|
||||
|
||||
|
||||
bp = Blueprint('mod', 'mod')
|
||||
@@ -6,7 +6,7 @@ from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_mobility import Mobility
|
||||
from web3 import Web3
|
||||
|
||||
from suchwowx import config
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
db = SQLAlchemy()
|
||||
@@ -39,14 +39,14 @@ def create_app():
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
from suchwowx.models import User
|
||||
from tubbymemes.models import User
|
||||
user = User.query.get(user_id)
|
||||
return user
|
||||
|
||||
with app.app_context():
|
||||
from suchwowx import filters
|
||||
from suchwowx.routes import api, meme, meta, user
|
||||
from suchwowx.cli import mod, cli
|
||||
from tubbymemes import filters
|
||||
from tubbymemes.routes import api, meme, meta, user
|
||||
from tubbymemes.cli import mod, cli
|
||||
app.register_blueprint(filters.bp)
|
||||
app.register_blueprint(api.bp)
|
||||
app.register_blueprint(meme.bp)
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import Blueprint
|
||||
from arrow import get as arrow_get
|
||||
|
||||
from suchwowx import config
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
bp = Blueprint('filters', 'filters')
|
||||
@@ -1,15 +1,15 @@
|
||||
import ipfsApi
|
||||
from eth_account.messages import encode_defunct
|
||||
|
||||
from suchwowx.models import Meme
|
||||
from suchwowx.factory import w3
|
||||
from suchwowx import config
|
||||
from tubbymemes.models import Meme
|
||||
from tubbymemes.factory import w3
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
def get_eth_contract():
|
||||
"""
|
||||
Return a web3 contract object with the currently
|
||||
deployed SuchWowX smart contract.
|
||||
deployed tubbymemes smart contract.
|
||||
"""
|
||||
contract_abi = config.CONTRACT_ABI
|
||||
contract_address = w3.toChecksumAddress(config.CONTRACT_ADDRESS)
|
||||
@@ -5,8 +5,8 @@ from flask import url_for
|
||||
from flask_login import login_user
|
||||
from sqlalchemy import inspect
|
||||
|
||||
from suchwowx.factory import db
|
||||
from suchwowx import config
|
||||
from tubbymemes.factory import db
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
def rand_id():
|
||||
@@ -3,9 +3,9 @@ from secrets import token_urlsafe
|
||||
from flask import Blueprint, request, jsonify
|
||||
from flask_login import current_user
|
||||
|
||||
from suchwowx.factory import db
|
||||
from suchwowx.helpers import verify_signature
|
||||
from suchwowx.models import User, Meme
|
||||
from tubbymemes.factory import db
|
||||
from tubbymemes.helpers import verify_signature
|
||||
from tubbymemes.models import User, Meme
|
||||
|
||||
|
||||
bp = Blueprint('api', 'api', url_prefix='/api/v1')
|
||||
@@ -7,10 +7,10 @@ from flask import redirect, flash, url_for
|
||||
from flask_login import current_user
|
||||
from web3 import Web3
|
||||
|
||||
from suchwowx.models import Meme
|
||||
from suchwowx.helpers import upload_to_ipfs
|
||||
from suchwowx.factory import db
|
||||
from suchwowx import config
|
||||
from tubbymemes.models import Meme
|
||||
from tubbymemes.helpers import upload_to_ipfs
|
||||
from tubbymemes.factory import db
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
bp = Blueprint('meme', 'meme')
|
||||
@@ -2,9 +2,9 @@ from flask import Blueprint, render_template, send_from_directory
|
||||
from flask import redirect, url_for, flash, request
|
||||
from flask_login import logout_user, current_user
|
||||
|
||||
from suchwowx.models import User, Remote
|
||||
from suchwowx.factory import db
|
||||
from suchwowx import config
|
||||
from tubbymemes.models import User, Remote
|
||||
from tubbymemes.factory import db
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
bp = Blueprint('meta', 'meta')
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import Blueprint, render_template
|
||||
from flask import redirect, url_for
|
||||
|
||||
from suchwowx.models import User
|
||||
from tubbymemes.models import User
|
||||
|
||||
|
||||
bp = Blueprint('user', 'user')
|
||||
Vendored
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Vendored
Vendored
Vendored
@@ -1,7 +1,7 @@
|
||||
from huey import RedisHuey
|
||||
|
||||
from suchwowx.factory import create_app_huey
|
||||
from suchwowx import config
|
||||
from tubbymemes.factory import create_app_huey
|
||||
from tubbymemes import config
|
||||
|
||||
|
||||
huey = RedisHuey(
|
||||
@@ -12,7 +12,7 @@
|
||||
Welcome. </br>
|
||||
</br>
|
||||
This service is a continuation of <a href="https://suchwow.xyz">SuchWow</a> for the <a href="https://wownero.org">Wownero</a> cryptocurrency project.
|
||||
It has been revamped to use <a href="https://ipfs.io">Interplanetary Filesystem</a>, server federation / content sharing, and optionally <a href="https://www.avax.network/">Avalanche network</a> via a smart contract with some useful features (if you're into memes). It's a decentralized application (dApp); it's preferred you run it locally and bootstrap the services on your own machine. Here's the source code and instructions to run: <a href="https://github.com/lalanza808/suchwowx/" target="_blank">SuchWowX</a>
|
||||
It has been revamped to use <a href="https://ipfs.io">Interplanetary Filesystem</a>, server federation / content sharing, and optionally <a href="https://www.avax.network/">Avalanche network</a> via a smart contract with some useful features (if you're into memes). It's a decentralized application (dApp); it's preferred you run it locally and bootstrap the services on your own machine. Here's the source code and instructions to run: <a href="https://github.com/lalanza808/tubbymemes/" target="_blank">tubbymemes</a>
|
||||
</p>
|
||||
</br>
|
||||
<p>
|
||||
@@ -1,15 +1,15 @@
|
||||
<head>
|
||||
<title>SuchWowX Interplanetary Memes</title>
|
||||
<title>tubbymemes Interplanetary Memes</title>
|
||||
<meta property="og:description" content="Interplanetary meme platform powered by IPFS, Wownero, Avalanche, and degeneracy.">
|
||||
<meta property="og:image" content="https://suchwowx.xyz/static/img/logo.png">
|
||||
<meta property="og:title" content="SuchWowX">
|
||||
<meta property="og:image" content="https://tubbymemes.xyz/static/img/logo.png">
|
||||
<meta property="og:title" content="tubbymemes">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@lza_menace">
|
||||
<meta name="twitter:title" content="SuchWowX">
|
||||
<meta name="twitter:title" content="tubbymemes">
|
||||
<meta name="twitter:description" content="Interplanetary meme platform powered by IPFS, Wownero, Avalanche, and degeneracy.">
|
||||
<meta name="twitter:creator" content="@lza_menace">
|
||||
<meta name="twitter:image" content="https://suchwowx.xyz/static/img/logo.png">
|
||||
<meta name="twitter:domain" content="https://suchwowx.xyz">
|
||||
<meta name="twitter:image" content="https://tubbymemes.xyz/static/img/logo.png">
|
||||
<meta name="twitter:domain" content="https://tubbymemes.xyz">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="/static/js/vendor/unpoly-2.5.0.min.js"></script>
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="screen">
|
||||
<h1 class="title">
|
||||
SuchWowX.
|
||||
tubbymemes.
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Memes. <strong>Interplanetary</strong>!
|
||||
@@ -80,7 +80,7 @@
|
||||
nonce = data['nonce'];
|
||||
})
|
||||
|
||||
const msg = 'Authentication request from SuchWowX app! Verifying message with nonce ' + nonce
|
||||
const msg = 'Authentication request from tubbymemes app! Verifying message with nonce ' + nonce
|
||||
const signedData = await window.ethereum.request({
|
||||
method: 'personal_sign',
|
||||
params: [msg, allAccounts[0]]
|
||||
@@ -122,7 +122,7 @@
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<p>
|
||||
Sending a tip via the <a href="{{ config.CONTRACT_ADDRESS | show_snowtrace }}" target="_blank">SuchWowX smart contract</a> will send a small amount to the
|
||||
Sending a tip via the <a href="{{ config.CONTRACT_ADDRESS | show_snowtrace }}" target="_blank">tubbymemes smart contract</a> will send a small amount to the
|
||||
publisher (the address that minted the meme) and the contract owner ({{ config.CONTRACT_OWNER }}), and the remainder is sent to the meme creator (whoever uploaded it). Everyone gets tipped for their contribution, but primarily the meme creator.
|
||||
</p>
|
||||
</br>
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="field">
|
||||
<label class="label">Remote Server</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="https://suchwowx.xyz" name="endpoint">
|
||||
<input class="input" type="text" placeholder="https://tubbymemes.xyz" name="endpoint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-grouped">
|
||||
Reference in New Issue
Block a user