Compare commits
1 Commits
main
...
developmen
Author | SHA1 | Date |
---|---|---|
Andrew | a5187c751a | 4 years ago |
@ -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…
Reference in new issue