* Implement Titan Tokens clientside

* Titan Tokens can be modified in the admin panel
This commit is contained in:
Jeremy "EndenDragon" Zhang 2017-08-13 18:10:03 -07:00 committed by GitHub
parent d363b66799
commit 8bc95f7b0e
16 changed files with 618 additions and 10 deletions

View File

@ -0,0 +1,160 @@
"""Added Titan Tokens
Revision ID: 2a2f32ac91d6
Revises: 6fe130518448
Create Date: 2017-08-13 22:44:15.996936
"""
# revision identifiers, used by Alembic.
revision = '2a2f32ac91d6'
down_revision = '6fe130518448'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('titan_tokens',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.String(length=255), nullable=False),
sa.Column('tokens', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('token_transactions',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.String(length=255), nullable=False),
sa.Column('timestamp', sa.TIMESTAMP(), nullable=False),
sa.Column('action', sa.String(length=255), nullable=False),
sa.Column('net_tokens', sa.Integer(), nullable=False),
sa.Column('start_tokens', sa.Integer(), nullable=False),
sa.Column('end_tokens', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.alter_column(u'cosmetics', 'css',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False)
op.alter_column(u'guild_members', 'active',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guild_members', 'banned',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False,
existing_server_default=sa.text(u"'0'"))
op.alter_column(u'guilds', 'bracket_links',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guilds', 'channels',
existing_type=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
type_=sa.Text(length=4294967295),
existing_nullable=False)
op.alter_column(u'guilds', 'chat_links',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guilds', 'emojis',
existing_type=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
type_=sa.Text(length=4294967295),
existing_nullable=False)
op.alter_column(u'guilds', 'roles',
existing_type=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
type_=sa.Text(length=4294967295),
existing_nullable=False)
op.alter_column(u'guilds', 'unauth_users',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guilds', 'visitor_view',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False)
op.alter_column(u'guilds', 'webhooks',
existing_type=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
type_=sa.Text(length=4294967295),
existing_nullable=False)
op.alter_column(u'unauthenticated_users', 'revoked',
existing_type=mysql.TINYINT(display_width=1),
type_=sa.Boolean(),
existing_nullable=False,
existing_server_default=sa.text(u"'0'"))
op.alter_column(u'user_css', 'css',
existing_type=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
type_=sa.Text(length=4294967295),
existing_nullable=True)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(u'user_css', 'css',
existing_type=sa.Text(length=4294967295),
type_=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
existing_nullable=True)
op.alter_column(u'unauthenticated_users', 'revoked',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False,
existing_server_default=sa.text(u"'0'"))
op.alter_column(u'guilds', 'webhooks',
existing_type=sa.Text(length=4294967295),
type_=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
existing_nullable=False)
op.alter_column(u'guilds', 'visitor_view',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False)
op.alter_column(u'guilds', 'unauth_users',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guilds', 'roles',
existing_type=sa.Text(length=4294967295),
type_=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
existing_nullable=False)
op.alter_column(u'guilds', 'emojis',
existing_type=sa.Text(length=4294967295),
type_=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
existing_nullable=False)
op.alter_column(u'guilds', 'chat_links',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guilds', 'channels',
existing_type=sa.Text(length=4294967295),
type_=mysql.LONGTEXT(collation=u'utf8mb4_unicode_ci'),
existing_nullable=False)
op.alter_column(u'guilds', 'bracket_links',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'guild_members', 'banned',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False,
existing_server_default=sa.text(u"'0'"))
op.alter_column(u'guild_members', 'active',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False,
existing_server_default=sa.text(u"'1'"))
op.alter_column(u'cosmetics', 'css',
existing_type=sa.Boolean(),
type_=mysql.TINYINT(display_width=1),
existing_nullable=False)
op.drop_table('token_transactions')
op.drop_table('titan_tokens')
# ### end Alembic commands ###

View File

@ -4,6 +4,10 @@ config = {
'client-id': "Your app client id",
'client-secret': "Your discord client secret",
'bot-token': "Discord bot token",
# Rest API in https://developer.paypal.com/developer/applications
'paypal-client-id': "Paypal client id",
'paypal-client-secret': "Paypal client secret",
'app-location': "/var/www/Titan/webapp/",
'app-secret': "Type something random here, go wild.",

View File

@ -1,6 +1,6 @@
from flask import Blueprint, url_for, redirect, session, render_template, abort, request, jsonify
from functools import wraps
from titanembeds.database import db, get_administrators_list, Cosmetics, Guilds, UnauthenticatedUsers, UnauthenticatedBans
from titanembeds.database import db, get_administrators_list, Cosmetics, Guilds, UnauthenticatedUsers, UnauthenticatedBans, TitanTokens, TokenTransactions, get_titan_token, set_titan_token
from titanembeds.oauth import generate_guild_icon_url
import datetime
@ -172,3 +172,52 @@ def update_administrate_guild(guild_id):
def guilds():
guilds = db.session.query(Guilds).all()
return render_template("admin_guilds.html.j2", servers=guilds, icon_generate=generate_guild_icon_url)
@admin.route("/tokens", methods=["GET"])
@is_admin
def manage_titan_tokens():
tokeners = db.session.query(TitanTokens).all()
donators = []
for usr in tokeners:
row = {
"user_id": usr.user_id,
"tokens": usr.tokens,
"transactions": []
}
transact = db.session.query(TokenTransactions).filter(TokenTransactions.user_id == usr.user_id).all()
for tr in transact:
row["transactions"].append({
"id": tr.id,
"user_id": tr.user_id,
"timestamp": tr.timestamp,
"action": tr.action,
"net_tokens": tr.net_tokens,
"start_tokens": tr.start_tokens,
"end_tokens": tr.end_tokens
})
donators.append(row)
return render_template("admin_token_transactions.html.j2", donators=donators)
@admin.route("/tokens", methods=["POST"])
@is_admin
def post_titan_tokens():
user_id = request.form.get("user_id", None)
amount = request.form.get("amount", None, type=int)
if not user_id or not amount:
abort(400)
if get_titan_token(user_id) != -1:
abort(409)
set_titan_token(user_id, amount, "NEW VIA ADMIN")
return ('', 204)
@admin.route("/tokens", methods=["PATCH"])
@is_admin
def patch_titan_tokens():
user_id = request.form.get("user_id", None)
amount = request.form.get("amount", None, type=int)
if not user_id or not amount:
abort(400)
if get_titan_token(user_id) == -1:
abort(409)
set_titan_token(user_id, amount, "MODIFY VIA ADMIN")
return ('', 204)

View File

@ -1,10 +1,12 @@
from flask import Blueprint, request, redirect, jsonify, abort, session, url_for, render_template
from flask import current_app as app
from config import config
from titanembeds.decorators import discord_users_only
from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans, Cosmetics, UserCSS
from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans, Cosmetics, UserCSS, set_titan_token, get_titan_token
from titanembeds.oauth import authorize_url, token_url, make_authenticated_session, get_current_authenticated_user, get_user_managed_servers, check_user_can_administrate_guild, check_user_permission, generate_avatar_url, generate_guild_icon_url, generate_bot_invite_url
import time
import datetime
import paypalrestsdk
user = Blueprint("user", __name__)
@ -70,7 +72,10 @@ def dashboard():
css_list = None
if cosmetics and cosmetics.css:
css_list = db.session.query(UserCSS).filter(UserCSS.user_id == session['user_id']).all()
return render_template("dashboard.html.j2", servers=guilds, icon_generate=generate_guild_icon_url, cosmetics=cosmetics, css_list=css_list)
tokens = get_titan_token(session["user_id"])
if tokens == -1:
tokens = 0
return render_template("dashboard.html.j2", servers=guilds, icon_generate=generate_guild_icon_url, cosmetics=cosmetics, css_list=css_list, tokens=tokens)
@user.route("/custom_css/new", methods=["GET"])
@discord_users_only()
@ -322,3 +327,69 @@ def revoke_unauthenticated_user():
abort(409)
db_user.revokeUser()
return ('', 204)
@user.route('/donate', methods=["GET"])
@discord_users_only()
def donate_get():
return render_template('donate.html.j2')
def get_paypal_api():
return paypalrestsdk.Api({
'mode': 'sandbox' if app.config["DEBUG"] else 'live',
'client_id': config["paypal-client-id"],
'client_secret': config["paypal-client-secret"]})
@user.route('/donate', methods=['POST'])
@discord_users_only()
def donate_post():
donation_amount = request.form.get('amount')
if not donation_amount:
abort(402)
donation_amount = "{0:.2f}".format(float(donation_amount))
payer = {"payment_method": "paypal"}
items = [{"name": "TitanEmbeds Donation",
"price": donation_amount,
"currency": "USD",
"quantity": "1"}]
amount = {"total": donation_amount,
"currency": "USD"}
description = "Donate and support TitanEmbeds development."
redirect_urls = {"return_url": url_for('user.donate_confirm', success="true", _external=True),
"cancel_url": url_for('index', _external=True)}
payment = paypalrestsdk.Payment({"intent": "sale",
"payer": payer,
"redirect_urls": redirect_urls,
"transactions": [{"item_list": {"items":
items},
"amount": amount,
"description":
description}]}, api=get_paypal_api())
if payment.create():
for link in payment.links:
if link['method'] == "REDIRECT":
return redirect(link["href"])
return redirect(url_for('index'))
@user.route("/donate/confirm")
@discord_users_only()
def donate_confirm():
if not request.args.get('success'):
return redirect(url_for('index'))
payment = paypalrestsdk.Payment.find(request.args.get('paymentId'), api=get_paypal_api())
if payment.execute({"payer_id": request.args.get('PayerID')}):
trans_id = str(payment.transactions[0]["related_resources"][0]["sale"]["id"])
amount = float(payment.transactions[0]["amount"]["total"])
tokens = int(amount * 100)
action = "PAYPAL {}".format(trans_id)
set_titan_token(session["user_id"], tokens, action)
return redirect(url_for('user.donate_thanks', transaction=trans_id))
else:
return redirect(url_for('index'))
@user.route("/donate/thanks")
@discord_users_only()
def donate_thanks():
tokens = get_titan_token(session["user_id"])
transaction = request.args.get("transaction")
return render_template("donate_thanks.html.j2", tokens=tokens, transaction=transaction)

View File

@ -11,4 +11,25 @@ from keyvalue_properties import KeyValueProperties, set_keyvalproperty, get_keyv
from messages import Messages, get_channel_messages
from cosmetics import Cosmetics
from user_css import UserCSS
from administrators import Administrators, get_administrators_list
from administrators import Administrators, get_administrators_list
from titan_tokens import TitanTokens, get_titan_token
from token_transactions import TokenTransactions
def set_titan_token(user_id, amt_change, action):
token_count = get_titan_token(user_id)
if token_count >= 0:
token_usr = db.session.query(TitanTokens).filter(TitanTokens.user_id == user_id).first()
else:
token_count = 0
token_usr = TitanTokens(user_id, 0)
db.session.add(token_usr)
db.session.commit()
new_token_count = token_count + amt_change
if new_token_count < 0:
return False
transact = TokenTransactions(user_id, action, amt_change, token_count, new_token_count)
db.session.add(transact)
token_usr.tokens = new_token_count
db.session.add(token_usr)
db.session.commit()
return True

View File

@ -0,0 +1,18 @@
from titanembeds.database import db
class TitanTokens(db.Model):
__tablename__ = "titan_tokens"
id = db.Column(db.Integer, primary_key=True) # Auto increment id
user_id = db.Column(db.String(255), nullable=False) # Discord user id of user
tokens = db.Column(db.Integer, nullable=False, default=0) # Token amount
def __init__(self, user_id, tokens):
self.user_id = user_id
self.tokens = tokens
def get_titan_token(user_id):
q = db.session.query(TitanTokens).filter(TitanTokens.user_id == user_id).first()
if q:
return q.tokens
else:
return -1

View File

@ -0,0 +1,21 @@
from titanembeds.database import db
import datetime
import time
class TokenTransactions(db.Model):
__tablename__ = "token_transactions"
id = db.Column(db.Integer, primary_key=True) # Auto increment id
user_id = db.Column(db.String(255), nullable=False) # Discord user id of user
timestamp = db.Column(db.TIMESTAMP, nullable=False) # The timestamp of when the action took place
action = db.Column(db.String(255), nullable=False) # Very short description of the action
net_tokens = db.Column(db.Integer, nullable=False) # Net change of the token amount
start_tokens = db.Column(db.Integer, nullable=False) # Token amount before transaction
end_tokens = db.Column(db.Integer, nullable=False) # Tokens after transaction
def __init__(self, user_id, action, net_tokens, start_tokens, end_tokens):
self.user_id = user_id
self.timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
self.action = action
self.net_tokens = net_tokens
self.start_tokens = start_tokens
self.end_tokens = end_tokens

View File

@ -0,0 +1,56 @@
/* global $, Materialize, location */
function postForm(user_id, amount) {
var funct = $.ajax({
dataType: "json",
method: "POST",
data: {"user_id": user_id, "amount": amount}
});
return funct.promise();
}
function patchForm(user_id, amount) {
var funct = $.ajax({
dataType: "json",
method: "PATCH",
data: {"user_id": user_id, "amount": amount}
});
return funct.promise();
}
$(function() {
$("#new_submit").click(function () {
var user_id = $("#new_user_id").val();
var user_token = $("#new_user_token").val();
if (user_id.length < 1 || user_token.length < 1) {
Materialize.toast("The user ID or balance field can't be blank!", 2000);
return;
}
var formPost = postForm(user_id, user_token);
formPost.done(function (data) {
location.reload();
});
formPost.fail(function (data) {
if (data.status == 409) {
Materialize.toast('This user id already exists!', 10000);
} else {
Materialize.toast('Oh no! Something has failed submitting a new entry!', 10000);
}
});
});
});
function submit_modify_user(user_id) {
var amount = $("#input_"+user_id).val();
var formPatch = patchForm(user_id, amount);
formPatch.done(function (data) {
location.reload();
});
formPatch.fail(function (data) {
if (data.status == 409) {
Materialize.toast('This user id does not exists!', 10000);
} else {
Materialize.toast('Oh no! Something has failed changing the css toggle!', 10000);
}
});
}

View File

@ -0,0 +1,19 @@
/* global $ */
(function () {
$('#token-slider').on('input', function(){
var slider_value = $("#token-slider").val();
var multiplier = 100;
$("#money-display").text(slider_value);
$("#token-display").text(slider_value * multiplier);
});
$("#donate-btn").click(function () {
var slider_value = $("#token-slider").val();
var form = $('<form method="POST">' +
'<input type="hidden" name="amount" value="' + slider_value + '">' +
'</form>');
$(document.body).append(form);
form.submit();
});
})();

View File

@ -20,6 +20,13 @@
<a class="waves-effect waves-light btn" href="{{ url_for('admin.guilds') }}">Manage</a>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>Titan Tokens</h4>
<p class="flow-text">View transactions and modify Titan Tokens per user.</p>
<a class="waves-effect waves-light btn" href="{{ url_for('admin.manage_titan_tokens') }}">Manage</a>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>Run a Database Cleanup</h4>

View File

@ -0,0 +1,105 @@
{% extends 'site_layout.html.j2' %}
{% set title="Editing User Titan Tokens" %}
{% block content %}
<h1>Administrating Titan Tokens</h1>
<div class="row">
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<p class="flow-text">New Entry</p>
<table class="bordered striped">
<thead>
<tr>
<th>User ID</th>
<th>Starting Balance</th>
<th>Submit</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="input-field inline">
<input id="new_user_id" placeholder="User ID">
</div>
</td>
<td>
<div class="input-field inline">
<input id="new_user_token" placeholder="Starting Balance" type="number">
</div>
</td>
<td>
<a class="waves-effect waves-light btn" id="new_submit">Submit</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<p class="flow-text">View Transactions and Modify User Tokens</p>
<ul class="collapsible" data-collapsible="accordion">
{% for don in donators %}
<li>
<div class="collapsible-header">{{ don.user_id }}</div>
<div class="collapsible-body">
<table class="bordered striped">
<thead>
<tr>
<th>Modify Amount</th>
<th>Submit</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="input-field inline">
<input placeholder="Modify Amount" type="number" id="input_{{ don.user_id }}">
</div>
<p>(Place a subtract sign in the front to remove tokens. Otherwise, it will add the amount)</p>
</td>
<td>
<a class="waves-effect waves-light btn" onclick="submit_modify_user('{{ don.user_id }}')">Submit</a>
</td>
</tr>
</tbody>
</table>
<h4>Balance: <strong>{{ don.tokens }}</strong> Tokens</h4>
<table class="striped">
<thead>
<tr>
<th>Trans #</th>
<th>Timestamp</th>
<th>Action</th>
<th>Change</th>
<th>Starting Bal</th>
<th>Ending Bal</th>
</tr>
</thead>
<tbody>
{% for trans in don.transactions %}
<tr>
<td>{{ trans.id }}</td>
<td>{{ trans.timestamp }}</td>
<td>{{ trans.action }}.</td>
<td>{{ trans.net_tokens }}</td>
<td>{{ trans.start_tokens }}</td>
<td>{{ trans.end_tokens }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript" src="{{ url_for('static', filename='js/admin_token_transactions.js') }}"></script>
{% endblock %}

View File

@ -2,7 +2,6 @@
{% set title="Dashboard" %}
{% block content %}
{% include 'patreon_banner.html.j2' %}
<h1>User Dashboard</h1>
<p class="flow-text">Select a server to configure Titan Embeds.</p>
<p>*List missing some servers? It's because you must have either <strong>Manage Server</strong>, <strong>Kick Members</strong>, or <strong>Ban Members</strong> permissions to modify embed settings.</p>
@ -61,4 +60,17 @@
{% endfor %}
</div>
{% endif %}
{% endblock %}
<hr>
<div class="row">
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>Donations!</h4>
<p class="flow-text">Would you like to support the Titan Embeds project?</p>
<p>You currently have <strong>{{ tokens }}</strong> Titan Tokens.</p>
<a class="waves-effect waves-light btn" href="{{ url_for('user.donate_get') }}">Donate!!</a>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,51 @@
{% extends 'site_layout.html.j2' %}
{% set title="Donate" %}
{% block content %}
<h1>Donate and Support Titan Embeds</h1>
<p class="flow-text">Contributing to the Titan project has never been so easy! Donate to support our project development and hosting.</p>
<div class="row">
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>The Name-Your-Price Tool</h4>
<p class="flow-text">Currently if you donate, we cannot give much back in return, yet. However, we do have some donatator features up our sleeves and will be implemented.</p>
<p class="flow-text">For now, you will receive <strong>Titan Tokens&trade;</strong> (to be spent on donator features) and a <strong>supporter role</strong> on our support server.</p>
<p class="range-field">
<input type="range" id="token-slider" min="1" max="100" value="5" />
</p>
<p class="flow-text">$<span id="money-display">5</span> for <strong><span id="token-display">500</span> tokens</strong>!</p>
<a class="waves-effect waves-light btn" id="donate-btn">Donate</a>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript" src="{{ url_for('static', filename='js/donate.js') }}"></script>
{% endblock %}
{% block additional_head_elements %}
<style>
input[type=range]::-webkit-slider-thumb {
background-color: #303f9f;
}
input[type=range]::-moz-range-thumb {
background-color: #303f9f;
}
input[type=range]::-ms-thumb {
background-color: #303f9f;
}
/***** These are to edit the thumb and the text inside the thumb *****/
input[type=range] + .thumb {
background-color: #dedede;
}
input[type=range] + .thumb.active .value {
font-size: 12pt;
color: #303f9f;
}
input[type=range] + .thumb.active .value::before {
content: "$";
}
</style>
{% endblock %}

View File

@ -0,0 +1,18 @@
{% extends 'site_layout.html.j2' %}
{% set title="Thanks for Donating" %}
{% block content %}
<h1>Thank you for Donating and Supporting the Titan Embeds project!</h1>
<div class="row">
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>You're officially one step closer to becoming a True Titan!</h4>
<p class="flow-text">You now have <strong>{{ tokens }}</strong> tokens!</p>
<p>Please visit our support server and contact a True Titan (Administrators Role) to claim your Supporter role, if you haven't done so already. Mention the transaction ID of <strong>{{ transaction }}</strong>.</p>
<a class="waves-effect waves-light btn" href="https://discord.io/Titan" target="_blank">Support Server</a>
<p><em>Have a nice day!</em></p>
</div>
</div>
</div>
{% endblock %}

View File

@ -2,7 +2,6 @@
{% set title="Index" %}
{% block content %}
{% include 'patreon_banner.html.j2' %}
<h1 class="center-align">Embed Discord like a<br><strong>true Titan</strong></h1>
<p class="flow-text center-align">Add <strong>Titan</strong> to your discord server to create your own personalized chat embed!</p>
<a class="waves-effect waves-light btn btn-large center_content" href="{{ url_for('user.dashboard') }}">Start here!</a>

View File

@ -1,3 +0,0 @@
<div class="collection">
<a href="https://www.patreon.com/TitanEmbeds" class="collection-item"><i class="material-icons">monetization_on</i> We have decided to open a Patreon page to help fund the Titan. If you are interested and would like to help, please check it out!</a>
</div>