Procházet zdrojové kódy

add Self Signed SSL Cert option to all homepage items (#1177) and changed homepage item settings to new cleaner format

CauseFX před 4 roky
rodič
revize
ea1c77ed06

+ 19 - 84
api/homepage/calendar.php

@@ -14,91 +14,26 @@ trait CalendarHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageCalendarEnabled',
-						'label' => 'Enable iCal',
-						'value' => $this->config['homepageCalendarEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageCalendarAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageCalendarAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'input',
-						'name' => 'calendariCal',
-						'label' => 'iCal URL\'s',
-						'value' => $this->config['calendariCal'],
-						'placeholder' => 'separate by comma\'s'
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'number',
-						'name' => 'calendarStart',
-						'label' => '# of Days Before',
-						'value' => $this->config['calendarStart'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'number',
-						'name' => 'calendarEnd',
-						'label' => '# of Days After',
-						'value' => $this->config['calendarEnd'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					)
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageCalendarEnabled'),
+					$this->settingsOption('auth', 'homepageCalendarAuth'),
+					$this->settingsOption('multiple-url', 'calendariCal', ['label' => 'iCal URL\'s']),
+				],
+				'Misc Options' => [
+					$this->settingsOption('calendar-start', 'calendarStart'),
+					$this->settingsOption('calendar-end', 'calendarEnd'),
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	

+ 26 - 80
api/homepage/couchpotato.php

@@ -15,86 +15,31 @@ trait CouchPotatoHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageCouchpotatoEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageCouchpotatoEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageCouchpotatoAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageCouchpotatoAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'couchpotatoURL',
-						'label' => 'URL',
-						'value' => $this->config['couchpotatoURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'couchpotatoToken',
-						'label' => 'Token',
-						'value' => $this->config['couchpotatoToken']
-					)
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					)
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageCouchpotatoEnabled'),
+					$this->settingsOption('auth', 'homepageCouchpotatoAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('multiple-url', 'couchpotatoURL'),
+					$this->settingsOption('multiple-token', 'couchpotatoToken'),
+					$this->settingsOption('disable-cert-check', 'couchpotatoDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'couchpotatoUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('calendar-start', 'calendarStart'),
+					$this->settingsOption('calendar-end', 'calendarEnd'),
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -132,7 +77,8 @@ trait CouchPotatoHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['couchpotatoURL'], $this->config['couchpotatoToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\CouchPotato\CouchPotato($value['url'], $value['token']);
+				$options = $this->requestOptions($value['url'], 60, $this->config['couchpotatoDisableCertCheck'], $this->config['couchpotatoUseCustomCertificate']);
+				$downloader = new Kryptonit3\CouchPotato\CouchPotato($value['url'], $value['token'], null, null, $options);
 				$calendar = $this->formatCouchCalendar($downloader->getMediaList(array('status' => 'active,done')), $key);
 			} catch (Exception $e) {
 				$this->writeLog('error', 'Radarr Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');

+ 52 - 101
api/homepage/deluge.php

@@ -14,103 +14,53 @@ trait DelugeHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'custom' => '
-				<div class="row">
-                    <div class="col-lg-12">
-                        <div class="panel panel-info">
-                            <div class="panel-heading">
-								<span lang="en">Notice</span>
-                            </div>
-                            <div class="panel-wrapper collapse in" aria-expanded="true">
-                                <div class="panel-body">
-									<ul class="list-icons">
-                                        <li><i class="fa fa-chevron-right text-danger"></i> <a href="https://github.com/idlesign/deluge-webapi/tree/master/dist" target="_blank">Download Plugin</a></li>
-                                        <li><i class="fa fa-chevron-right text-danger"></i> Open Deluge Web UI, go to "Preferences -> Plugins -> Install plugin" and choose egg file.</li>
-                                        <li><i class="fa fa-chevron-right text-danger"></i> Activate WebAPI plugin </li>
-                                    </ul>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-				</div>
-				',
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageDelugeEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageDelugeEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageDelugeAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageDelugeAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'delugeURL',
-						'label' => 'URL',
-						'value' => $this->config['delugeURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password',
-						'name' => 'delugePassword',
-						'label' => 'Password',
-						'help' => 'Note that using a blank password might not work correctly.',
-						'value' => $this->config['delugePassword']
+			'settings' => [
+				'FYI' => [
+					$this->settingsOption('html', null, ['override' => 12, 'html' => '
+						<div class="row">
+							<div class="col-lg-12">
+								<div class="panel panel-info">
+									<div class="panel-heading">
+										<span lang="en">Notice</span>
+									</div>
+									<div class="panel-wrapper collapse in" aria-expanded="true">
+										<div class="panel-body">
+											<ul class="list-icons">
+												<li><i class="fa fa-chevron-right text-danger"></i> <a href="https://github.com/idlesign/deluge-webapi/tree/master/dist" target="_blank">Download Plugin</a></li>
+												<li><i class="fa fa-chevron-right text-danger"></i> Open Deluge Web UI, go to "Preferences -> Plugins -> Install plugin" and choose egg file.</li>
+												<li><i class="fa fa-chevron-right text-danger"></i> Activate WebAPI plugin </li>
+											</ul>
+										</div>
+									</div>
+								</div>
+							</div>
+						</div>']
 					)
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'delugeHideSeeding',
-						'label' => 'Hide Seeding',
-						'value' => $this->config['delugeHideSeeding']
-					), array(
-						'type' => 'switch',
-						'name' => 'delugeHideCompleted',
-						'label' => 'Hide Completed',
-						'value' => $this->config['delugeHideCompleted']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'delugeRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['delugeRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'delugeCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['delugeCombine']
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing. Note that using a blank password might not work correctly.'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'deluge\')"'
-					),
-				)
-			)
-		);
+				],
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageDelugeEnabled'),
+					$this->settingsOption('auth', 'homepageDelugeAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'delugeURL'),
+					$this->settingsOption('password', 'delugePassword', ['help' => 'Note that using a blank password might not work correctly.']),
+					$this->settingsOption('disable-cert-check', 'delugeDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'delugeUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('hide-seeding', 'delugeHideSeeding'),
+					$this->settingsOption('hide-completed', 'delugeHideCompleted'),
+					$this->settingsOption('refresh', 'delugeRefresh'),
+					$this->settingsOption('combine', 'delugeCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing. Note that using a blank password might not work correctly.']),
+					$this->settingsOption('test', 'deluge'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -121,7 +71,8 @@ trait DelugeHomepageItem
 			return false;
 		}
 		try {
-			$deluge = new deluge($this->config['delugeURL'], $this->decrypt($this->config['delugePassword']));
+			$options = $this->requestOptions($this->config['delugeURL'], $this->config['delugeRefresh'], $this->config['delugeDisableCertCheck'], $this->config['delugeUseCustomCertificate'], ['organizr_cert' => $this->getCert(), 'custom_cert' => $this->getCustomCert()]);
+			$deluge = new deluge($this->config['delugeURL'], $this->decrypt($this->config['delugePassword']), $options);
 			$torrents = $deluge->getTorrents(null, 'comment, download_payload_rate, eta, hash, is_finished, is_seed, message, name, paused, progress, queue, state, total_size, upload_payload_rate');
 			$this->setAPIResponse('success', 'API Connection succeeded', 200);
 			return true;
@@ -166,11 +117,11 @@ trait DelugeHomepageItem
 				<div id="' . __FUNCTION__ . '">
 					' . $loadingBox . '
 					<script>
-		                // homepageOrderdeluge
-		                ' . $builder . '
-		                homepageDownloader("deluge", "' . $this->config['delugeRefresh'] . '");
-		                // End homepageOrderdeluge
-	                </script>
+						// homepageOrderdeluge
+						' . $builder . '
+						homepageDownloader("deluge", "' . $this->config['delugeRefresh'] . '");
+						// End homepageOrderdeluge
+					</script>
 				</div>
 				';
 		}

+ 47 - 171
api/homepage/emby.php

@@ -14,166 +14,44 @@ trait EmbyHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageEmbyEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageEmbyEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageEmbyAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageEmbyAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'embyURL',
-						'label' => 'URL',
-						'value' => $this->config['embyURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'embyToken',
-						'label' => 'Token',
-						'value' => $this->config['embyToken']
-					)
-				),
-				'Active Streams' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageEmbyStreams',
-						'label' => 'Enable',
-						'value' => $this->config['homepageEmbyStreams']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageEmbyStreamsAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageEmbyStreamsAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageShowStreamNames',
-						'label' => 'User Information',
-						'value' => $this->config['homepageShowStreamNames']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageShowStreamNamesAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageShowStreamNamesAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageStreamRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageStreamRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Recent Items' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageEmbyRecent',
-						'label' => 'Enable',
-						'value' => $this->config['homepageEmbyRecent']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageEmbyRecentAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageEmbyRecentAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'number',
-						'name' => 'homepageRecentLimit',
-						'label' => 'Item Limit',
-						'value' => $this->config['homepageRecentLimit'],
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageRecentRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageRecentRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'homepageEmbyLink',
-						'label' => 'Emby Homepage Link URL',
-						'value' => $this->config['homepageEmbyLink'],
-						'help' => 'Available variables: {id} {serverId}'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'embyTabName',
-						'label' => 'Emby Tab Name',
-						'value' => $this->config['embyTabName'],
-						'placeholder' => 'Only use if you have Emby in a reverse proxy'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'embyTabURL',
-						'label' => 'Emby Tab WAN URL',
-						'value' => $this->config['embyTabURL'],
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'cacheImageSize',
-						'label' => 'Image Cache Size',
-						'value' => $this->config['cacheImageSize'],
-						'options' => array(
-							array(
-								'name' => 'Low',
-								'value' => '.5'
-							),
-							array(
-								'name' => '1x',
-								'value' => '1'
-							),
-							array(
-								'name' => '2x',
-								'value' => '2'
-							),
-							array(
-								'name' => '3x',
-								'value' => '3'
-							)
-						)
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'emby\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageEmbyEnabled'),
+					$this->settingsOption('auth', 'homepageEmbyAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'embyURL'),
+					$this->settingsOption('token', 'embyToken'),
+					$this->settingsOption('disable-cert-check', 'embyDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'embyUseCustomCertificate'),
+				],
+				'Active Streams' => [
+					$this->settingsOption('enable', 'homepageEmbyStreams'),
+					$this->settingsOption('auth', 'homepageEmbyStreamsAuth'),
+					$this->settingsOption('switch', 'homepageShowStreamNames', ['label' => 'User Information']),
+					$this->settingsOption('auth', 'homepageShowStreamNamesAuth'),
+					$this->settingsOption('refresh', 'homepageStreamRefresh'),
+				],
+				'Recent Items' => [
+					$this->settingsOption('enable', 'homepageEmbyRecent'),
+					$this->settingsOption('auth', 'homepageEmbyRecentAuth'),
+					$this->settingsOption('limit', 'homepageRecentLimit'),
+					$this->settingsOption('refresh', 'homepageRecentRefresh'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('input', 'homepageEmbyLink', ['label' => 'Emby Homepage Link URL', 'help' => 'Available variables: {id} {serverId}']),
+					$this->settingsOption('input', 'embyTabName', ['label' => 'Emby Tab Name', 'placeholder' => 'Only use if you have Emby in a reverse proxy']),
+					$this->settingsOption('input', 'embyTabURL', ['label' => 'Emby Tab WAN URL', 'placeholder' => 'Only use if you have Emby in a reverse proxy']),
+					$this->settingsOption('image-cache-quality', 'cacheImageSize'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'emby'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -189,9 +67,9 @@ trait EmbyHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['embyURL']);
 		$url = $url . "/Users?api_key=" . $this->config['embyToken'];
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, null, $this->config['embyDisableCertCheck'], $this->config['embyUseCustomCertificate']);
 		try {
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$this->setAPIResponse('success', 'API Connection succeeded', 200);
 				return true;
@@ -297,9 +175,9 @@ trait EmbyHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['embyURL']);
 		$url = $url . '/Sessions?api_key=' . $this->config['embyToken'] . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, $this->config['homepageStreamRefresh'], $this->config['embyDisableCertCheck'], $this->config['embyUseCustomCertificate']);
 		try {
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$items = array();
 				$emby = json_decode($response->body, true);
@@ -328,7 +206,7 @@ trait EmbyHomepageItem
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['embyURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, $this->config['homepageRecentRefresh'], $this->config['embyDisableCertCheck'], $this->config['embyUseCustomCertificate']);
 		$username = false;
 		$showPlayed = false;
 		$userId = 0;
@@ -340,7 +218,7 @@ trait EmbyHomepageItem
 			}
 			// Get A User
 			$userIds = $url . "/Users?api_key=" . $this->config['embyToken'];
-			$response = Requests::get($userIds, array(), $options);
+			$response = Requests::get($userIds, [], $options);
 			if ($response->success) {
 				$emby = json_decode($response->body, true);
 				foreach ($emby as $value) { // Scan for admin user
@@ -358,7 +236,7 @@ trait EmbyHomepageItem
 				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
 				return false;
 			}
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$items = array();
 				$emby = json_decode($response->body, true);
@@ -392,19 +270,17 @@ trait EmbyHomepageItem
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['embyURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, 60, $this->config['embyDisableCertCheck'], $this->config['embyUseCustomCertificate']);
 		$username = false;
 		$showPlayed = false;
 		$userId = 0;
 		try {
-			
-			
 			if (isset($this->user['username'])) {
 				$username = strtolower($this->user['username']);
 			}
 			// Get A User
 			$userIds = $url . "/Users?api_key=" . $this->config['embyToken'];
-			$response = Requests::get($userIds, array(), $options);
+			$response = Requests::get($userIds, [], $options);
 			if ($response->success) {
 				$emby = json_decode($response->body, true);
 				foreach ($emby as $value) { // Scan for admin user
@@ -422,7 +298,7 @@ trait EmbyHomepageItem
 				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
 				return false;
 			}
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$items = array();
 				$emby = json_decode($response->body, true);

+ 21 - 65
api/homepage/healthchecks.php

@@ -14,71 +14,27 @@ trait HealthChecksHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageHealthChecksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageHealthChecksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageHealthChecksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageHealthChecksAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'healthChecksURL',
-						'label' => 'URL',
-						'value' => $this->config['healthChecksURL'],
-						'help' => 'URL for HealthChecks API',
-						'placeholder' => 'HealthChecks API URL'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'healthChecksToken',
-						'label' => 'Token',
-						'value' => $this->config['healthChecksToken']
-					)
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'healthChecksTags',
-						'label' => 'Tags',
-						'value' => $this->config['healthChecksTags'],
-						'help' => 'Pull only checks with this tag - Blank for all',
-						'placeholder' => 'Multiple tags using CSV - tag1,tag2'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageHealthChecksRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageHealthChecksRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageHealthChecksShowDesc',
-						'label' => 'Show Description',
-						'value' => $this->config['homepageHealthChecksShowDesc'],
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageHealthChecksShowTags',
-						'label' => 'Show Tags',
-						'value' => $this->config['homepageHealthChecksShowTags'],
-					),
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageHealthChecksEnabled'),
+					$this->settingsOption('auth', 'homepageHealthChecksAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'healthChecksURL'),
+					$this->settingsOption('multiple-token', 'healthChecksToken'),
+					$this->settingsOption('disable-cert-check', 'healthChecksDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'healthChecksUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('multiple', 'healthChecksTags', ['label' => 'Tags', 'help' => 'Pull only checks with this tag - Blank for all', 'placeholder' => 'Multiple tags using CSV - tag1,tag2']),
+					$this->settingsOption('refresh', 'homepageHealthChecksRefresh'),
+					$this->settingsOption('switch', 'homepageHealthChecksShowDesc', ['label' => 'Show Description']),
+					$this->settingsOption('switch', 'homepageHealthChecksShowTags', ['label' => 'Show Tags']),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -135,7 +91,7 @@ trait HealthChecksHomepageItem
 			$url = $this->qualifyURL($this->config['healthChecksURL']) . '/' . $tags;
 			try {
 				$headers = array('X-Api-Key' => $token);
-				$options = ($this->localURL($url)) ? array('verify' => false) : array('verify' => $this->getCert());
+				$options = $this->requestOptions($url, $this->config['homepageHealthChecksRefresh'], $this->config['healthChecksDisableCertCheck'], $this->config['healthChecksUseCustomCertificate']);
 				$response = Requests::get($url, $headers, $options);
 				if ($response->success) {
 					$healthResults = json_decode($response->body, true);

+ 24 - 72
api/homepage/html.php

@@ -14,41 +14,19 @@ trait HTMLHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageCustomHTMLoneEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageCustomHTMLoneEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageCustomHTMLoneAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageCustomHTMLoneAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Code' => array(
-					array(
-						'type' => 'textbox',
-						'name' => 'customHTMLone',
-						'class' => 'hidden customHTMLoneTextarea',
-						'label' => '',
-						'value' => $this->config['customHTMLone'],
-					),
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => 'Custom HTML/JavaScript',
-						'html' => '<button type="button" class="hidden savecustomHTMLoneTextarea btn btn-info btn-circle pull-right m-r-5 m-l-10"><i class="fa fa-save"></i> </button><div id="customHTMLoneEditor" style="height:300px">' . htmlentities($this->config['customHTMLone']) . '</div>'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageCustomHTMLoneEnabled'),
+					$this->settingsOption('auth', 'homepageCustomHTMLoneAuth'),
+				],
+				'Code' => [
+					$this->settingsOption('pre-code-editor', 'customHTMLone'),
+					$this->settingsOption('code-editor', 'customHTMLone'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -64,45 +42,19 @@ trait HTMLHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
-			'name' => 'CustomHTML-2',
-			'enabled' => strpos('personal,business', $this->config['license']) !== false,
-			'image' => 'plugins/images/tabs/custom2.png',
-			'category' => 'Custom',
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageCustomHTMLtwoEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageCustomHTMLtwoEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageCustomHTMLtwoAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageCustomHTMLtwoAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Code' => array(
-					array(
-						'type' => 'textbox',
-						'name' => 'customHTMLtwo',
-						'class' => 'hidden customHTMLtwoTextarea',
-						'label' => '',
-						'value' => $this->config['customHTMLtwo'],
-					),
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => 'Custom HTML/JavaScript',
-						'html' => '<button type="button" class="hidden savecustomHTMLtwoTextarea btn btn-info btn-circle pull-right m-r-5 m-l-10"><i class="fa fa-save"></i> </button><div id="customHTMLtwoEditor" style="height:300px">' . htmlentities($this->config['customHTMLtwo']) . '</div>'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageCustomHTMLtwoEnabled'),
+					$this->settingsOption('auth', 'homepageCustomHTMLtwoAuth'),
+				],
+				'Code' => [
+					$this->settingsOption('pre-code-editor', 'customHTMLtwo'),
+					$this->settingsOption('code-editor', 'customHTMLtwo'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	

+ 21 - 48
api/homepage/jackett.php

@@ -14,51 +14,24 @@ trait JackettHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageJackettEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageJackettEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageJackettAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageJackettAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'jackettURL',
-						'label' => 'URL',
-						'value' => $this->config['jackettURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'jackettToken',
-						'label' => 'Token',
-						'value' => $this->config['jackettToken']
-					)
-				),
-				'Options' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageJackettBackholeDownload',
-						'label' => 'Prefer black hole download',
-						'help' => 'Prefer black hole download link instead of direct/magnet download',
-						'value' => $this->config['homepageJackettBackholeDownload']
-					)
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageJackettEnabled'),
+					$this->settingsOption('auth', 'homepageJackettAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'jackettURL'),
+					$this->settingsOption('token', 'jackettToken'),
+					$this->settingsOption('disable-cert-check', 'jackettDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'jackettUseCustomCertificate'),
+				],
+				'Options' => [
+					$this->settingsOption('switch', 'homepageJackettBackholeDownload', ['label' => 'Prefer black hole download', 'help' => 'Prefer black hole download link instead of direct/magnet download']),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -115,8 +88,8 @@ trait JackettHomepageItem
 		$apiURL = $this->qualifyURL($this->config['jackettURL']);
 		$endpoint = $apiURL . '/api/v2.0/indexers/all/results?apikey=' . $this->config['jackettToken'] . '&Query=' . urlencode($query);
 		try {
-			$headers = array();
-			$options = array('timeout' => 120);
+			$headers = [];
+			$options = $this->requestOptions($apiURL, 120, $this->config['jackettDisableCertCheck'], $this->config['jackettUseCustomCertificate']);
 			$response = Requests::get($endpoint, $headers, $options);
 			if ($response->success) {
 				$apiData = json_decode($response->body, true);
@@ -146,8 +119,8 @@ trait JackettHomepageItem
 		$endpoint = $apiURL . $url;
 		error_log($endpoint);
 		try {
-			$headers = array();
-			$options = array('timeout' => 120);
+			$headers = [];
+			$options = $this->requestOptions($apiURL, 120, $this->config['jackettDisableCertCheck'], $this->config['jackettUseCustomCertificate']);
 			$response = Requests::get($endpoint, $headers, $options);
 			if ($response->success) {
 				$apiData = json_decode($response->body, true);

+ 51 - 85
api/homepage/jdownloader.php

@@ -14,84 +14,50 @@ trait JDownloaderHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'custom' => '
-				<div class="row">
-                    <div class="col-lg-12">
-                        <div class="panel panel-info">
-                            <div class="panel-heading">
-								<span lang="en">Notice</span>
-                            </div>
-                            <div class="panel-wrapper collapse in" aria-expanded="true">
-                                <div class="panel-body">
-									<ul class="list-icons">
-                                        <li><i class="fa fa-chevron-right text-danger"></i> <a href="https://pypi.org/project/myjd-api/" target="_blank">Download [myjd-api] Module</a></li>
-                                        <li><i class="fa fa-chevron-right text-danger"></i> Add <b>/api/myjd</b> to the URL if you are using <a href="https://pypi.org/project/FeedCrawler/" target="_blank">FeedCrawler</a></li>
-                                    </ul>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-				</div>
-				',
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageJdownloaderEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageJdownloaderEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageJdownloaderAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageJdownloaderAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'jdownloaderURL',
-						'label' => 'URL',
-						'value' => $this->config['jdownloaderURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					)
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'jdownloaderRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['jdownloaderRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'jdownloaderCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['jdownloaderCombine']
+			'settings' => [
+				'FYI' => [
+					$this->settingsOption('html', null, ['override' => 12, 'html' => '
+						<div class="row">
+							<div class="col-lg-12">
+								<div class="panel panel-info">
+									<div class="panel-heading">
+										<span lang="en">Notice</span>
+									</div>
+									<div class="panel-wrapper collapse in" aria-expanded="true">
+										<div class="panel-body">
+											<ul class="list-icons">
+												<li><i class="fa fa-chevron-right text-danger"></i> <a href="https://pypi.org/project/myjd-api/" target="_blank">Download [myjd-api] Module</a></li>
+												<li><i class="fa fa-chevron-right text-danger"></i> Add <b>/api/myjd</b> to the URL if you are using <a href="https://pypi.org/project/FeedCrawler/" target="_blank">FeedCrawler</a></li>
+											</ul>
+										</div>
+									</div>
+								</div>
+							</div>
+						</div>']
 					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'jdownloader\')"'
-					),
-				)
-			)
-		);
+				],
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageJdownloaderEnabled'),
+					$this->settingsOption('auth', 'homepageJdownloaderAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'jdownloaderURL'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('disable-cert-check', 'jdownloaderDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'jdownloaderUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('refresh', 'jdownloaderRefresh'),
+					$this->settingsOption('combine', 'jdownloaderCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'jdownloader'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -103,8 +69,8 @@ trait JDownloaderHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['jdownloaderURL']);
 		try {
-			$options = $this->requestOptions($this->config['jdownloaderURL'], false, $this->config['jdownloaderRefresh']);
-			$response = Requests::get($url, array(), $options);
+			$options = $this->requestOptions($url, $this->config['jdownloaderRefresh'], $this->config['jdownloaderDisableCertCheck'], $this->config['jdownloaderUseCustomCertificate']);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$this->setAPIResponse('success', 'API Connection succeeded', 200);
 				return true;
@@ -152,11 +118,11 @@ trait JDownloaderHomepageItem
 				<div id="' . __FUNCTION__ . '">
 					' . $loadingBox . '
 					<script>
-		                // homepageOrderjdownloader
-		                ' . $builder . '
-		                homepageDownloader("jdownloader", "' . $this->config['jdownloaderRefresh'] . '");
-		                // End homepageOrderjdownloader
-	                </script>
+						// homepageOrderjdownloader
+						' . $builder . '
+						homepageDownloader("jdownloader", "' . $this->config['jdownloaderRefresh'] . '");
+						// End homepageOrderjdownloader
+					</script>
 				</div>
 				';
 		}
@@ -169,8 +135,8 @@ trait JDownloaderHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['jdownloaderURL']);
 		try {
-			$options = $this->requestOptions($this->config['jdownloaderURL'], false, $this->config['jdownloaderRefresh']);
-			$response = Requests::get($url, array(), $options);
+			$options = $this->requestOptions($url, $this->config['jdownloaderRefresh'], $this->config['jdownloaderDisableCertCheck'], $this->config['jdownloaderUseCustomCertificate']);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$temp = json_decode($response->body, true);
 				$packages = $temp['packages'];

+ 46 - 162
api/homepage/jellyfin.php

@@ -15,159 +15,43 @@ trait JellyfinHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageJellyfinEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageJellyfinEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageJellyfinAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageJellyfinAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'jellyfinURL',
-						'label' => 'URL',
-						'value' => $this->config['jellyfinURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'jellyfinToken',
-						'label' => 'Token',
-						'value' => $this->config['jellyfinToken']
-					)
-				),
-				'Active Streams' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageJellyfinStreams',
-						'label' => 'Enable',
-						'value' => $this->config['homepageJellyfinStreams']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageJellyStreamsAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageJellyStreamsAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageShowStreamNames',
-						'label' => 'User Information',
-						'value' => $this->config['homepageShowStreamNames']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageShowStreamNamesAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageShowStreamNamesAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageStreamRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageStreamRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Recent Items' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageJellyfinRecent',
-						'label' => 'Enable',
-						'value' => $this->config['homepageJellyfinRecent']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageJellyfinRecentAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageJellyfinRecentAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'number',
-						'name' => 'homepageRecentLimit',
-						'label' => 'Item Limit',
-						'value' => $this->config['homepageRecentLimit'],
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageRecentRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageRecentRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'homepageJellyfinLink',
-						'label' => 'Jellyfin Homepage Link URL',
-						'value' => $this->config['homepageJellyfinLink'],
-						'help' => 'Available variables: {id} {serverId}'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'jellyfinTabName',
-						'label' => 'Jellyfin Tab Name',
-						'value' => $this->config['jellyfinTabName'],
-						'placeholder' => 'Only use if you have Jellyfin in a reverse proxy'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'cacheImageSize',
-						'label' => 'Image Cache Size',
-						'value' => $this->config['cacheImageSize'],
-						'options' => array(
-							array(
-								'name' => 'Low',
-								'value' => '.5'
-							),
-							array(
-								'name' => '1x',
-								'value' => '1'
-							),
-							array(
-								'name' => '2x',
-								'value' => '2'
-							),
-							array(
-								'name' => '3x',
-								'value' => '3'
-							)
-						)
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'jellyfin\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageJellyfinEnabled'),
+					$this->settingsOption('auth', 'homepageJellyfinAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'jellyfinURL'),
+					$this->settingsOption('token', 'jellyfinToken'),
+					$this->settingsOption('disable-cert-check', 'jellyfinDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'jellyfinUseCustomCertificate'),
+				],
+				'Active Streams' => [
+					$this->settingsOption('enable', 'homepageJellyfinStreams'),
+					$this->settingsOption('auth', 'homepageJellyStreamsAuth'),
+					$this->settingsOption('switch', 'homepageShowStreamNames', ['label' => 'User Information']),
+					$this->settingsOption('auth', 'homepageShowStreamNamesAuth'),
+					$this->settingsOption('refresh', 'homepageStreamRefresh'),
+				],
+				'Recent Items' => [
+					$this->settingsOption('enable', 'homepageJellyfinRecent'),
+					$this->settingsOption('auth', 'homepageJellyfinRecentAuth'),
+					$this->settingsOption('limit', 'homepageRecentLimit'),
+					$this->settingsOption('refresh', 'homepageRecentRefresh'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('input', 'homepageJellyfinLink', ['label' => 'Jellyfin Homepage Link URL', 'help' => 'Available variables: {id} {serverId}']),
+					$this->settingsOption('input', 'jellyfinTabName', ['label' => 'Jellyfin Tab Name', 'placeholder' => 'Only use if you have Jellyfin in a reverse proxy']),
+					$this->settingsOption('image-cache-quality', 'cacheImageSize'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'jellyfin'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -183,9 +67,9 @@ trait JellyfinHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['jellyfinURL']);
 		$url = $url . "/Users?api_key=" . $this->config['jellyfinToken'];
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, null, $this->config['jellyfinDisableCertCheck'], $this->config['jellyfinUseCustomCertificate']);
 		try {
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body);
 				if (is_array($json) || is_object($json)) {
@@ -297,9 +181,9 @@ trait JellyfinHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['jellyfinURL']);
 		$url = $url . '/Sessions?api_key=' . $this->config['jellyfinToken'] . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, $this->config['homepageStreamRefresh'], $this->config['jellyfinDisableCertCheck'], $this->config['jellyfinUseCustomCertificate']);
 		try {
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$items = array();
 				$jellyfin = json_decode($response->body, true);
@@ -328,7 +212,7 @@ trait JellyfinHomepageItem
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['jellyfinURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, $this->config['homepageRecentRefresh'], $this->config['jellyfinDisableCertCheck'], $this->config['jellyfinUseCustomCertificate']);
 		$username = false;
 		$showPlayed = false;
 		$userId = 0;
@@ -338,7 +222,7 @@ trait JellyfinHomepageItem
 			}
 			// Get A User
 			$userIds = $url . "/Users?api_key=" . $this->config['jellyfinToken'];
-			$response = Requests::get($userIds, array(), $options);
+			$response = Requests::get($userIds, [], $options);
 			if ($response->success) {
 				$jellyfin = json_decode($response->body, true);
 				foreach ($jellyfin as $value) { // Scan for admin user
@@ -356,7 +240,7 @@ trait JellyfinHomepageItem
 				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
 				return false;
 			}
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$items = array();
 				$jellyfin = json_decode($response->body, true);
@@ -390,7 +274,7 @@ trait JellyfinHomepageItem
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['jellyfinURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$options = $this->requestOptions($url, 60, $this->config['jellyfinDisableCertCheck'], $this->config['jellyfinUseCustomCertificate']);
 		$username = false;
 		$showPlayed = false;
 		$userId = 0;
@@ -400,7 +284,7 @@ trait JellyfinHomepageItem
 			}
 			// Get A User
 			$userIds = $url . "/Users?api_key=" . $this->config['jellyfinToken'];
-			$response = Requests::get($userIds, array(), $options);
+			$response = Requests::get($userIds, [], $options);
 			if ($response->success) {
 				$jellyfin = json_decode($response->body, true);
 				foreach ($jellyfin as $value) { // Scan for admin user
@@ -418,7 +302,7 @@ trait JellyfinHomepageItem
 				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
 				return false;
 			}
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$items = array();
 				$jellyfin = json_decode($response->body, true);

+ 40 - 136
api/homepage/lidarr.php

@@ -14,140 +14,41 @@ trait LidarrHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageLidarrEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageLidarrEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageLidarrAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageLidarrAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'lidarrURL',
-						'label' => 'URL',
-						'value' => $this->config['lidarrURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'lidarrToken',
-						'label' => 'Token',
-						'value' => $this->config['lidarrToken']
-					)
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('lidarr') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'lidarrSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['lidarrSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'lidarrSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['lidarrSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'number',
-						'name' => 'calendarStart',
-						'label' => '# of Days Before',
-						'value' => $this->config['calendarStart'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'number',
-						'name' => 'calendarEnd',
-						'label' => '# of Days After',
-						'value' => $this->config['calendarEnd'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'lidarr\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageLidarrEnabled'),
+					$this->settingsOption('auth', 'homepageLidarrAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('multiple-url', 'lidarrURL'),
+					$this->settingsOption('multiple-token', 'lidarrToken'),
+					$this->settingsOption('disable-cert-check', 'lidarrDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'lidarrUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'lidarr'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'lidarrSocksEnabled'),
+					$this->settingsOption('auth', 'lidarrSocksAuth'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('calendar-start', 'calendarStart'),
+					$this->settingsOption('calendar-end', 'calendarEnd'),
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'lidarr'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -166,7 +67,8 @@ trait LidarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['lidarrURL'], $this->config['lidarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'lidarr');
+				$options = $this->requestOptions($value['url'], null, $this->config['lidarrDisableCertCheck'], $this->config['lidarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'lidarr', null . null, $options);
 				$results = $downloader->getRootFolder();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -246,7 +148,8 @@ trait LidarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['lidarrURL'], $this->config['lidarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'lidarr');
+				$options = $this->requestOptions($value['url'], null, $this->config['lidarrDisableCertCheck'], $this->config['lidarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'lidarr', null, null, $options);
 				$results = $downloader->getQueue();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -279,7 +182,8 @@ trait LidarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['lidarrURL'], $this->config['lidarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'lidarr');
+				$options = $this->requestOptions($value['url'], null, $this->config['lidarrDisableCertCheck'], $this->config['lidarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'lidarr', null, null, $options);
 				$results = $downloader->getCalendar($startDate, $endDate);
 				$result = json_decode($results, true);
 				if (is_array($result) || is_object($result)) {

+ 8 - 19
api/homepage/misc.php

@@ -14,26 +14,15 @@ trait MiscHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'YouTube' => array(
-					array(
-						'type' => 'input',
-						'name' => 'youtubeAPI',
-						'label' => 'Youtube API Key',
-						'value' => $this->config['youtubeAPI'],
-						'help' => 'Please make sure to input this API key as the organizr one gets limited'
-					),
-					array(
-						'type' => 'html',
-						'override' => 6,
-						'label' => 'Instructions',
-						'html' => '<a href="https://www.slickremix.com/docs/get-api-key-for-youtube/" target="_blank">Click here for instructions</a>'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'YouTube' => [
+					$this->settingsOption('token', 'youtubeAPI', ['label' => 'Youtube API Key', 'help' => 'Please make sure to input this API key as the organizr one gets limited']),
+					$this->settingsOption('html', null, ['override' => 6, 'label' => 'Instructions', 'html' => '<a href="https://www.slickremix.com/docs/get-api-key-for-youtube/" target="_blank">Click here for instructions</a>']),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	

+ 21 - 61
api/homepage/monitorr.php

@@ -14,66 +14,27 @@ trait MonitorrHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageMonitorrEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageMonitorrEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageMonitorrAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageMonitorrAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'monitorrURL',
-						'label' => 'URL',
-						'value' => $this->config['monitorrURL'],
-						'help' => 'URL for Monitorr. Please use the revers proxy URL i.e. https://domain.com/monitorr/.',
-						'placeholder' => 'http://domain.com/monitorr/'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageMonitorrRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageMonitorrRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'monitorrHeader',
-						'label' => 'Title',
-						'value' => $this->config['monitorrHeader'],
-						'help' => 'Sets the title of this homepage module',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'monitorrHeaderToggle',
-						'label' => 'Toggle Title',
-						'value' => $this->config['monitorrHeaderToggle'],
-						'help' => 'Shows/hides the title of this homepage module'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'monitorrCompact',
-						'label' => 'Compact view',
-						'value' => $this->config['monitorrCompact'],
-						'help' => 'Toggles the compact view of this homepage module'
-					),
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageMonitorrEnabled'),
+					$this->settingsOption('auth', 'homepageMonitorrAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'monitorrURL', ['help' => 'URL for Monitorr. Please use the reverse proxy URL i.e. https://domain.com/monitorr/.', 'placeholder' => 'http://domain.com/monitorr/']),
+					$this->settingsOption('blank'),
+					$this->settingsOption('disable-cert-check', 'monitorrDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'monitorrUseCustomCertificate'),
+				],
+				'Options' => [
+					$this->settingsOption('refresh', 'homepageMonitorrRefresh'),
+					$this->settingsOption('switch', 'monitorrCompact', ['label' => 'Compact view', 'help' => 'Toggles the compact view of this homepage module']),
+					$this->settingsOption('title', 'monitorrHeader'),
+					$this->settingsOption('toggle-title', 'monitorrHeaderToggle'),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -126,7 +87,7 @@ trait MonitorrHomepageItem
 		$url = $this->qualifyURL($this->config['monitorrURL']);
 		$dataUrl = $url . '/assets/php/loop.php';
 		try {
-			$options = $this->requestOptions($this->config['monitorrURL'], false, $this->config['homepageMonitorrRefresh']);
+			$options = $this->requestOptions($url, $this->config['homepageMonitorrRefresh'], $this->config['monitorrDisableCertCheck'], $this->config['monitorrUseCustomCertificate']);
 			$response = Requests::get($dataUrl, ['Token' => $this->config['organizrAPI']], $options);
 			if ($response->success) {
 				$html = html_entity_decode($response->body);
@@ -170,7 +131,6 @@ trait MonitorrHomepageItem
 					$ext = $ext[key(array_slice($ext, -1, 1, true))];
 					$imageUrl = $url . '/assets' . $image;
 					$cacheDirectory = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
-					$options = $this->requestOptions($this->config['monitorrURL'], false, $this->config['homepageMonitorrRefresh']);
 					$img = Requests::get($imageUrl, ['Token' => $this->config['organizrAPI']], $options);
 					if ($img->success) {
 						$base64 = 'data:image/' . $ext . ';base64,' . base64_encode($img->body);

+ 98 - 188
api/homepage/netdata.php

@@ -97,196 +97,99 @@ trait NetDataHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageNetdataEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageNetdataEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageNetdataAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageNetdataAuth'],
-						'options' => $this->groupSelect()
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'netdataURL',
-						'label' => 'URL',
-						'value' => $this->config['netdataURL'],
-						'help' => 'Please enter the local IP:PORT of your netdata instance'
-					),
-					array(
-						'type' => 'blank',
-						'label' => ''
-					),
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageNetdataEnabled'),
+					$this->settingsOption('auth', 'homepageNetdataAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'netdataURL'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('disable-cert-check', 'netdataDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'netdataUseCustomCertificate'),
+				],
+			]
+		];
 		for ($i = 1; $i <= 7; $i++) {
 			$homepageSettings['settings']['Chart ' . $i] = array(
-				array(
-					'type' => 'switch',
-					'name' => 'netdata' . $i . 'Enabled',
-					'label' => 'Enable',
-					'value' => $this->config['netdata' . $i . 'Enabled']
-				),
-				array(
-					'type' => 'blank',
-					'label' => ''
-				),
-				array(
-					'type' => 'input',
-					'name' => 'netdata' . $i . 'Title',
-					'label' => 'Title',
-					'value' => $this->config['netdata' . $i . 'Title'],
-					'help' => 'Title for the netdata graph'
-				),
-				array(
-					'type' => 'select',
-					'name' => 'netdata' . $i . 'Data',
-					'label' => 'Data',
-					'value' => $this->config['netdata' . $i . 'Data'],
-					'options' => $this->netdataOptions(),
-				),
-				array(
-					'type' => 'select',
-					'name' => 'netdata' . $i . 'Chart',
-					'label' => 'Chart',
-					'value' => $this->config['netdata' . $i . 'Chart'],
-					'options' => $this->netdataChartOptions(),
-				),
-				array(
-					'type' => 'select',
-					'name' => 'netdata' . $i . 'Colour',
-					'label' => 'Colour',
-					'value' => $this->config['netdata' . $i . 'Colour'],
-					'options' => $this->netdataColourOptions(),
-				),
-				array(
-					'type' => 'select',
-					'name' => 'netdata' . $i . 'Size',
-					'label' => 'Size',
-					'value' => $this->config['netdata' . $i . 'Size'],
-					'options' => $this->netdataSizeOptions(),
-				),
-				array(
-					'type' => 'blank',
-					'label' => ''
-				),
-				array(
-					'type' => 'switch',
-					'name' => 'netdata' . $i . 'lg',
-					'label' => 'Show on large screens',
-					'value' => $this->config['netdata' . $i . 'lg']
-				),
-				array(
-					'type' => 'switch',
-					'name' => 'netdata' . $i . 'md',
-					'label' => 'Show on medium screens',
-					'value' => $this->config['netdata' . $i . 'md']
-				),
-				array(
-					'type' => 'switch',
-					'name' => 'netdata' . $i . 'sm',
-					'label' => 'Show on small screens',
-					'value' => $this->config['netdata' . $i . 'sm']
-				),
+				$this->settingsOption('enable', 'netdata' . $i . 'Enabled'),
+				$this->settingsOption('blank'),
+				$this->settingsOption('input', 'netdata' . $i . 'Title', ['label' => 'Title', 'help' => 'Title for the netdata graph']),
+				$this->settingsOption('select', 'netdata' . $i . 'Data', ['label' => 'Data', 'options' => $this->netdataOptions()]),
+				$this->settingsOption('select', 'netdata' . $i . 'Chart', ['label' => 'Chart', 'options' => $this->netdataChartOptions()]),
+				$this->settingsOption('select', 'netdata' . $i . 'Colour', ['label' => 'Colour', 'options' => $this->netdataColourOptions()]),
+				$this->settingsOption('select', 'netdata' . $i . 'Size', ['label' => 'Size', 'options' => $this->netdataSizeOptions()]),
+				$this->settingsOption('blank'),
+				$this->settingsOption('switch', 'netdata' . $i . 'lg', ['label' => 'Show on large screens']),
+				$this->settingsOption('switch', 'netdata' . $i . 'md', ['label' => 'Show on medium screens']),
+				$this->settingsOption('switch', 'netdata' . $i . 'sm', ['label' => 'Show on small screens']),
 			);
 		}
 		$homepageSettings['settings']['Custom data'] = array(
-			array(
-				'type' => 'html',
-				'label' => '',
-				'override' => 12,
-				'html' => '
+			$this->settingsOption('html', null, ['label' => '', 'override' => 12, 'html' => '
 			<div>
-			    <p>This is where you can define custom data sources for your netdata charts. To use a custom source, you need to select "Custom" in the data field for the chart.</p>
-			    <p>To define a custom data source, you need to add an entry to the JSON below, where the key is the chart number you want the custom data to be used for. Here is an example to set chart 1 custom data source to RAM percentage:</p>
-			    <pre>{
-			    "1": {
-			        "url": "/api/v1/data?chart=system.ram&format=array&points=540&group=average&gtime=0&options=absolute|percentage|jsonwrap|nonzero&after=-540&dimensions=used|buffers|active|wired",
-			        "value": "result,0",
-			        "units": "%",
-			        "max": 100
-			    }
-			}</pre>
-			    <p>The URL is appended to your netdata URL and returns JSON formatted data. The value field tells Organizr how to return the value you want from the netdata API. This should be formatted as comma-separated keys to access the desired value.</p>
-			    <table class="table table-striped">
-			        <thead>
-			            <tr>
-			                <th>Parameter</th>
-			                <th>Description</th>
-			                <th>Required</th>
-			            </tr>
-			        </thead>
-			        <tbody>
-			            <tr>
-			                <td>url</td>
-			                <td>Specifies the netdata API endpoint</td>
-			                <td><i class="fa fa-check text-success" aria-hidden="true"></i></td>
-			            </tr>
-			            <tr>
-			                <td>value</td>
-			                <td>Specifies the selector used to get the data form the netdata response</td>
-			                <td><i class="fa fa-check text-success" aria-hidden="true"></i></td>
-			            </tr>
-			            <tr>
-			                <td>units</td>
-			                <td>Specifies the units shown in the graph/chart. Defaults to %</td>
-			                <td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
-			            </tr>
-			            <tr>
-			                <td>max</td>
-			                <td>Specifies the maximum possible value for the data. Defaults to 100</td>
-			                <td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
-			            </tr>
-			            <tr>
-			                <td>mutator</td>
-			                <td>Used to perform simple mathematical operations on the result (+, -, /, *). For example: dividing the result by 1000 would be "/1000". These operations can be chained together by putting them in a comma-seprated format.</td>
-			                <td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
-			            </tr>
-			            <tr>
-			                <td>netdata</td>
-			                <td>Can be used to override the netdata instance data is retrieved from (in the format: http://IP:PORT)</td>
-			                <td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
-			            </tr>
-			        </tbody>
-			    </table>
-			</div>'
-			),
-			array(
-				'type' => 'html',
-				'name' => 'netdataCustomTextAce',
-				'class' => 'jsonTextarea hidden',
-				'label' => 'Custom definitions',
-				'override' => 12,
-				'html' => '<div id="netdataCustomTextAce" style="height: 300px;">' . htmlentities($this->config['netdataCustom']) . '</div>',
-			),
-			array(
-				'type' => 'textbox',
-				'name' => 'netdataCustom',
-				'class' => 'jsonTextarea hidden',
-				'id' => 'netdataCustomText',
-				'label' => '',
-				'value' => $this->config['netdataCustom'],
-			)
+				<p>This is where you can define custom data sources for your netdata charts. To use a custom source, you need to select "Custom" in the data field for the chart.</p>
+				<p>To define a custom data source, you need to add an entry to the JSON below, where the key is the chart number you want the custom data to be used for. Here is an example to set chart 1 custom data source to RAM percentage:</p>
+				<pre>
+{
+	"1": {
+		"url": "/api/v1/data?chart=system.ram&format=array&points=540&group=average&gtime=0&options=absolute|percentage|jsonwrap|nonzero&after=-540&dimensions=used|buffers|active|wired",
+		"value": "result,0",
+		"units": "%",
+		"max": 100
+	}
+}
+				</pre>
+				<p>The URL is appended to your netdata URL and returns JSON formatted data. The value field tells Organizr how to return the value you want from the netdata API. This should be formatted as comma-separated keys to access the desired value.</p>
+				<table class="table table-striped">
+					<thead>
+						<tr>
+							<th>Parameter</th>
+							<th>Description</th>
+							<th>Required</th>
+						</tr>
+					</thead>
+					<tbody>
+						<tr>
+							<td>url</td>
+							<td>Specifies the netdata API endpoint</td>
+							<td><i class="fa fa-check text-success" aria-hidden="true"></i></td>
+						</tr>
+						<tr>
+							<td>value</td>
+							<td>Specifies the selector used to get the data form the netdata response</td>
+							<td><i class="fa fa-check text-success" aria-hidden="true"></i></td>
+						</tr>
+						<tr>
+							<td>units</td>
+							<td>Specifies the units shown in the graph/chart. Defaults to %</td>
+							<td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
+						</tr>
+						<tr>
+							<td>max</td>
+							<td>Specifies the maximum possible value for the data. Defaults to 100</td>
+							<td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
+						</tr>
+						<tr>
+							<td>mutator</td>
+							<td>Used to perform simple mathematical operations on the result (+, -, /, *). For example: dividing the result by 1000 would be "/1000". These operations can be chained together by putting them in a comma-seprated format.</td>
+							<td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
+						</tr>
+						<tr>
+							<td>netdata</td>
+							<td>Can be used to override the netdata instance data is retrieved from (in the format: http://IP:PORT)</td>
+							<td><i class="fa fa-times text-danger" aria-hidden="true"></i></td>
+						</tr>
+					</tbody>
+				</table>
+			</div>']),
+			$this->settingsOption('html', 'netdataCustomTextAce', ['class' => 'jsonTextarea hidden', 'label' => 'Custom definitions', 'override' => 12, 'html' => '<div id="netdataCustomTextAce" style="height: 300px;">' . htmlentities($this->config['netdataCustom']) . '</div>']),
+			$this->settingsOption('textbox', 'netdataCustom', ['class' => 'jsonTextarea hidden', 'id' => 'netdataCustomText', 'label' => '']),
 		);
 		$homepageSettings['settings']['Options'] = array(
-			array(
-				'type' => 'select',
-				'name' => 'homepageNetdataRefresh',
-				'label' => 'Refresh Seconds',
-				'value' => $this->config['homepageNetdataRefresh'],
-				'options' => $this->timeOptions()
-			),
+			$this->settingsOption('refresh', 'homepageNetdataRefresh'),
 		);
 		return array_merge($homepageInformation, $homepageSettings);
 	}
@@ -337,7 +240,8 @@ trait NetDataHomepageItem
 		// Get Data
 		$dataUrl = $url . '/api/v1/data?chart=system.io&dimensions=' . $dimension . '&format=array&points=540&group=average&gtime=0&options=absolute|jsonwrap|nonzero&after=-540';
 		try {
-			$response = Requests::get($dataUrl);
+			$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$data['value'] = $json['latest_values'][0] / 1000;
@@ -357,7 +261,8 @@ trait NetDataHomepageItem
 		// Get Data
 		$dataUrl = $url . '/api/v1/data?chart=disk_space._&format=json&points=509&group=average&gtime=0&options=ms|jsonwrap|nonzero&after=-540&dimension=' . $dimension;
 		try {
-			$response = Requests::get($dataUrl);
+			$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$data['value'] = $json['result']['data'][0][1];
@@ -377,7 +282,8 @@ trait NetDataHomepageItem
 		// Get Data
 		$dataUrl = $url . '/api/v1/data?chart=system.net&dimensions=' . $dimension . '&format=array&points=540&group=average&gtime=0&options=absolute|jsonwrap|nonzero&after=-540';
 		try {
-			$response = Requests::get($dataUrl);
+			$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$data['value'] = $json['latest_values'][0] / 1000;
@@ -396,7 +302,8 @@ trait NetDataHomepageItem
 		$data = [];
 		$dataUrl = $url . '/api/v1/data?chart=system.cpu&format=array';
 		try {
-			$response = Requests::get($dataUrl);
+			$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$data['value'] = $json[0];
@@ -415,7 +322,8 @@ trait NetDataHomepageItem
 		$data = [];
 		$dataUrl = $url . '/api/v1/data?chart=system.ram&format=array&points=540&group=average&gtime=0&options=absolute|percentage|jsonwrap|nonzero&after=-540&dimensions=used|buffers|active|wired';
 		try {
-			$response = Requests::get($dataUrl);
+			$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$data['value'] = $json['result'][0];
@@ -434,7 +342,8 @@ trait NetDataHomepageItem
 		$data = [];
 		$dataUrl = $url . '/api/v1/data?chart=system.swap&format=array&points=540&group=average&gtime=0&options=absolute|percentage|jsonwrap|nonzero&after=-540&dimensions=used';
 		try {
-			$response = Requests::get($dataUrl);
+			$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$data['value'] = $json['result'][0];
@@ -481,7 +390,8 @@ trait NetDataHomepageItem
 				}
 				$dataUrl = $url . '/' . $custom['url'];
 				try {
-					$response = Requests::get($dataUrl);
+					$options = $this->requestOptions($url, $this->config['homepageNetdataRefresh'], $this->config['netdataDisableCertCheck'], $this->config['netdataUseCustomCertificate']);
+					$response = Requests::get($dataUrl, [], $options);
 					if ($response->success) {
 						$json = json_decode($response->body, true);
 						if (!isset($custom['max']) || $custom['max'] == '') {

+ 32 - 98
api/homepage/nzbget.php

@@ -14,103 +14,37 @@ trait NZBGetHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageNzbgetEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageNzbgetEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageNzbgetAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageNzbgetAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'nzbgetURL',
-						'label' => 'URL',
-						'value' => $this->config['nzbgetURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'nzbgetUsername',
-						'label' => 'Username',
-						'value' => $this->config['nzbgetUsername']
-					),
-					array(
-						'type' => 'password',
-						'name' => 'nzbgetPassword',
-						'label' => 'Password',
-						'value' => $this->config['nzbgetPassword']
-					)
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('nzbget') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'nzbgetSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['nzbgetSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'nzbgetSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['nzbgetSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'nzbgetRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['nzbgetRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'nzbgetCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['nzbgetCombine']
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'nzbget\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageNzbgetEnabled'),
+					$this->settingsOption('auth', 'homepageNzbgetAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'nzbgetURL'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('username', 'nzbgetUsername'),
+					$this->settingsOption('password', 'nzbgetPassword'),
+					$this->settingsOption('disable-cert-check', 'nzbgetDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'nzbgetUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'nzbget'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'nzbgetSocksEnabled'),
+					$this->settingsOption('auth', 'nzbgetSocksAuth'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('refresh', 'nzbgetRefresh'),
+					$this->settingsOption('combine', 'nzbgetCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'nzbget'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -122,7 +56,7 @@ trait NZBGetHomepageItem
 		}
 		try {
 			$url = $this->qualifyURL($this->config['nzbgetURL']);
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
+			$options = $this->requestOptions($url, null, $this->config['nzbgetDisableCertCheck'], $this->config['nzbgetUseCustomCertificate']);
 			$urlGroups = $url . '/jsonrpc/listgroups';
 			if ($this->config['nzbgetUsername'] !== '' && $this->decrypt($this->config['nzbgetPassword']) !== '') {
 				$credentials = array('auth' => new Requests_Auth_Basic(array($this->config['nzbgetUsername'], $this->decrypt($this->config['nzbgetPassword']))));
@@ -193,7 +127,7 @@ trait NZBGetHomepageItem
 		}
 		try {
 			$url = $this->qualifyURL($this->config['nzbgetURL']);
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
+			$options = $this->requestOptions($url, $this->config['nzbgetRefresh'], $this->config['nzbgetDisableCertCheck'], $this->config['nzbgetUseCustomCertificate']);
 			$urlGroups = $url . '/jsonrpc/listgroups';
 			$urlHistory = $url . '/jsonrpc/history';
 			if ($this->config['nzbgetUsername'] !== '' && $this->decrypt($this->config['nzbgetPassword']) !== '') {

+ 20 - 52
api/homepage/octoprint.php

@@ -14,58 +14,25 @@ trait OctoPrintHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageOctoprintEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageOctoprintEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageOctoprintAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageOctoprintAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'octoprintURL',
-						'label' => 'URL',
-						'value' => $this->config['octoprintURL'],
-						'help' => 'Enter the IP:PORT of your Octoprint instance e.g. http://octopi.local'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'octoprintToken',
-						'label' => 'API Key',
-						'value' => $this->config['octoprintToken'],
-						'help' => 'Enter your Octoprint API key, found in Octoprint settings page.'
-					),
-				),
-				'Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'octoprintHeader',
-						'label' => 'Title',
-						'value' => $this->config['octoprintHeader'],
-						'help' => 'Sets the title of this homepage module',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'octoprintToggle',
-						'label' => 'Toggle Title',
-						'value' => $this->config['octoprintHeaderToggle'],
-						'help' => 'Shows/hides the title of this homepage module'
-					),
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageOctoprintEnabled'),
+					$this->settingsOption('auth', 'homepageOctoprintAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'octoprintURL'),
+					$this->settingsOption('token', 'octoprintToken'),
+					$this->settingsOption('disable-cert-check', 'octoprintDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'octoprintUseCustomCertificate'),
+				],
+				'Options' => [
+					$this->settingsOption('title', 'octoprintHeader'),
+					$this->settingsOption('toggle-title', 'octoprintHeaderToggle'),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -123,7 +90,8 @@ trait OctoPrintHomepageItem
 			$dataUrl = $url . '/api/' . $endpoint;
 			try {
 				$headers = array('X-API-KEY' => $this->config['octoprintToken']);
-				$response = Requests::get($dataUrl, $headers);
+				$options = $this->requestOptions($url, $this->config['homepageOctoprintRefresh'], $this->config['octoprintDisableCertCheck'], $this->config['octoprintUseCustomCertificate']);
+				$response = Requests::get($dataUrl, $headers, $options);
 				if ($response->success) {
 					$json = json_decode($response->body, true);
 					$api['data'][$endpoint] = $json;

+ 40 - 145
api/homepage/ombi.php

@@ -15,148 +15,42 @@ trait OmbiHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageOmbiEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageOmbiEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageOmbiAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageOmbiAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'ombiURL',
-						'label' => 'URL',
-						'value' => $this->config['ombiURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'ombiToken',
-						'label' => 'Token',
-						'value' => $this->config['ombiToken']
-					),
-					array(
-						'type' => 'input',
-						'name' => 'ombiFallbackUser',
-						'label' => 'Ombi Fallback User',
-						'value' => $this->config['ombiFallbackUser'],
-						'help' => 'Organizr will request an Ombi User Token based off of this user credentials'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'ombiFallbackPassword',
-						'label' => 'Ombi Fallback Password',
-						'value' => $this->config['ombiFallbackPassword']
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'homepageOmbiRequestAuth',
-						'label' => 'Minimum Group to Request',
-						'value' => $this->config['homepageOmbiRequestAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'select',
-						'name' => 'ombiTvDefault',
-						'label' => 'TV Show Default Request',
-						'value' => $this->config['ombiTvDefault'],
-						'options' => $this->ombiTvOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'ombiLimitUser',
-						'label' => 'Limit to User',
-						'value' => $this->config['ombiLimitUser']
-					),
-					array(
-						'type' => 'number',
-						'name' => 'ombiLimit',
-						'label' => 'Item Limit',
-						'value' => $this->config['ombiLimit'],
-					),
-					array(
-						'type' => 'select',
-						'name' => 'ombiRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['ombiRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'ombiAlias',
-						'label' => 'Use Ombi Alias Names',
-						'value' => $this->config['ombiAlias'],
-						'help' => 'Use Ombi Alias Names instead of Usernames - If Alias is blank, Alias will fallback to Username'
-					)
-				),
-				'Default Filter' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'ombiDefaultFilterAvailable',
-						'label' => 'Show Available',
-						'value' => $this->config['ombiDefaultFilterAvailable'],
-						'help' => 'Show All Available Ombi Requests'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'ombiDefaultFilterUnavailable',
-						'label' => 'Show Unavailable',
-						'value' => $this->config['ombiDefaultFilterUnavailable'],
-						'help' => 'Show All Unavailable Ombi Requests'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'ombiDefaultFilterApproved',
-						'label' => 'Show Approved',
-						'value' => $this->config['ombiDefaultFilterApproved'],
-						'help' => 'Show All Approved Ombi Requests'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'ombiDefaultFilterUnapproved',
-						'label' => 'Show Unapproved',
-						'value' => $this->config['ombiDefaultFilterUnapproved'],
-						'help' => 'Show All Unapproved Ombi Requests'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'ombiDefaultFilterDenied',
-						'label' => 'Show Denied',
-						'value' => $this->config['ombiDefaultFilterDenied'],
-						'help' => 'Show All Denied Ombi Requests'
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'ombi\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageOmbiEnabled'),
+					$this->settingsOption('auth', 'homepageOmbiAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'ombiURL'),
+					$this->settingsOption('token', 'ombiToken'),
+					$this->settingsOption('username', 'ombiFallbackUser', ['label' => 'Ombi Fallback User', 'help' => 'Organizr will request an Ombi User Token based off of this user credentials']),
+					$this->settingsOption('password', 'ombiFallbackPassword', ['label' => 'Ombi Fallback Password',]),
+					$this->settingsOption('disable-cert-check', 'ombiDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'ombiUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('auth', 'homepageOmbiRequestAuth', ['label' => 'Minimum Group to Request']),
+					$this->settingsOption('select', 'ombiTvDefault', ['label' => 'TV Show Default Request', 'options' => $this->ombiTvOptions()]),
+					$this->settingsOption('switch', 'ombiLimitUser', ['label' => 'Limit to User']),
+					$this->settingsOption('limit', 'ombiLimit'),
+					$this->settingsOption('refresh', 'ombiRefresh'),
+					$this->settingsOption('switch', 'ombiAlias', ['label' => 'Use Ombi Alias Names', 'help' => 'Use Ombi Alias Names instead of Usernames - If Alias is blank, Alias will fallback to Username']),
+				],
+				'Default Filter' => [
+					$this->settingsOption('switch', 'ombiDefaultFilterAvailable', ['label' => 'Show Available', 'help' => 'Show All Available Ombi Requests']),
+					$this->settingsOption('switch', 'ombiDefaultFilterUnavailable', ['label' => 'Show Unavailable', 'help' => 'Show All Unavailable Ombi Requests']),
+					$this->settingsOption('switch', 'ombiDefaultFilterApproved', ['label' => 'Show Approved', 'help' => 'Show All Approved Ombi Requests']),
+					$this->settingsOption('switch', 'ombiDefaultFilterUnapproved', ['label' => 'Show Unapproved', 'help' => 'Show All Unapproved Ombi Requests']),
+					$this->settingsOption('switch', 'ombiDefaultFilterDenied', ['label' => 'Show Denied', 'help' => 'Show All Denied Ombi Requests']),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'ombi'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -176,7 +70,7 @@ trait OmbiHomepageItem
 		);
 		$url = $this->qualifyURL($this->config['ombiURL']);
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
+			$options = $this->requestOptions($url, null, $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
 			$test = Requests::get($url . "/api/v1/Settings/about", $headers, $options);
 			if ($test->success) {
 				$this->setAPIResponse('success', 'API Connection succeeded', 200);
@@ -250,7 +144,7 @@ trait OmbiHomepageItem
 		$requests = array();
 		$url = $this->qualifyURL($this->config['ombiURL']);
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
+			$options = $this->requestOptions($url, $this->config['ombiRefresh'], $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
 			switch ($type) {
 				case 'movie':
 					$movie = Requests::get($url . "/api/v1/Request/movie", $headers, $options);
@@ -374,7 +268,7 @@ trait OmbiHomepageItem
 				break;
 		}
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false, 'timeout' => 30) : array('timeout' => 30);
+			$options = array('timeout' => 30);
 			if (isset($_COOKIE['Auth'])) {
 				$headers = array(
 					"Accept" => "application/json",
@@ -428,6 +322,7 @@ trait OmbiHomepageItem
 				$this->setAPIResponse('error', 'Could not contact TMDB', 422);
 				return false;
 			}
+			$options = $this->requestOptions($url, null, $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
 			$searchResponse = Requests::get($url . '/api/v1/Search/' . $type . '/' . urlencode($title), $headers, $options);
 			if ($searchResponse->success) {
 				$details = json_decode($searchResponse->body, true);
@@ -503,7 +398,7 @@ trait OmbiHomepageItem
 				break;
 		}
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false, 'timeout' => 30) : array('timeout' => 30);
+			$options = $this->requestOptions($url, 60, $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
 			switch ($action) {
 				case 'approve':
 					$response = Requests::post($url . "/api/v1/Request/" . $type . "/approve", $headers, json_encode($data), $options);

+ 19 - 59
api/homepage/pihole.php

@@ -14,66 +14,26 @@ trait PiHoleHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepagePiholeEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepagePiholeEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepagePiholeAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepagePiholeAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'piholeURL',
-						'label' => 'URL',
-						'value' => $this->config['piholeURL'],
-						'help' => 'Please make sure to use local IP address and port and to include \'/admin/\' at the end of the URL. You can add multiple Pi-holes by comma separating the URLs.',
-						'placeholder' => 'http(s)://hostname:port/admin/'
-					),
-				),
-				'Misc' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'piholeHeaderToggle',
-						'label' => 'Toggle Title',
-						'value' => $this->config['piholeHeaderToggle'],
-						'help' => 'Shows/hides the title of this homepage module'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepagePiholeCombine',
-						'label' => 'Combine stat cards',
-						'value' => $this->config['homepagePiholeCombine'],
-						'help' => 'This controls whether to combine the stats for multiple pihole instances into 1 card.',
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'pihole\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepagePiholeEnabled'),
+					$this->settingsOption('auth', 'homepagePiholeAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'piholeURL', ['help' => 'Please make sure to use local IP address and port and to include \'/admin/\' at the end of the URL. You can add multiple Pi-holes by comma separating the URLs.', 'placeholder' => 'http(s)://hostname:port/admin/']),
+				],
+				'Misc' => [
+					$this->settingsOption('toggle-title', 'piholeHeaderToggle'),
+					$this->settingsOption('switch', 'homepagePiholeCombine', ['label' => 'Combine stat cards', 'help' => 'This controls whether to combine the stats for multiple pihole instances into 1 card.']),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'pihole'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	

+ 73 - 282
api/homepage/plex.php

@@ -15,279 +15,69 @@ trait PlexHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
+		$libraryList = [['name' => 'Refresh page to update List', 'value' => '', 'disabled' => true]];
 		if ($this->config['plexID'] !== '' && $this->config['plexToken'] !== '') {
+			$libraryList = [];
 			$loop = $this->plexLibraryList('key')['libraries'];
 			foreach ($loop as $key => $value) {
-				$libraryList[] = array(
-					'name' => $key,
-					'value' => $value
-				);
+				$libraryList[] = ['name' => $key, 'value' => $value];
 			}
-		} else {
-			$libraryList = array(
-				array(
-					'name' => 'Refresh page to update List',
-					'value' => '',
-					'disabled' => true,
-				),
-			);
-		}
-		$homepageSettings = array(
-			'name' => 'Plex',
-			'enabled' => strpos('personal', $this->config['license']) !== false,
-			'image' => 'plugins/images/tabs/plex.png',
-			'category' => 'Media Server',
+		}
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepagePlexEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepagePlexEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepagePlexAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepagePlexAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'plexURL',
-						'label' => 'URL',
-						'value' => $this->config['plexURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'blank',
-						'name' => '',
-						'label' => '',
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'plexToken',
-						'label' => 'Token',
-						'value' => $this->config['plexToken']
-					),
-					array(
-						'type' => 'button',
-						'label' => 'Get Plex Token',
-						'icon' => 'fa fa-ticket',
-						'text' => 'Retrieve',
-						'attr' => 'onclick="showPlexTokenForm(\'#homepage-Plex-form [name=plexToken]\')"'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'plexID',
-						'label' => 'Plex Machine',
-						'value' => $this->config['plexID']
-					),
-					array(
-						'type' => 'button',
-						'label' => 'Get Plex Machine',
-						'icon' => 'fa fa-id-badge',
-						'text' => 'Retrieve',
-						'attr' => 'onclick="showPlexMachineForm(\'#homepage-Plex-form [name=plexID]\')"'
-					),
-				),
-				'Active Streams' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepagePlexStreams',
-						'label' => 'Enable',
-						'value' => $this->config['homepagePlexStreams']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepagePlexStreamsAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepagePlexStreamsAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageShowStreamNames',
-						'label' => 'User Information',
-						'value' => $this->config['homepageShowStreamNames']
-					),
-					array(
-						'type' => 'select2',
-						'class' => 'select2-multiple',
-						'id' => 'plex-stream-exclude-select',
-						'name' => 'homepagePlexStreamsExclude',
-						'label' => 'Libraries to Exclude',
-						'value' => $this->config['homepagePlexStreamsExclude'],
-						'options' => $libraryList
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageShowStreamNamesAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepageShowStreamNamesAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageStreamRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageStreamRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Recent Items' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepagePlexRecent',
-						'label' => 'Enable',
-						'value' => $this->config['homepagePlexRecent']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepagePlexRecentAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepagePlexRecentAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'select2',
-						'class' => 'select2-multiple',
-						'id' => 'plex-recent-exclude-select',
-						'name' => 'homepagePlexRecentExclude',
-						'label' => 'Libraries to Exclude',
-						'value' => $this->config['homepagePlexRecentExclude'],
-						'options' => $libraryList
-					),
-					array(
-						'type' => 'number',
-						'name' => 'homepageRecentLimit',
-						'label' => 'Item Limit',
-						'value' => $this->config['homepageRecentLimit'],
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageRecentRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageRecentRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Media Search' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'mediaSearch',
-						'label' => 'Enable',
-						'value' => $this->config['mediaSearch']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'mediaSearchAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['mediaSearchAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'select2',
-						'class' => 'select2-multiple',
-						'id' => 'plex-search-exclude-select',
-						'name' => 'homepagePlexSearchExclude',
-						'label' => 'Libraries to Exclude',
-						'value' => $this->config['homepagePlexSearchExclude'],
-						'options' => $libraryList
-					),
-					array(
-						'type' => 'select',
-						'name' => 'mediaSearchType',
-						'label' => 'Media Server',
-						'value' => $this->config['mediaSearchType'],
-						'options' => $this->mediaServerOptions()
-					),
-				),
-				'Playlists' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepagePlexPlaylist',
-						'label' => 'Enable',
-						'value' => $this->config['homepagePlexPlaylist']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepagePlexPlaylistAuth',
-						'label' => 'Minimum Authorization',
-						'value' => $this->config['homepagePlexPlaylistAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'plexTabName',
-						'label' => 'Plex Tab Name',
-						'value' => $this->config['plexTabName'],
-						'placeholder' => 'Only use if you have Plex in a reverse proxy'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'plexTabURL',
-						'label' => 'Plex Tab WAN URL',
-						'value' => $this->config['plexTabURL'],
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'cacheImageSize',
-						'label' => 'Image Cache Size',
-						'value' => $this->config['cacheImageSize'],
-						'options' => array(
-							array(
-								'name' => 'Low',
-								'value' => '.5'
-							),
-							array(
-								'name' => '1x',
-								'value' => '1'
-							),
-							array(
-								'name' => '2x',
-								'value' => '2'
-							),
-							array(
-								'name' => '3x',
-								'value' => '3'
-							)
-						)
-					),
-					array(
-						'type' => 'blank',
-						'label' => ''
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageUseCustomStreamNames',
-						'label' => 'Use Tautulli custom names for users',
-						'value' => $this->config['homepageUseCustomStreamNames']
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'plex\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepagePlexEnabled'),
+					$this->settingsOption('auth', 'homepagePlexAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'plexURL'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('disable-cert-check', 'plexDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'plexUseCustomCertificate'),
+					$this->settingsOption('token', 'plexToken'),
+					$this->settingsOption('button', '', ['label' => 'Get Plex Token', 'icon' => 'fa fa-ticket', 'text' => 'Retrieve', 'attr' => 'onclick="showPlexTokenForm(\'#homepage-Plex-form [name=plexToken]\')"']),
+					$this->settingsOption('password-alt', 'plexID', ['label' => 'Plex Machine']),
+					$this->settingsOption('button', '', ['label' => 'Get Plex Machine', 'icon' => 'fa fa-id-badge', 'text' => 'Retrieve', 'attr' => 'onclick="showPlexMachineForm(\'#homepage-Plex-form [name=plexID]\')"']),
+				],
+				'Active Streams' => [
+					$this->settingsOption('enable', 'homepagePlexStreams'),
+					$this->settingsOption('auth', 'homepagePlexStreamsAuth'),
+					$this->settingsOption('switch', 'homepageShowStreamNames', ['label' => 'User Information']),
+					$this->settingsOption('auth', 'homepageShowStreamNamesAuth'),
+					$this->settingsOption('refresh', 'homepageStreamRefresh'),
+					$this->settingsOption('plex-library-exclude', 'homepagePlexStreamsExclude', ['options' => $libraryList]),
+				],
+				'Recent Items' => [
+					$this->settingsOption('enable', 'homepagePlexRecent'),
+					$this->settingsOption('auth', 'homepagePlexRecentAuth'),
+					$this->settingsOption('plex-library-exclude', 'homepagePlexRecentExclude', ['options' => $libraryList]),
+					$this->settingsOption('limit', 'homepageRecentLimit'),
+					$this->settingsOption('refresh', 'homepageRecentRefresh'),
+				],
+				'Media Search' => [
+					$this->settingsOption('enable', 'mediaSearch'),
+					$this->settingsOption('auth', 'mediaSearchAuth'),
+					$this->settingsOption('plex-library-exclude', 'homepagePlexSearchExclude', ['options' => $libraryList]),
+					$this->settingsOption('media-search-server', 'mediaSearchType'),
+				],
+				'Playlists' => [
+					$this->settingsOption('enable', 'homepagePlexPlaylist'),
+					$this->settingsOption('auth', 'homepagePlexPlaylistAuth'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('input', 'plexTabName', ['label' => 'Plex Tab Name', 'placeholder' => 'Only use if you have Plex in a reverse proxy']),
+					$this->settingsOption('input', 'plexTabURL', ['label' => 'Plex Tab WAN URL', 'placeholder' => 'http(s)://domain.com/plex']),
+					$this->settingsOption('image-cache-quality', 'cacheImageSize'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('switch', 'homepageUseCustomStreamNames', ['label' => 'Use Tautulli custom names for users']),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'plex'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -296,8 +86,8 @@ trait PlexHomepageItem
 		if (!empty($this->config['plexURL']) && !empty($this->config['plexToken'])) {
 			$url = $this->qualifyURL($this->config['plexURL']) . "/servers?X-Plex-Token=" . $this->config['plexToken'];
 			try {
-				$options = ($this->localURL($url)) ? array('verify' => false) : array();
-				$response = Requests::get($url, array(), $options);
+				$options = $this->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
+				$response = Requests::get($url, [], $options);
 				libxml_use_internal_errors(true);
 				if ($response->success) {
 					$this->setAPIResponse('success', 'API Connection succeeded', 200);
@@ -461,8 +251,8 @@ trait PlexHomepageItem
 		$resolve = true;
 		$url = $this->qualifyURL($this->config['plexURL']);
 		$url = $url . "/status/sessions?X-Plex-Token=" . $this->config['plexToken'];
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$response = Requests::get($url, array(), $options);
+		$options = $this->requestOptions($url, $this->config['homepageStreamRefresh'], $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
+		$response = Requests::get($url, [], $options);
 		libxml_use_internal_errors(true);
 		if ($response->success) {
 			$items = array();
@@ -494,8 +284,8 @@ trait PlexHomepageItem
 		$urls['tv'] = $url . "/hubs/home/recentlyAdded?X-Plex-Token=" . $this->config['plexToken'] . "&X-Plex-Container-Start=0&X-Plex-Container-Size=" . $this->config['homepageRecentLimit'] . "&type=2";
 		$urls['music'] = $url . "/hubs/home/recentlyAdded?X-Plex-Token=" . $this->config['plexToken'] . "&X-Plex-Container-Start=0&X-Plex-Container-Size=" . $this->config['homepageRecentLimit'] . "&type=8";
 		foreach ($urls as $k => $v) {
-			$options = ($this->localURL($v)) ? array('verify' => false) : array();
-			$response = Requests::get($v, array(), $options);
+			$options = $this->requestOptions($url, $this->config['homepageRecentRefresh'], $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
+			$response = Requests::get($v, [], $options);
 			libxml_use_internal_errors(true);
 			if ($response->success) {
 				$items = array();
@@ -531,8 +321,8 @@ trait PlexHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['plexURL']);
 		$url = $url . "/playlists?X-Plex-Token=" . $this->config['plexToken'];
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$response = Requests::get($url, array(), $options);
+		$options = $this->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
+		$response = Requests::get($url, [], $options);
 		libxml_use_internal_errors(true);
 		if ($response->success) {
 			$items = array();
@@ -579,8 +369,8 @@ trait PlexHomepageItem
 		$resolve = true;
 		$url = $this->qualifyURL($this->config['plexURL']);
 		$url = $url . "/library/metadata/" . $key . "?X-Plex-Token=" . $this->config['plexToken'];
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$response = Requests::get($url, array(), $options);
+		$options = $this->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
+		$response = Requests::get($url, [], $options);
 		libxml_use_internal_errors(true);
 		if ($response->success) {
 			$items = array();
@@ -614,8 +404,8 @@ trait PlexHomepageItem
 		$resolve = true;
 		$url = $this->qualifyURL($this->config['plexURL']);
 		$url = $url . "/search?query=" . rawurlencode($query) . "&X-Plex-Token=" . $this->config['plexToken'];
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$response = Requests::get($url, array(), $options);
+		$options = $this->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
+		$response = Requests::get($url, [], $options);
 		libxml_use_internal_errors(true);
 		if ($response->success) {
 			$items = array();
@@ -836,7 +626,8 @@ trait PlexHomepageItem
 		$url = $this->qualifyURL($this->config['tautulliURL']);
 		$url .= '/api/v2?apikey=' . $this->config['tautulliApikey'];
 		$url .= '&cmd=get_users';
-		$response = Requests::get($url, [], []);
+		$options = $this->requestOptions($url, null, $this->config['tautulliDisableCertCheck'], $this->config['tautulliUseCustomCertificate']);
+		$response = Requests::get($url, [], $options);
 		try {
 			$response = json_decode($response->body, true);
 			foreach ($response['response']['data'] as $user) {
@@ -845,7 +636,7 @@ trait PlexHomepageItem
 				}
 			}
 		} catch (Exception $e) {
-			$this->setAPIResponse('failure', null, 422, [$e->getMessage()]);
+			$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
 		}
 		$this->setAPIResponse('success', null, 200, $names);
 		return $names;

+ 39 - 138
api/homepage/qbittorrent.php

@@ -14,140 +14,41 @@ trait QBitTorrentHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageqBittorrentEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageqBittorrentEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageqBittorrentAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageqBittorrentAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'qBittorrentURL',
-						'label' => 'URL',
-						'value' => $this->config['qBittorrentURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'qBittorrentDisableCertCheck',
-						'label' => 'Disable Certificate Check',
-						'value' => $this->config['qBittorrentDisableCertCheck']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'qBittorrentApiVersion',
-						'label' => 'API Version',
-						'value' => $this->config['qBittorrentApiVersion'],
-						'options' => $this->qBittorrentApiOptions()
-					),
-					array(
-						'type' => 'input',
-						'name' => 'qBittorrentUsername',
-						'label' => 'Username',
-						'value' => $this->config['qBittorrentUsername']
-					),
-					array(
-						'type' => 'password',
-						'name' => 'qBittorrentPassword',
-						'label' => 'Password',
-						'value' => $this->config['qBittorrentPassword']
-					)
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('qbittorrent') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'qBittorrentSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['qBittorrentSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'qBittorrentSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['qBittorrentSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'qBittorrentHideSeeding',
-						'label' => 'Hide Seeding',
-						'value' => $this->config['qBittorrentHideSeeding']
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'qBittorrentHideCompleted',
-						'label' => 'Hide Completed',
-						'value' => $this->config['qBittorrentHideCompleted']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'qBittorrentSortOrder',
-						'label' => 'Order',
-						'value' => $this->config['qBittorrentSortOrder'],
-						'options' => $this->qBittorrentSortOptions()
-					), array(
-						'type' => 'switch',
-						'name' => 'qBittorrentReverseSorting',
-						'label' => 'Reverse Sorting',
-						'value' => $this->config['qBittorrentReverseSorting']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'qBittorrentRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['qBittorrentRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'qBittorrentCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['qBittorrentCombine']
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'qbittorrent\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageqBittorrentEnabled'),
+					$this->settingsOption('auth', 'homepageqBittorrentAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'qBittorrentURL'),
+					$this->settingsOption('select', 'qBittorrentApiVersion', ['label' => 'API Version', 'options' => $this->qBittorrentApiOptions()]),
+					$this->settingsOption('username', 'qBittorrentUsername'),
+					$this->settingsOption('password', 'qBittorrentPassword'),
+					$this->settingsOption('disable-cert-check', 'qBittorrentDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'qBittorrentUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'qbittorrent'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'qBittorrentSocksEnabled'),
+					$this->settingsOption('auth', 'qBittorrentSocksAuth'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('hide-seeding', 'qBittorrentHideSeeding'),
+					$this->settingsOption('hide-completed', 'qBittorrentHideCompleted'),
+					$this->settingsOption('select', 'qBittorrentSortOrder', ['label' => 'Order', 'options' => $this->qBittorrentSortOptions()]),
+					$this->settingsOption('switch', 'qBittorrentReverseSorting', ['label' => 'Reverse Sorting']),
+					$this->settingsOption('refresh', 'qBittorrentRefresh'),
+					$this->settingsOption('combine', 'qBittorrentCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'qbittorrent'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -163,8 +64,8 @@ trait QBitTorrentHomepageItem
 		$apiVersionQuery = ($this->config['qBittorrentApiVersion'] == '1') ? '/query/torrents?sort=' : '/api/v2/torrents/info?sort=';
 		$url = $digest['scheme'] . '://' . $digest['host'] . $digest['port'] . $digest['path'] . $apiVersionLogin;
 		try {
-			$options = $this->requestOptions($this->config['qBittorrentURL'], $this->config['qBittorrentDisableCertCheck'], $this->config['qBittorrentRefresh']);
-			$response = Requests::post($url, array(), $data, $options);
+			$options = $this->requestOptions($this->config['qBittorrentURL'], null, $this->config['qBittorrentDisableCertCheck'], $this->config['qBittorrentUseCustomCertificate']);
+			$response = Requests::post($url, [], $data, $options);
 			$reflection = new ReflectionClass($response->cookies);
 			$cookie = $reflection->getProperty("cookies");
 			$cookie->setAccessible(true);
@@ -255,8 +156,8 @@ trait QBitTorrentHomepageItem
 		$apiVersionQuery = ($this->config['qBittorrentApiVersion'] == '1') ? '/query/torrents?sort=' : '/api/v2/torrents/info?sort=';
 		$url = $digest['scheme'] . '://' . $digest['host'] . $digest['port'] . $digest['path'] . $apiVersionLogin;
 		try {
-			$options = $this->requestOptions($this->config['qBittorrentURL'], $this->config['qBittorrentDisableCertCheck'], $this->config['qBittorrentRefresh']);
-			$response = Requests::post($url, array(), $data, $options);
+			$options = $this->requestOptions($this->config['qBittorrentURL'], $this->config['qBittorrentRefresh'], $this->config['qBittorrentDisableCertCheck'], $this->config['qBittorrentUseCustomCertificate']);
+			$response = Requests::post($url, [], $data, $options);
 			$reflection = new ReflectionClass($response->cookies);
 			$cookie = $reflection->getProperty("cookies");
 			$cookie->setAccessible(true);
@@ -289,7 +190,7 @@ trait QBitTorrentHomepageItem
 					}
 					$api['content']['queueItems'] = $torrents;
 					$api['content']['historyItems'] = false;
-					$api['content'] = isset($api['content']) ? $api['content'] : false;
+					$api['content'] = $api['content'] ?? false;
 					$this->setAPIResponse('success', null, 200, $api);
 					return $api;
 				}

+ 50 - 188
api/homepage/radarr.php

@@ -14,192 +14,51 @@ trait RadarrHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageRadarrEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageRadarrEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageRadarrAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageRadarrAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'radarrURL',
-						'label' => 'URL',
-						'value' => $this->config['radarrURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'radarrToken',
-						'label' => 'Token',
-						'value' => $this->config['radarrToken']
-					)
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('radarr') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'radarrSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['radarrSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'radarrSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['radarrSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Queue' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageRadarrQueueEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageRadarrQueueEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageRadarrQueueAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageRadarrQueueAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageRadarrQueueCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['homepageRadarrQueueCombine']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageRadarrQueueRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageRadarrQueueRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Calendar' => array(
-					array(
-						'type' => 'number',
-						'name' => 'calendarStart',
-						'label' => '# of Days Before',
-						'value' => $this->config['calendarStart'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'number',
-						'name' => 'calendarEnd',
-						'label' => '# of Days After',
-						'value' => $this->config['calendarEnd'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'radarrUnmonitored',
-						'label' => 'Show Unmonitored',
-						'value' => $this->config['radarrUnmonitored']
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'radarrPhysicalRelease',
-						'label' => 'Show Physical Release',
-						'value' => $this->config['radarrPhysicalRelease']
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'radarrDigitalRelease',
-						'label' => 'Show Digital Release',
-						'value' => $this->config['radarrDigitalRelease']
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'radarrCinemaRelease',
-						'label' => 'Show Cinema Releases',
-						'value' => $this->config['radarrCinemaRelease']
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'radarr\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageRadarrEnabled'),
+					$this->settingsOption('auth', 'homepageRadarrEnabled'),
+				],
+				'Connection' => [
+					$this->settingsOption('multiple-url', 'radarrURL'),
+					$this->settingsOption('multiple-token', 'radarrToken'),
+					$this->settingsOption('disable-cert-check', 'radarrDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'radarrUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'radarr'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'radarrSocksEnabled'),
+					$this->settingsOption('auth', 'radarrSocksAuth'),
+				],
+				'Queue' => [
+					$this->settingsOption('enable', 'homepageRadarrQueueEnabled'),
+					$this->settingsOption('auth', 'homepageRadarrQueueAuth'),
+					$this->settingsOption('combine', 'homepageRadarrQueueCombine'),
+					$this->settingsOption('refresh', 'homepageRadarrQueueRefresh'),
+				],
+				'Calendar' => [
+					$this->settingsOption('calendar-start', 'calendarStart'),
+					$this->settingsOption('calendar-end', 'calendarEnd'),
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+					$this->settingsOption('switch', 'radarrUnmonitored', ['label' => 'Show Unmonitored']),
+					$this->settingsOption('switch', 'radarrPhysicalRelease', ['label' => 'Show Physical Releases']),
+					$this->settingsOption('switch', 'radarrDigitalRelease', ['label' => 'Show Digital Releases']),
+					$this->settingsOption('switch', 'radarrCinemaRelease', ['label' => 'Show Cinema Releases']),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'radarr'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -218,7 +77,8 @@ trait RadarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['radarrURL'], $this->config['radarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'radarr');
+				$options = $this->requestOptions($value['url'], null, $this->config['radarrDisableCertCheck'], $this->config['radarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'radarr', null, null, $options);
 				$results = $downloader->getRootFolder();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -317,7 +177,8 @@ trait RadarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['radarrURL'], $this->config['radarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'radarr');
+				$options = $this->requestOptions($value['url'], $this->config['homepageRadarrQueueRefresh'], $this->config['radarrDisableCertCheck'], $this->config['radarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'radarr', null, null, $options);
 				$results = $downloader->getQueue();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -350,7 +211,8 @@ trait RadarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['radarrURL'], $this->config['radarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'radarr');
+				$options = $this->requestOptions($value['url'], $this->config['homepageRadarrQueueRefresh'], $this->config['radarrDisableCertCheck'], $this->config['radarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'radarr', null, null, $options);
 				$results = $downloader->getCalendar($startDate, $endDate, $this->config['radarrUnmonitored']);
 				$result = json_decode($results, true);
 				if (is_array($result) || is_object($result)) {

+ 63 - 146
api/homepage/rtorrent.php

@@ -16,148 +16,65 @@ trait RTorrentHomepageItem
 			return $homepageInformation;
 		}
 		$xmlStatus = (extension_loaded('xmlrpc')) ? 'Installed' : 'Not Installed';
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'FYI' => array(
-					array(
-						'type' => 'html',
-						'label' => '',
-						'override' => 12,
+			'settings' => [
+				'FYI' => [
+					$this->settingsOption('html', null, ['label' => '', 'override' => 12,
 						'html' => '
 						<div class="row">
-						    <div class="col-lg-12">
-						        <div class="panel panel-info">
-						            <div class="panel-heading">
-						                <span lang="en">ATTENTION</span>
-						            </div>
-						            <div class="panel-wrapper collapse in" aria-expanded="true">
-						                <div class="panel-body">
-						                	<h4 lang="en">This module requires XMLRPC</h4>
-						                    <span lang="en">Status: [ <b>' . $xmlStatus . '</b> ]</span>
-						                    <br/></br>
-						                    <span lang="en">
-						                    	<h4><b>Note about API URL</b></h4>
-						                    	Organizr appends the url with <code>/RPC2</code> unless the URL ends in <code>.php</code><br/>
-						                    	<h5>Possible URLs:</h5>
-						                    	<li>http://localhost:8080</li>
-						                    	<li>https://domain.site/xmlrpc.php</li>
-						                    	<li>https://seedbox.site/rutorrent/plugins/httprpc/action.php</li>
-						                    </span>
-						                </div>
-						            </div>
-						        </div>
-						    </div>
+							<div class="col-lg-12">
+								<div class="panel panel-info">
+									<div class="panel-heading">
+										<span lang="en">ATTENTION</span>
+									</div>
+									<div class="panel-wrapper collapse in" aria-expanded="true">
+										<div class="panel-body">
+											<h4 lang="en">This module requires XMLRPC</h4>
+											<span lang="en">Status: [ <b>' . $xmlStatus . '</b> ]</span>
+											<br/></br>
+											<span lang="en">
+												<h4><b>Note about API URL</b></h4>
+												Organizr appends the url with <code>/RPC2</code> unless the URL ends in <code>.php</code><br/>
+												<h5>Possible URLs:</h5>
+												<li>http://localhost:8080</li>
+												<li>https://domain.site/xmlrpc.php</li>
+												<li>https://seedbox.site/rutorrent/plugins/httprpc/action.php</li>
+											</span>
+										</div>
+									</div>
+								</div>
+							</div>
 						</div>
 						'
-					)
-				),
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepagerTorrentEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepagerTorrentEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepagerTorrentAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepagerTorrentAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'rTorrentURL',
-						'label' => 'URL',
-						'value' => $this->config['rTorrentURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'rTorrentURLOverride',
-						'label' => 'rTorrent API URL Override',
-						'value' => $this->config['rTorrentURLOverride'],
-						'help' => 'Only use if you cannot connect.  Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port/xmlrpc'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'rTorrentUsername',
-						'label' => 'Username',
-						'value' => $this->config['rTorrentUsername']
-					),
-					array(
-						'type' => 'password',
-						'name' => 'rTorrentPassword',
-						'label' => 'Password',
-						'value' => $this->config['rTorrentPassword']
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'rTorrentDisableCertCheck',
-						'label' => 'Disable Certificate Check',
-						'value' => $this->config['rTorrentDisableCertCheck']
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'rTorrentHideSeeding',
-						'label' => 'Hide Seeding',
-						'value' => $this->config['rTorrentHideSeeding']
-					), array(
-						'type' => 'switch',
-						'name' => 'rTorrentHideCompleted',
-						'label' => 'Hide Completed',
-						'value' => $this->config['rTorrentHideCompleted']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'rTorrentSortOrder',
-						'label' => 'Order',
-						'value' => $this->config['rTorrentSortOrder'],
-						'options' => $this->rTorrentSortOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'rTorrentRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['rTorrentRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'number',
-						'name' => 'rTorrentLimit',
-						'label' => 'Item Limit',
-						'value' => $this->config['rTorrentLimit'],
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'rTorrentCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['rTorrentCombine']
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'rtorrent\')"'
-					),
-				)
-			)
-		);
+					]),
+				],
+				'Enable' => [
+					$this->settingsOption('enable', 'homepagerTorrentEnabled'),
+					$this->settingsOption('auth', 'homepagerTorrentAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'rTorrentURL'),
+					$this->settingsOption('input', 'rTorrentURLOverride', ['label' => 'rTorrent API URL Override', 'help' => 'Only use if you cannot connect.  Please make sure to use local IP address and port - You also may use local dns name too.', 'placeholder' => 'http(s)://hostname:port/xmlrpc']),
+					$this->settingsOption('username', 'rTorrentUsername'),
+					$this->settingsOption('password', 'rTorrentPassword'),
+					$this->settingsOption('disable-cert-check', 'rTorrentDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'rTorrentUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('hide-seeding', 'rTorrentHideSeeding'),
+					$this->settingsOption('hide-completed', 'rTorrentHideCompleted'),
+					$this->settingsOption('select', 'rTorrentSortOrder', ['label' => 'Order', 'options' => $this->rTorrentSortOptions()]),
+					$this->settingsOption('limit', 'rTorrentLimit'),
+					$this->settingsOption('refresh', 'rTorrentRefresh'),
+					$this->settingsOption('combine', 'rTorrentCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'rtorrent'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -172,13 +89,13 @@ trait RTorrentHomepageItem
 			$extraPath = (strpos($this->config['rTorrentURL'], '.php') !== false) ? '' : '/RPC2';
 			$extraPath = (empty($this->config['rTorrentURLOverride'])) ? $extraPath : '';
 			$url = $digest['scheme'] . '://' . $digest['host'] . $digest['port'] . $digest['path'] . $extraPath;
-			$options = ($this->localURL($url, $this->config['rTorrentDisableCertCheck'])) ? array('verify' => false) : array();
+			$options = $this->requestOptions($url, null, $this->config['rTorrentDisableCertCheck'], $this->config['rtorrentUseCustomCertificate']);
 			if ($this->config['rTorrentUsername'] !== '' && $this->decrypt($this->config['rTorrentPassword']) !== '') {
 				$credentials = array('auth' => new Requests_Auth_Digest(array($this->config['rTorrentUsername'], $this->decrypt($this->config['rTorrentPassword']))));
 				$options = array_merge($options, $credentials);
 			}
 			$data = xmlrpc_encode_request("system.listMethods", null);
-			$response = Requests::post($url, array(), $data, $options);
+			$response = Requests::post($url, [], $data, $options);
 			if ($response->success) {
 				$methods = xmlrpc_decode(str_replace('i8>', 'i4>', $response->body));
 				if (count($methods) !== 0) {
@@ -227,11 +144,11 @@ trait RTorrentHomepageItem
 				<div id="' . __FUNCTION__ . '">
 					' . $loadingBox . '
 					<script>
-		                // homepageOrderrTorrent
-		                ' . $builder . '
-		                homepageDownloader("rTorrent", "' . $this->config['rTorrentRefresh'] . '");
-		                // End homepageOrderrTorrent
-	                </script>
+						// homepageOrderrTorrent
+						' . $builder . '
+						homepageDownloader("rTorrent", "' . $this->config['rTorrentRefresh'] . '");
+						// End homepageOrderrTorrent
+					</script>
 				</div>
 				';
 		}
@@ -278,7 +195,7 @@ trait RTorrentHomepageItem
 			$extraPath = (strpos($this->config['rTorrentURL'], '.php') !== false) ? '' : '/RPC2';
 			$extraPath = (empty($this->config['rTorrentURLOverride'])) ? $extraPath : '';
 			$url = $digest['scheme'] . '://' . $digest['host'] . $digest['port'] . $digest['path'] . $extraPath;
-			$options = ($this->localURL($url, $this->config['rTorrentDisableCertCheck'])) ? array('verify' => false) : array();
+			$options = $this->requestOptions($url, $this->config['rTorrentRefresh'], $this->config['rTorrentDisableCertCheck'], $this->config['rtorrentUseCustomCertificate']);
 			if ($this->config['rTorrentUsername'] !== '' && $this->decrypt($this->config['rTorrentPassword']) !== '') {
 				$credentials = array('auth' => new Requests_Auth_Digest(array($this->config['rTorrentUsername'], $this->decrypt($this->config['rTorrentPassword']))));
 				$options = array_merge($options, $credentials);
@@ -312,7 +229,7 @@ trait RTorrentHomepageItem
 				"d.custom4=",
 				"d.custom5=",
 			), array());
-			$response = Requests::post($url, array(), $data, $options);
+			$response = Requests::post($url, [], $data, $options);
 			if ($response->success) {
 				$torrentList = xmlrpc_decode(str_replace('i8>', 'string>', $response->body));
 				if (is_array($torrentList)) {

+ 36 - 98
api/homepage/sabnzbd.php

@@ -15,97 +15,35 @@ trait SabNZBdHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageSabnzbdEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageSabnzbdEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageSabnzbdAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageSabnzbdAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'sabnzbdURL',
-						'label' => 'URL',
-						'value' => $this->config['sabnzbdURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'sabnzbdToken',
-						'label' => 'Token',
-						'value' => $this->config['sabnzbdToken']
-					)
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('sabnzbd') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'sabnzbdSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['sabnzbdSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'sabnzbdSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['sabnzbdSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'sabnzbdRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['sabnzbdRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'sabnzbdCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['sabnzbdCombine']
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'sabnzbd\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageSabnzbdEnabled'),
+					$this->settingsOption('auth', 'homepageSabnzbdAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'sabnzbdURL'),
+					$this->settingsOption('token', 'sabnzbdToken'),
+					$this->settingsOption('disable-cert-check', 'sabnzbdDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'sabnzbdUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'sabnzbd'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'sabnzbdSocksEnabled'),
+					$this->settingsOption('auth', 'sabnzbdSocksAuth'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('refresh', 'sabnzbdRefresh'),
+					$this->settingsOption('combine', 'sabnzbdCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'sabnzbd'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -115,8 +53,8 @@ trait SabNZBdHomepageItem
 			$url = $this->qualifyURL($this->config['sabnzbdURL']);
 			$url = $url . '/api?mode=queue&output=json&apikey=' . $this->config['sabnzbdToken'];
 			try {
-				$options = ($this->localURL($url)) ? array('verify' => false) : array();
-				$response = Requests::get($url, array(), $options);
+				$options = $this->requestOptions($url, null, $this->config['sabnzbdDisableCertCheck'], $this->config['sabnzbdUseCustomCertificate']);
+				$response = Requests::get($url, [], $options);
 				if ($response->success) {
 					$data = json_decode($response->body, true);
 					$status = 'success';
@@ -195,8 +133,8 @@ trait SabNZBdHomepageItem
 		$url = $this->qualifyURL($this->config['sabnzbdURL']);
 		$url = $url . '/api?mode=queue&output=json&apikey=' . $this->config['sabnzbdToken'];
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
-			$response = Requests::get($url, array(), $options);
+			$options = $this->requestOptions($url, $this->config['sabnzbdRefresh'], $this->config['sabnzbdDisableCertCheck'], $this->config['sabnzbdUseCustomCertificate']);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$api['content']['queueItems'] = json_decode($response->body, true);
 			}
@@ -232,8 +170,8 @@ trait SabNZBdHomepageItem
 		$id = ($target !== '' && $target !== 'main' && isset($target)) ? 'mode=queue&name=pause&value=' . $target . '&' : 'mode=pause';
 		$url = $url . '/api?' . $id . '&output=json&apikey=' . $this->config['sabnzbdToken'];
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
-			$response = Requests::get($url, array(), $options);
+			$options = $this->requestOptions($url, $this->config['sabnzbdRefresh'], $this->config['sabnzbdDisableCertCheck'], $this->config['sabnzbdUseCustomCertificate']);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$api['content'] = json_decode($response->body, true);
 			}
@@ -256,8 +194,8 @@ trait SabNZBdHomepageItem
 		$id = ($target !== '' && $target !== 'main' && isset($target)) ? 'mode=queue&name=resume&value=' . $target . '&' : 'mode=resume';
 		$url = $url . '/api?' . $id . '&output=json&apikey=' . $this->config['sabnzbdToken'];
 		try {
-			$options = ($this->localURL($url)) ? array('verify' => false) : array();
-			$response = Requests::get($url, array(), $options);
+			$options = $this->requestOptions($url, $this->config['sabnzbdRefresh'], $this->config['sabnzbdDisableCertCheck'], $this->config['sabnzbdUseCustomCertificate']);
+			$response = Requests::get($url, [], $options);
 			if ($response->success) {
 				$api['content'] = json_decode($response->body, true);
 			}

+ 30 - 95
api/homepage/sickrage.php

@@ -14,100 +14,33 @@ trait SickRageHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageSickrageEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageSickrageEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageSickrageAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageSickrageAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'sickrageURL',
-						'label' => 'URL',
-						'value' => $this->config['sickrageURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'sickrageToken',
-						'label' => 'Token',
-						'value' => $this->config['sickrageToken']
-					)
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'sickrage\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageSickrageEnabled'),
+					$this->settingsOption('auth', 'homepageSickrageAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'sickrageURL'),
+					$this->settingsOption('token', 'sickrageToken'),
+					$this->settingsOption('disable-cert-check', 'sickrageDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'sickrageUseCustomCertificate'),
+				],
+				'Calendar' => [
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'sickrage'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -126,7 +59,8 @@ trait SickRageHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['sickrageURL'], $this->config['sickrageToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\SickRage\SickRage($value['url'], $value['token']);
+				$options = $this->requestOptions($value['url'], null, $this->config['sickrageDisableCertCheck'], $this->config['sickrageUseCustomCertificate']);
+				$downloader = new Kryptonit3\SickRage\SickRage($value['url'], $value['token'], null, null, $options);
 				$results = $downloader->sb();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -192,7 +126,8 @@ trait SickRageHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['sickrageURL'], $this->config['sickrageToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\SickRage\SickRage($value['url'], $value['token']);
+				$options = $this->requestOptions($value['url'], null, $this->config['sickrageDisableCertCheck'], $this->config['sickrageUseCustomCertificate']);
+				$downloader = new Kryptonit3\SickRage\SickRage($value['url'], $value['token'], null, null, $options);
 				$sickrageFuture = $this->formatSickrageCalendarWanted($downloader->future(), $key);
 				$sickrageHistory = $this->formatSickrageCalendarHistory($downloader->history("100", "downloaded"), $key);
 				if (!empty($sickrageFuture)) {

+ 50 - 194
api/homepage/sonarr.php

@@ -14,199 +14,52 @@ trait SonarrHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'docs' => 'https://docs.organizr.app/books/setup-features/page/sonarr',
 			'debug' => true,
-			'settings' => array(
-				'About' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">
-										<h3 lang="en">Sonarr Homepage Item</h3>
-										<p lang="en">This item allows access to Sonarr\'s calendar data and aggregates it to Organizr\'s calendar.  Along with that you also have the Downloader function that allow access to Sonarr\'s queue.  The last item that is included is the API SOCKS function which acts as a middleman between API\'s which is useful if you are not port forwarding or reverse proxying Sonarr.</p>
-									</div>
-								</div>
-							</div>'
-					),
-				),
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageSonarrEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageSonarrEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageSonarrAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageSonarrAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'select2',
-						'class' => 'select2-multiple',
-						'id' => 'sonarrURL-select',
-						'name' => 'sonarrURL',
-						'label' => 'Sonarr URL',
-						'value' => $this->config['sonarrURL'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port',
-						'options' => $this->makeOptionsFromValues($this->config['sonarrURL']),
-						'settings' => '{tags: true, selectOnClose: true, closeOnSelect: true}',
-					),
-					array(
-						'type' => 'select2',
-						'class' => 'select2-multiple',
-						'id' => 'sonarrToken-select',
-						'name' => 'sonarrToken',
-						'label' => 'Sonarr Token',
-						'value' => $this->config['sonarrToken'],
-						'options' => $this->makeOptionsFromValues($this->config['sonarrToken']),
-						'settings' => '{tags: true, theme: "default password-alt, selectOnClose: true, closeOnSelect: true"}',
-					)
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('sonarr') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'sonarrSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['sonarrSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'sonarrSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['sonarrSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Queue' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageSonarrQueueEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageSonarrQueueEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageSonarrQueueAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageSonarrQueueAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageSonarrQueueCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['homepageSonarrQueueCombine']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageSonarrQueueRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageSonarrQueueRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Calendar' => array(
-					array(
-						'type' => 'number',
-						'name' => 'calendarStart',
-						'label' => '# of Days Before',
-						'value' => $this->config['calendarStart'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'number',
-						'name' => 'calendarEnd',
-						'label' => '# of Days After',
-						'value' => $this->config['calendarEnd'],
-						'placeholder' => ''
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'sonarrUnmonitored',
-						'label' => 'Show Unmonitored',
-						'value' => $this->config['sonarrUnmonitored']
-					)
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'sonarr\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'About' => [
+					$this->settingsOption('about', 'Sonarr', ['about' => 'This item allows access to Sonarr\'s calendar data and aggregates it to Organizr\'s calendar.  Along with that you also have the Downloader function that allow access to Sonarr\'s queue.  The last item that is included is the API SOCKS function which acts as a middleman between API\'s which is useful if you are not port forwarding or reverse proxying Sonarr.']),
+				],
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageSonarrEnabled'),
+					$this->settingsOption('auth', 'homepageSonarrAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('multiple-url', 'sonarrURL'),
+					$this->settingsOption('multiple-token', 'sonarrToken'),
+					$this->settingsOption('disable-cert-check', 'sonarrDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'sonarrUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'sonarr'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'sonarrSocksEnabled'),
+					$this->settingsOption('auth', 'sonarrSocksAuth'),
+				],
+				'Queue' => [
+					$this->settingsOption('enable', 'homepageSonarrQueueEnabled'),
+					$this->settingsOption('auth', 'homepageSonarrQueueAuth'),
+					$this->settingsOption('combine', 'homepageSonarrQueueCombine'),
+					$this->settingsOption('refresh', 'homepageSonarrQueueRefresh'),
+				],
+				'Calendar' => [
+					$this->settingsOption('calendar-start', 'calendarStart'),
+					$this->settingsOption('calendar-end', 'calendarEnd'),
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+					$this->settingsOption('switch', 'sonarrUnmonitored', ['label' => 'Show Unmonitored']),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'sonarr'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -225,7 +78,8 @@ trait SonarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['sonarrURL'], $this->config['sonarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'sonarr');
+				$options = $this->requestOptions($value['url'], null, $this->config['sonarrDisableCertCheck'], $this->config['sonarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'sonarr', null, null, $options);
 				$results = $downloader->getRootFolder();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -324,7 +178,8 @@ trait SonarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['sonarrURL'], $this->config['sonarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'sonarr');
+				$options = $this->requestOptions($value['url'], $this->config['homepageSonarrQueueRefresh'], $this->config['sonarrDisableCertCheck'], $this->config['sonarrUseCustomCertificate']);
+				$downloader = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'sonarr', null, null, $options);
 				$results = $downloader->getQueue();
 				$downloadList = json_decode($results, true);
 				if (is_array($downloadList) || is_object($downloadList)) {
@@ -357,7 +212,8 @@ trait SonarrHomepageItem
 		$list = $this->csvHomepageUrlToken($this->config['sonarrURL'], $this->config['sonarrToken']);
 		foreach ($list as $key => $value) {
 			try {
-				$sonarr = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'sonarr');
+				$options = $this->requestOptions($value['url'], null, $this->config['sonarrDisableCertCheck'], $this->config['sonarrUseCustomCertificate']);
+				$sonarr = new Kryptonit3\Sonarr\Sonarr($value['url'], $value['token'], 'sonarr', null, null, $options);
 				$sonarr = $sonarr->getCalendar($startDate, $endDate, $this->config['sonarrUnmonitored']);
 				$result = json_decode($sonarr, true);
 				if (is_array($result) || is_object($result)) {

+ 20 - 51
api/homepage/speedtest.php

@@ -14,57 +14,25 @@ trait SpeedTestHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'html',
-						'override' => 6,
-						'label' => 'Info',
-						'html' => '<p>This homepage item requires <a href="https://github.com/henrywhitaker3/Speedtest-Tracker" target="_blank" rel="noreferrer noopener">Speedtest-Tracker <i class="fa fa-external-link" aria-hidden="true"></i></a> to be running on your network.</p>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageSpeedtestEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageSpeedtestEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageSpeedtestAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageSpeedtestAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'speedtestURL',
-						'label' => 'URL',
-						'value' => $this->config['speedtestURL'],
-						'help' => 'Enter the IP:PORT of your speedtest instance e.g. http(s)://<ip>:<port>'
-					),
-				),
-				'Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'speedtestHeader',
-						'label' => 'Title',
-						'value' => $this->config['speedtestHeader'],
-						'help' => 'Sets the title of this homepage module',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'speedtestHeaderToggle',
-						'label' => 'Toggle Title',
-						'value' => $this->config['speedtestHeaderToggle'],
-						'help' => 'Shows/hides the title of this homepage module'
-					),
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('html', null, ['override' => 6, 'label' => 'Info', 'html' => '<p>This homepage item requires <a href="https://github.com/henrywhitaker3/Speedtest-Tracker" target="_blank" rel="noreferrer noopener">Speedtest-Tracker <i class="fa fa-external-link" aria-hidden="true"></i></a> to be running on your network.</p>']),
+					$this->settingsOption('enable', 'homepageSpeedtestEnabled'),
+					$this->settingsOption('auth', 'homepageSpeedtestAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'speedtestURL'),
+					$this->settingsOption('disable-cert-check', 'speedtestDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'speedtestUseCustomCertificate'),
+				],
+				'Options' => [
+					$this->settingsOption('title', 'speedtestHeader'),
+					$this->settingsOption('toggle-title', 'speedtestHeaderToggle'),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -115,9 +83,10 @@ trait SpeedTestHomepageItem
 		}
 		$api = [];
 		$url = $this->qualifyURL($this->config['speedtestURL']);
+		$options = $this->requestOptions($url, null, $this->config['speedtestDisableCertCheck'], $this->config['speedtestUseCustomCertificate']);
 		$dataUrl = $url . '/api/speedtest/latest';
 		try {
-			$response = Requests::get($dataUrl);
+			$response = Requests::get($dataUrl, [], $options);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
 				$api['data'] = [

+ 49 - 184
api/homepage/tautulli.php

@@ -14,188 +14,53 @@ trait TautulliHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageTautulliEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageTautulliEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTautulliAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageTautulliAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'tautulliHeader',
-						'label' => 'Title',
-						'value' => $this->config['tautulliHeader'],
-						'help' => 'Sets the title of this homepage module'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliHeaderToggle',
-						'label' => 'Toggle Title',
-						'value' => $this->config['tautulliHeaderToggle'],
-						'help' => 'Shows/hides the title of this homepage module'
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'tautulliURL',
-						'label' => 'URL',
-						'value' => $this->config['tautulliURL'],
-						'help' => 'URL for Tautulli API, include the IP, the port and the base URL (e.g. /tautulli/) in the URL',
-						'placeholder' => 'http://<ip>:<port>'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'tautulliApikey',
-						'label' => 'API Key',
-						'value' => $this->config['tautulliApikey']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTautulliRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageTautulliRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'API SOCKS' => array(
-					array(
-						'type' => 'html',
-						'override' => 12,
-						'label' => '',
-						'html' => '
-							<div class="panel panel-default">
-								<div class="panel-wrapper collapse in">
-									<div class="panel-body">' . $this->socksHeadingHTML('tautulli') . '</div>
-								</div>
-							</div>'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliSocksEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['tautulliSocksEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'tautulliSocksAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['tautulliSocksAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Library Stats' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliLibraries',
-						'label' => 'Libraries',
-						'value' => $this->config['tautulliLibraries'],
-						'help' => 'Shows/hides the card with library information.',
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTautulliLibraryAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageTautulliLibraryAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Viewing Stats' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliPopularMovies',
-						'label' => 'Popular Movies',
-						'value' => $this->config['tautulliPopularMovies'],
-						'help' => 'Shows/hides the card with Popular Movies information.',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliPopularTV',
-						'label' => 'Popular TV',
-						'value' => $this->config['tautulliPopularTV'],
-						'help' => 'Shows/hides the card with Popular TV information.',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliTopMovies',
-						'label' => 'Top Movies',
-						'value' => $this->config['tautulliTopMovies'],
-						'help' => 'Shows/hides the card with Top Movies information.',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliTopTV',
-						'label' => 'Top TV',
-						'value' => $this->config['tautulliTopTV'],
-						'help' => 'Shows/hides the card with Top TV information.',
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTautulliViewsAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageTautulliViewsAuth'],
-						'options' => $this->groupOptions
-					),
-				),
-				'Misc Stats' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliTopUsers',
-						'label' => 'Top Users',
-						'value' => $this->config['tautulliTopUsers'],
-						'help' => 'Shows/hides the card with Top Users information.',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliTopPlatforms',
-						'label' => 'Top Platforms',
-						'value' => $this->config['tautulliTopPlatforms'],
-						'help' => 'Shows/hides the card with Top Platforms information.',
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTautulliMiscAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageTautulliMiscAuth'],
-						'options' => $this->groupOptions
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'tautulliFriendlyName',
-						'label' => 'Use Friendly Name',
-						'value' => $this->config['tautulliFriendlyName'],
-						'help' => 'Use the friendly name set in tautulli for users.',
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'tautulli\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageTautulliEnabled'),
+					$this->settingsOption('auth', 'homepageTautulliAuth'),
+				],
+				'Options' => [
+					$this->settingsOption('title', 'tautulliHeader'),
+					$this->settingsOption('toggle-title', 'tautulliHeaderToggle'),
+					$this->settingsOption('refresh', 'homepageTautulliRefresh'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'tautulliURL'),
+					$this->settingsOption('api-key', 'tautulliApikey'),
+					$this->settingsOption('disable-cert-check', 'tautulliDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'tautulliUseCustomCertificate'),
+				],
+				'API SOCKS' => [
+					$this->settingsOption('socks', 'tautulli'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('enable', 'tautulliSocksEnabled'),
+					$this->settingsOption('auth', 'tautulliSocksAuth'),
+				],
+				'Library Stats' => [
+					$this->settingsOption('switch', 'tautulliLibraries', ['label' => 'Libraries', 'help' => 'Shows/hides the card with library information.']),
+					$this->settingsOption('auth', 'homepageTautulliLibraryAuth'),
+				],
+				'Viewing Stats' => [
+					$this->settingsOption('switch', 'tautulliPopularMovies', ['label' => 'Popular Movies', 'help' => 'Shows/hides the card with Popular Movie information.']),
+					$this->settingsOption('switch', 'tautulliPopularTV', ['label' => 'Popular TV', 'help' => 'Shows/hides the card with Popular TV information.']),
+					$this->settingsOption('switch', 'tautulliTopMovies', ['label' => 'Top Movies', 'help' => 'Shows/hides the card with Top Movies information.']),
+					$this->settingsOption('switch', 'tautulliTopTV', ['label' => 'Top TV', 'help' => 'Shows/hides the card with Top TV information.']),
+					$this->settingsOption('auth', 'homepageTautulliViewsAuth'),
+				],
+				'Misc Stats' => [
+					$this->settingsOption('switch', 'tautulliTopUsers', ['label' => 'Top Users', 'help' => 'Shows/hides the card with Top Users information.']),
+					$this->settingsOption('switch', 'tautulliTopPlatforms', ['label' => 'Top Platforms', 'help' => 'Shows/hides the card with Top Platforms information.']),
+					$this->settingsOption('auth', 'homepageTautulliMiscAuth'),
+					$this->settingsOption('switch', 'tautulliFriendlyName', ['label' => 'Use Friendly Name', 'help' => 'Use the friendly name set in tautulli for users.']),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'tautulli'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -213,7 +78,7 @@ trait TautulliHomepageItem
 		$apiURL = $url . '/api/v2?apikey=' . $this->config['tautulliApikey'];
 		try {
 			$homestatsUrl = $apiURL . '&cmd=get_home_stats&grouping=1';
-			$options = $this->requestOptions($this->config['tautulliURL'], false, $this->config['homepageTautulliRefresh']);
+			$options = $this->requestOptions($this->config['tautulliURL'], $this->config['homepageTautulliRefresh'], $this->config['tautulliDisableCertCheck'], $this->config['tautulliUseCustomCertificate']);
 			$homestats = Requests::get($homestatsUrl, [], $options);
 			if ($homestats->success) {
 				$this->setAPIResponse('success', 'API Connection succeeded', 200);
@@ -284,7 +149,7 @@ trait TautulliHomepageItem
 		$nowPlayingWidth = $this->getCacheImageSize('npw');
 		try {
 			$homestatsUrl = $apiURL . '&cmd=get_home_stats&grouping=1';
-			$options = $this->requestOptions($this->config['tautulliURL'], false, $this->config['homepageTautulliRefresh']);
+			$options = $this->requestOptions($this->config['tautulliURL'], $this->config['homepageTautulliRefresh'], $this->config['tautulliDisableCertCheck'], $this->config['tautulliUseCustomCertificate']);
 			$homestats = Requests::get($homestatsUrl, [], $options);
 			if ($homestats->success) {
 				$homestats = json_decode($homestats->body, true);
@@ -306,7 +171,7 @@ trait TautulliHomepageItem
 				$this->cacheImage($url . '/images/platforms/' . $platform . '.svg', 'tautulli-' . $platform, 'svg');
 			}
 			$libstatsUrl = $apiURL . '&cmd=get_libraries_table';
-			$options = $this->requestOptions($this->config['tautulliURL'], false, $this->config['homepageTautulliRefresh']);
+			$options = $this->requestOptions($this->config['tautulliURL'], $this->config['homepageTautulliRefresh'], $this->config['tautulliDisableCertCheck'], $this->config['tautulliUseCustomCertificate']);
 			$libstats = Requests::get($libstatsUrl, [], $options);
 			if ($libstats->success) {
 				$libstats = json_decode($libstats->body, true);

+ 29 - 113
api/homepage/trakt.php

@@ -14,15 +14,13 @@ trait TraktHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'docs' => 'https://docs.organizr.app/books/setup-features/page/trakt',
 			'debug' => true,
-			'settings' => array(
-				'About' => array(
-					array(
-						'type' => 'html',
+			'settings' => [
+				'About' => [
+					$this->settingsOption('html', null, [
 						'override' => 12,
-						'label' => '',
 						'html' => '
 							<div class="panel panel-default">
 								<div class="panel-wrapper collapse in">
@@ -36,112 +34,30 @@ trait TraktHomepageItem
 									</div>
 								</div>
 							</div>'
-					),
-				),
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageTraktEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageTraktEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTraktAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageTraktAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'traktClientId',
-						'label' => 'Client Id',
-						'value' => $this->config['traktClientId'],
-						'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.'
-					),
-					array(
-						'type' => 'password-alt',
-						'name' => 'traktClientSecret',
-						'label' => 'Client Secret',
-						'value' => $this->config['traktClientSecret']
-					),
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before clicking button'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-user',
-						'class' => 'pull-right',
-						'text' => 'Connect Account',
-						'attr' => 'onclick="openOAuth(\'trakt\')"'
-					),
-				),
-				'Calendar' => array(
-					array(
-						'type' => 'number',
-						'name' => 'calendarStartTrakt',
-						'label' => '# of Days Before',
-						'value' => $this->config['calendarStartTrakt'],
-						'placeholder' => '',
-						'help' => 'Total Days (Adding start and end days) has a maximum of 33 Days from Trakt API'
-					),
-					array(
-						'type' => 'number',
-						'name' => 'calendarEndTrakt',
-						'label' => '# of Days After',
-						'value' => $this->config['calendarEndTrakt'],
-						'placeholder' => '',
-						'help' => 'Total Days (Adding start and end days) has a maximum of 33 Days from Trakt API'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarFirstDay',
-						'label' => 'Start Day',
-						'value' => $this->config['calendarFirstDay'],
-						'options' => $this->daysOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarDefault',
-						'label' => 'Default View',
-						'value' => $this->config['calendarDefault'],
-						'options' => $this->calendarDefaultOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarTimeFormat',
-						'label' => 'Time Format',
-						'value' => $this->config['calendarTimeFormat'],
-						'options' => $this->timeFormatOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLocale',
-						'label' => 'Locale',
-						'value' => $this->config['calendarLocale'],
-						'options' => $this->calendarLocaleOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarLimit',
-						'label' => 'Items Per Day',
-						'value' => $this->config['calendarLimit'],
-						'options' => $this->limitOptions()
-					),
-					array(
-						'type' => 'select',
-						'name' => 'calendarRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['calendarRefresh'],
-						'options' => $this->timeOptions()
-					)
-				)
-			)
-		);
+					]),
+				],
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageTraktEnabled'),
+					$this->settingsOption('auth', 'homepageTraktAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('input', 'traktClientId', ['label' => 'Client Id']),
+					$this->settingsOption('password-alt', 'traktClientSecret', ['label' => 'Client Secret']),
+					$this->settingsOption('blank'),
+					$this->settingsOption('button', '', ['label' => 'Please Save before clicking button', 'icon' => 'fa fa-user', 'class' => 'pull-right', 'text' => 'Connect Account', 'attr' => 'onclick="openOAuth(\'trakt\')"']),
+				],
+				'Calendar' => [
+					$this->settingsOption('calendar-start', 'calendarStartTrakt', ['help' => 'Total Days (Adding start and end days) has a maximum of 33 Days from Trakt API']),
+					$this->settingsOption('calendar-end', 'calendarEndTrakt', ['help' => 'Total Days (Adding start and end days) has a maximum of 33 Days from Trakt API']),
+					$this->settingsOption('calendar-starting-day', 'calendarFirstDay'),
+					$this->settingsOption('calendar-default-view', 'calendarDefault'),
+					$this->settingsOption('calendar-time-format', 'calendarTimeFormat'),
+					$this->settingsOption('calendar-locale', 'calendarLocale'),
+					$this->settingsOption('calendar-limit', 'calendarLimit'),
+					$this->settingsOption('refresh', 'calendarRefresh'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -186,7 +102,7 @@ trait TraktHomepageItem
 			'trakt-api-key' => $this->config['traktClientId']
 		];
 		$url = $this->qualifyURL('https://api.trakt.tv/calendars/my/shows/' . $startDate . '/' . $totalDays . '?extended=full');
-		$options = $this->requestOptions($url, false, $this->config['calendarRefresh']);
+		$options = $this->requestOptions($url, $this->config['calendarRefresh']);
 		try {
 			$response = Requests::get($url, $headers, $options);
 			if ($response->success) {

+ 29 - 90
api/homepage/transmission.php

@@ -14,94 +14,33 @@ trait TransmissionHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageTransmissionEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageTransmissionEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageTransmissionAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageTransmissionAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'transmissionURL',
-						'label' => 'URL',
-						'value' => $this->config['transmissionURL'],
-						'help' => 'Please do not included /web in URL.  Please make sure to use local IP address and port - You also may use local dns name too.',
-						'placeholder' => 'http(s)://hostname:port'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'transmissionDisableCertCheck',
-						'label' => 'Disable Certificate Check',
-						'value' => $this->config['transmissionDisableCertCheck']
-					),
-					array(
-						'type' => 'input',
-						'name' => 'transmissionUsername',
-						'label' => 'Username',
-						'value' => $this->config['transmissionUsername']
-					),
-					array(
-						'type' => 'password',
-						'name' => 'transmissionPassword',
-						'label' => 'Password',
-						'value' => $this->config['transmissionPassword']
-					)
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'transmissionHideSeeding',
-						'label' => 'Hide Seeding',
-						'value' => $this->config['transmissionHideSeeding']
-					), array(
-						'type' => 'switch',
-						'name' => 'transmissionHideCompleted',
-						'label' => 'Hide Completed',
-						'value' => $this->config['transmissionHideCompleted']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'transmissionRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['transmissionRefresh'],
-						'options' => $this->timeOptions()
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'transmissionCombine',
-						'label' => 'Add to Combined Downloader',
-						'value' => $this->config['transmissionCombine']
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'transmission\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageTransmissionEnabled'),
+					$this->settingsOption('auth', 'homepageTransmissionAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'transmissionURL', ['help' => 'Please do not included /web in URL.  Please make sure to use local IP address and port - You also may use local dns name too.']),
+					$this->settingsOption('blank'),
+					$this->settingsOption('username', 'transmissionUsername'),
+					$this->settingsOption('password', 'transmissionPassword'),
+					$this->settingsOption('disable-cert-check', 'transmissionDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'transmissionUseCustomCertificate'),
+				],
+				'Misc Options' => [
+					$this->settingsOption('hide-seeding', 'transmissionHideSeeding'),
+					$this->settingsOption('hide-completed', 'transmissionHideCompleted'),
+					$this->settingsOption('refresh', 'transmissionRefresh'),
+					$this->settingsOption('combine', 'transmissionCombine'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'transmission'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -115,8 +54,8 @@ trait TransmissionHomepageItem
 		$passwordInclude = ($this->config['transmissionUsername'] != '' && $this->config['transmissionPassword'] != '') ? $this->config['transmissionUsername'] . ':' . rawurlencode($this->decrypt($this->config['transmissionPassword'])) . "@" : '';
 		$url = $digest['scheme'] . '://' . $passwordInclude . $digest['host'] . $digest['port'] . $digest['path'] . '/rpc';
 		try {
-			$options = $this->requestOptions($this->config['transmissionURL'], $this->config['transmissionDisableCertCheck'], $this->config['transmissionRefresh']);
-			$response = Requests::get($url, array(), $options);
+			$options = $this->requestOptions($this->config['transmissionURL'], $this->config['transmissionRefresh'], $this->config['transmissionDisableCertCheck'], $this->config['transmissionUseCustomCertificate']);
+			$response = Requests::get($url, [], $options);
 			if ($response->headers['x-transmission-session-id']) {
 				$headers = array(
 					'X-Transmission-Session-Id' => $response->headers['x-transmission-session-id'],
@@ -203,7 +142,7 @@ trait TransmissionHomepageItem
 		$passwordInclude = ($this->config['transmissionUsername'] != '' && $this->config['transmissionPassword'] != '') ? $this->config['transmissionUsername'] . ':' . rawurlencode($this->decrypt($this->config['transmissionPassword'])) . "@" : '';
 		$url = $digest['scheme'] . '://' . $passwordInclude . $digest['host'] . $digest['port'] . $digest['path'] . '/rpc';
 		try {
-			$options = $this->requestOptions($this->config['transmissionURL'], $this->config['transmissionDisableCertCheck'], $this->config['transmissionRefresh']);
+			$options = $this->requestOptions($this->config['transmissionURL'], $this->config['transmissionRefresh'], $this->config['transmissionDisableCertCheck'], $this->config['transmissionUseCustomCertificate']);
 			$response = Requests::get($url, array(), $options);
 			if ($response->headers['x-transmission-session-id']) {
 				$headers = array(

+ 28 - 87
api/homepage/unifi.php

@@ -14,90 +14,32 @@ trait UnifiHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageUnifiEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageUnifiEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageUnifiAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageUnifiAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'unifiURL',
-						'label' => 'URL',
-						'value' => $this->config['unifiURL'],
-						'help' => 'URL for Unifi',
-						'placeholder' => 'Unifi API URL'
-					),
-					array(
-						'type' => 'blank',
-						'label' => ''
-					),
-					array(
-						'type' => 'input',
-						'name' => 'unifiUsername',
-						'label' => 'Username',
-						'value' => $this->config['unifiUsername'],
-						'help' => 'Username is case-sensitive',
-					),
-					array(
-						'type' => 'password',
-						'name' => 'unifiPassword',
-						'label' => 'Password',
-						'value' => $this->config['unifiPassword']
-					),
-					array(
-						'type' => 'input',
-						'name' => 'unifiSiteName',
-						'label' => 'Site Name (Not for UnifiOS)',
-						'value' => $this->config['unifiSiteName'],
-						'help' => 'Site Name - not Site ID nor Site Description',
-					),
-					array(
-						'type' => 'button',
-						'label' => 'Grab Unifi Site (Not for UnifiOS)',
-						'icon' => 'fa fa-building',
-						'text' => 'Get Unifi Site',
-						'attr' => 'onclick="getUnifiSite()"'
-					),
-				),
-				'Misc Options' => array(
-					array(
-						'type' => 'select',
-						'name' => 'homepageUnifiRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageUnifiRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-				'Test Connection' => array(
-					array(
-						'type' => 'blank',
-						'label' => 'Please Save before Testing'
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-flask',
-						'class' => 'pull-right',
-						'text' => 'Test Connection',
-						'attr' => 'onclick="testAPIConnection(\'unifi\')"'
-					),
-				)
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageUnifiEnabled'),
+					$this->settingsOption('auth', 'homepageUnifiAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('url', 'unifiURL'),
+					$this->settingsOption('blank'),
+					$this->settingsOption('disable-cert-check', 'unifiDisableCertCheck'),
+					$this->settingsOption('use-custom-certificate', 'unifiUseCustomCertificate'),
+					$this->settingsOption('username', 'unifiUsername', ['help' => 'Username is case-sensitive']),
+					$this->settingsOption('password', 'unifiPassword'),
+					$this->settingsOption('input', 'unifiSiteName', ['label' => 'Site Name (Not for UnifiOS)', 'help' => 'Site Name - not Site ID nor Site Description']),
+					$this->settingsOption('button', '', ['label' => 'Grab Unifi Site (Not for UnifiOS)', 'icon' => 'fa fa-building', 'text' => 'Get Unifi Site', 'attr' => 'onclick="getUnifiSite()"']),
+				],
+				'Misc Options' => [
+					$this->settingsOption('refresh', 'homepageUnifiRefresh'),
+				],
+				'Test Connection' => [
+					$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
+					$this->settingsOption('test', 'unifi'),
+				]
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -159,7 +101,7 @@ trait UnifiHomepageItem
 		}
 		$url = $this->qualifyURL($this->config['unifiURL']);
 		try {
-			$options = array('verify' => false, 'verifyname' => false, 'follow_redirects' => false);
+			$options = $this->requestOptions($url, $this->config['homepageUnifiRefresh'], $this->config['unifiDisableCertCheck'], $this->config['unifiUseCustomCertificate'], ['follow_redirects' => true]);
 			$data = array(
 				'username' => $this->config['unifiUsername'],
 				'password' => $this->decrypt($this->config['unifiPassword']),
@@ -210,7 +152,7 @@ trait UnifiHomepageItem
 		}
 		$api['content']['unifi'] = array();
 		$url = $this->qualifyURL($this->config['unifiURL']);
-		$options = array('verify' => false, 'verifyname' => false, 'follow_redirects' => true);
+		$options = $this->requestOptions($url, $this->config['homepageUnifiRefresh'], $this->config['unifiDisableCertCheck'], $this->config['unifiUseCustomCertificate'], ['follow_redirects' => true]);
 		$data = array(
 			'username' => $this->config['unifiUsername'],
 			'password' => $this->decrypt($this->config['unifiPassword']),
@@ -267,8 +209,7 @@ trait UnifiHomepageItem
 		}
 		$api['content']['unifi'] = array();
 		$url = $this->qualifyURL($this->config['unifiURL']);
-		$extras = array('verify' => false, 'verifyname' => false, 'follow_redirects' => true);
-		$options = $this->requestOptions($url, true, $this->config['homepageUnifiRefresh'], $extras);
+		$options = $this->requestOptions($url, $this->config['homepageUnifiRefresh'], $this->config['unifiDisableCertCheck'], $this->config['unifiUseCustomCertificate'], ['follow_redirects' => true]);
 		$data = array(
 			'username' => $this->config['unifiUsername'],
 			'password' => $this->decrypt($this->config['unifiPassword']),

+ 27 - 114
api/homepage/weather.php

@@ -14,114 +14,30 @@ trait WeatherHomepageItem
 		if ($infoOnly) {
 			return $homepageInformation;
 		}
-		$homepageSettings = array(
+		$homepageSettings = [
 			'debug' => true,
-			'settings' => array(
-				'Enable' => array(
-					array(
-						'type' => 'switch',
-						'name' => 'homepageWeatherAndAirEnabled',
-						'label' => 'Enable',
-						'value' => $this->config['homepageWeatherAndAirEnabled']
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageWeatherAndAirAuth',
-						'label' => 'Minimum Authentication',
-						'value' => $this->config['homepageWeatherAndAirAuth'],
-						'options' => $this->groupOptions
-					)
-				),
-				'Connection' => array(
-					array(
-						'type' => 'input',
-						'name' => 'homepageWeatherAndAirLatitude',
-						'label' => 'Latitude',
-						'value' => $this->config['homepageWeatherAndAirLatitude'],
-						'help' => 'Please enter full latitude including minus if needed'
-					),
-					array(
-						'type' => 'input',
-						'name' => 'homepageWeatherAndAirLongitude',
-						'label' => 'Longitude',
-						'value' => $this->config['homepageWeatherAndAirLongitude'],
-						'help' => 'Please enter full longitude including minus if needed'
-					),
-					array(
-						'type' => 'blank',
-						'label' => ''
-					),
-					array(
-						'type' => 'button',
-						'label' => '',
-						'icon' => 'fa fa-search',
-						'class' => 'pull-right',
-						'text' => 'Need Help With Coordinates?',
-						'attr' => 'onclick="showLookupCoordinatesModal()"'
-					),
-				),
-				'Options' => array(
-					array(
-						'type' => 'input',
-						'name' => 'homepageWeatherAndAirWeatherHeader',
-						'label' => 'Title',
-						'value' => $this->config['homepageWeatherAndAirWeatherHeader'],
-						'help' => 'Sets the title of this homepage module',
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageWeatherAndAirWeatherHeaderToggle',
-						'label' => 'Toggle Title',
-						'value' => $this->config['homepageWeatherAndAirWeatherHeaderToggle'],
-						'help' => 'Shows/hides the title of this homepage module'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageWeatherAndAirWeatherEnabled',
-						'label' => 'Enable Weather',
-						'value' => $this->config['homepageWeatherAndAirWeatherEnabled'],
-						'help' => 'Toggles the view module for Weather'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageWeatherAndAirAirQualityEnabled',
-						'label' => 'Enable Air Quality',
-						'value' => $this->config['homepageWeatherAndAirAirQualityEnabled'],
-						'help' => 'Toggles the view module for Air Quality'
-					),
-					array(
-						'type' => 'switch',
-						'name' => 'homepageWeatherAndAirPollenEnabled',
-						'label' => 'Enable Pollen',
-						'value' => $this->config['homepageWeatherAndAirPollenEnabled'],
-						'help' => 'Toggles the view module for Pollen'
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageWeatherAndAirUnits',
-						'label' => 'Unit of Measurement',
-						'value' => $this->config['homepageWeatherAndAirUnits'],
-						'options' => array(
-							array(
-								'name' => 'Imperial',
-								'value' => 'imperial'
-							),
-							array(
-								'name' => 'Metric',
-								'value' => 'metric'
-							)
-						)
-					),
-					array(
-						'type' => 'select',
-						'name' => 'homepageWeatherAndAirRefresh',
-						'label' => 'Refresh Seconds',
-						'value' => $this->config['homepageWeatherAndAirRefresh'],
-						'options' => $this->timeOptions()
-					),
-				),
-			)
-		);
+			'settings' => [
+				'Enable' => [
+					$this->settingsOption('enable', 'homepageWeatherAndAirEnabled'),
+					$this->settingsOption('auth', 'homepageWeatherAndAirAuth'),
+				],
+				'Connection' => [
+					$this->settingsOption('input', 'homepageWeatherAndAirLatitude', ['label' => 'Latitude', 'help' => 'Please enter full latitude including minus if needed']),
+					$this->settingsOption('input', 'homepageWeatherAndAirLongitude', ['label' => 'Longitude', 'help' => 'Please enter full longitude including minus if needed']),
+					$this->settingsOption('blank'),
+					$this->settingsOption('button', null, ['type' => 'button', 'label' => '', 'icon' => 'fa fa-search', 'class' => 'pull-right', 'text' => 'Need Help With Coordinates?', 'attr' => 'onclick="showLookupCoordinatesModal()"']),
+				],
+				'Options' => [
+					$this->settingsOption('title', 'homepageWeatherAndAirWeatherHeader'),
+					$this->settingsOption('toggle-title', 'homepageWeatherAndAirWeatherHeaderToggle'),
+					$this->settingsOption('enable', 'homepageWeatherAndAirWeatherEnabled', ['label' => 'Enable Weather', 'help' => 'Toggles the view module for Weather']),
+					$this->settingsOption('enable', 'homepageWeatherAndAirAirQualityEnabled', ['label' => 'Enable Air Quality', 'help' => 'Toggles the view module for Air Quality']),
+					$this->settingsOption('enable', 'homepageWeatherAndAirPollenEnabled', ['label' => 'Enable Pollen', 'help' => 'Toggles the view module for Pollen']),
+					$this->settingsOption('select', 'homepageWeatherAndAirUnits', ['label' => 'Unit of Measurement', 'options' => [['name' => 'Imperial', 'value' => 'imperial'], ['name' => 'Metric', 'value' => 'metric']]]),
+					$this->settingsOption('refresh', 'homepageWeatherAndAirRefresh'),
+				],
+			]
+		];
 		return array_merge($homepageInformation, $homepageSettings);
 	}
 	
@@ -175,8 +91,7 @@ trait WeatherHomepageItem
 				return false;
 			}
 			$url = $this->qualifyURL('https://api.mapbox.com/geocoding/v5/mapbox.places/' . urlencode($query) . '.json?access_token=pk.eyJ1IjoiY2F1c2VmeCIsImEiOiJjazhyeGxqeXgwMWd2M2ZydWQ4YmdjdGlzIn0.R50iYuMewh1CnUZ7sFPdHA&limit=5&fuzzyMatch=true');
-			$options = array('verify' => false);
-			$response = Requests::get($url, array(), $options);
+			$response = Requests::get($url);
 			if ($response->success) {
 				$this->setAPIResponse('success', null, 200, json_decode($response->body));
 				return json_decode($response->body);
@@ -200,11 +115,9 @@ trait WeatherHomepageItem
 		$apiURL = $this->qualifyURL('https://api.breezometer.com/');
 		$info = '&lat=' . $this->config['homepageWeatherAndAirLatitude'] . '&lon=' . $this->config['homepageWeatherAndAirLongitude'] . '&units=' . $this->config['homepageWeatherAndAirUnits'] . '&key=' . $this->config['breezometerToken'];
 		try {
-			$headers = array();
-			$options = array();
 			if ($this->config['homepageWeatherAndAirWeatherEnabled']) {
 				$endpoint = '/weather/v1/forecast/hourly?hours=120&metadata=true';
-				$response = Requests::get($apiURL . $endpoint . $info, $headers, $options);
+				$response = Requests::get($apiURL . $endpoint . $info);
 				if ($response->success) {
 					$apiData = json_decode($response->body, true);
 					$api['content']['weather'] = ($apiData['error'] === null) ? $apiData : false;
@@ -213,7 +126,7 @@ trait WeatherHomepageItem
 			}
 			if ($this->config['homepageWeatherAndAirAirQualityEnabled']) {
 				$endpoint = '/air-quality/v2/current-conditions?features=breezometer_aqi,local_aqi,health_recommendations,sources_and_effects,dominant_pollutant_concentrations,pollutants_concentrations,pollutants_aqi_information&metadata=true';
-				$response = Requests::get($apiURL . $endpoint . $info, $headers, $options);
+				$response = Requests::get($apiURL . $endpoint . $info);
 				if ($response->success) {
 					$apiData = json_decode($response->body, true);
 					$api['content']['air'] = ($apiData['error'] === null) ? $apiData : false;
@@ -222,7 +135,7 @@ trait WeatherHomepageItem
 			}
 			if ($this->config['homepageWeatherAndAirPollenEnabled']) {
 				$endpoint = '/pollen/v2/forecast/daily?features=plants_information,types_information&days=1&metadata=true';
-				$response = Requests::get($apiURL . $endpoint . $info, $headers, $options);
+				$response = Requests::get($apiURL . $endpoint . $info);
 				if ($response->success) {
 					$apiData = json_decode($response->body, true);
 					$api['content']['pollen'] = ($apiData['error'] === null) ? $apiData : false;