Initial development commit

development
Andrew 4 years ago
parent b607ded743
commit a5187c751a
  1. 158
      __init__.py
  2. 59
      config.py
  3. 37
      forms.py
  4. 126
      templates/pushbullet_settings.html
  5. 6
      templates/pushbullet_tep_settings_menu.html

@ -0,0 +1,158 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""-------------------------------------------------------------------------------------------
-- IMPORTS
-------------------------------------------------------------------------------------------"""
""" --- PYTHON IMPORTS --- """
import os
from os.path import dirname, abspath
""" --- STASHR CORE IMPORTS --- """
from stashr import log, utils
from stashr import database as stashr_database
from stashr.stashr import stashr_notification, stashr_notification
from stashr.api import create_json_return
""" --- STASHR PLUGIN IMPORTS --- """
from . import forms
from .config import pushconfig
""" --- STASHR PLUGIN DEPENDENCY IMPORTS --- """
try:
from pushbullet import Pushbullet
except:
utils.install_package('pushbullet.py')
from pushbullet import Pushbullet
""" --- FLASK EXTENSION IMPORTS --- """
from flask_login import login_required, current_user
""" --- STASHR DEPENDENCY IMPORTS --- """
from flask import Blueprint, render_template, request, redirect, flash, url_for
""" --- CREATE LOGGER --- """
logger = log.stashr_logger(__name__)
"""-------------------------------------------------------------------------------------------
-- PLUGIN
-------------------------------------------------------------------------------------------"""
__plugin_name__ = "Stashr Pushbullet"
__version__ = "0.1.0"
__author__ = "Stashr"
__description__ = "Send notifications via Pushbullet"
"""------------------------------
- PUSHBULLET OBJECT
------------------------------"""
pb = None
pb_active = False
"""------------------------------
- PLUGIN ROUTES
------------------------------"""
""" --- DEFINE BLUEPRINT --- """
bp = Blueprint('pushbullet', __name__, root_path=dirname(abspath(__file__)), template_folder='templates', static_folder='static')
""" --- PAGES --- """
@bp.route('/settings', methods=['GET', 'POST'])
@login_required
def pushbullet_settings_page():
if current_user.role != 'admin':
flash('Permission Denied', 'error')
return redirect(url_for('index_page'))
settings_form = forms.settings_form()
if request.method == 'POST':
if settings_form.validate():
pushconfig['PUSHBULLET']['api_key'] = settings_form.api_key.data
pushconfig['PUSHBULLET']['channel'] = settings_form.channel.data
pushconfig.write()
define_pushbullet()
flash('Pushbullet Settings Updated', 'success')
else:
for error in settings_form.errors.items():
flash(f'{error[0]}: {error[1]}', 'error')
return render_template(
'pushbullet_settings.html',
title='Pushbullet Settings',
settings_form=settings_form
)
""" --- API --- """
@bp.route('/api/settings', methods=['GET'])
def api_get_settings():
user = current_user
if not user.is_authenticated:
api_key = request.args.get('api_key')
if api_key == "":
return create_json_return('100')
user = stashr_database.session \
.query(stashr_database.Users) \
.filter(stashr_database.Users.api_key == api_key) \
.first()
if user is None:
return create_json_return('100')
if user.role.lower() != 'admin':
return create_json_return('401')
settings = pushconfig
return create_json_return('200', results=settings)
"""------------------------------
- PLUGIN FUNCTIONS
------------------------------"""
# --- Subscribe to stashr_notifications signal --- #
@stashr_notification.connect
def send_notification(*args, **kwargs):
global pb
global pb_active
if not pb_active:
define_pushbullet()
if 'title' in kwargs and 'message' in kwargs:
pb_channel = pb.get_channel(pushconfig['PUSHBULLET']['channel'])
pb_channel.push_note(kwargs['title'], kwargs['message'])
def define_pushbullet():
global pb
global pb_active
try:
pb = Pushbullet(pushconfig['PUSHBULLET']['api_key'])
pb_active = True
except Exception as e:
logger.error(e)
"""------------------------------
- REGISTER PLUGIN
------------------------------"""
def register():
return dict(
bep=dict(
blueprint=bp,
prefix='/pushbullet'
),
tep = dict(
settings_menu='pushbullet_tep_settings_menu.html',
)
)

@ -0,0 +1,59 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""-------------------------------------------------------------------------------------------
-- IMPORTS
-------------------------------------------------------------------------------------------"""
""" --- PYTHON IMPORTS --- """
import os, io, shutil
from os.path import dirname, abspath
from configobj import ConfigObj
from validate import Validator
"""-------------------------------------------------------------------------------------------
-- PUSHBULLET CONFIG
-------------------------------------------------------------------------------------------"""
class PushConfig(ConfigObj):
configspec = u"""
[PUSHBULLET]
api_key = string(default='')
channel = string(default='')
"""
def __init__(self):
super(PushConfig, self).__init__()
configspecfile = os.path.join(
dirname(abspath(__file__)),
'configspec.ini'
)
if not os.path.exists(configspecfile):
with open(configspecfile, 'w') as fd:
shutil.copyfileobj(io.StringIO(PushConfig.configspec), fd)
self.filename = os.path.join(
dirname(abspath(__file__)),
'config.ini'
)
self.configspec = configspecfile
self.encoding = "UTF8"
tmp = ConfigObj(self.filename, configspec=self.configspec, encoding=self.encoding)
validator = Validator()
tmp.validate(validator, copy=True)
self.merge(tmp)
if not os.path.exists(self.filename):
self.write()
"""-------------------------------------------------------------------------------------------
-- CONFIGURATION DEFINITION
-------------------------------------------------------------------------------------------"""
pushconfig = PushConfig()

