Implemented Cosmetics and User Custom CSS, closes #7

This commit is contained in:
Jeremy Zhang 2017-05-22 01:07:32 +00:00
parent 6480df1b57
commit d18c9bf1c9
9 changed files with 274 additions and 5 deletions

View File

@ -1,7 +1,7 @@
from flask import Blueprint, render_template, abort, redirect, url_for, session from flask import Blueprint, render_template, abort, redirect, url_for, session, request
from titanembeds.utils import check_guild_existance, guild_query_unauth_users_bool from titanembeds.utils import check_guild_existance, guild_query_unauth_users_bool
from titanembeds.oauth import generate_guild_icon_url, generate_avatar_url from titanembeds.oauth import generate_guild_icon_url, generate_avatar_url
from titanembeds.database import db, Guilds from titanembeds.database import db, Guilds, UserCSS
from config import config from config import config
import random import random
@ -20,6 +20,12 @@ def get_logingreeting():
] ]
return random.choice(greetings) return random.choice(greetings)
def get_custom_css():
css = request.args.get("css", None)
if css:
css = db.session.query(UserCSS).filter(UserCSS.id == css).first()
return css
@embed.route("/<string:guild_id>") @embed.route("/<string:guild_id>")
def guild_embed(guild_id): def guild_embed(guild_id):
if check_guild_existance(guild_id): if check_guild_existance(guild_id):
@ -35,7 +41,8 @@ def guild_embed(guild_id):
guild_id=guild_id, guild=guild_dict, guild_id=guild_id, guild=guild_dict,
generate_guild_icon=generate_guild_icon_url, generate_guild_icon=generate_guild_icon_url,
unauth_enabled=guild_query_unauth_users_bool(guild_id), unauth_enabled=guild_query_unauth_users_bool(guild_id),
client_id=config['client-id'] client_id=config['client-id'],
css=get_custom_css()
) )
abort(404) abort(404)

View File

@ -1,7 +1,7 @@
from flask import Blueprint, request, redirect, jsonify, abort, session, url_for, render_template from flask import Blueprint, request, redirect, jsonify, abort, session, url_for, render_template
from config import config from config import config
from titanembeds.decorators import discord_users_only from titanembeds.decorators import discord_users_only
from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans, Cosmetics, UserCSS
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 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 time
import datetime import datetime
@ -66,7 +66,90 @@ def dashboard():
redir = session['redirect'] redir = session['redirect']
session['redirect'] = None session['redirect'] = None
return redirect(redir) return redirect(redir)
return render_template("dashboard.html.j2", servers=guilds, icon_generate=generate_guild_icon_url) cosmetics = db.session.query(Cosmetics).filter(Cosmetics.user_id == session['user_id']).first()
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)
@user.route("/custom_css/new", methods=["GET"])
@discord_users_only()
def new_custom_css_get():
cosmetics = db.session.query(Cosmetics).filter(Cosmetics.user_id == session['user_id']).first()
if not cosmetics or not cosmetics.css:
abort(403)
return render_template("usercss.html.j2", new=True)
@user.route("/custom_css/new", methods=["POST"])
@discord_users_only()
def new_custom_css_post():
cosmetics = db.session.query(Cosmetics).filter(Cosmetics.user_id == session['user_id']).first()
if not cosmetics or not cosmetics.css:
abort(403)
name = request.form.get("name", None)
user_id = session["user_id"]
css = request.form.get("css","")
if not name:
abort(400)
else:
name = name.strip()
css = css.strip()
css = UserCSS(name, user_id, css)
db.session.add(css)
db.session.commit()
return jsonify({"id": css.id})
@user.route("/custom_css/edit/<css_id>", methods=["GET"])
@discord_users_only()
def edit_custom_css_get(css_id):
cosmetics = db.session.query(Cosmetics).filter(Cosmetics.user_id == session['user_id']).first()
if not cosmetics or not cosmetics.css:
abort(403)
css = db.session.query(UserCSS).filter(UserCSS.id == css_id).first()
if not css:
abort(404)
if css.user_id != session['user_id']:
abort(403)
return render_template("usercss.html.j2", new=False, css=css)
@user.route("/custom_css/edit/<css_id>", methods=["POST"])
@discord_users_only()
def edit_custom_css_post(css_id):
cosmetics = db.session.query(Cosmetics).filter(Cosmetics.user_id == session['user_id']).first()
if not cosmetics or not cosmetics.css:
abort(403)
dbcss = db.session.query(UserCSS).filter(UserCSS.id == css_id).first()
if not dbcss:
abort(404)
if dbcss.user_id != session['user_id']:
abort(403)
name = request.form.get("name", None)
css = request.form.get("css", "")
if not name:
abort(400)
else:
name = name.strip()
css = css.strip()
dbcss.name = name
dbcss.css = css
db.session.commit()
return jsonify({"id": dbcss.id})
@user.route("/custom_css/edit/<css_id>", methods=["DELETE"])
@discord_users_only()
def edit_custom_css_delete(css_id):
cosmetics = db.session.query(Cosmetics).filter(Cosmetics.user_id == session['user_id']).first()
if not cosmetics or not cosmetics.css:
abort(403)
dbcss = db.session.query(UserCSS).filter(UserCSS.id == css_id).first()
if not dbcss:
abort(404)
if dbcss.user_id != session['user_id']:
abort(403)
db.session.delete(dbcss)
db.session.commit()
return jsonify({})
@user.route("/administrate_guild/<guild_id>", methods=["GET"]) @user.route("/administrate_guild/<guild_id>", methods=["GET"])
@discord_users_only() @discord_users_only()

