Plugins 0.1 - Lang Strings in DB

This commit is contained in:
Jokob-sk
2023-02-06 21:47:58 +11:00
parent 5ed142a6b8
commit 06d7aa6623
7 changed files with 219 additions and 119 deletions

View File

@@ -269,7 +269,7 @@ def ccd(key, default, config, name, inputtype, options, group, events=[], desc =
def importConfig ():
# Specify globals so they can be overwritten with the new config
global lastTimeImported, mySettings
global lastTimeImported, mySettings, plugins
# General
global ENABLE_ARPSCAN, SCAN_SUBNETS, PRINT_LOG, TIMEZONE, PIALERT_WEB_PROTECTION, PIALERT_WEB_PASSWORD, INCLUDED_SECTIONS, SCAN_CYCLE_MINUTES, DAYS_TO_KEEP_EVENTS, REPORT_DASHBOARD_URL, DIG_GET_IP_ARG, UI_LANG
# Email
@@ -404,17 +404,24 @@ def importConfig ():
#Plugins
plugins = get_plugins_configs()
file_print('[', timeNow(), '] Plugins: Number of dynamically loaded plugins: ', len(plugins) )
for plugin in plugins:
file_print('[', timeNow(), '] Plugins: Number of dynamically loaded plugins: ', len(plugins.dict) )
for plugin in plugins.list:
file_print(' ---------------------------------------------')
file_print(' Name : ', plugin.display_name )
file_print(' Description: ', plugin.description.en_us )
file_print(' Name : ', plugin["display_name"][0]["string"] )
file_print(' Description: ', plugin["description"][0]["string"] )
prefix = plugin.settings_short_prefix
pref = plugin["settings_short_prefix"]
for set in plugin.settings:
codeName = prefix + "_" + set.type
ccd(codeName, set.default_value , c_d, set.name.en_us, get_setting_type(set), str(set.options), prefix)
collect_lang_strings(plugin, pref)
for set in plugin["settings"]:
codeName = pref + "_" + set["type"]
ccd(codeName, set["default_value"] , c_d, set["name"][0]["string"], get_setting_type(set), str(set["options"]), pref)
collect_lang_strings(set, pref + "_" + set["type"])
# Update scheduler
@@ -3075,7 +3082,7 @@ def upgradeDB ():
Extra TEXT NOT NULL,
PRIMARY KEY("Index" AUTOINCREMENT)
); """
# sql.execute(sql_Plugins_State)
sql.execute(sql_Plugins_State)
# Plugin execution results
sql_Plugin_Events = """ CREATE TABLE IF NOT EXISTS Plugins_Events(
@@ -3091,7 +3098,18 @@ def upgradeDB ():
Processed TEXT NOT NULL,
PRIMARY KEY("Index" AUTOINCREMENT)
); """
# sql.execute(sql_Plugin_Events)
sql.execute(sql_Plugin_Events)
# Dynamically generated language strings
sql.execute("DROP TABLE Language_Strings;")
sql.execute(""" CREATE TABLE IF NOT EXISTS Language_Strings(
"Index" INTEGER,
Language_Code TEXT NOT NULL,
String_Key TEXT NOT NULL,
String_Value TEXT NOT NULL,
Extra TEXT NOT NULL,
PRIMARY KEY("Index" AUTOINCREMENT)
); """)
commitDB ()
@@ -3482,25 +3500,49 @@ def isNewVersion():
#-------------------------------------------------------------------------------
def get_plugins_configs():
plugins = []
pluginsDict = []
pluginsList = []
for root, dirs, files in os.walk(pluginsPath):
for d in dirs: # Loop over directories, not files
pluginsDict.append(json.loads(get_file_content(pluginsPath + "/" + d + '/config.json'), object_hook=custom_plugin_decoder))
pluginsList.append(json.loads(get_file_content(pluginsPath + "/" + d + '/config.json')))
# filelist.append(os.path.join(root, d))
return plugins_struct(pluginsDict, pluginsList)
plugins.append(json.loads(get_file_content(pluginsPath + "/" + d + '/config.json'), object_hook=custom_plugin_decoder))
return plugins
#-------------------------------------------------------------------------------
class plugins_struct:
def __init__(self, dict, list):
self.dict = dict
self.list = list
#-------------------------------------------------------------------------------
def collect_lang_strings(json, pref):
for prop in json["localized"]:
for language_string in json[prop]:
import_language_string(language_string["language_code"], pref + "_" + prop, language_string["string"])
#-------------------------------------------------------------------------------
def import_language_string(code, key, value, extra = ""):
sql.execute ("""INSERT INTO Language_Strings ("Language_Code", "String_Key", "String_Value", "Extra") VALUES (?, ?, ?, ?)""", (str(code), str(key), str(value), str(extra)))
commitDB ()
#-------------------------------------------------------------------------------
def get_setting_type(setting):
if setting.type in ['RUN']:
type = setting["type"]
if type in ['RUN']:
return 'selecttext'
if setting.type in ['ENABLE', 'FORCE_REPORT']:
if type in ['ENABLE', 'FORCE_REPORT']:
return 'boolean'
if setting.type in ['TIMEOUT', 'RUN_TIMEOUT']:
if type in ['TIMEOUT', 'RUN_TIMEOUT']:
return 'integer'
if setting.type in ['NOTIFY_ON']:
if type in ['NOTIFY_ON']:
return 'multiselect'
return 'text'

View File

@@ -9,7 +9,7 @@ services:
volumes:
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
# - ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
- ${APP_DATA_LOCATION}/pialert/db:/home/pi/pialert/db
- ${APP_DATA_LOCATION}/pialert/db2:/home/pi/pialert/db
# (optional) useful for debugging if you have issues setting up the container
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes

View File

@@ -482,7 +482,8 @@ $lang['en_us'] = array(
//General
'General_settings_group' => '<i class="fa fa-gears"></i> General',
'General_display_name' => 'General',
'General_icon' => '<i class="fa fa-gears"></i>',
'ENABLE_ARPSCAN_name' => 'Enable ARP scan',
'ENABLE_ARPSCAN_description' => 'Arp-scan is a command-line tool that uses the ARP protocol to discover and fingerprint IP hosts on the local network. An alternative to ARP scan is to enable the <a onclick="toggleAllSettings()" href="#PIHOLE_ACTIVE"><code>PIHOLE_ACTIVE</code>PiHole integration settings</a>.',
'SCAN_SUBNETS_name' => 'Subnets to scan',
@@ -519,7 +520,8 @@ the arp-scan will take hours to complete instead of seconds.
'UI_LANG_description' => 'Select the preferred UI language.',
//Email
'Email_settings_group' => '<i class="fa fa-at"></i> Email',
'Email_display_name' => 'Email',
'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\'ve subscribed to. Please also fill out all remaining settings related to the SMTP setup below.',
'SMTP_SERVER_name' => 'SMTP server URL',
@@ -542,7 +544,8 @@ the arp-scan will take hours to complete instead of seconds.
'REPORT_FROM_description' => 'Notification email subject line.',
//Webhooks
'Webhooks_settings_group' => '<i class="fa fa-circle-nodes"></i> Webhooks',
'Webhooks_display_name' => 'Webhooks',
'Webhooks_icon' => '<i class="fa fa-circle-nodes"></i>',
'REPORT_WEBHOOK_name' => 'Enable Webhooks',
'REPORT_WEBHOOK_description' => 'Enable webhooks for notifications. Webhooks help you to connect to a lot of 3rd party tools, such as IFTTT, Zapier or <a href="https://n8n.io/" target="_blank">n8n</a> to name a few. Check out this simple <a href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md" target="_blank">n8n guide here</a> to get started. If enabled, configure related settings below.',
'WEBHOOK_URL_name' => 'Target URL',
@@ -553,7 +556,8 @@ the arp-scan will take hours to complete instead of seconds.
'WEBHOOK_REQUEST_METHOD_description' => 'The HTTP request method to be used for the webhook call.',
// Apprise
'Apprise_settings_group' => '<i class="fa fa-bullhorn"></i> Apprise',
'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',
@@ -562,7 +566,8 @@ the arp-scan will take hours to complete instead of seconds.
'APPRISE_URL_description' => 'Apprise notification target URL. For example for Telegram it would be <code>tgram://{bot_token}/{chat_id}</code>.',
// NTFY
'NTFY_settings_group' => '<i class="fa fa-terminal"></i> NTFY',
'NTFY_display_name' => 'NTFY',
'NTFY_icon' => '<i class="fa fa-terminal"></i>',
'REPORT_NTFY_name' => 'Enable NTFY',
'REPORT_NTFY_description' => 'Enable sending notifications via <a target="_blank" href="https://ntfy.sh/">NTFY</a>.',
'NTFY_HOST_name' => 'NTFY host URL',
@@ -575,7 +580,8 @@ the arp-scan will take hours to complete instead of seconds.
'NTFY_PASSWORD_description' => 'Enter password if you need (host) an instance with enabled authetication.',
// Pushsafer
'PUSHSAFER_settings_group' => '<i class="fa fa-bell"></i> Pushsafer',
'PUSHSAFER_display_name' => 'Pushsafer',
'PUSHSAFER_icon' => '<i class="fa fa-bell"></i>',
'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',
@@ -585,7 +591,8 @@ the arp-scan will take hours to complete instead of seconds.
// MQTT
'MQTT_settings_group' => '<i class="fa fa-square-rss"></i> MQTT',
'MQTT_display_name' => 'MQTT',
'MQTT_icon' => '<i class="fa fa-square-rss"></i>',
'REPORT_MQTT_name' => 'Enable MQTT',
'REPORT_MQTT_description' => 'Enable sending notifications via <a target="_blank" href="https://www.home-assistant.io/integrations/mqtt/">MQTT</a> to your Home Assistance instance.',
'MQTT_BROKER_name' => 'MQTT broker URL',
@@ -602,7 +609,8 @@ the arp-scan will take hours to complete instead of seconds.
'MQTT_DELAY_SEC_description' => 'A little hack - delay adding to the queue in case the process is restarted and previous publish processes aborted (it takes ~<code>2</code>s to update a sensor config on the broker). Tested with <code>2</code>-<code>3</code> seconds of delay. This delay is only applied when devices are created (during the first notification loop). It doesn\'t affect subsequent scans or notifications.',
//DynDNS
'DynDNS_settings_group' => '<i class="fa fa-globe"></i> DynDNS',
'DynDNS_display_name' => 'DynDNS',
'DynDNS_icon' => '<i class="fa fa-globe"></i>',
'DDNS_ACTIVE_name' => 'Enable DynDNS',
'DDNS_ACTIVE_description' => '',
'DDNS_DOMAIN_name' => 'DynDNS domain URL',
@@ -615,14 +623,16 @@ the arp-scan will take hours to complete instead of seconds.
'DDNS_UPDATE_URL_description' => 'Update URL starting with <code>http://</code> or <code>https://</code>.',
// PiHole
'PiHole_settings_group' => '<i class="fa fa-seedling"></i> PiHole',
'PiHole_display_name' => 'PiHole',
'PiHole_icon' => '<i class="fa fa-seedling"></i>',
'PIHOLE_ACTIVE_name' => 'Enable PiHole mapping',
'PIHOLE_ACTIVE_description' => 'You need to map<code>:/etc/pihole/pihole-FTL.db</code> in the <code>docker-compose.yml</code> file if you enable this setting.',
'DHCP_ACTIVE_name' => 'Enable PiHole DHCP',
'DHCP_ACTIVE_description' => 'You need to map <code>:/etc/pihole/dhcp.leases</code> in the <code>docker-compose.yml</code> file if you enable this setting.',
// Pholus
'Pholus_settings_group' => '<i class="fa fa-search"></i> Pholus',
'Pholus_display_name' => 'Pholus',
'Pholus_icon' => '<i class="fa fa-search"></i>',
'PHOLUS_ACTIVE_name' => 'Cycle run',
'PHOLUS_ACTIVE_description' => '<a href="https://github.com/jokob-sk/Pi.Alert/tree/main/pholus" target="_blank" >Pholus</a> is a sniffing tool to discover additional information about the devices on the network, including the device name. If enabled this will execute the scan before every network scan cycle until there are no <code>(unknown)</code> or <code>(name not found)</code> devices. Please be aware it can spam the network with unnecessary traffic. Depends on the <a onclick="toggleAllSettings()" href="#SCAN_SUBNETS"><code>SCAN_SUBNETS</code> setting</a>. For a scheduled or one-off scan, check the <a href="#PHOLUS_RUN"><code>PHOLUS_RUN</code> setting</a>.',
'PHOLUS_TIMEOUT_name' => 'Cycle run timeout',
@@ -640,7 +650,8 @@ the arp-scan will take hours to complete instead of seconds.
'PHOLUS_DAYS_DATA_description' => 'How many days of Pholus scan entries should be kept (globally, not device specific!). The <a href="/maintenance.php#tab_Logging">pialert_pholus.log</a> file is not touched. Enter <code>0</code> to disable.',
// Nmap
'Nmap_settings_group' => '<i class="fa fa-ethernet"></i> Nmap',
'Nmap_display_name' => 'Nmap',
'Nmap_icon' => '<i class="fa fa-ethernet"></i>',
'NMAP_ACTIVE_name' => 'Cycle run',
'NMAP_ACTIVE_description' => 'If enabled this will execute a scan on a newly found device. For a scheduled or one-off scan, check the <a href="#NMAP_RUN"><code>NMAP_RUN</code> setting</a>.',
'NMAP_TIMEOUT_name' => 'Run timeout',
@@ -653,7 +664,8 @@ the arp-scan will take hours to complete instead of seconds.
'NMAP_ARGS_description' => 'Arguments used to run the Nmap scan. Be careful to specify <a href="https://linux.die.net/man/1/nmap" target="_blank">the arguments</a> correctly. For example <code>-p -10000</code> scans ports from 1 to 10000.',
// API
'API_settings_group' => '<i class="fa fa-arrow-down-up-across-line"></i> API',
'API_display_name' => 'API',
'API_icon' => '<i class="fa fa-arrow-down-up-across-line"></i>',
'ENABLE_API_name' => 'Enable API',
'ENABLE_API_description' => 'If enabled the app will start publishing and updating <a href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md" target="_blank">simple API endpoints</a> under the <code>/home/pi/pialert/front/api/</code> folder and thus on the <code>pialert_url/api/File_name</code> url.',
'API_RUN_name' => 'Scheduling updates',

View File

@@ -5,6 +5,7 @@
// ###################################
$defaultLang = "en_us";
$allLanguages = ["en_us","es_es","de_de"];
global $db;
@@ -17,6 +18,20 @@ switch($result){
if (isset($pia_lang_selected) == FALSE or (strlen($pia_lang_selected) == 0)) {$pia_lang_selected = $defaultLang;}
//Language_Strings ("Language_Code", "String_Key", "String_Value", "Extra")
$result = $db->query("SELECT * FROM Language_Strings");
// array
$strings = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
// Push row data
$strings[] = array( 'Language_Code' => $row['Language_Code'],
'String_Key' => $row['String_Key'],
'String_Value' => $row['String_Value'],
'Extra' => $row['Extra']
);
}
require dirname(__FILE__).'/../skinUI.php';
require dirname(__FILE__).'/en_us.php';
require dirname(__FILE__).'/de_de.php';
@@ -24,7 +39,13 @@ require dirname(__FILE__).'/es_es.php';
function lang($key)
{
global $pia_lang_selected, $lang, $defaultLang;
global $pia_lang_selected, $lang, $defaultLang, $strings;
// get strings from the DB and append them to the ones from the files
foreach ($strings as $string)
{
$lang[$string["Language_Code"]][$string["String_Key"]] = $string["String_Value"];
}
// check if key exists in selected language
if(array_key_exists($key, $lang[$pia_lang_selected]) == FALSE)

View File

@@ -1,28 +1,42 @@
{
"code_name": "website_monitor",
"settings_short_prefix": "WEBMON",
"display_name" : "Website monitor",
"font_awesome_icon_classses": "fa-solid fa-globe",
"description": {
"en_us" : "This plugin is to monitor status changes of different services or websites."
},
"localized": ["display_name", "description", "icon"],
"display_name" : [{
"language_code":"en_us",
"string" : "Website monitor"
}],
"icon":[{
"language_code":"en_us",
"string" : "<i class=\"fa-solid fa-globe\"></i>"
}],
"argument" : "urls",
"description": [{
"language_code":"en_us",
"string" : "This plugin is to monitor status changes of different services or websites."
}],
"database_column_aliases":{
"Plugins_Events":{
"Index":{
"en_us" : "Index"
},
"Object_PrimaryID":{
"en_us" : "Monitored URL"
},
"DateTime":{
"en_us" : "Checked on"
},
"Watched_Value1":{
"en_us" : "Status code"
},
"Watched_Value2":{
"en_us" : "Latency"
}
"Index":[{
"language_code":"en_us",
"string" : "Index"
}],
"Object_PrimaryID":[{
"language_code":"en_us",
"string" : "Monitored URL"
}],
"DateTime":[{
"language_code":"en_us",
"string" : "Checked on"
}],
"Watched_Value1":[{
"language_code":"en_us",
"string" : "Status code"
}],
"Watched_Value2":[{
"language_code":"en_us",
"string" : "Latency"
}]
}
},
"settings":[
@@ -30,103 +44,114 @@
"type": "ENABLE",
"default_value":"False",
"options": [],
"name" : {
"en_us" : "Enable plugin"
},
"description":
{
"en_us" : "Enable a regular scan of your services. You need to enable this setting for anything to be executed regarding this plugin."
}
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Enable plugin"
}],
"description": [{
"language_code":"en_us",
"string" : "Enable a regular scan of your services. You need to enable this setting for anything to be executed regarding this plugin."
}]
},
{
"type": "RUN",
"default_value":"none",
"options": ["none","once","schedule"],
"name" : {
"en_us" : "Schedule"
},
"description":
{
"en_us" : "Enable a regular scan of your services. 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=\"#WEBMON_TIMEOUT\"><code>WEBMON_TIMEOUT</code> setting</a>."
}
"localized": ["name", "description"],
"name" :[{
"language_code":"en_us",
"string" : "Schedule"
}],
"description": [{
"language_code":"en_us",
"string" : "Enable a regular scan of your services. 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=\"#WEBMON_TIMEOUT\"><code>WEBMON_TIMEOUT</code> setting</a>."
}]
},
{
"type": "FORCE_REPORT",
"default_value": false,
"options": [],
"name" : {
"en_us" : "Schedule"
},
"description":
{
"en_us" : "Enable a regular scan of your services. 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=\"#WEBMON_TIMEOUT\"><code>WEBMON_TIMEOUT</code> setting</a>."
}
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Force report"
}],
"description": [{
"language_code":"en_us",
"string" : "Force a notification message even if there are nochanges detected."
}]
},
{
"type": "RUN_SCHD",
"default_value":"0 2 * * *",
"options": [],
"name" : {
"en_us" : "Schedule"
},
"description":
{
"en_us" : "Only enabled if you select <code>schedule</code> in the <a href=\"#WEBMON_RUN\"><code>WEBMON_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."
}
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Schedule"
}],
"description": [{
"language_code":"en_us",
"string" : "Only enabled if you select <code>schedule</code> in the <a href=\"#WEBMON_RUN\"><code>WEBMON_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."
}]
},
{
"type": "API_SQL",
"default_value":"SELECT * FROM plugin_website_monitor",
"options": [],
"name" : {
"en_us" : "API endpoint"
},
"description":
{
"en_us" : "You can specify a custom SQL query which will generate a JSON file and then expose it via the <a href=\"/api/plugin_website_monitor.json\" target=\"_blank\"><code>plugin_website_monitor.json</code> file endpoint</a>."
}
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "API endpoint"
}],
"description": [{
"language_code":"en_us",
"string" : "You can specify a custom SQL query which will generate a JSON file and then expose it via the <a href=\"/api/plugin_website_monitor.json\" target=\"_blank\"><code>plugin_website_monitor.json</code> file endpoint</a>."
}]
},
{
"type": "RUN_TIMEOUT",
"default_value":5,
"options": [],
"name" : {
"en_us" : "Run timeout"
},
"description":
{
"en_us" : "Maximum time in seconds to wait for a Website monitor check to finish for any url."
}
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Run timeout"
}],
"description": [{
"language_code":"en_us",
"string" : "Maximum time in seconds to wait for a Website monitor check to finish for any url."
}]
},
{
"type": "NOTIFY_ON",
"default_value":["Watched_Value1"],
"options": ["Watched_Value1","Watched_Value2","Watched_Value3","Watched_Value4"],
"name" : {
"en_us" : "Notify on"
},
"description":
{
"en_us" : "Send a notification if selected values change. Use <code>CTRL + Click</code> to select/deselect. <ul> <li><code>Watched_Value1</code> is response status code (e.g.: 200, 404)</li><li><code>Watched_Value2</code> is Latency (not recommended)</li><li><code>Watched_Value3</code> unused </li><li><code>Watched_Value4</code> unused </li></ul>"
}
"localized": ["name", "description"],
"name" :[{
"language_code":"en_us",
"string" : "Notify on"
}] ,
"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 response status code (e.g.: 200, 404)</li><li><code>Watched_Value2</code> is Latency (not recommended)</li><li><code>Watched_Value3</code> unused </li><li><code>Watched_Value4</code> unused </li></ul>"
}]
},
{
"type": "ARGS",
"default_value":"",
"options": [],
"name" : {
"en_us" : "Run timeout"
},
"description":
{
"en_us" : "Change the <a href=\"https://linux.die.net/man/1/dig\" target=\"_blank\">dig utility</a> arguments if you have issues resolving your Internet IP. Arguments are added at the end of the following command: <code>dig +short </code>."
}
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Arguments"
}],
"description": [{
"language_code":"en_us",
"string" : "Change the <a href=\"https://linux.die.net/man/1/dig\" target=\"_blank\">dig utility</a> arguments if you have issues resolving your Internet IP. Arguments are added at the end of the following command: <code>dig +short </code>."
}]
}
]

View File

@@ -72,7 +72,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$html = $html.'<div class=" box panel panel-default">
<a data-toggle="collapse" data-parent="#accordion_gen" href="#'.$group.'">
<div class="panel-heading">
<h4 class="panel-title">'.lang($group.'_settings_group').'</h4>
<h4 class="panel-title">'.lang($group.'_icon')." ".lang($group.'_display_name').'</h4>
</div>
</a>
<div id="'.$group.'" data-myid="collapsible" class="panel-collapse collapse '.$isIn.'">