removing web gui

This commit is contained in:
Faiz Ahmed
2021-07-17 11:10:40 -04:00
parent fae35f057a
commit e285697f2d
42 changed files with 4 additions and 2333 deletions

View File

@@ -1,19 +0,0 @@
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
app = Flask(__name__)
SECRET_KEY = os.urandom(32)
app.config['SECRET_KEY'] = SECRET_KEY
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///config/app.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
from app import routes

View File

@@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -1,56 +0,0 @@
import configparser
config = configparser.ConfigParser()
CONFIG_PATH = 'app/config/config.ini'
BOT_SECTION = 'bot_envs'
CONFIG_KEYS = ['username', 'password', 'discord_bot_token', 'plex_user', 'plex_pass',
'role_id', 'plex_server_name', 'plex_libs', 'owner_id', 'channel_id',
'auto_remove_user']
def get_config():
"""
Function to return current config
"""
try:
config.read(CONFIG_PATH)
return config
except Exception as e:
print(e)
print('error in reading config')
return None
def change_config(key, value):
"""
Function to change the key, value pair in config
"""
try:
config = configparser.ConfigParser()
config.read(CONFIG_PATH)
except Exception as e:
print(e)
print("Cannot Read config.")
try:
config.set(BOT_SECTION, key, str(value))
except Exception as e:
config.add_section(BOT_SECTION)
config.set(BOT_SECTION, key, str(value))
try:
with open(CONFIG_PATH, 'w') as configfile:
config.write(configfile)
except Exception as e:
print(e)
print("Cannot write to config.")
def change_config_form(form_output):
"""
Function to change config on the basis of form_output from web
"""
for key in CONFIG_KEYS:
try:
change_config(key, form_output[key].data)
except:
pass

View File

@@ -1,52 +0,0 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField, IntegerField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField('Username',
validators=[DataRequired()])
password = PasswordField('Password',
validators=[DataRequired()])
submit = SubmitField('Save Changes')
class GeneralForm(FlaskForm):
username = StringField('Username',
validators=[DataRequired()])
password = PasswordField('Password',
validators=[DataRequired()])
submit = SubmitField('Save Changes')
class BotForm(FlaskForm):
discord_bot_token = StringField('Discord Bot Token',
validators=[DataRequired()])
role_id = StringField('Role Id',
validators=[DataRequired()])
channel_id = IntegerField('Channel Id',
validators=[DataRequired()])
owner_id = IntegerField('Owner Id',
validators=[DataRequired()])
# Auto Remove User
auto_remove_user = BooleanField('On')
submit = SubmitField('Save Changes')
class PlexForm(FlaskForm):
plex_user = StringField('Plex User',
validators=[DataRequired()])
plex_pass = StringField('Plex Pass',
validators=[DataRequired()])
plex_server_name = StringField('Plex Server Name',
validators=[DataRequired()])
plex_libs = StringField('Plex Libs',
validators=[DataRequired()])
submit = SubmitField('Save Changes')

View File

@@ -1,15 +0,0 @@
from app import db, login_manager
from flask_login import UserMixin
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
def __repr__(self):
return f"User('{self.username}')"

View File