View File

@ -9,3 +9,5 @@ from authenticated_users import AuthenticatedUsers
from guild_members import GuildMembers, list_all_guild_members from guild_members import GuildMembers, list_all_guild_members
from keyvalue_properties import KeyValueProperties, set_keyvalproperty, get_keyvalproperty, getexpir_keyvalproperty, setexpir_keyvalproperty, ifexists_keyvalproperty, delete_keyvalproperty from keyvalue_properties import KeyValueProperties, set_keyvalproperty, get_keyvalproperty, getexpir_keyvalproperty, setexpir_keyvalproperty, ifexists_keyvalproperty, delete_keyvalproperty
from messages import Messages, get_channel_messages from messages import Messages, get_channel_messages
from cosmetics import Cosmetics
from user_css import UserCSS

View File

@ -0,0 +1,7 @@
from titanembeds.database import db
class Cosmetics(db.Model):
__tablename__ = "cosmetics"
id = db.Column(db.Integer, primary_key=True) # Auto increment id
user_id = db.Column(db.String(255)) # Discord user id of user of cosmetics
css = db.Column(db.Boolean()) # If they can create/edit custom CSS

View File

@ -0,0 +1,13 @@
from titanembeds.database import db
class UserCSS(db.Model):
__tablename__ = "user_css"
id = db.Column(db.Integer, primary_key=True) # Auto increment id
name = db.Column(db.String(255)) # CSS Name
user_id = db.Column(db.String(255)) # Discord client ID of the owner of the css (can edit)
css = db.Column(db.Text()) # CSS contents
def __init__(self, name, user_id, css=None):
self.name = name
self.user_id = user_id
self.css = css

View File

@ -0,0 +1,57 @@
/*global $, ace, Materialize, newCSS*/
(function () {
var editor = ace.edit("css_editor");
function postForm() {
var name = $('#css_name').val();
var css = editor.getValue();
var funct = $.ajax({
dataType: "json",
method: "POST",
data: {"name": name, "css": css}
});
return funct.promise();
}
$(function(){
editor.getSession().setMode("ace/mode/css");
editor.setTheme("ace/theme/chrome");
$("#submit-btn").click(submitForm);
if (!newCSS) {
$("#delete-btn").click(delete_css);
}
});
function submitForm() {
var formPost = postForm();
formPost.done(function (data) {
if (newCSS) {
window.location.href = "edit/" + data.id;
} else {
Materialize.toast('CSS Updated!', 10000);
}
});
formPost.fail(function () {
Materialize.toast('Oh no! Something has failed posting your CSS!', 10000);
});
}
function delete_css() {
var candelete = confirm("Do you really want to delete this css???");
if (!candelete) {
return;
}
$.ajax({
type: 'DELETE',
success: function() {
alert("You have successfully deleted the CSS!");
window.location.href = "/user/dashboard";
},
error: function() {
Materialize.toast('Oh no! Something has failed deleting your CSS!', 10000);
}
});
}
})();

