feat: Add initial tribes
This commit is contained in:
parent
5d70dc862d
commit
cd43dd3dc6
136
db.py
136
db.py
@ -14,9 +14,6 @@ dbargs = {
|
|||||||
'database':os.getenv('DB_NAME')
|
'database':os.getenv('DB_NAME')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_tables():
|
def check_tables():
|
||||||
connection = mysql.connector.connect(**dbargs)
|
connection = mysql.connector.connect(**dbargs)
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
@ -38,6 +35,15 @@ def check_tables():
|
|||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS tribes (
|
||||||
|
id INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
tribe VARCHAR(255) NOT NULL,
|
||||||
|
data JSON,
|
||||||
|
owner VARCHAR(255) NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
print("Checked tables")
|
print("Checked tables")
|
||||||
@ -221,3 +227,127 @@ def get_random_sites():
|
|||||||
names.append(site[1])
|
names.append(site[1])
|
||||||
|
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
def get_tribes():
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM tribes
|
||||||
|
""")
|
||||||
|
data = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
tribes = []
|
||||||
|
for tribe in data:
|
||||||
|
tribes.append(tribe[1])
|
||||||
|
|
||||||
|
return tribes
|
||||||
|
|
||||||
|
def get_user_tribes(user):
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM tribes WHERE owner = %s
|
||||||
|
""", (user,))
|
||||||
|
data = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# Also check members
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM tribes
|
||||||
|
""")
|
||||||
|
data2 = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
|
||||||
|
for tribe in data2:
|
||||||
|
tribe = json.loads(tribe[2])
|
||||||
|
if user in tribe['members']:
|
||||||
|
data.append(tribe)
|
||||||
|
|
||||||
|
|
||||||
|
return len(data)
|
||||||
|
|
||||||
|
def get_user_owned_tribe(user):
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM tribes WHERE owner = %s
|
||||||
|
""", (user,))
|
||||||
|
data = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create_tribe(tribe,owner):
|
||||||
|
# Get users' tribes
|
||||||
|
if (get_user_tribes(owner) > 0):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
data = {
|
||||||
|
"data": "",
|
||||||
|
"members": [
|
||||||
|
owner
|
||||||
|
]
|
||||||
|
}
|
||||||
|
insert_query = "INSERT INTO tribes (data,tribe,owner) VALUES (%s,%s,%s)"
|
||||||
|
cursor.execute(insert_query, (json.dumps(data), tribe, owner))
|
||||||
|
connection.commit()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_tribe_data_raw(tribe):
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM tribes WHERE tribe = %s
|
||||||
|
""", (tribe,))
|
||||||
|
data = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
if len(data) == 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return json.loads(data[0][2])
|
||||||
|
|
||||||
|
def check_tribe_owner(tribe,owner):
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM tribes WHERE tribe = %s
|
||||||
|
""", (tribe,))
|
||||||
|
data = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
if len(data) == 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if data[0][3] == owner:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def update_tribe_data_raw(tribe,data):
|
||||||
|
connection = mysql.connector.connect(**dbargs)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
# Update json object
|
||||||
|
data = json.loads(data)
|
||||||
|
|
||||||
|
update_query = "UPDATE tribes SET data = %s WHERE tribe = %s"
|
||||||
|
cursor.execute(update_query, (json.dumps(data), tribe))
|
||||||
|
|
||||||
|
connection.commit()
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
256
main.py
256
main.py
@ -65,7 +65,10 @@ def index():
|
|||||||
for site in random_sites_names:
|
for site in random_sites_names:
|
||||||
random_sites += "<a href='https://" + site + "." + CITY_DOMAIN + "' target='_blank'>" + site + "." +CITY_DOMAIN+ "</a><br>"
|
random_sites += "<a href='https://" + site + "." + CITY_DOMAIN + "' target='_blank'>" + site + "." +CITY_DOMAIN+ "</a><br>"
|
||||||
|
|
||||||
|
tribes = db.get_tribes()
|
||||||
|
tribesHTML = ""
|
||||||
|
for tribe in tribes:
|
||||||
|
tribesHTML += "<a href='/tribe/" + tribe + "'>" + tribe + "</a><br>"
|
||||||
|
|
||||||
|
|
||||||
if 'token' in request.cookies:
|
if 'token' in request.cookies:
|
||||||
@ -77,8 +80,8 @@ def index():
|
|||||||
resp = make_response(redirect('/'))
|
resp = make_response(redirect('/'))
|
||||||
resp.set_cookie('token', '', expires=0)
|
resp.set_cookie('token', '', expires=0)
|
||||||
return resp
|
return resp
|
||||||
return render_template('index.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,random_sites=random_sites)
|
return render_template('index.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,random_sites=random_sites,tribes=tribesHTML)
|
||||||
return render_template('index.html',account="Login",account_link="login",account_link_name="Login",CITY_DOMAIN=CITY_DOMAIN,random_sites=random_sites)
|
return render_template('index.html',account="Login",account_link="login",account_link_name="Login",CITY_DOMAIN=CITY_DOMAIN,random_sites=random_sites,tribes=tribesHTML)
|
||||||
|
|
||||||
@app.route('/signup', methods=['POST'])
|
@app.route('/signup', methods=['POST'])
|
||||||
def signup():
|
def signup():
|
||||||
@ -329,6 +332,232 @@ def avatar_clear():
|
|||||||
return redirect('/edit')
|
return redirect('/edit')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/tribe')
|
||||||
|
def tribe_list():
|
||||||
|
tribes = db.get_tribes()
|
||||||
|
tribesHTML = ""
|
||||||
|
for tribe in tribes:
|
||||||
|
tribesHTML += "<a href='/tribe/" + tribe + "'>" + tribe + "</a><br>"
|
||||||
|
|
||||||
|
# Add create link if user is logged in
|
||||||
|
if 'token' in request.cookies:
|
||||||
|
token = request.cookies['token']
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if user:
|
||||||
|
tribesHTML += "<br><br><a class='btn btn-primary' role='button' style='width: 100%;' href='/new_tribe'>Create a tribe</a>"
|
||||||
|
return render_template('tribe.html',account="Account",account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,tribes=tribesHTML)
|
||||||
|
|
||||||
|
return render_template('tribe.html',account="Login",account_link="login",account_link_name="Login",CITY_DOMAIN=CITY_DOMAIN,tribes=tribesHTML)
|
||||||
|
|
||||||
|
@app.route('/new_tribe')
|
||||||
|
def new_tribe():
|
||||||
|
if 'token' not in request.cookies:
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
|
token = request.cookies['token']
|
||||||
|
if not accounts.validate_token(token):
|
||||||
|
return error('Sorry we had an issue verifying your account')
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if not user:
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/login'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
return render_template('new_tribe.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN)
|
||||||
|
|
||||||
|
@app.route('/new_tribe', methods=['POST'])
|
||||||
|
def create_tribe():
|
||||||
|
token = request.cookies['token']
|
||||||
|
if not accounts.validate_token(token):
|
||||||
|
return error('Sorry we had an issue verifying your account')
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if not user:
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/login'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
tribe = request.form['tribe'].strip().lower()
|
||||||
|
if not re.match("^[a-z0-9]*$", tribe):
|
||||||
|
return error('Sorry tribe can only contain lowercase letters and numbers')
|
||||||
|
|
||||||
|
if len(tribe) < 3:
|
||||||
|
return error('Sorry tribe must be at least 3 characters long')
|
||||||
|
if len(tribe) > 255:
|
||||||
|
return error('Sorry tribe must be less than 255 characters long')
|
||||||
|
|
||||||
|
if db.create_tribe(tribe,user['domain']):
|
||||||
|
return redirect('/tribe/' + tribe)
|
||||||
|
else:
|
||||||
|
return error('Sorry you already have a tribe')
|
||||||
|
|
||||||
|
@app.route('/tribe/<tribe>')
|
||||||
|
def tribe(tribe):
|
||||||
|
tribe = tribe.lower()
|
||||||
|
if not re.match("^[a-z0-9]*$", tribe):
|
||||||
|
return error('Sorry we couldn\'t find that tribe')
|
||||||
|
|
||||||
|
data = db.get_tribe_data_raw(tribe)
|
||||||
|
if data == None:
|
||||||
|
return error('Sorry we couldn\'t find that tribe')
|
||||||
|
|
||||||
|
html = ""
|
||||||
|
if 'data' in data:
|
||||||
|
html = data['data'].encode('utf-8').decode('unicode-escape')
|
||||||
|
html = html.replace("\n","<br>")
|
||||||
|
|
||||||
|
tribe = tribe.capitalize()
|
||||||
|
|
||||||
|
members_html = ""
|
||||||
|
members = data['members']
|
||||||
|
for member in members:
|
||||||
|
members_html += "<a href='https://" + member + "." + CITY_DOMAIN + "' target='_blank'>" + member + "." +CITY_DOMAIN+ "</a><br>"
|
||||||
|
|
||||||
|
edit = ""
|
||||||
|
|
||||||
|
# Add edit link if user is logged in
|
||||||
|
if 'token' in request.cookies:
|
||||||
|
token = request.cookies['token']
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if user:
|
||||||
|
if db.check_tribe_owner(tribe,user['domain']):
|
||||||
|
edit = "<a class='btn btn-primary' role='button' style='width: 100%;' href='/edit_tribe'>Edit tribe</a>"
|
||||||
|
elif user['domain'] not in members:
|
||||||
|
edit = "<a class='btn btn-primary' role='button' style='width: 100%;' href='/join_tribe/" + tribe + "'>Join tribe</a>"
|
||||||
|
|
||||||
|
return render_template('tribe_view.html',tribe=tribe,data=html,edit=edit,members=members_html)
|
||||||
|
|
||||||
|
@app.route('/join_tribe/<tribe>')
|
||||||
|
def join_tribe(tribe):
|
||||||
|
tribe = tribe.lower()
|
||||||
|
if not re.match("^[a-z0-9]*$", tribe):
|
||||||
|
return error('Sorry we couldn\'t find that tribe')
|
||||||
|
|
||||||
|
data = db.get_tribe_data_raw(tribe)
|
||||||
|
if data == None:
|
||||||
|
return error('Sorry we couldn\'t find that tribe')
|
||||||
|
|
||||||
|
# Verify token
|
||||||
|
token = request.cookies['token']
|
||||||
|
if not accounts.validate_token(token):
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/login'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if not user:
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/login'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
members = data['members']
|
||||||
|
if user['domain'] in members:
|
||||||
|
return error('Sorry you are already a member of this tribe')
|
||||||
|
|
||||||
|
members.append(user['domain'])
|
||||||
|
data['members'] = members
|
||||||
|
# Convert to json
|
||||||
|
data = json.dumps(data)
|
||||||
|
db.update_tribe_data_raw(tribe,data)
|
||||||
|
return redirect('/tribe/' + tribe)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/edit_tribe')
|
||||||
|
def edit_tribe_view():
|
||||||
|
token = request.cookies['token']
|
||||||
|
if not accounts.validate_token(token):
|
||||||
|
return error('Sorry we had an issue verifying your account')
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if not user:
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
tribeData = db.get_user_owned_tribe(user['domain'])
|
||||||
|
if len(tribeData) == 0:
|
||||||
|
return error('Sorry you don\'t own a tribe')
|
||||||
|
|
||||||
|
tribe = tribeData[0][1]
|
||||||
|
data = tribeData[0][2]
|
||||||
|
data = json.loads(data)
|
||||||
|
html = data['data'].encode('utf-8').decode('unicode-escape')
|
||||||
|
members = data['members']
|
||||||
|
members_html = ""
|
||||||
|
for member in members:
|
||||||
|
members_html += "<a href='https://" + member + "." + CITY_DOMAIN + "' target='_blank'>" + member + "." +CITY_DOMAIN+ "</a> <a href='/remove_member?member=" + member + "'>(Remove)</a><br>"
|
||||||
|
|
||||||
|
return render_template('edit_tribe.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,tribe=tribe,data=html,members=members_html)
|
||||||
|
|
||||||
|
@app.route('/edit_tribe', methods=['POST'])
|
||||||
|
def edit_tribe():
|
||||||
|
token = request.cookies['token']
|
||||||
|
if not accounts.validate_token(token):
|
||||||
|
return error('Sorry we had an issue verifying your account')
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if not user:
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
tribeData = db.get_user_owned_tribe(user['domain'])
|
||||||
|
if len(tribeData) == 0:
|
||||||
|
return error('Sorry you don\'t own a tribe')
|
||||||
|
|
||||||
|
tribe = tribeData[0][1]
|
||||||
|
data = tribeData[0][2]
|
||||||
|
data = json.loads(data)
|
||||||
|
data['data'] = request.form['data'].strip()
|
||||||
|
|
||||||
|
# Convert to json
|
||||||
|
data = json.dumps(data)
|
||||||
|
db.update_tribe_data_raw(tribe,data)
|
||||||
|
return redirect('/edit_tribe')
|
||||||
|
|
||||||
|
@app.route('/remove_member')
|
||||||
|
def remove_member():
|
||||||
|
token = request.cookies['token']
|
||||||
|
if not accounts.validate_token(token):
|
||||||
|
return error('Sorry we had an issue verifying your account')
|
||||||
|
|
||||||
|
member = request.args.get('member')
|
||||||
|
# Verify token
|
||||||
|
user = accounts.validate_token(token)
|
||||||
|
if not user:
|
||||||
|
# Remove cookie
|
||||||
|
resp = make_response(redirect('/'))
|
||||||
|
resp.set_cookie('token', '', expires=0)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
tribeData = db.get_user_owned_tribe(user['domain'])
|
||||||
|
if len(tribeData) == 0:
|
||||||
|
return error('Sorry you don\'t own a tribe')
|
||||||
|
|
||||||
|
# Verify member isn't owner
|
||||||
|
if member == user['domain']:
|
||||||
|
return error('Sorry you can\'t remove yourself from your own tribe')
|
||||||
|
|
||||||
|
tribe = tribeData[0][1]
|
||||||
|
data = tribeData[0][2]
|
||||||
|
data = json.loads(data)
|
||||||
|
members = data['members']
|
||||||
|
if member in members:
|
||||||
|
members.remove(member)
|
||||||
|
data['members'] = members
|
||||||
|
# Convert to json
|
||||||
|
data = json.dumps(data)
|
||||||
|
db.update_tribe_data_raw(tribe,data)
|
||||||
|
return redirect('/edit_tribe')
|
||||||
|
|
||||||
@app.route('/<path:path>')
|
@app.route('/<path:path>')
|
||||||
def catch_all(path):
|
def catch_all(path):
|
||||||
account = "Login"
|
account = "Login"
|
||||||
@ -336,6 +565,9 @@ def catch_all(path):
|
|||||||
account_link_name = "Login"
|
account_link_name = "Login"
|
||||||
site = "Null"
|
site = "Null"
|
||||||
domain = ""
|
domain = ""
|
||||||
|
tribe_title = "Join a tribe"
|
||||||
|
tribe_link = "tribe"
|
||||||
|
|
||||||
if 'domain' in request.args:
|
if 'domain' in request.args:
|
||||||
domain = request.args.get('domain')
|
domain = request.args.get('domain')
|
||||||
if 'token' in request.cookies:
|
if 'token' in request.cookies:
|
||||||
@ -351,6 +583,12 @@ def catch_all(path):
|
|||||||
account_link = "account"
|
account_link = "account"
|
||||||
account_link_name = "Account"
|
account_link_name = "Account"
|
||||||
site = user['domain'] + "." + CITY_DOMAIN
|
site = user['domain'] + "." + CITY_DOMAIN
|
||||||
|
# Check if user owns tribe
|
||||||
|
tribeData = db.get_user_owned_tribe(user['domain'])
|
||||||
|
if len(tribeData) > 0:
|
||||||
|
tribe_title = "Edit your tribe"
|
||||||
|
tribe_link = "edit_tribe"
|
||||||
|
|
||||||
elif path != "signup" and path != "login" and path != "empty_site":
|
elif path != "signup" and path != "login" and path != "empty_site":
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
@ -360,11 +598,17 @@ def catch_all(path):
|
|||||||
|
|
||||||
# If file exists, load it
|
# If file exists, load it
|
||||||
if os.path.isfile('templates/' + path):
|
if os.path.isfile('templates/' + path):
|
||||||
return render_template(path,account=account,account_link=account_link,account_link_name=account_link_name,site=site,CITY_DOMAIN=CITY_DOMAIN,domain=domain)
|
return render_template(path,account=account,account_link=account_link,
|
||||||
|
account_link_name=account_link_name,site=site,
|
||||||
|
CITY_DOMAIN=CITY_DOMAIN,domain=domain,
|
||||||
|
tribe_title=tribe_title,tribe_link=tribe_link)
|
||||||
|
|
||||||
# Try with .html
|
# Try with .html
|
||||||
if os.path.isfile('templates/' + path + '.html'):
|
if os.path.isfile('templates/' + path + '.html'):
|
||||||
return render_template(path + '.html',account=account,account_link=account_link,account_link_name=account_link_name,site=site,CITY_DOMAIN=CITY_DOMAIN,domain=domain)
|
return render_template(path + '.html',account=account,account_link=account_link,
|
||||||
|
account_link_name=account_link_name,site=site,
|
||||||
|
CITY_DOMAIN=CITY_DOMAIN,domain=domain,
|
||||||
|
tribe_title=tribe_title,tribe_link=tribe_link)
|
||||||
return redirect('/') # 404 catch all
|
return redirect('/') # 404 catch all
|
||||||
|
|
||||||
|
|
||||||
@ -382,4 +626,4 @@ def update_random_sites():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
db.check_tables()
|
db.check_tables()
|
||||||
app.run(debug=False, port=5000, host='0.0.0.0')
|
app.run(debug=True, port=5000, host='0.0.0.0')
|
@ -7,6 +7,8 @@ import os
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
template = "city"
|
template = "city"
|
||||||
data = "<h1>Test site</h1><p>This is a test site</p>"
|
data = "<h1>Test site</h1><p>This is a test site</p>"
|
||||||
|
# data = "<div style=\"text-align:center;\"><h1>Nathan.Woodburn/</h1><h2>This is fully customizable!</h2><p>You can even add custom css rules like below.<br>Try hovering over this image</p><style>img.background:hover {filter: blur(5px)}</style><div class=\"profile-container\" style=\"height: 300px;margin-bottom: 2em;\"><img class=\"profile background\" src=\"https://nathan.woodburn.au/assets/img/profile.jpg\" style=\"border-radius: 50%;width: 300px;position: absolute;left: 50%;margin-left: -150px;aspect-ratio: 1;padding-top: calc(var(--s)/5);transform: scale(1);transition: .5s;\" alt=\"My Profile\"><img class=\"profile foreground\" src=\"https://nathan.woodburn.au/assets/img/pfront.webp\" alt=\"\" style=\"border-radius: 50%;pointer-events: none;width: 300px;position: absolute;left: 50%;margin-left: -150px;aspect-ratio: 1;padding-top: calc(var(--s)/5);transform: scale(1);transition: .5s;\"></div>"
|
||||||
|
|
||||||
db_object = {
|
db_object = {
|
||||||
'avatar': "https://woodburn.au/favicon.png",
|
'avatar': "https://woodburn.au/favicon.png",
|
||||||
'hnschat':"nathan.woodburn",
|
'hnschat':"nathan.woodburn",
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
<section style="margin-top: 50px;text-align: center;">
|
<section style="margin-top: 50px;text-align: center;">
|
||||||
<h1>Welcome to ShakeCities</h1>
|
<h1>Welcome to ShakeCities</h1>
|
||||||
<p>Congratulations your site is ready for use.<br><br></p>
|
<p>Congratulations your site is ready for use.<br><br></p>
|
||||||
<div style="max-width: 10em;margin: auto;"><a class="btn btn-primary" role="button" href="https://{{site}}" style="display: block;margin: 10px;" target="_blank">Visit your site</a><a class="btn btn-primary" role="button" href="/edit" style="display: block;margin: 10px;">Edit your site</a><a class="btn btn-primary" role="button" href="/tribe" style="display: block;margin: 10px;">Join a tribe</a><a class="btn btn-primary" role="button" href="/hnschat" style="display: block;margin: 10px;">Link HNSChat</a><a class="btn btn-primary" role="button" href="/logout" style="display: block;margin: 10px;">Logout</a></div>
|
<div style="max-width: 10em;margin: auto;"><a class="btn btn-primary" role="button" href="https://{{site}}" style="display: block;margin: 10px;" target="_blank">Visit your site</a><a class="btn btn-primary" role="button" href="/edit" style="display: block;margin: 10px;">Edit your site</a><a class="btn btn-primary" role="button" href="/{{tribe_link}}" style="display: block;margin: 10px;">{{tribe_title}}</a><a class="btn btn-primary" role="button" href="/hnschat" style="display: block;margin: 10px;">Link HNSChat</a><a class="btn btn-primary" role="button" href="/logout" style="display: block;margin: 10px;">Logout</a></div>
|
||||||
</section>
|
</section>
|
||||||
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
|
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
|
||||||
<footer class="text-center bg-dark"></footer>
|
<footer class="text-center bg-dark"></footer>
|
||||||
|
102
templates/edit_tribe.html
Normal file
102
templates/edit_tribe.html
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="light" lang="en" style="background: black;">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>ShakeCities | Tribes</title>
|
||||||
|
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/styles.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
|
||||||
|
<section>
|
||||||
|
<section style="height: 15vh;background: url("assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp") bottom / cover no-repeat;min-height: 130px;"></section>
|
||||||
|
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
|
||||||
|
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
|
||||||
|
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
|
||||||
|
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
|
||||||
|
</section>
|
||||||
|
<section style="margin-top: 10px;">
|
||||||
|
<div class="row" style="margin: 0px;">
|
||||||
|
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
|
||||||
|
<h1 style="margin: 10px;">Edit {{tribe}} tribe</h1>
|
||||||
|
<form method="post" style="margin-bottom: 20px;"><input class="form-control" type="text" style="margin-top: 20px;" name="tribe" placeholder="Tribe Name" value="{{tribe}}"><textarea class="form-control" style="margin-top: 20px;" rows="5" placeholder="Content" name="data">{{data}}</textarea>
|
||||||
|
<p style="margin-top: 20px;">{{members|safe}}</p><input class="btn btn-primary" type="submit" style="margin-top: 20px;" value="Edit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Donate</h1>
|
||||||
|
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Donate</h1>
|
||||||
|
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
|
||||||
|
function copyToClipboard(element) {
|
||||||
|
const textToCopy = element.textContent;
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = textToCopy;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hns = document.getElementById('hns_address');
|
||||||
|
hns.addEventListener('click', () => {
|
||||||
|
copyToClipboard(hns);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
|
||||||
|
<footer class="text-center bg-dark"></footer>
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<ul class="list-inline">
|
||||||
|
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
|
||||||
|
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
|
||||||
|
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -57,6 +57,12 @@
|
|||||||
<p style="margin: 10px;font-size: 20px;">{{random_sites|safe}}</p>
|
<p style="margin: 10px;font-size: 20px;">{{random_sites|safe}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" style="margin: 0px;">
|
||||||
|
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
|
||||||
|
<h1 style="margin: 10px;">Tribes</h1>
|
||||||
|
<p style="margin: 10px;">{{tribes|safe}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
100
templates/new_tribe.html
Normal file
100
templates/new_tribe.html
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="light" lang="en" style="background: black;">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>ShakeCities | Tribes</title>
|
||||||
|
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/styles.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
|
||||||
|
<section>
|
||||||
|
<section style="height: 15vh;background: url("assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp") bottom / cover no-repeat;min-height: 130px;"></section>
|
||||||
|
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
|
||||||
|
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
|
||||||
|
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
|
||||||
|
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
|
||||||
|
</section>
|
||||||
|
<section style="margin-top: 10px;">
|
||||||
|
<div class="row" style="margin: 0px;">
|
||||||
|
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
|
||||||
|
<h1 style="margin: 10px;">Create a tribe</h1>
|
||||||
|
<form method="post"><input class="form-control" type="text" style="margin-top: 20px;" name="tribe" placeholder="Tribe Name"><input class="btn btn-primary" type="submit" style="margin-top: 20px;" value="Create"></form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Donate</h1>
|
||||||
|
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Donate</h1>
|
||||||
|
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
|
||||||
|
function copyToClipboard(element) {
|
||||||
|
const textToCopy = element.textContent;
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = textToCopy;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hns = document.getElementById('hns_address');
|
||||||
|
hns.addEventListener('click', () => {
|
||||||
|
copyToClipboard(hns);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
|
||||||
|
<footer class="text-center bg-dark"></footer>
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<ul class="list-inline">
|
||||||
|
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
|
||||||
|
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
|
||||||
|
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
104
templates/tribe.html
Normal file
104
templates/tribe.html
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="light" lang="en" style="background: black;">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>ShakeCities | Tribes</title>
|
||||||
|
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
|
||||||
|
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/styles.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
|
||||||
|
<section>
|
||||||
|
<section style="height: 15vh;background: url("assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp") bottom / cover no-repeat;min-height: 130px;"></section>
|
||||||
|
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
|
||||||
|
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
|
||||||
|
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
|
||||||
|
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
|
||||||
|
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
|
||||||
|
</section>
|
||||||
|
<section style="margin-top: 10px;">
|
||||||
|
<div class="row" style="margin: 0px;">
|
||||||
|
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
|
||||||
|
<h1 style="margin: 10px;">About Tribes</h1>
|
||||||
|
<p style="margin: 10px;">ShakeCities is a site offering free personalizable websites. This is a perfect way to start your journey into Handshake domains! Step into a new experience where Handshake domains become instant sites, and where everyone can create their own unique decentralized page.<br>Secured with HTTPS powered by DANE (DNS-based Authentication of Named Entities).<br>But that's not all – ShakeCities goes beyond, allowing you to seamlessly integrate crypto addresses into your site, providing an easy way to get paid. Simply send crypto to <code>@yourname.{{CITY_DOMAIN}}</code><br>Your ShakeCity domain can be used to chat on <a href="https://hns.chat" target="_blank">HNSChat</a> or to authenticate on any site using Varo auth<br>Join us in building a decentralized, secure, and innovative internet landscape. Embrace the future with ShakeCities – where Handshake domains meet simplicity.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col" style="background: var(--bs-body-color);margin-left: 10px;border-radius: 10px;margin-top: 10px;margin-right: 10px;">
|
||||||
|
<h1 style="margin: 10px;">Find a tribe</h1>
|
||||||
|
<p style="margin: 10px;font-size: 20px;">{{tribes|safe}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Donate</h1>
|
||||||
|
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 20px;">
|
||||||
|
<h1>Donate</h1>
|
||||||
|
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
|
||||||
|
function copyToClipboard(element) {
|
||||||
|
const textToCopy = element.textContent;
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = textToCopy;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hns = document.getElementById('hns_address');
|
||||||
|
hns.addEventListener('click', () => {
|
||||||
|
copyToClipboard(hns);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
|
||||||
|
<footer class="text-center bg-dark"></footer>
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<ul class="list-inline">
|
||||||
|
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
|
||||||
|
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
|
||||||
|
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
63
templates/tribe_view.html
Normal file
63
templates/tribe_view.html
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html style="width: 100vw;height: 99vh;">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>ShakeCities</title>
|
||||||
|
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:title" content="ShakeCities">
|
||||||
|
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
|
||||||
|
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
|
||||||
|
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/styles.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body style="height: 99vh;width: 100vw;color: #ffffff;background: #000000;overflow-x: hidden;">
|
||||||
|
<h1 style="margin: auto;text-align: center;font-size: 5em;">{{tribe}}</h1>
|
||||||
|
<div style="padding: 2%;margin: 22px;text-align: center;">
|
||||||
|
<p style="font-size: 24px;">
|
||||||
|
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 2%;margin: 22px;text-align: center;">
|
||||||
|
<h2>Tribe members</h2>
|
||||||
|
<p style="font-size: 24px;">
|
||||||
|
{{members|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Edit footer -->
|
||||||
|
<div style="height: 100px;"></div>
|
||||||
|
<div style="position: fixed;bottom: 10px;right:25px;">
|
||||||
|
<p style="color:#ffffff;">{{edit|safe}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer to display the powered by ShakeCities. -->
|
||||||
|
<div style="height: 100px;"></div>
|
||||||
|
<div style="position: fixed;bottom: 10px;left:25px;">
|
||||||
|
<div style="display: inline-block; background: #ffffff;border-radius: 50%;padding: 10px;">
|
||||||
|
<img src="/assets/img/HNS.png" width="50px" height="50px">
|
||||||
|
</div>
|
||||||
|
<p style="margin-left: 25px; display:inline; color:#ffffff;">Powered by <a style="color: inherit;" href="https://shakecities.com" target="_blank">ShakeCities</a></p>
|
||||||
|
</div>
|
||||||
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user