@@ -1,129 +0,0 @@
from flask import render_template, flash, request, redirect, url_for
from flask_login import login_user, current_user, logout_user, login_required
import subprocess
import os.path
from app import app, db, bcrypt
from app.models import User
from app.forms import LoginForm, GeneralForm, BotForm, PlexForm
from app import configHandler
db.create_all()
BOT_SECTION = 'bot_envs'
proc = None
def manage_bot(option):
global proc
if option == 'start':
proc = subprocess.Popen(["python", "app/bot/Invitarr.py"])
elif option == 'kill':
if proc:
proc.terminate()
@app.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user, remember=True)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check email and password')
return render_template('login.html', title='Login', form=form)
@app.route('/logout')
@login_required
def logout():
flash('Logged out.')
logout_user()
return redirect(url_for('login'))
@app.route('/', methods=['GET', 'POST'])
@login_required
def home():
form = GeneralForm()
if request.method == 'GET':
user = User.query.all()[0]
form.username.data = user.username
form.password.data = user.password
elif request.method == 'POST':
if form.validate_on_submit():
user = User.query.all()[0]
user.username = form.username.data
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user.password = hashed_password
db.session.commit()
logout_user()
flash('Details updated.')
return redirect(url_for('login'))
return render_template('index.html', form=form)
@app.route('/bot', methods=['GET', 'POST'])
@login_required
def bot():
form = BotForm()
if request.method == 'GET':
try:
config = configHandler.get_config()
form.discord_bot_token.data = config.get(BOT_SECTION, 'discord_bot_token')
form.role_id.data = config.get(BOT_SECTION, 'role_id')
form.channel_id.data = config.get(BOT_SECTION, 'channel_id')
form.owner_id.data = config.get(BOT_SECTION, 'owner_id')
form.auto_remove_user.data = config.get(BOT_SECTION, 'auto_remove_user')
except:
pass
elif request.method == 'POST':
if form.validate_on_submit():
try:
configHandler.change_config_form(form)
flash('Settings updated.')
manage_bot('kill')
manage_bot('start')
except:
flash('Some error in updating settings')
return render_template('bot.html', form = form)
@app.route('/plex', methods=['GET', 'POST'])
@login_required
def plex():
form = PlexForm()
if request.method == 'GET':
try:
config = configHandler.get_config()
form.plex_user.data = config.get(BOT_SECTION, 'plex_user')
form.plex_pass.data = config.get(BOT_SECTION, 'plex_pass')
form.plex_server_name.data = config.get(BOT_SECTION, 'plex_server_name')
form.plex_libs.data = config.get(BOT_SECTION, 'plex_libs')
except:
pass
elif request.method == 'POST':
if form.validate_on_submit():
try:
configHandler.change_config_form(form)
flash('Settings updated.')
except:
flash('Some error in updating settings')
try:
manage_bot('kill')
manage_bot('start')
except Exception as e:
raise Exception(e)
return render_template('plex.html', form = form)
#starting bot process only if config file exist
if os.path.exists('/app/app/config/config.ini'):
try:
manage_bot('kill')
manage_bot('start')
except Exception as e:
manage_bot('kill')
print(e)
else:
print("Please configure bot in the webapi and click save changes to start the bot.")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FF4A4F;}
.st1{fill:#E94A4F;}
.st2{fill:#FFFFFF;}
.st3{fill:#2A2A2C;}
.st4{fill:#171719;}
.st5{fill:#57555C;}
.st6{fill:#3C3B41;}
.st7{fill:#C8C6CC;}
</style>
<circle class="st0" cx="256" cy="256" r="256"/>
<path class="st1" d="M512,256c0-13.4-1-26.6-3-39.4L397.9,105.5H108.4H82.9v241.4v97.6l0,0C128.5,486.4,189.2,512,256,512
C397.4,512,512,397.4,512,256z"/>
<path class="st2" d="M82.9,105.5v339.1c8,7.4,16.6,14.3,25.5,20.6V105.5L82.9,105.5L82.9,105.5z"/>
<rect x="334.6" y="152.9" class="st3" width="105.8" height="241.5"/>
<polygon class="st4" points="397.9,105.5 334.6,152.9 334.6,394.4 397.9,346.9 "/>
<rect x="82.9" y="105.5" class="st5" width="315" height="241.5"/>
<rect x="240.4" y="105.5" class="st6" width="157.5" height="241.5"/>
<path class="st2" d="M187.4,158.4l14,14c-6,5.2-11,11.6-14.6,18.8l-16.1-16.1c-6,5.8-15.4,5.7-21.3-0.2c-5.9-5.9-5.9-15.6,0-21.5
c3.3-3.3,7.7-4.7,11.9-4.4c-0.3-4.3,1.1-8.7,4.4-11.9c5.9-5.9,15.6-5.9,21.5,0C193.1,143,193.2,152.5,187.4,158.4z"/>
<path class="st7" d="M331.4,302.7c-3.3,3.3-7.7,4.7-11.9,4.4c0.3,4.3-1.1,8.7-4.4,11.9c-5.9,5.9-15.6,5.9-21.5,0
c-5.9-5.9-5.9-15.4-0.2-21.3L272,276.3v-5.2c1.6,0.3,3.2,0.5,4.8,0.5c6.6,0,12.5-2.7,16.8-7L310,281c5.9-5.8,15.4-5.7,21.3,0.2
C337.3,287.1,337.3,296.8,331.4,302.7z"/>
<path class="st2" d="M204,271.6c1.6,0,3.3-0.2,4.8-0.5v5.2l-21.4,21.4c5.8,5.9,5.7,15.4-0.2,21.3c-5.9,5.9-15.6,5.9-21.5,0
c-3.3-3.3-4.7-7.7-4.4-11.9c-4.3,0.3-8.7-1.1-11.9-4.4c-5.9-5.9-5.9-15.6,0-21.5c5.9-5.9,15.4-5.9,21.3-0.2l16.5-16.5
C191.5,268.9,197.4,271.6,204,271.6z"/>
<path class="st7" d="M331.4,174.9c-5.9,5.9-15.4,5.9-21.3,0.2l-16.1,16.1c-3.6-7.2-8.6-13.6-14.6-18.8l14-14
c-5.8-6-5.7-15.4,0.2-21.3c5.9-5.9,15.6-5.9,21.5,0c3.3,3.3,4.7,7.7,4.4,11.9c4.3-0.3,8.7,1.1,11.9,4.4
C337.3,159.4,337.3,169,331.4,174.9z"/>
<path class="st2" d="M286.7,237.7c2.6-6.1,4.1-12.9,4.1-20c0-27.9-22.6-50.5-50.5-50.5s-50.5,22.6-50.5,50.5c0,7.1,1.5,13.8,4.1,20
c-2.7,2.6-4.4,6.3-4.4,10.4c0,7.9,6.4,14.4,14.4,14.4c3.1,0,6-1,8.4-2.7c1.8,1.2,3.7,2.3,5.7,3.3v15.8c0,3.8,3.1,6.8,6.8,6.8h0.8
v-18.3h6.6v18.3h4.8v-18.3h6.6v18.3h4.8v-18.3h6.6v18.3h0.8c3.8,0,6.8-3.1,6.8-6.8v-15.8c2-1,3.9-2.1,5.7-3.3
c2.4,1.7,5.3,2.7,8.4,2.7c7.9,0,14.4-6.4,14.4-14.4C291.2,243.9,289.5,240.3,286.7,237.7z M222.7,226.2h-5c-5.3,0-9.6-4.3-9.6-9.6
v-5c0-5.3,4.3-9.6,9.6-9.6h5c5.3,0,9.6,4.3,9.6,9.6v5C232.4,221.8,228,226.2,222.7,226.2z M246.5,246.1h-6.1h-6.1
c-2.9,0-4.7-3.1-3.3-5.6l3-5.3l3-5.3c1.4-2.5,5.1-2.5,6.5,0l3,5.3l3,5.3C251.2,243,249.4,246.1,246.5,246.1z M272.7,216.5
c0,5.3-4.3,9.6-9.6,9.6h-5c-5.3,0-9.6-4.3-9.6-9.6v-5c0-5.3,4.3-9.6,9.6-9.6h5c5.3,0,9.6,4.3,9.6,9.6V216.5z"/>
<path class="st7" d="M286.7,237.7c2.6-6.1,4.1-12.9,4.1-20c0-27.9-22.6-50.5-50.5-50.5v60.8c1.3,0,2.5,0.6,3.3,1.9l3,5.3l3,5.3
c1.4,2.5-0.4,5.6-3.3,5.6h-6.1v21.2h3.3v18.3h4.8v-18.3h6.6v18.3h0.8c3.8,0,6.8-3.1,6.8-6.8v-15.9c2-1,3.9-2.1,5.7-3.3
c2.4,1.7,5.3,2.7,8.4,2.7c7.9,0,14.4-6.4,14.4-14.4C291.2,243.9,289.5,240.3,286.7,237.7z M272.7,216.5c0,5.3-4.3,9.6-9.6,9.6h-5
c-5.3,0-9.6-4.3-9.6-9.6v-5c0-5.3,4.3-9.6,9.6-9.6h5c5.3,0,9.6,4.3,9.6,9.6V216.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,86 +0,0 @@
/* Universal */
:root {
--main-bg-color: #000000;
--content-background: #17151C;
--secondary-content-background: #2A2731;
--primary-text-color: #FFFFFF;
}
body{
background-color: var(--main-bg-color);
color: var(--primary-text-color);
}
/* Header */
h3{
font-weight: bold;
display: inline-block;
margin: 0.5em 0 1.5em 0.25em;
padding-top: 0.5em;
}
.header img{
vertical-align: middle;
}
a.nav-link{
color: var(--primary-text-color);
}
.header button{
max-height: 50px;
/* margin: 1em 0.5em; */
}
/* Form */
.form-container{
padding: 1.5em;
padding-top: 2em;
border-radius: 0 0 10px 10px;
background-color: var(--content-background);
}
.form-stringfield{
background-color: var(--secondary-content-background);
color: var(--primary-text-color);
}
.form-stringfield:focus{
background-color: var(--secondary-content-background);
color: var(--primary-text-color);
}
.custom-checkbox{
padding-left: 3em;
}
/* Modal */
.modal-content{
background-color: var(--secondary-content-background);
padding: 1em !important;
}
.modal-body{
text-align: center;
}
.modal-header{
padding: 1em;
border-bottom: none;
}
.modal-header h4{
color: var(--primary-text-color)
}
/* Login Page */
.login{
margin: auto;
margin-top: 5em;
text-align: center;
}
.login h2{
margin-top: 1em;
font-weight: bold;
}

View File

@@ -1,194 +0,0 @@
{%extends 'layout.html'%}
{% block content %}
<div class="header mt-5 d-flex">
<img src="{{ url_for('static', filename='img/logo.svg') }}" class="img align-self-center" height="45">
<h3 class="align-self-center">Invitarr Configuration</h3>
<!-- <button class="ml-auto btn btn-danger align-self-center">Restart bot</button> -->
</div>
<nav>
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('home') }}">General</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="#">Bot</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('plex') }}">Plex</a>
</li>
<li class="nav-item ml-auto">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
</ul>
</nav>
<div class="form-container">
<!-- Form Section -->
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="form-group mb-3">
<div class="row">
<div class="col-md-3">
{{ form.discord_bot_token.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.discord_bot_token.errors %}
{{ form.discord_bot_token(class="form-control form-stringfield")}}
<small id="emailHelp" class="form-text text-muted">Some text describing this field</small>
<div class="invalid-feedback">
{% for error in form.discord_bot_token.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.discord_bot_token(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.role_id.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.role_id.errors %}
{{ form.role_id(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.role_id.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.role_id(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.channel_id.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.channel_id.errors %}
{{ form.channel_id(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.channel_id.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.channel_id(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.owner_id.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.owner_id.errors %}
{{ form.owner_id(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.owner_id.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.owner_id(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="my-3">
<div class="row">
<div class="col-md-3">
<p>Auto Remove User</p>
</div>
<div class="col-md-1"></div>
<div class="col-md-1 custom-control custom-control-inline custom-switch custom-checkbox">
{% if form.auto_remove_user.errors %}
{{ form.auto_remove_user(class="custom-control-input form-stringfield", id="removeSwitch")}}
{{ form.auto_remove_user.label(class="custom-control-label", for="removeSwitch")}}
<div class="invalid-feedback">
{% for error in form.auto_remove_user.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.auto_remove_user(class="custom-control-input form-stringfield", id="removeSwitch")}}
{{ form.auto_remove_user.label(class="custom-control-label", for="removeSwitch")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-5 submit-btn">
{{ form.submit(class="btn btn-primary submit-btn") }}
</div>
</form>
</div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
{% with messages = get_flashed_messages() %}
{% if messages %}
<h4>
{% for message in messages %}
{{ message }}
{% endfor %}
</h4>
{% endif %}
{% endwith %}
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block script %}
<script>
$(document).ready(()=> {
// Trigger flash modal
let messages = "{{ get_flashed_messages() }}";
if (typeof messages != 'undefined' && messages != '[]') {
$("#myModal").modal();
};
// Adding Validation
number_validaitons = ['channel_id', 'owner_id']
number_validaitons.forEach(element => {
$('#' + element).keyup(function () {
this.value = this.value.replace(/[^0-9\.]/g,'');
});
});
let checkbox_state = $('input[name=auto_remove_user]').is(':checked');
if(checkbox_state == false){
$('.custom-control-label').text('Off');
}
$('#removeSwitch').on('change', (e)=> {
checkbox_state = $('input[name=auto_remove_user]').is(':checked');
if(checkbox_state == false){
$('.custom-control-label').text('Off');
} else {
$('.custom-control-label').text('On');
}
});
});
</script>
{% endblock script %}

View File

@@ -1,131 +0,0 @@
{%extends 'layout.html'%}
{% block content %}
<div class="header mt-5">
<img src="{{ url_for('static', filename='img/logo.svg') }}" class="img" height="45">
<h3>Invitarr Configuration</h3>
</div>
<nav>
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" href="#">General</a>
</li>
<li class="nav-item">
<a class="nav-link " href="{{ url_for('bot') }}">Bot</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('plex') }}">Plex</a>
</li>
<li class="nav-item ml-auto">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
</ul>
</nav>
<div class="form-container">
<!-- Form Section -->
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="form-group mb-3">
<div class="row">
<div class="col-md-3">
{{ form.username.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.username.errors %}
{{ form.username(class="form-control form-stringfield")}}
<small id="emailHelp" class="form-text text-muted">Some text describing this field</small>
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.password.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.password.errors %}
{{ form.password(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-5 submit-btn">
{{ form.submit(class="btn btn-primary submit-btn") }}
</div>
</form>
</div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
{% with messages = get_flashed_messages() %}
{% if messages %}
<h4>
{% for message in messages %}
{{ message }}
{% endfor %}
</h4>
{% endif %}
{% endwith %}
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block script %}
<script>
$(document).ready(()=> {
// Trigger flash modal
let messages = "{{ get_flashed_messages() }}";
if (typeof messages != 'undefined' && messages != '[]') {
$("#myModal").modal();
};
// Adding Validation
number_validaitons = ['role_id', 'channel_id', 'owner_id']
number_validaitons.forEach(element => {
$('#' + element).keyup(function () {
this.value = this.value.replace(/[^0-9\.]/g,'');
});
});
let checkbox_state = $('input[name=auto_remove_user]').is(':checked');
if(checkbox_state == false){
$('.custom-control-label').text('Off');
}
$('#removeSwitch').on('change', (e)=> {
checkbox_state = $('input[name=auto_remove_user]').is(':checked');
if(checkbox_state == false){
$('.custom-control-label').text('Off');
} else {
$('.custom-control-label').text('On');
}
});
});
</script>
{% endblock script %}

View File

@@ -1,42 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}">
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-beta.1/dist/css/select2.min.css" rel="stylesheet" />
{% if title %}
<title>{{ title }} - Invitarr</title>
{% else %}
<title>Invitarr</title>
{% endif %}
</head>
<body>
<div class="container">
{% block content %}{% endblock %}
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-beta.1/dist/js/select2.min.js"></script>
{% block script %}{% endblock %}
<script>
$( document ).ready(function() {
$(".topbar-quicklinks").hide();
$(".topbar-toggle").click(() => {
$(".topbar-quicklinks").toggle();
});
});
</script>
</body>
</html>

View File

@@ -1,105 +0,0 @@
{%extends 'layout.html'%}
{% block content %}
<div class="login">
<img src="{{url_for('static', filename='img/logo.svg')}}" class="img" height="120">
<h2 class="mb-5">Invitarr</h2>
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="form-group mb-3">
<div class="row">
<div class="col-md-4 offset-4">
{% if form.username.errors %}
{{ form.username(class="form-control form-stringfield", placeholder="Username*")}}
<small id="emailHelp" class="form-text text-muted">Some text describing this field</small>
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-stringfield", placeholder="Username*")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-4 offset-4">
{% if form.password.errors %}
{{ form.password(class="form-control form-stringfield", placeholder="Password*")}}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-stringfield", placeholder="Password*")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-5 submit-btn">
{{ form.submit(class="btn btn-primary submit-btn") }}
</div>
</form>
</div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
{% with messages = get_flashed_messages() %}
{% if messages %}
<h4>
{% for message in messages %}
{{ message }}
{% endfor %}
</h4>
{% endif %}
{% endwith %}
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block script %}
<script>
$(document).ready(()=> {
// Trigger flash modal
let messages = "{{ get_flashed_messages() }}";
if (typeof messages != 'undefined' && messages != '[]') {
$("#myModal").modal();
};
// Adding Validation
number_validaitons = ['role_id', 'channel_id', 'owner_id']
number_validaitons.forEach(element => {
$('#' + element).keyup(function () {
this.value = this.value.replace(/[^0-9\.]/g,'');
});
});
let checkbox_state = $('input[name=auto_remove_user]').is(':checked');
if(checkbox_state == false){
$('.custom-control-label').text('Off');
}
$('#removeSwitch').on('change', (e)=> {
checkbox_state = $('input[name=auto_remove_user]').is(':checked');
if(checkbox_state == false){
$('.custom-control-label').text('Off');
} else {
$('.custom-control-label').text('On');
}
});
});
</script>
{% endblock script %}

View File

@@ -1,155 +0,0 @@
{%extends 'layout.html'%}
{% block content %}
<div class="header mt-5">
<img src="{{ url_for('static', filename='img/logo.svg') }}" class="img" height="45">
<h3>Invitarr Configuration</h3>
</div>
<nav>
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('home') }}">General</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('bot') }}">Bot</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="#">Plex</a>
</li>
<li class="nav-item ml-auto">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
</ul>
</nav>
<div class="form-container">
<!-- Form Section -->
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="form-group mb-3">
<div class="row">
<div class="col-md-3">
{{ form.plex_user.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.plex_user.errors %}
{{ form.plex_user(class="form-control form-stringfield")}}
<small id="emailHelp" class="form-text text-muted">Some text describing this field</small>
<div class="invalid-feedback">
{% for error in form.plex_user.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.plex_user(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.plex_pass.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.plex_pass.errors %}
{{ form.plex_pass(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.plex_pass.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.plex_pass(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.plex_server_name.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.plex_server_name.errors %}
{{ form.plex_server_name(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.plex_server_name.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.plex_server_name(class="form-control form-stringfield")}}
{% endif %}
</div>
</div>
</div>
<div class="form-group my-3">
<div class="row">
<div class="col-md-3">
{{ form.plex_libs.label(class="form-control-label")}}
</div>
<div class="col-md-1"></div>
<div class="col-md-6">
{% if form.plex_libs.errors %}
{{ form.plex_libs(class="form-control form-stringfield")}}
<div class="invalid-feedback">
{% for error in form.plex_libs.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.plex_libs(class="form-control form-stringfield")}}
{% endif %}
<small id="emailHelp" class="form-text text-muted">Enter comma seperated values</small>
</div>
</div>
</div>
<div class="form-group my-5 submit-btn">
{{ form.submit(class="btn btn-primary submit-btn") }}
</div>
</form>
</div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
{% with messages = get_flashed_messages() %}
{% if messages %}
<h4>
{% for message in messages %}
{{ message }}
{% endfor %}
</h4>
{% endif %}
{% endwith %}
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block script %}
<script>
$(document).ready(()=> {
// Trigger flash modal
let messages = "{{ get_flashed_messages() }}";
if (typeof messages != 'undefined' && messages != '[]') {
$("#myModal").modal();
};
$(".plex-libs").select2({
theme: "classic",
tags: true,
tokenSeparators: [',', ' ']
});
});
</script>
{% endblock script %}

4
app/config/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@@ -1,7 +0,0 @@
#! /usr/bin/env bash
FILE=/app/app/config/app.db
if [ -f "$FILE" ]; then
echo "$FILE exists."
else
python setup.py
fi

View File

@@ -1,34 +0,0 @@
aiohttp==3.6.2
async-timeout==3.0.1
attrs==19.3.0
bcrypt==3.1.7
certifi==2020.4.5.2
cffi==1.14.0
chardet==3.0.4
click==7.1.2
discord.py
Flask==1.1.2
Flask-Bcrypt==0.7.1
Flask-Login==0.5.0
Flask-SQLAlchemy==2.4.3
Flask-WTF==0.14.3
idna==2.9
idna-ssl==1.1.0
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
multidict==4.7.6
plex.py==0.9.0
PlexAPI==4.0.0
pycparser==2.20
python-dotenv==0.13.0
requests==2.23.0
six==1.15.0
SQLAlchemy==1.3.17
typing-extensions==3.7.4.2
urllib3==1.25.9
websockets==8.1
Werkzeug==1.0.1
WTForms==2.3.1
yarl==1.4.2
texttable

View File

@@ -1,17 +0,0 @@
from app import app
from app import db, bcrypt
from app.models import User
from os import path
'''
if path.exists("app.config.app.db") is False:
db.create_all()
try:
hashed_password = bcrypt.generate_password_hash(DEFAULT_PASS).decode('utf-8')
user = User(username=DEFAULT_USER, password=hashed_password)
db.session.add(user)
db.session.commit()
except:
print("Some error in setting up.")
'''
if __name__ == "__main__":
app.run(debug=True)

View File

@@ -1,14 +0,0 @@
from app import db, bcrypt
from app.models import User
DEFAULT_USER = "admin"
DEFAULT_PASS = "admin"
db.create_all()
try:
hashed_password = bcrypt.generate_password_hash(DEFAULT_PASS).decode('utf-8')
user = User(username=DEFAULT_USER, password=hashed_password)
db.session.add(user)
db.session.commit()
except:
print("Some error in setting up.")

View File

@@ -1,4 +0,0 @@
[uwsgi]
enable-threads = true
module = run
callable = app