@ -0,0 +1,37 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""-------------------------------------------------------------------------------------------
-- IMPORTS
-------------------------------------------------------------------------------------------"""
""" --- HUEY IMPORT --- """
""" --- PYTHON IMPORTS --- """
""" --- STASHR DEPENDENCY IMPORTS --- """
""" --- STASHR CORE IMPORTS --- """
from stashr import log, database
""" --- FLASK EXTENSION IMPORTS --- """
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError, NumberRange
""" --- CREATE LOGGER --- """
logger = log.stashr_logger(__name__)
"""-------------------------------------------------------------------------------------------
-- FORMS
-------------------------------------------------------------------------------------------"""
class settings_form(FlaskForm):
api_key = StringField(
'Pushbullet API Key',
)
channel = StringField(
'Pushbullet Channel',
)
settings_button = SubmitField(
'Save',
)

@ -0,0 +1,126 @@
{% extends "settings_page.html" %}
{% block header_script_files %}
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
{% endblock %}
{% block settings_pane %}
<div id="app">
<settings ref="settings" v-bind:settings="settings"></settings>
<modals ref="modal" v-bind:settings="settings"></modals>
</div>
{% endblock %}
{% block script %}
Vue.component('settings', {
props: ['settings'],
template: `
<div class="row r-10 m-2">
<div class="col col-12">
<div class="row">
<div class="col-sm-12 col-md-6 text-center text-md-start">
<h2>Thumbnailer</h2>
</div>
</div>
<hr />
<div class="row">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="settings-tab" data-bs-toggle="tab" data-bs-target="#settings" type="button" role="tab" aria-controls="settings" aria-selected="true">Settings</button>
</li>
</ul>
<div class="tab-content py-2" id="myTabContent">
<div class="tab-pane fade show active" id="settings" role="tabpanel" aria-labelledby="settings-tab">
<div class="row">
<table class="table table-striped">
<tbody>
<tr>
<th scope="row">{{ settings_form.api_key.label.text }}</th><td>[[ settings.PUSHBULLET.api_key ]]</td>
</tr>
<tr>
<th scope="row">{{ settings_form.channel.label.text }}</th><td>[[ settings.PUSHBULLET.channel ]]</td>
</tr>
</tbody>
</table>
</div>
<div class="row w-100">
<div class="col-12 text-end my-2">
<button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#settingsModal">Modify Settings</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`,
methods: {},
delimiters: ["[[","]]"]
})
Vue.component('modals',{
props: ['settings'],
template: `
<div>
<div class="modal" id="settingsModal" role="dialog" aria-labelledby="settingsModal" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="notesModalTitle">
Modify App Settings
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST">
<div class="modal-body">
{{ settings_form.csrf_token }}
<div class="mb-3">
{{ settings_form.api_key.label }}
{{ settings_form.api_key(class_='form-control', placeholder=settings_form.api_key.label.text) }}
</div>
<div class="mb-3">
{{ settings_form.channel.label }}
{{ settings_form.channel(class_='form-control', placeholder=settings_form.channel.label.text) }}
</div>
</div>
<div class="modal-footer">
{{ settings_form.settings_button(class_='btn btn-success') }}
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
`,
methods: {},
delimiters: ["[[","]]"]
})
var app = new Vue({
el: '#app',
data: {
settings: []
},
created() {
this.getSettings()
},
methods: {
getSettings() {
axios.get('{{ url_for('pushbullet.api_get_settings') }}')
.then(res => {
this.settings = res.data.results;
})
}
},
delimiters: ["[[","]]"]
})
{% endblock %}

@ -0,0 +1,6 @@
<li class="nav-item">
<a class="nav-link{% if request.path == url_for('pushbullet.pushbullet_settings_page') %} active{% endif %}" href="{{ url_for('pushbullet.pushbullet_settings_page') }}">
<i class="fas fa-bell"></i>
Pushbullet
</a>
</li>
Loading…
Cancel
Save