mirror of
				https://github.com/TitanEmbeds/Titan.git
				synced 2025-10-31 13:59:08 +01:00 
			
		
		
		
	Implemented Cosmetics and User Custom CSS, closes #7
This commit is contained in:
		| @@ -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) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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() | ||||||
|   | |||||||
| @@ -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 | ||||||
							
								
								
									
										7
									
								
								webapp/titanembeds/database/cosmetics.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								webapp/titanembeds/database/cosmetics.py
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										13
									
								
								webapp/titanembeds/database/user_css.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								webapp/titanembeds/database/user_css.py
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										57
									
								
								webapp/titanembeds/static/js/usercss.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								webapp/titanembeds/static/js/usercss.js
									
									
									
									
									
										Normal 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); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | })(); | ||||||
| @@ -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 %} | ||||||
|   | |||||||
| @@ -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"> | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								webapp/titanembeds/templates/usercss.html.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								webapp/titanembeds/templates/usercss.html.j2
									
									
									
									
									
										Normal 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 %} | ||||||
		Reference in New Issue
	
	Block a user