View File

@ -29,4 +29,35 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
<hr>
{% if cosmetics is none %}
<div class="row">
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>Cosmetics!</h4>
<p class="flow-text">Would you like to have <strong>cosmetics</strong> such as <em>custom CSS</em> for your embed?</p>
<a class="waves-effect waves-light btn" href="https://discord.io/Titan">Talk to us!</a>
</div>
</div>
</div>
{% endif %}
{% if css_list is not none %}
<p class="flow-text">
Create or modify your custom CSS.
<a class="waves-effect waves-light btn" href="{{ url_for("user.new_custom_css_get") }}">New</a>
</p>
<div class="row">
{% for css in css_list %}
<div class="col l4 m6 s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<p class="flow-text truncate"><code>#{{ css.id }}</code> {{ css.name }}</p>
<a class="waves-effect waves-light btn" href="{{ url_for("user.edit_custom_css_get", css_id=css.id) }}">Modify</a>
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -14,6 +14,10 @@
<title>{{ guild['name'] }} - Embed - Titan Embeds for Discord</title> <title>{{ guild['name'] }} - Embed - Titan Embeds for Discord</title>
{% include 'google_analytics.html.j2' %} {% include 'google_analytics.html.j2' %}
{% if css is not none %}
<style>{{ css.css }}</style>
{% endif %}
</head> </head>
<body> <body>
<div class="navbar-fixed"> <div class="navbar-fixed">

View File

@ -0,0 +1,65 @@
{% extends 'site_layout.html.j2' %}
{% block title %}{% if new %}New{% else %}Editing {{ css.name }} -{% endif %} User CSS{% endblock %}
{% block content %}
<h1>{% if new %}New{% else %}Editing {{ css.name }}{% endif %} - User Defined CSS</h1>
<p><strong>Note:</strong> This feature is only used for CSS. Any attempts to enter HTML or malicious CSS code
will have CSS cosmetic privilages removed, if caught. Please don't, we check the databases often. Thanks!</p>
{% if not new %}
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<div class="row">
<div class="col s12">
<p class="flow-text">Using your custom CSS</p>
<p><strong>This user defined CSS has a unique ID of <em style="font-size: 130%;">{{ css.id }}</em>.</strong></p>
<p>To use this CSS in the embed, you must apped a <code>?css={{ css.id }}</code> to the embed URL.</p>
<p>Something like this will work:</p>
<input readonly value="https://titanembeds.tk/embed/1234567890987654321?css={{ css.id }}" id="disabled" type="text" onClick="this.setSelectionRange(48, this.value.length)">
</div>
</div>
</div>
{% endif %}
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<div class="row">
<div class="col s12">
<p class="flow-text">Give your CSS a name</p>
<input placeholder="Some Lit CSS" id="css_name" type="text" {% if not new %}value="{{ css.name }}"{% endif %}>
<label for="css_name">Name</label>
</div>
<div class="col s12">
<p class="flow-text">Edit your CSS code here</p>
<div style="position: relative; height: 40vh;">
<div id="css_editor">{% if new %}/* Enter your CSS code here! */{% else %}{{ css.css }}{% endif %}</div>
</div>
<br>
</div>
<div class="col s12">
<a id="submit-btn" class="waves-effect waves-light btn">Submit</a>
{% if not new %}<a id="delete-btn" class="waves-effect waves-light btn red">Delete</a>{% endif %}
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js" integrity="sha256-xrr4HH5eSY+cFz4SH7ja/LaAi9qcEdjMpeMP49/iOLs=" crossorigin="anonymous"></script>
<script>
const newCSS = {% if new %}true{% else %}false{% endif %};
</script>
<script type="text/javascript" src="{{ url_for('static', filename='js/usercss.js') }}"></script>
{% endblock %}
{% block additional_head_elements %}
<style>
#css_editor {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
{% endblock %}