mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Merge branch 'main' into feat/german-translation
This commit is contained in:
@@ -718,6 +718,10 @@ input[readonly] {
|
||||
}
|
||||
|
||||
/* Devices */
|
||||
#txtIconFA {
|
||||
min-width: 18px;
|
||||
}
|
||||
|
||||
.drp-edit
|
||||
{
|
||||
cursor: pointer;
|
||||
@@ -795,7 +799,8 @@ input[readonly] {
|
||||
#networkTree .netPort
|
||||
{
|
||||
float:left;
|
||||
display:inline;
|
||||
display:inline;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#networkTree .portBckgIcon
|
||||
@@ -816,7 +821,8 @@ input[readonly] {
|
||||
{
|
||||
width: 25px;;
|
||||
float:left;
|
||||
display:inline;
|
||||
display:inline;
|
||||
text-align: center;
|
||||
}
|
||||
#networkTree .netCollapse
|
||||
{
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="txtName" type="text" value="--">
|
||||
<span class="input-group-addon"><i class="fa fa-pencil pointer" onclick="editDrp('txtName');"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -196,9 +196,9 @@
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="txtIcon" type="text" value="--">
|
||||
<span class="input-group-addon"><i class="fa" id="txtIconFA" onclick="editDrp('txtIcon');"></i></span>
|
||||
<input class="form-control" id="txtIcon" type="text" value="--">
|
||||
<span class="input-group-addon" title='<?= lang('DevDetail_button_OverwriteIcons_Tooltip');?>'><i class="fa fa-copy pointer" onclick="askOverwriteIconType();"></i></span>
|
||||
<span class="input-group-addon"><i class="fa fa-pencil pointer" onclick="editDrp('txtIcon');"></i></span>
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
<span class="fa fa-caret-down"></span>
|
||||
@@ -749,6 +749,11 @@ function main () {
|
||||
}
|
||||
});
|
||||
|
||||
// Show device icon as it changes
|
||||
$('#txtIcon').on('change input', function() {
|
||||
$('#txtIconFA').removeClass().addClass(`fa fa-${$(this).val()} pointer`)
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1285,7 +1290,8 @@ function getDeviceData (readAllData=false) {
|
||||
$('#txtOwner').val (deviceData['dev_Owner']);
|
||||
$('#txtDeviceType').val (deviceData['dev_DeviceType']);
|
||||
$('#txtVendor').val (deviceData['dev_Vendor']);
|
||||
$('#txtIcon').val (initDefault(deviceData['dev_Icon'], 'laptop'));
|
||||
$('#txtIcon').val (initDefault(deviceData['dev_Icon'], 'laptop'));
|
||||
$('#txtIcon').trigger('change')
|
||||
|
||||
if (deviceData['dev_Favorite'] == 1) {$('#chkFavorite').iCheck('check');} else {$('#chkFavorite').iCheck('uncheck');}
|
||||
$('#txtGroup').val (deviceData['dev_Group']);
|
||||
@@ -1700,6 +1706,7 @@ function setTextValue (textElement, textValue) {
|
||||
$('#'+textElement).attr ('data-myvalue', textValue);
|
||||
$('#'+textElement).val (textValue);
|
||||
}
|
||||
$('#'+textElement).trigger('change')
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -617,23 +617,20 @@
|
||||
var sizeCoefficient = 1
|
||||
|
||||
function initTree(myHierarchy)
|
||||
{
|
||||
{
|
||||
// calculate the font size of the leaf nodes to fit everything into the tree area
|
||||
leafNodesCount == 0 ? 1 : leafNodesCount;
|
||||
emSize = ((treeAreaHeight/(25*leafNodesCount)).toFixed(2));
|
||||
emSize = emSize > 1 ? 1 : emSize;
|
||||
|
||||
emSize = ((treeAreaHeight/(25*leafNodesCount)).toFixed(2));
|
||||
emSize = emSize > 1 ? 1 : emSize;
|
||||
|
||||
// nodeHeight = ((emSize*100*0.30).toFixed(0))
|
||||
nodeHeight = ((emSize*100*0.30).toFixed(0))
|
||||
|
||||
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${$('.content-header').width()}px`)
|
||||
|
||||
console.log('here')
|
||||
|
||||
myTree = Treeviz.create({
|
||||
htmlId: "networkTree",
|
||||
|
||||
renderNode: nodeData => {
|
||||
renderNode: nodeData => {
|
||||
var fontSize = "font-size:"+emSize+"em;";
|
||||
|
||||
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
|
||||
@@ -641,52 +638,51 @@
|
||||
(port == "" || port == 0 ) ? portBckgIcon = `<i class="fa fa-wifi"></i>` : portBckgIcon = `<i class="fa fa-ethernet"></i>`;
|
||||
|
||||
// Build HTML for individual nodes in the network diagram
|
||||
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ? "<div class='netIcon ' ><i class='fa fa-"+nodeData.data.icon +"'></i></div>" : "";
|
||||
devicePort = `<div class='netPort ' style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em" >${port}</div> <div class="portBckgIcon" style="margin-left:-${emSize*sizeCoefficient}em;">${portBckgIcon}</div>`;
|
||||
collapseExpandIcon = nodeData.data.hiddenChildren ? "square-plus" :"square-minus";
|
||||
collapseExpandHtml = (nodeData.data.hasChildren) ? "<div class='netCollapse' style='font-size:"+emSize*sizeCoefficient+"em;' data-mytreepath='"+nodeData.data.path+"' data-mytreemac='"+nodeData.data.mac+"'><i class='fa fa-"+ collapseExpandIcon +" pointer'></i></div>" : "";
|
||||
statusCss = " netStatus-" + nodeData.data.status;
|
||||
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ? `<div class="netIcon"><i class="fa fa-${nodeData.data.icon}"></i></div>` : "";
|
||||
devicePort = `<div class="netPort" style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em">${port}</div> <div class="portBckgIcon" style="margin-left:-${emSize*sizeCoefficient}em;">${portBckgIcon}</div>`;
|
||||
collapseExpandIcon = nodeData.data.hiddenChildren ? "square-plus" : "square-minus";
|
||||
collapseExpandHtml = nodeData.data.hasChildren ? `<div class="netCollapse" style="font-size:${emSize*sizeCoefficient}em;" data-mytreepath='${nodeData.data.path}" data-mytreemac="${nodeData.data.mac}"><i class='fa fa-${collapseExpandIcon} pointer"></i></div>` : "";
|
||||
statusCss = ` netStatus-${nodeData.data.status}`;
|
||||
|
||||
selectedNodeMac = $(".nav-tabs-custom .active a").attr('data-mytabmac')
|
||||
|
||||
highlightedCss = nodeData.data.mac == selectedNodeMac ? " highlightedNode" : "";
|
||||
highlightedCss = nodeData.data.mac == selectedNodeMac ? " highlightedNode" : "";
|
||||
|
||||
return result = `<div class='box ${(nodeData.data.hasChildren)? "pointer":""} ${statusCss} ${highlightedCss}'
|
||||
data-mytreemacmain='${nodeData.data.mac}'
|
||||
style='height:${nodeData.settings.nodeHeight}px;${fontSize}
|
||||
return result = `<div class="box ${nodeData.data.hasChildren ? "pointer":""} ${statusCss} ${highlightedCss}"
|
||||
data-mytreemacmain="${nodeData.data.mac}"
|
||||
style="height:${nodeData.settings.nodeHeight}px;${fontSize}"
|
||||
>
|
||||
<div class='netNodeText '>\
|
||||
<strong>${devicePort} ${deviceIcon}
|
||||
<span class='spanNetworkTree anonymizeDev'>${nodeData.data.name}</span>\
|
||||
</strong>
|
||||
${collapseExpandHtml}
|
||||
</div></div>`;
|
||||
},
|
||||
<div class="netNodeText">
|
||||
<strong>${devicePort} ${deviceIcon}
|
||||
<span class="spanNetworkTree anonymizeDev">${nodeData.data.name}</span>
|
||||
</strong>
|
||||
${collapseExpandHtml}
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
onNodeClick: nodeData => {
|
||||
console.log(this)
|
||||
},
|
||||
onNodeClick: nodeData => {
|
||||
console.log(this)
|
||||
},
|
||||
mainAxisNodeSpacing: 'auto',
|
||||
// mainAxisNodeSpacing: 3,
|
||||
secondaryAxisNodeSpacing: 0.3,
|
||||
nodeHeight: nodeHeight.toString(),
|
||||
nodeHeight: nodeHeight.toString(),
|
||||
marginTop: '5',
|
||||
hasZoom: false,
|
||||
hasPan: false,
|
||||
// marginLeft: '15',
|
||||
idKey: "id",
|
||||
hasFlatData: false,
|
||||
hasFlatData: false,
|
||||
linkWidth: (nodeData) => 3,
|
||||
linkColor: (nodeData) => "#ffcc80",
|
||||
onNodeClick: (nodeData) => handleNodeClick(nodeData),
|
||||
relationnalField: "children",
|
||||
relationnalField: "children",
|
||||
});
|
||||
|
||||
|
||||
console.log(myHierarchy)
|
||||
|
||||
|
||||
myTree.refresh(myHierarchy);
|
||||
|
||||
myTree.refresh(myHierarchy);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -504,25 +504,13 @@
|
||||
"Email_icon" : "<i class=\"fa fa-at\"></i>",
|
||||
"REPORT_MAIL_name" : "Enable email",
|
||||
"REPORT_MAIL_description" : "If enabled an email is sent out with a list of changes you nove subscribed to. Please also fill out all remaining settings related to the SMTP setup below. If facing issues, set <code>LOG_LEVEL</code> to <code>debug</code> and check the <a href=\"/maintenance.php#tab_Logging\">error log</a>.",
|
||||
"SMTP_SERVER_name" : "SMTP server URL",
|
||||
"SMTP_SERVER_description" : "The SMTP server host URL. For example <code>smtp-relay.sendinblue.com</code>. To use Gmail as an SMTP server <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SMTP.md\">follow this guide</a>",
|
||||
"SMTP_PORT_name" : "SMTP server PORT",
|
||||
"SMTP_PORT_description" : "Port number used for the SMTP connection. Set to <code>0</code> if you do not want to use a port when connecting to the SMTP server.",
|
||||
"SMTP_SKIP_LOGIN_name" : "Skip authentication",
|
||||
"SMTP_SKIP_LOGIN_description" : "Do not use authentication when connecting to the SMTP server.",
|
||||
"SMTP_USER_name" : "SMTP user",
|
||||
"SMTP_USER_description" : "The user name used to login into the SMTP server (sometimes a full email address).",
|
||||
"SMTP_PASS_name" : "SMTP password",
|
||||
"SMTP_PASS_description" : "The SMTP server password. ",
|
||||
"SMTP_SKIP_TLS_name" : "Do not use TLS",
|
||||
"SMTP_SKIP_TLS_description" : "Disable TLS when connecting to your SMTP server.",
|
||||
"SMTP_FORCE_SSL_name" : "Force SSL",
|
||||
"SMTP_FORCE_SSL_description" : "Force SSL when connecting to your SMTP server.",
|
||||
"SYSTEM_TITLE" : "System Information",
|
||||
"REPORT_TO_name" : "Send email to",
|
||||
"REPORT_TO_description" : "Email address to which the notification will be send to.",
|
||||
"REPORT_FROM_name" : "Email subject",
|
||||
"REPORT_FROM_description" : "Notification email subject line. Some SMTP servers need this to be an email.",
|
||||
"SYSTEM_TITLE" : "System Information",
|
||||
|
||||
"REPORT_TO_name" : "deprecated",
|
||||
"REPORT_TO_description" : "deprecated",
|
||||
"REPORT_FROM_name" : "deprecated",
|
||||
"REPORT_FROM_description" : "deprecated",
|
||||
|
||||
"Webhooks_display_name" : "Webhooks",
|
||||
"Webhooks_icon" : "<i class=\"fa fa-circle-nodes\"></i>",
|
||||
"REPORT_WEBHOOK_name" : "Enable Webhooks",
|
||||
@@ -536,17 +524,7 @@
|
||||
"WEBHOOK_SIZE_name" : "Max payload size",
|
||||
"WEBHOOK_SIZE_description" : "The maximum size of the webhook payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended.",
|
||||
"WEBHOOK_SECRET_name": "HMAC Secret",
|
||||
"WEBHOOK_SECRET_description": "When set, use this secret to generate the SHA256-HMAC hex digest value of the request body, which will be passed as the <code>X-Webhook-Signature</code> header to the request. You can find more informations <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_SECRET.md\">here</a>.",
|
||||
"Apprise_display_name" : "Apprise",
|
||||
"Apprise_icon" : "<i class=\"fa fa-bullhorn\"></i>",
|
||||
"REPORT_APPRISE_name" : "Enable Apprise",
|
||||
"REPORT_APPRISE_description" : "Enable sending notifications via <a target=\"_blank\" href=\"https://hub.docker.com/r/caronc/apprise\">Apprise</a>.",
|
||||
"APPRISE_HOST_name" : "Apprise host URL",
|
||||
"APPRISE_HOST_description" : "Apprise host URL starting with <code>http://</code> or <code>https://</code>. (do not forget to include <code>/notify</code> at the end)",
|
||||
"APPRISE_URL_name" : "Apprise notification URL",
|
||||
"APPRISE_URL_description" : "Apprise notification target URL. For example for Telegram it would be <code>tgram://{bot_token}/{chat_id}</code>.",
|
||||
"APPRISE_SIZE_name" : "Max payload size",
|
||||
"APPRISE_SIZE_description" : "The maximum size of the apprise payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended.",
|
||||
"WEBHOOK_SECRET_description": "When set, use this secret to generate the SHA256-HMAC hex digest value of the request body, which will be passed as the <code>X-Webhook-Signature</code> header to the request. You can find more informations <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_SECRET.md\">here</a>.",
|
||||
"NTFY_display_name" : "NTFY",
|
||||
"NTFY_icon" : "<i class=\"fa fa-terminal\"></i>",
|
||||
"REPORT_NTFY_name" : "Enable NTFY",
|
||||
@@ -564,9 +542,7 @@
|
||||
"REPORT_PUSHSAFER_name" : "Enable Pushsafer",
|
||||
"REPORT_PUSHSAFER_description" : "Enable sending notifications via <a target=\"_blank\" href=\"https://www.pushsafer.com/\">Pushsafer</a>.",
|
||||
"PUSHSAFER_TOKEN_name" : "Pushsafer token",
|
||||
"PUSHSAFER_TOKEN_description" : "Your secret Pushsafer API key (token).",
|
||||
"APPRISE_PAYLOAD_name" : "Payload type",
|
||||
"APPRISE_PAYLOAD_description" : "Select the payoad type sent to Apprise. For example <code>html</code> works well with emails, <code>text</code> with chat apps, such as Telegram.",
|
||||
"PUSHSAFER_TOKEN_description" : "Your secret Pushsafer API key (token).",
|
||||
"MQTT_display_name" : "MQTT",
|
||||
"MQTT_icon" : "<i class=\"fa fa-square-rss\"></i>",
|
||||
"REPORT_TITLE" : "Report",
|
||||
|
||||
@@ -542,8 +542,8 @@ Required attributes are:
|
||||
| `"name"` | Displayed on the Settings page. An array of localized strings. See Localized strings below. |
|
||||
| `"description"` | Displayed on the Settings page. An array of localized strings. See Localized strings below. |
|
||||
| (optional) `"events"` | Specifies whether to generate an execution button next to the input field of the setting. Supported values: |
|
||||
| | - `test` |
|
||||
| | - `run` |
|
||||
| | - `"test"` - For notification plugins testing |
|
||||
| | - `"run"` - Regular plugins testing |
|
||||
| (optional) `"override_value"` | Used to determine a user-defined override for the setting. Useful for template-based plugins, where you can choose to leave the current value or override it with the value defined in the setting. (Work in progress) |
|
||||
| (optional) `"events"` | Used to trigger the plugin. Usually used on the `RUN` setting. Not fully tested in all scenarios. Will show a play button next to the setting. After clicking, an event is generated for the backend in the `Parameters` database table to process the front-end event on the next run. |
|
||||
|
||||
@@ -619,7 +619,8 @@ The UI will adjust how columns are displayed in the UI based on the resolvers de
|
||||
| Supported Types | Description |
|
||||
| -------------- | ----------- |
|
||||
| `label` | Displays a column only. |
|
||||
| `text` | Makes a column editable, and a save icon is displayed next to it. See below for information on `threshold`, `replace`. |
|
||||
| `textarea_readonly` | Generates a read only text area and cleans up the text to display it somewhat formatted with new lines preserved. |
|
||||
| See below for information on `threshold`, `replace`. | |
|
||||
| | |
|
||||
| `options` Property | Used in conjunction with types like `threshold`, `replace`, `regex`. |
|
||||
| `threshold` | The `options` array contains objects ordered from the lowest `maximum` to the highest. The corresponding `hexColor` is used for the value background color if it's less than the specified `maximum` but more than the previous one in the `options` array. |
|
||||
|
||||
8
front/plugins/_publisher_apprise/README.md
Executable file
8
front/plugins/_publisher_apprise/README.md
Executable file
@@ -0,0 +1,8 @@
|
||||
## Overview
|
||||
|
||||
[Apprise](front/plugins/arp_scan/README.md) is a notification gateway/publisher that allows you to push notifications to 80+ different services.
|
||||
|
||||
### Usage
|
||||
|
||||
- Go to settings and fill in relevant details.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# Based on the work of https://github.com/leiweibau/Pi.Alert
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
@@ -15,87 +14,115 @@ sys.path.extend(["/home/pi/pialert/front/plugins", "/home/pi/pialert/pialert"])
|
||||
import conf
|
||||
from plugin_helper import Plugin_Objects
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ, noti_struc
|
||||
from helper import timeNowTZ, noti_obj, get_setting_value
|
||||
from notification import Notification_obj
|
||||
from database import DB
|
||||
|
||||
|
||||
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
|
||||
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
|
||||
|
||||
pluginName = 'APPRISE'
|
||||
|
||||
def main():
|
||||
|
||||
mylog('verbose', ['[APPRISE](publisher) In script'])
|
||||
mylog('verbose', [f'[{pluginName}](publisher) In script'])
|
||||
|
||||
# Check if basic config settings supplied
|
||||
if check_config() == False:
|
||||
mylog('none', [f'[{pluginName}] Error: Publisher notification gateway not set up correctly. Check your pialert.conf {pluginName}_* variables.'])
|
||||
return
|
||||
|
||||
parser = argparse.ArgumentParser(description='APPRISE publisher Plugin')
|
||||
values = parser.parse_args()
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
speedtest_result = send()
|
||||
# Create a Notification_obj instance
|
||||
notifications = Notification_obj(db)
|
||||
|
||||
plugin_objects.add_object(
|
||||
primaryId = 'APPRISE',
|
||||
secondaryId = timeNowTZ(),
|
||||
watched1 = speedtest_result['download_speed'],
|
||||
watched2 = speedtest_result['upload_speed'],
|
||||
watched3 = 'null',
|
||||
watched4 = 'null',
|
||||
extra = 'null',
|
||||
foreignKey = 'null'
|
||||
)
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
result = send(notification["HTML"], notification["Text"])
|
||||
|
||||
# Log result
|
||||
plugin_objects.add_object(
|
||||
primaryId = pluginName,
|
||||
secondaryId = timeNowTZ(),
|
||||
watched1 = notification["GUID"],
|
||||
watched2 = result,
|
||||
watched3 = 'null',
|
||||
watched4 = 'null',
|
||||
extra = 'null',
|
||||
foreignKey = 'null'
|
||||
)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def check_config():
|
||||
if conf.APPRISE_URL == '' or conf.APPRISE_HOST == '':
|
||||
mylog('none', ['[Check Config] Error: Apprise service not set up correctly. Check your pialert.conf APPRISE_* variables.'])
|
||||
if get_setting_value('APPRISE_URL') == '' or get_setting_value('APPRISE_HOST') == '':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def send(msg: noti_struc):
|
||||
html = msg.html
|
||||
text = msg.text
|
||||
def send(html, text):
|
||||
|
||||
payloadData = ''
|
||||
result = ''
|
||||
|
||||
# limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB)
|
||||
limit = conf.APPRISE_SIZE
|
||||
limit = get_setting_value('APPRISE_SIZE')
|
||||
|
||||
# truncate size
|
||||
if conf.APPRISE_PAYLOAD == 'html':
|
||||
if len(msg.html) > limit:
|
||||
payloadData = msg.html[:limit] + " <h1> (text was truncated)</h1>"
|
||||
if get_setting_value('APPRISE_PAYLOAD') == 'html':
|
||||
if len(html) > limit:
|
||||
payloadData = html[:limit] + "<h1>(text was truncated)</h1>"
|
||||
else:
|
||||
payloadData = msg.html
|
||||
if conf.APPRISE_PAYLOAD == 'text':
|
||||
if len(msg.text) > limit:
|
||||
payloadData = msg.text[:limit] + " (text was truncated)"
|
||||
payloadData = html
|
||||
if get_setting_value('APPRISE_PAYLOAD') == 'text':
|
||||
if len(text) > limit:
|
||||
payloadData = text[:limit] + " (text was truncated)"
|
||||
else:
|
||||
payloadData = msg.text
|
||||
payloadData = text
|
||||
|
||||
# Define Apprise compatible payload (https://github.com/caronc/apprise-api#stateless-solution)
|
||||
|
||||
_json_payload = {
|
||||
"urls": conf.APPRISE_URL,
|
||||
"urls": get_setting_value('APPRISE_URL'),
|
||||
"title": "Pi.Alert Notifications",
|
||||
"format": conf.APPRISE_PAYLOAD,
|
||||
"format": get_setting_value('APPRISE_PAYLOAD'),
|
||||
"body": payloadData
|
||||
}
|
||||
|
||||
try:
|
||||
# try runnning a subprocess
|
||||
p = subprocess.Popen(["curl","-i","-X", "POST" ,"-H", "Content-Type:application/json" ,"-d", json.dumps(_json_payload), conf.APPRISE_HOST], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
p = subprocess.Popen(["curl","-i","-X", "POST" ,"-H", "Content-Type:application/json" ,"-d", json.dumps(_json_payload), get_setting_value('APPRISE_HOST')], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
stdout, stderr = p.communicate()
|
||||
# write stdout and stderr into .log files for debugging if needed
|
||||
|
||||
|
||||
# write stdout and stderr into .log files for debugging if needed
|
||||
# Log the stdout and stderr
|
||||
mylog('debug', [stdout, stderr]) # TO-DO should be changed to mylog
|
||||
mylog('debug', [stdout, stderr])
|
||||
|
||||
# log result
|
||||
result = stdout
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
# An error occurred, handle it
|
||||
mylog('none', [e.output])
|
||||
|
||||
# log result
|
||||
result = e.output
|
||||
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -1,22 +1,30 @@
|
||||
{
|
||||
"code_name": "internet_speedtest",
|
||||
"unique_prefix": "INTRSPD",
|
||||
"code_name": "_publisher_apprise",
|
||||
"unique_prefix": "APPRISE",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name" : [{
|
||||
"display_name" : [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string" : "Internet speedtest"
|
||||
}],
|
||||
"string" : "Apprise publisher"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Habilitar Apprise"
|
||||
}
|
||||
],
|
||||
"icon":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "<i class=\"fa-solid fa-gauge-high\"></i>"
|
||||
"string" : "<i class=\"fa-solid fa-bullhorn\"></i>"
|
||||
}],
|
||||
"description": [{
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string" : "A plugin to perform a scheduled internet speedtest."
|
||||
}],
|
||||
"string" : "A plugin to publish a notification via the Apprise gateway."
|
||||
}
|
||||
],
|
||||
"params" : [],
|
||||
"database_column_definitions":
|
||||
[
|
||||
@@ -94,7 +102,7 @@
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Test run on"
|
||||
"string" : "Sent when"
|
||||
}]
|
||||
},
|
||||
{
|
||||
@@ -118,60 +126,26 @@
|
||||
"column": "Watched_Value1",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "threshold",
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [
|
||||
{
|
||||
"maximum": 1,
|
||||
"hexColor": "#D33115"
|
||||
},
|
||||
{
|
||||
"maximum": 5,
|
||||
"hexColor": "#792D86"
|
||||
},
|
||||
{
|
||||
"maximum": 10,
|
||||
"hexColor": "#7D862D"
|
||||
},
|
||||
{
|
||||
"maximum": 100,
|
||||
"hexColor": "#05483C"
|
||||
}
|
||||
],
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Download"
|
||||
"string" : "Notification GUID"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value2",
|
||||
"css_classes": "col-sm-2",
|
||||
"css_classes": "col-sm-8",
|
||||
"show": true,
|
||||
"type": "threshold",
|
||||
"type": "textarea_readonly",
|
||||
"default_value":"",
|
||||
"options": [
|
||||
{
|
||||
"maximum": 1,
|
||||
"hexColor": "#D33115"
|
||||
},
|
||||
{
|
||||
"maximum": 5,
|
||||
"hexColor": "#792D86"
|
||||
},
|
||||
{
|
||||
"maximum": 10,
|
||||
"hexColor": "#7D862D"
|
||||
},
|
||||
{
|
||||
"maximum": 100,
|
||||
"hexColor": "#05483C"
|
||||
}
|
||||
],
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Upload"
|
||||
"string" : "Result"
|
||||
}]
|
||||
},
|
||||
{
|
||||
@@ -280,10 +254,10 @@
|
||||
"settings":[
|
||||
{
|
||||
"function": "RUN",
|
||||
"events": ["run"],
|
||||
"events": ["test"],
|
||||
"type": "text.select",
|
||||
"default_value":"disabled",
|
||||
"options": ["disabled", "once", "schedule", "always_after_scan" ],
|
||||
"options": ["disabled", "on_notification" ],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"language_code": "en_us",
|
||||
@@ -293,15 +267,21 @@
|
||||
"language_code": "es_es",
|
||||
"string" : "Cuando ejecuta"
|
||||
}],
|
||||
"description": [{
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string" : "Enable a regular internet speedtest. If you select <code>schedule</code> the scheduling settings from below are applied. If you select <code>once</code> the scan is run only once on start of the application (container) for the time specified in <a href=\"#INTRSPD_RUN_TIMEOUT\"><code>INTRSPD_RUN_TIMEOUT</code> setting</a>."
|
||||
}]
|
||||
"string" : "Enable sending notifications via <a target=\"_blank\" href=\"https://hub.docker.com/r/caronc/apprise\">Apprise</a>."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Habilitar el envío de notificaciones a través de <a target=\"_blank\" href=\"https://hub.docker.com/r/caronc/apprise\">Apprise</a>."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "CMD",
|
||||
"type": "readonly",
|
||||
"default_value":"python3 /home/pi/pialert/front/plugins/internet_speedtest/script.py",
|
||||
"default_value":"python3 /home/pi/pialert/front/plugins/_publisher_apprise/apprise.py",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
@@ -321,33 +301,10 @@
|
||||
"string" : "Comando a ejecutar"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "RUN_SCHD",
|
||||
"type": "text",
|
||||
"default_value":"*/30 * * * *",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Schedule"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Schedule"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Only enabled if you select <code>schedule</code> in the <a href=\"#INTRSPD_RUN\"><code>INTRSPD_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format (e.g. validate at <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). For example entering <code>0 4 * * *</code> will run the scan after 4 am in the <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> you set above</a>. Will be run NEXT time the time passes."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Solo habilitado si selecciona <code>schedule</code> en la configuración <a href=\"#INTRSPD_RUN\"><code>INTRSPD_RUN</code></a>. Asegúrese de ingresar el schedule en el formato similar a cron correcto (por ejemplo, valide en <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). Por ejemplo, ingrese <code >0 4 * * *</code> ejecutará el escaneo después de las 4 am en el <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> que configuró arriba </a>. Se ejecutará la PRÓXIMA vez que pase el tiempo."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "RUN_TIMEOUT",
|
||||
"type": "integer",
|
||||
"default_value":60,
|
||||
"default_value": 10,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
@@ -372,46 +329,96 @@
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "WATCH",
|
||||
"type": "text.multiselect",
|
||||
"default_value":[],
|
||||
"options": ["Watched_Value1","Watched_Value2","Watched_Value3","Watched_Value4"],
|
||||
"function": "HOST",
|
||||
"type": "text",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Watched"
|
||||
"string" : "Apprise host URL"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Visto"
|
||||
}],
|
||||
"description":[{
|
||||
"string" : "URL del host de Apprise"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Send a notification if selected values change. Use <code>CTRL + Click</code> to select/deselect. <ul> <li><code>Watched_Value1</code> is Download speed (not recommended)</li><li><code>Watched_Value2</code> is Upload speed (not recommended)</li><li><code>Watched_Value3</code> unused </li><li><code>Watched_Value4</code> unused </li></ul>"
|
||||
}]
|
||||
"string" : "Apprise host URL starting with <code>http://</code> or <code>https://</code>. (do not forget to include <code>/notify</code> at the end)"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "URL del host de Apprise que comienza con <code>http://</code> o <code>https://</code>. (no olvide incluir <code>/notify</code> al final)"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "REPORT_ON",
|
||||
"type": "text.multiselect",
|
||||
"default_value":[],
|
||||
"options": ["new","watched-changed","watched-not-changed", "missing-in-last-scan"],
|
||||
"function": "URL",
|
||||
"type": "text",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Report on"
|
||||
"string" : "Apprise notification URL"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Informar sobre"
|
||||
}] ,
|
||||
"description":[{
|
||||
"string" : "URL de notificación de Apprise"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Send a notification only on these statuses. <code>new</code> means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. <code>watched-changed</code> means that selected <code>Watched_ValueN</code> columns changed."
|
||||
"string" : "Apprise notification target URL. For example for Telegram it would be <code>tgram://{bot_token}/{chat_id}</code>."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Envíe una notificación solo en estos estados. <code>new</code> significa que se descubrió un nuevo objeto único (combinación única de PrimaryId y SecondaryId). <code>watched-changed</code> significa que seleccionó <code>Watched_ValueN Las columnas </code> cambiaron."
|
||||
}]
|
||||
}
|
||||
"string" : "Informar de la URL de destino de la notificación. Por ejemplo, para Telegram sería <code>tgram://{bot_token}/{chat_id}</code>."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "PAYLOAD",
|
||||
"type": "text.select",
|
||||
"default_value": "html",
|
||||
"options": ["html", "text"],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Payload type"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Tipo de carga"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Select the payoad type sent to Apprise. For example <code>html</code> works well with emails, <code>text</code> with chat apps, such as Telegram."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Seleccione el tipo de carga útil enviada a Apprise. Por ejemplo, <code>html</code> funciona bien con correos electrónicos, <code>text</code> con aplicaciones de chat, como Telegram."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "SIZE",
|
||||
"type": "integer",
|
||||
"default_value": 1024,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Max payload size"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Tamaño máximo de carga útil"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "The maximum size of the apprise payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "El tamaño máximo de la carga útil de información como número de caracteres en la cadena pasada. Si supera el límite, se truncará y se agregará un mensaje <code>(text was truncated)</code>."
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
This plugin will not be loaded
|
||||
8
front/plugins/_publisher_email/README.md
Executable file
8
front/plugins/_publisher_email/README.md
Executable file
@@ -0,0 +1,8 @@
|
||||
## Overview
|
||||
|
||||
[Apprise](front/plugins/arp_scan/README.md) is a notification gateway/publisher that allows you to push notifications to 80+ different services.
|
||||
|
||||
### Usage
|
||||
|
||||
- Go to settings and fill in relevant details.
|
||||
|
||||
683
front/plugins/_publisher_email/config.json
Executable file
683
front/plugins/_publisher_email/config.json
Executable file
@@ -0,0 +1,683 @@
|
||||
{
|
||||
"code_name": "_publisher_email",
|
||||
"unique_prefix": "SMTP",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
"localized": [
|
||||
"display_name",
|
||||
"description",
|
||||
"icon"
|
||||
],
|
||||
"display_name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Email publisher (SMTP)"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Habilitar email (SMTP)"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "<i class=\"fa-solid fa-at\"></i>"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "A plugin to publish a notification via Email (SMTP) gateway."
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"database_column_definitions": [
|
||||
{
|
||||
"column": "Index",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Plugin",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Object_PrimaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "url",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Object_SecondaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeCreated",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Sent when"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeChanged",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Changed"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Cambiado"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value1",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Notification GUID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value2",
|
||||
"css_classes": "col-sm-8",
|
||||
"show": true,
|
||||
"type": "textarea_readonly",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Result"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value3",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value4",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "UserData",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "textbox_save",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Comments"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comentarios"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Status",
|
||||
"css_classes": "col-sm-1",
|
||||
"show": false,
|
||||
"type": "replace",
|
||||
"default_value": "",
|
||||
"options": [
|
||||
{
|
||||
"equals": "watched-not-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
|
||||
},
|
||||
{
|
||||
"equals": "watched-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "new",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "missing-in-last-scan",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-question'></i></div>"
|
||||
}
|
||||
],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Status"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Estado"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Extra",
|
||||
"css_classes": "col-sm-3",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Extra"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Extra"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"settings": [
|
||||
{
|
||||
"function": "RUN",
|
||||
"events": [
|
||||
"test"
|
||||
],
|
||||
"type": "text.select",
|
||||
"default_value": "disabled",
|
||||
"options": [
|
||||
"disabled",
|
||||
"on_notification"
|
||||
],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "When to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Cuando ejecuta"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Enable sending notifications via the Email (SMTP) gateway."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Si está habilitado, se envía un correo electrónico con una lista de cambios a los que se ha suscrito. Complete también todas las configuraciones restantes relacionadas con la configuración de SMTP a continuación"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "CMD",
|
||||
"type": "readonly",
|
||||
"default_value": "python3 /home/pi/pialert/front/plugins/_publisher_email/email_smtp.py",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Command"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comando"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Command to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comando a ejecutar"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "RUN_TIMEOUT",
|
||||
"type": "integer",
|
||||
"default_value": 20,
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Run timeout"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tiempo de espera de ejecución"
|
||||
},
|
||||
{
|
||||
"language_code": "de_de",
|
||||
"string": "Wartezeit"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "SERVER",
|
||||
"type": "text",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "SMTP server URL"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "URL del servidor SMTP"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "The SMTP server host URL. For example <code>smtp-relay.sendinblue.com</code>. To use Gmail as an SMTP server <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SMTP.md\">follow this guide</a>"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "La URL del host del servidor SMTP. Por ejemplo, <code>smtp-relay.sendinblue.com</code>. Para utilizar Gmail como servidor SMTP <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SMTP.md\">siga esta guía</a >"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "PORT",
|
||||
"type": "integer",
|
||||
"default_value": 587,
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "SMTP server PORT"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Puerto del servidor SMTP"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Port number used for the SMTP connection. Set to <code>0</code> if you do not want to use a port when connecting to the SMTP server."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Número de puerto utilizado para la conexión SMTP. Establézcalo en <code>0</code> si no desea utilizar un puerto al conectarse al servidor SMTP."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "SKIP_LOGIN",
|
||||
"type": "boolean",
|
||||
"default_value": false,
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Skip authentication"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Omitir autenticación"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Do not use authentication when connecting to the SMTP server."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "No utilice la autenticación cuando se conecte al servidor SMTP."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "USER",
|
||||
"type": "text",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "SMTP user"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Nombre de usuario SMTP"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "The user name used to login into the SMTP server (sometimes a full email address)."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "El nombre de usuario utilizado para iniciar sesión en el servidor SMTP (a veces, una dirección de correo electrónico completa)."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "PASS",
|
||||
"type": "password",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "SMTP password"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Contraseña de SMTP"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "The SMTP server password."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "La contraseña del servidor SMTP."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "SKIP_TLS",
|
||||
"type": "boolean",
|
||||
"default_value": false,
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Do not use TLS"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "No usar TLS"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Disable TLS when connecting to your SMTP server."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Deshabilite TLS cuando se conecte a su servidor SMTP."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "FORCE_SSL",
|
||||
"type": "boolean",
|
||||
"default_value": false,
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Force SSL"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Forzar SSL"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Force SSL when connecting to your SMTP server."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Forzar SSL al conectarse a su servidor SMTP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "REPORT_TO",
|
||||
"type": "text",
|
||||
"default_value": "user@gmail.com",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Send email to"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Enviar el email a"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Email address to which the notification will be send to."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Dirección de correo electrónico a la que se enviará la notificación."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "REPORT_FROM",
|
||||
"type": "text",
|
||||
"default_value": "Pi.Alert <user@gmail.com>",
|
||||
"options": [],
|
||||
"localized": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Email subject"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Asunto del email"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Notification email subject line. Some SMTP servers need this to be an email."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Asunto del correo electrónico de notificación."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
160
front/plugins/_publisher_email/email_smtp.py
Executable file
160
front/plugins/_publisher_email/email_smtp.py
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
import smtplib
|
||||
import socket
|
||||
|
||||
# Replace these paths with the actual paths to your Pi.Alert directories
|
||||
sys.path.extend(["/home/pi/pialert/front/plugins", "/home/pi/pialert/pialert"])
|
||||
|
||||
# PiAlert modules
|
||||
import conf
|
||||
from plugin_helper import Plugin_Objects
|
||||
from logger import mylog, append_line_to_file, print_log
|
||||
from helper import timeNowTZ, noti_obj, get_setting_value, hide_email
|
||||
from notification import Notification_obj
|
||||
from database import DB
|
||||
|
||||
|
||||
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
|
||||
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
|
||||
|
||||
pluginName = 'SMTP'
|
||||
|
||||
def main():
|
||||
|
||||
mylog('verbose', [f'[{pluginName}](publisher) In script'])
|
||||
|
||||
# Check if basic config settings supplied
|
||||
if check_config() == False:
|
||||
mylog('none', [f'[{pluginName}] Error: Publisher notification gateway not set up correctly. Check your pialert.conf {pluginName}_* variables.'])
|
||||
return
|
||||
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
# Create a Notification_obj instance
|
||||
notifications = Notification_obj(db)
|
||||
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
result = send(notification["HTML"], notification["Text"])
|
||||
|
||||
# Log result
|
||||
plugin_objects.add_object(
|
||||
primaryId = pluginName,
|
||||
secondaryId = timeNowTZ(),
|
||||
watched1 = notification["GUID"],
|
||||
watched2 = result,
|
||||
watched3 = 'null',
|
||||
watched4 = 'null',
|
||||
extra = 'null',
|
||||
foreignKey = 'null'
|
||||
)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def check_config ():
|
||||
if get_setting_value('SMTP_SERVER') == '' or get_setting_value('SMTP_REPORT_FROM') == '' or get_setting_value('SMTP_REPORT_TO') == '':
|
||||
mylog('none', ['[Email Check Config] Error: Email service not set up correctly. Check your pialert.conf SMTP_*, SMTP_REPORT_FROM and SMTP_REPORT_TO variables.'])
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def send(pHTML, pText):
|
||||
|
||||
mylog('debug', [f'[{pluginName}] SMTP_REPORT_TO: {hide_email(str(get_setting_value("SMTP_REPORT_TO")))} SMTP_USER: {hide_email(str(get_setting_value("SMTP_USER")))}'])
|
||||
|
||||
# Compose email
|
||||
msg = MIMEMultipart('alternative')
|
||||
msg['Subject'] = 'Pi.Alert Report'
|
||||
msg['From'] = get_setting_value('SMTP_REPORT_FROM')
|
||||
msg['To'] = get_setting_value('SMTP_REPORT_TO')
|
||||
msg.attach (MIMEText (pText, 'plain'))
|
||||
msg.attach (MIMEText (pHTML, 'html'))
|
||||
|
||||
failedAt = ''
|
||||
|
||||
failedAt = print_log ('SMTP try')
|
||||
|
||||
try:
|
||||
# Send mail
|
||||
failedAt = print_log('Trying to open connection to ' + str(get_setting_value('SMTP_SERVER')) + ':' + str(get_setting_value('SMTP_PORT')))
|
||||
|
||||
# Set a timeout for the SMTP connection (in seconds)
|
||||
smtp_timeout = 30
|
||||
|
||||
if get_setting_value('SMTP_FORCE_SSL'):
|
||||
failedAt = print_log('SMTP_FORCE_SSL == True so using .SMTP_SSL()')
|
||||
if get_setting_value('SMTP_PORT') == 0:
|
||||
failedAt = print_log('SMTP_PORT == 0 so sending .SMTP_SSL(SMTP_SERVER)')
|
||||
smtp_connection = smtplib.SMTP_SSL(get_setting_value('SMTP_SERVER'))
|
||||
else:
|
||||
failedAt = print_log('SMTP_PORT == 0 so sending .SMTP_SSL(SMTP_SERVER, SMTP_PORT)')
|
||||
smtp_connection = smtplib.SMTP_SSL(get_setting_value('SMTP_SERVER'), get_setting_value('SMTP_PORT'), timeout=smtp_timeout)
|
||||
|
||||
else:
|
||||
failedAt = print_log('SMTP_FORCE_SSL == False so using .SMTP()')
|
||||
if get_setting_value('SMTP_PORT') == 0:
|
||||
failedAt = print_log('SMTP_PORT == 0 so sending .SMTP(SMTP_SERVER)')
|
||||
smtp_connection = smtplib.SMTP (get_setting_value('SMTP_SERVER'))
|
||||
else:
|
||||
failedAt = print_log('SMTP_PORT == 0 so sending .SMTP(SMTP_SERVER, SMTP_PORT)')
|
||||
smtp_connection = smtplib.SMTP (get_setting_value('SMTP_SERVER'), get_setting_value('SMTP_PORT'))
|
||||
|
||||
failedAt = print_log('Setting SMTP debug level')
|
||||
|
||||
# Log level set to debug of the communication between SMTP server and client
|
||||
if get_setting_value('LOG_LEVEL') == 'debug':
|
||||
smtp_connection.set_debuglevel(1)
|
||||
|
||||
failedAt = print_log( 'Sending .ehlo()')
|
||||
smtp_connection.ehlo()
|
||||
|
||||
if not get_setting_value('SMTP_SKIP_TLS'):
|
||||
failedAt = print_log('SMTP_SKIP_TLS == False so sending .starttls()')
|
||||
smtp_connection.starttls()
|
||||
failedAt = print_log('SMTP_SKIP_TLS == False so sending .ehlo()')
|
||||
smtp_connection.ehlo()
|
||||
if not get_setting_value('SMTP_SKIP_LOGIN'):
|
||||
failedAt = print_log('SMTP_SKIP_LOGIN == False so sending .login()')
|
||||
smtp_connection.login (get_setting_value('SMTP_USER'), get_setting_value('SMTP_PASS'))
|
||||
|
||||
failedAt = print_log('Sending .sendmail()')
|
||||
smtp_connection.sendmail (get_setting_value('SMTP_REPORT_FROM'), get_setting_value('SMTP_REPORT_TO'), msg.as_string())
|
||||
smtp_connection.quit()
|
||||
except smtplib.SMTPAuthenticationError as e:
|
||||
mylog('none', [' ERROR: Failed at - ', failedAt])
|
||||
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPAuthenticationError), skipping Email (enable LOG_LEVEL=debug for more logging)'])
|
||||
mylog('none', [' ERROR: ', str(e)])
|
||||
except smtplib.SMTPServerDisconnected as e:
|
||||
mylog('none', [' ERROR: Failed at - ', failedAt])
|
||||
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPServerDisconnected), skipping Email (enable LOG_LEVEL=debug for more logging)'])
|
||||
mylog('none', [' ERROR: ', str(e)])
|
||||
except socket.gaierror as e:
|
||||
mylog('none', [' ERROR: Failed at - ', failedAt])
|
||||
mylog('none', [' ERROR: Could not resolve hostname (socket.gaierror), skipping Email (enable LOG_LEVEL=debug for more logging)'])
|
||||
mylog('none', [' ERROR: ', str(e)])
|
||||
|
||||
mylog('debug', [f'[{pluginName}] Last executed - {str(failedAt)}'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -1 +0,0 @@
|
||||
This plugin will not be loaded
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# Based on the work of https://github.com/leiweibau/Pi.Alert
|
||||
|
||||
import argparse
|
||||
import os
|
||||
|
||||
@@ -89,6 +89,11 @@ function processColumnValue(dbColumnDef, value, index, type) {
|
||||
case 'label':
|
||||
value = `<span>${value}<span>`;
|
||||
break;
|
||||
case 'textarea_readonly':
|
||||
value = `<textarea cols="70" rows="3" wrap="off" readonly style="white-space: pre-wrap;">
|
||||
${value.replace(/^b'(.*)'$/gm, '$1').replace(/\\n/g, '\n').replace(/\\r/g, '\r')}
|
||||
</textarea>`;
|
||||
break;
|
||||
case 'textbox_save':
|
||||
|
||||
value = value == 'null' ? '' : value; // hide 'null' values
|
||||
|
||||
@@ -112,7 +112,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
||||
const settingGroups = [];
|
||||
const settingKeyOfLists = [];
|
||||
// core groups are the ones not generated by plugins
|
||||
const settingCoreGroups = ['General', 'Email', 'Webhooks', 'Apprise', 'NTFY', 'PUSHSAFER', 'MQTT', 'DynDNS', 'API'];
|
||||
const settingCoreGroups = ['General'];
|
||||
|
||||
|
||||
// Loop through the settingsArray and collect unique settingGroups
|
||||
@@ -749,8 +749,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Show last time settings have been imported
|
||||
// getParam("lastImportedTime", "Back_Settings_Imported", skipCache = true);
|
||||
// Show last time settings have been imported
|
||||
|
||||
handleLoadingDialog()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user