Ver código fonte

changed permission styles for all homepage items - may break homepage items as i could not test all

CauseFX 5 anos atrás
pai
commit
c29835da07

+ 47 - 0
api/homepage/calendar.php

@@ -94,6 +94,53 @@ trait CalendarHomepageItem
 		);
 	}
 	
+	public function calendarHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageCalendarEnabled'
+				],
+				'auth' => [
+					'homepageCalendarAuth'
+				],
+				'not_empty' => [
+					'calendariCal'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrdercalendar()
+	{
+		if (
+			$this->homepageItemPermissions($this->sonarrHomepagePermissions('calendar')) ||
+			$this->homepageItemPermissions($this->radarrHomepagePermissions('calendar')) ||
+			$this->homepageItemPermissions($this->lidarrHomepagePermissions('calendar')) ||
+			$this->homepageItemPermissions($this->sickrageHomepagePermissions('calendar')) ||
+			$this->homepageItemPermissions($this->couchPotatoHomepagePermissions('calendar')) ||
+			$this->homepageItemPermissions($this->calendarHomepagePermissions('calendar'))
+		) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div id="calendar" class="fc fc-ltr m-b-30"></div>
+					<script>
+						// Calendar
+						homepageCalendar("' . $this->config['calendarRefresh'] . '");
+						// End Calendar
+					</script>
+					</div>
+				';
+		}
+	}
+	
 	public function loadCalendarJS()
 	{
 		$locale = ($this->config['calendarLocale'] !== 'en') ?? false;

+ 26 - 14
api/homepage/couchpotato.php

@@ -90,22 +90,34 @@ trait CouchPotatoHomepageItem
 		);
 	}
 	
-	public function getCouchPotatoCalendar()
+	public function couchPotatoHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageCouchpotatoEnabled']) {
-			$this->setAPIResponse('error', 'CouchPotato homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageCouchpotatoAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['couchpotatoURL'])) {
-			$this->setAPIResponse('error', 'Radarr URL is not defined', 422);
-			return false;
+		$permissions = [
+			'calendar' => [
+				'enabled' => [
+					'homepageCouchpotatoEnabled'
+				],
+				'auth' => [
+					'homepageCouchpotatoAuth'
+				],
+				'not_empty' => [
+					'couchpotatoURL',
+					'couchpotatoToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['couchpotatoToken'])) {
-			$this->setAPIResponse('error', 'Radarr Token is not defined', 422);
+	}
+	
+	public function getCouchPotatoCalendar()
+	{
+		if (!$this->homepageItemPermissions($this->couchPotatoHomepagePermissions('calendar'), true)) {
 			return false;
 		}
 		$calendarItems = array();

+ 52 - 21
api/homepage/deluge.php

@@ -128,34 +128,53 @@ trait DelugeHomepageItem
 		
 	}
 	
-	public function delugeStatus($queued, $status, $state)
+	public function delugeHomepagePermissions($key = null)
 	{
-		if ($queued == '-1' && $state == '100' && ($status == 'Seeding' || $status == 'Queued' || $status == 'Paused')) {
-			$state = 'Seeding';
-		} elseif ($state !== '100') {
-			$state = 'Downloading';
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageDelugeEnabled'
+				],
+				'auth' => [
+					'homepageDelugeAuth'
+				],
+				'not_empty' => [
+					'delugeURL',
+					'delugePassword'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
 		} else {
-			$state = 'Finished';
+			return [];
 		}
-		return ($state) ? $state : $status;
 	}
 	
-	public function getDelugeHomepageQueue()
+	public function homepageOrderdeluge()
 	{
-		if (!$this->config['homepageDelugeEnabled']) {
-			$this->setAPIResponse('error', 'Deluge homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageDelugeAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['delugeURL'])) {
-			$this->setAPIResponse('error', 'Deluge URL is not defined', 422);
-			return false;
+		if ($this->homepageItemPermissions($this->delugeHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['delugeCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['delugeCombine']) ? 'buildDownloaderCombined(\'deluge\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("deluge"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrderdeluge
+		                ' . $builder . '
+		                homepageDownloader("deluge", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrderdeluge
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['delugePassword'])) {
-			$this->setAPIResponse('error', 'Deluge Password is not defined', 422);
+	}
+	
+	public function getDelugeHomepageQueue()
+	{
+		if (!$this->homepageItemPermissions($this->delugeHomepagePermissions('main'), true)) {
 			return false;
 		}
 		try {
@@ -182,4 +201,16 @@ trait DelugeHomepageItem
 		$this->setAPIResponse('success', null, 200, $api);
 		return $api;
 	}
+	
+	public function delugeStatus($queued, $status, $state)
+	{
+		if ($queued == '-1' && $state == '100' && ($status == 'Seeding' || $status == 'Queued' || $status == 'Paused')) {
+			$state = 'Seeding';
+		} elseif ($state !== '100') {
+			$state = 'Downloading';
+		} else {
+			$state = 'Finished';
+		}
+		return ($state) ? $state : $status;
+	}
 }

+ 238 - 208
api/homepage/emby.php

@@ -190,6 +190,244 @@ trait EmbyHomepageItem
 		}
 	}
 	
+	public function embyHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'streams' => [
+				'enabled' => [
+					'homepageEmbyEnabled',
+					'homepageEmbyStreams'
+				],
+				'auth' => [
+					'homepageEmbyAuth',
+					'homepageEmbyStreamsAuth'
+				],
+				'not_empty' => [
+					'embyURL',
+					'embyToken'
+				]
+			],
+			'recent' => [
+				'enabled' => [
+					'homepageEmbyEnabled',
+					'homepageEmbyRecent'
+				],
+				'auth' => [
+					'homepageEmbyAuth',
+					'homepageEmbyRecentAuth'
+				],
+				'not_empty' => [
+					'embyURL',
+					'embyToken'
+				]
+			],
+			'metadata' => [
+				'enabled' => [
+					'homepageEmbyEnabled'
+				],
+				'auth' => [
+					'homepageEmbyAuth'
+				],
+				'not_empty' => [
+					'embyURL',
+					'embyToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderembynowplaying()
+	{
+		if ($this->homepageItemPermissions($this->embyHomepagePermissions('streams'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Now Playing...</h2></div>
+					<script>
+						// Emby Stream
+						homepageStream("emby", "' . $this->config['homepageStreamRefresh'] . '");
+						// End Emby Stream
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function homepageOrderembyrecent()
+	{
+		if ($this->homepageItemPermissions($this->embyHomepagePermissions('recent'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Recent...</h2></div>
+					<script>
+						// Emby Recent
+						homepageRecent("emby", "' . $this->config['homepageRecentRefresh'] . '");
+						// End Emby Recent
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function getEmbyHomepageStreams()
+	{
+		if (!$this->homepageItemPermissions($this->embyHomepagePermissions('streams'), true)) {
+			return false;
+		}
+		$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();
+		try {
+			$response = Requests::get($url, array(), $options);
+			if ($response->success) {
+				$items = array();
+				$emby = json_decode($response->body, true);
+				foreach ($emby as $child) {
+					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
+						$items[] = $this->resolveEmbyItem($child);
+					}
+				}
+				$api['content'] = array_filter($items);
+				$this->setAPIResponse('success', null, 200, $api);
+				return $api;
+			} else {
+				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
+				return false;
+			}
+		} catch (Requests_Exception $e) {
+			$this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
+			$this->setAPIResponse('error', $e->getMessage(), 500);
+			return false;
+		}
+	}
+	
+	public function getEmbyHomepageRecent()
+	{
+		if (!$this->homepageItemPermissions($this->embyHomepagePermissions('recent'), true)) {
+			return false;
+		}
+		$url = $this->qualifyURL($this->config['embyURL']);
+		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$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);
+			if ($response->success) {
+				$emby = json_decode($response->body, true);
+				foreach ($emby as $value) { // Scan for admin user
+					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
+						$userId = $value['Id'];
+					}
+					if ($username && strtolower($value['Name']) == $username) {
+						$userId = $value['Id'];
+						$showPlayed = false;
+						break;
+					}
+				}
+				$url = $url . '/Users/' . $userId . '/Items/Latest?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['embyToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
+			} else {
+				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
+				return false;
+			}
+			$response = Requests::get($url, array(), $options);
+			if ($response->success) {
+				$items = array();
+				$emby = json_decode($response->body, true);
+				foreach ($emby as $child) {
+					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
+						$items[] = $this->resolveEmbyItem($child);
+					}
+				}
+				$api['content'] = array_filter($items);
+				$this->setAPIResponse('success', null, 200, $api);
+				return $api;
+			} else {
+				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
+				return false;
+			}
+		} catch (Requests_Exception $e) {
+			$this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
+			$this->setAPIResponse('error', $e->getMessage(), 500);
+			return false;
+		}
+	}
+	
+	public function getEmbyHomepageMetadata($array)
+	{
+		if (!$this->homepageItemPermissions($this->embyHomepagePermissions('metadata'), true)) {
+			return false;
+		}
+		$key = $array['key'] ?? null;
+		if (!$key) {
+			$this->setAPIResponse('error', 'Emby Metadata key is not defined', 422);
+			return false;
+		}
+		$url = $this->qualifyURL($this->config['embyURL']);
+		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$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);
+			if ($response->success) {
+				$emby = json_decode($response->body, true);
+				foreach ($emby as $value) { // Scan for admin user
+					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
+						$userId = $value['Id'];
+					}
+					if ($username && strtolower($value['Name']) == $username) {
+						$userId = $value['Id'];
+						$showPlayed = false;
+						break;
+					}
+				}
+				$url = $url . '/Users/' . $userId . '/Items/' . $key . '?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['embyToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
+			} else {
+				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
+				return false;
+			}
+			$response = Requests::get($url, array(), $options);
+			if ($response->success) {
+				$items = array();
+				$emby = json_decode($response->body, true);
+				if (isset($emby['NowPlayingItem']) || isset($emby['Name'])) {
+					$items[] = $this->resolveEmbyItem($emby);
+				}
+				$api['content'] = array_filter($items);
+				$this->setAPIResponse('success', null, 200, $api);
+				return $api;
+			} else {
+				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
+				return false;
+			}
+		} catch (Requests_Exception $e) {
+			$this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
+			$this->setAPIResponse('error', $e->getMessage(), 500);
+			return false;
+		}
+	}
+	
 	public function resolveEmbyItem($itemDetails)
 	{
 		$item = isset($itemDetails['NowPlayingItem']['Id']) ? $itemDetails['NowPlayingItem'] : $itemDetails;
@@ -388,212 +626,4 @@ trait EmbyHomepageItem
 		return $embyItem;
 	}
 	
-	public function getEmbyHomepageStreams()
-	{
-		if (!$this->config['homepageEmbyEnabled']) {
-			$this->setAPIResponse('error', 'Emby homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageEmbyStreams']) {
-			$this->setAPIResponse('error', 'Emby homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageEmbyAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageEmbyStreamsAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['embyURL'])) {
-			$this->setAPIResponse('error', 'Emby URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['embyToken'])) {
-			$this->setAPIResponse('error', 'Emby Token is not defined', 422);
-			return false;
-		}
-		$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();
-		try {
-			$response = Requests::get($url, array(), $options);
-			if ($response->success) {
-				$items = array();
-				$emby = json_decode($response->body, true);
-				foreach ($emby as $child) {
-					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
-						$items[] = $this->resolveEmbyItem($child);
-					}
-				}
-				$api['content'] = array_filter($items);
-				$this->setAPIResponse('success', null, 200, $api);
-				return $api;
-			} else {
-				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
-				return false;
-			}
-		} catch (Requests_Exception $e) {
-			$this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
-			$this->setAPIResponse('error', $e->getMessage(), 500);
-			return false;
-		}
-	}
-	
-	public function getEmbyHomepageRecent()
-	{
-		if (!$this->config['homepageEmbyEnabled']) {
-			$this->setAPIResponse('error', 'Emby homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageEmbyRecent']) {
-			$this->setAPIResponse('error', 'Emby homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageEmbyAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageEmbyRecentAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['embyURL'])) {
-			$this->setAPIResponse('error', 'Emby URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['embyToken'])) {
-			$this->setAPIResponse('error', 'Emby Token is not defined', 422);
-			return false;
-		}
-		$url = $this->qualifyURL($this->config['embyURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$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);
-			if ($response->success) {
-				$emby = json_decode($response->body, true);
-				foreach ($emby as $value) { // Scan for admin user
-					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
-						$userId = $value['Id'];
-					}
-					if ($username && strtolower($value['Name']) == $username) {
-						$userId = $value['Id'];
-						$showPlayed = false;
-						break;
-					}
-				}
-				$url = $url . '/Users/' . $userId . '/Items/Latest?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['embyToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
-			} else {
-				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
-				return false;
-			}
-			$response = Requests::get($url, array(), $options);
-			if ($response->success) {
-				$items = array();
-				$emby = json_decode($response->body, true);
-				foreach ($emby as $child) {
-					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
-						$items[] = $this->resolveEmbyItem($child);
-					}
-				}
-				$api['content'] = array_filter($items);
-				$this->setAPIResponse('success', null, 200, $api);
-				return $api;
-			} else {
-				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
-				return false;
-			}
-		} catch (Requests_Exception $e) {
-			$this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
-			$this->setAPIResponse('error', $e->getMessage(), 500);
-			return false;
-		}
-	}
-	
-	public function getEmbyHomepageMetadata($array)
-	{
-		if (!$this->config['homepageEmbyEnabled']) {
-			$this->setAPIResponse('error', 'Emby homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageEmbyAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['embyURL'])) {
-			$this->setAPIResponse('error', 'Emby URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['embyToken'])) {
-			$this->setAPIResponse('error', 'Emby Token is not defined', 422);
-			return false;
-		}
-		$key = $array['key'] ?? null;
-		if (!$key) {
-			$this->setAPIResponse('error', 'Emby Metadata key is not defined', 422);
-			return false;
-		}
-		$url = $this->qualifyURL($this->config['embyURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$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);
-			if ($response->success) {
-				$emby = json_decode($response->body, true);
-				foreach ($emby as $value) { // Scan for admin user
-					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
-						$userId = $value['Id'];
-					}
-					if ($username && strtolower($value['Name']) == $username) {
-						$userId = $value['Id'];
-						$showPlayed = false;
-						break;
-					}
-				}
-				$url = $url . '/Users/' . $userId . '/Items/' . $key . '?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['embyToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
-			} else {
-				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
-				return false;
-			}
-			$response = Requests::get($url, array(), $options);
-			if ($response->success) {
-				$items = array();
-				$emby = json_decode($response->body, true);
-				if (isset($emby['NowPlayingItem']) || isset($emby['Name'])) {
-					$items[] = $this->resolveEmbyItem($emby);
-				}
-				$api['content'] = array_filter($items);
-				$this->setAPIResponse('success', null, 200, $api);
-				return $api;
-			} else {
-				$this->setAPIResponse('error', 'Emby Error Occurred', 500);
-				return false;
-			}
-		} catch (Requests_Exception $e) {
-			$this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
-			$this->setAPIResponse('error', $e->getMessage(), 500);
-			return false;
-		}
-	}
-	
 }

+ 54 - 26
api/homepage/healthchecks.php

@@ -62,39 +62,50 @@ trait HealthChecksHomepageItem
 		);
 	}
 	
-	public function healthChecksTags($tags)
+	public function healthChecksHomepagePermissions($key = null)
 	{
-		$return = '?tag=';
-		if (!$tags) {
-			return '';
-		} elseif ($tags == '*') {
-			return '';
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageHealthChecksEnabled'
+				],
+				'auth' => [
+					'homepageHealthChecksAuth'
+				],
+				'not_empty' => [
+					'healthChecksURL',
+					'healthChecksToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
 		} else {
-			if (strpos($tags, ',') !== false) {
-				$list = explode(',', $tags);
-				return $return . implode("&tag=", $list);
-			} else {
-				return $return . $tags;
-			}
+			return [];
 		}
 	}
 	
-	public function getHealthChecks($tags = null)
+	public function homepageOrderhealthchecks()
 	{
-		if (!$this->config['homepageHealthChecksEnabled']) {
-			$this->setAPIResponse('error', 'HealthChecks homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageHealthChecksAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['healthChecksURL'])) {
-			$this->setAPIResponse('error', 'HealthChecks URL is not defined', 422);
-			return false;
+		if ($this->homepageItemPermissions($this->healthChecksHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Health Checks...</h2></div>
+					<script>
+						// Health Checks
+						homepageHealthChecks("' . $this->config['healthChecksTags'] . '","' . $this->config['homepageHealthChecksRefresh'] . '");
+						// End Health Checks
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['healthChecksToken'])) {
-			$this->setAPIResponse('error', 'HealthChecks Token is not defined', 422);
+	}
+	
+	public function getHealthChecks($tags = null)
+	{
+		if (!$this->homepageItemPermissions($this->healthChecksHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api['content']['checks'] = array();
@@ -121,4 +132,21 @@ trait HealthChecksHomepageItem
 		$this->setAPIResponse('success', null, 200, $api);
 		return $api;
 	}
+	
+	public function healthChecksTags($tags)
+	{
+		$return = '?tag=';
+		if (!$tags) {
+			return '';
+		} elseif ($tags == '*') {
+			return '';
+		} else {
+			if (strpos($tags, ',') !== false) {
+				$list = explode(',', $tags);
+				return $return . implode("&tag=", $list);
+			} else {
+				return $return . $tags;
+			}
+		}
+	}
 }

+ 41 - 9
api/homepage/jackett.php

@@ -46,18 +46,50 @@ trait JackettHomepageItem
 		);
 	}
 	
-	public function searchJackettIndexers($query = null)
+	public function jackettHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageJackettEnabled']) {
-			$this->setAPIResponse('error', 'Jackett homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageJackettEnabled'
+				],
+				'auth' => [
+					'homepageJackettAuth'
+				],
+				'not_empty' => [
+					'jackettURL',
+					'jackettToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageJackettAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrderJackett()
+	{
+		if ($this->homepageItemPermissions($this->jackettHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Jackett...</h2></div>
+					<script>
+						// Jackett
+						homepageJackett();
+						// End Jackett
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['jackettURL']) || empty($this->config['jackettToken'])) {
-			$this->setAPIResponse('error', 'Jackett URL and/or Token were not defined', 422);
+	}
+	
+	public function searchJackettIndexers($query = null)
+	{
+		if (!$this->homepageItemPermissions($this->jackettHomepagePermissions('main'), true)) {
 			return false;
 		}
 		if (!$query) {

+ 43 - 9
api/homepage/jdownloader.php

@@ -111,18 +111,52 @@ trait JDownloaderHomepageItem
 		};
 	}
 	
-	public function getJdownloaderHomepageQueue()
+	public function jDownloaderHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageJdownloaderEnabled']) {
-			$this->setAPIResponse('error', 'JDownloader homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageJdownloaderEnabled'
+				],
+				'auth' => [
+					'homepageJdownloaderAuth'
+				],
+				'not_empty' => [
+					'jdownloaderURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageJdownloaderAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrderjdownloader()
+	{
+		if ($this->homepageItemPermissions($this->jDownloaderHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['jdownloaderCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['jdownloaderCombine']) ? 'buildDownloaderCombined(\'jdownloader\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("jdownloader"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrderjdownloader
+		                ' . $builder . '
+		                homepageDownloader("jdownloader", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrderjdownloader
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['jdownloaderURL'])) {
-			$this->setAPIResponse('error', 'JDownloader URL is not defined', 422);
+	}
+	
+	public function getJdownloaderHomepageQueue()
+	{
+		if (!$this->homepageItemPermissions($this->jDownloaderHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['jdownloaderURL']);

+ 234 - 204
api/homepage/jellyfin.php

@@ -197,6 +197,240 @@ trait JellyfinHomepageItem
 		}
 	}
 	
+	public function jellyfinHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'streams' => [
+				'enabled' => [
+					'homepageJellyfinEnabled',
+					'homepageJellyfinStreams'
+				],
+				'auth' => [
+					'homepageJellyfinAuth',
+					'homepageJellyfinStreamsAuth'
+				],
+				'not_empty' => [
+					'jellyfinURL',
+					'jellyfinToken'
+				]
+			],
+			'recent' => [
+				'enabled' => [
+					'homepageJellyfinEnabled',
+					'homepageJellyfinRecent'
+				],
+				'auth' => [
+					'homepageJellyfinAuth',
+					'homepageJellyfinRecentAuth'
+				],
+				'not_empty' => [
+					'jellyfinURL',
+					'jellyfinToken'
+				]
+			],
+			'metadata' => [
+				'enabled' => [
+					'homepageJellyfinEnabled'
+				],
+				'auth' => [
+					'homepageJellyfinAuth'
+				],
+				'not_empty' => [
+					'jellyfinURL',
+					'jellyfinToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderjellyfinnowplaying()
+	{
+		if ($this->homepageItemPermissions($this->jellyfinHomepagePermissions('streams'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Now Playing...</h2></div>
+					<script>
+						// Jellyfin Stream
+						homepageStream("jellyfin", "' . $this->config['homepageStreamRefresh'] . '");
+						// End Jellyfin Stream
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function homepageOrderjellyfinrecent()
+	{
+		if ($this->homepageItemPermissions($this->jellyfinHomepagePermissions('recent'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Recent...</h2></div>
+					<script>
+						// Jellyfin Recent
+						homepageRecent("jellyfin", "' . $this->config['homepageRecentRefresh'] . '");
+						// End Jellyfin Recent
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function getJellyfinHomepageStreams()
+	{
+		if (!$this->homepageItemPermissions($this->jellyfinHomepagePermissions('streams'), true)) {
+			return false;
+		}
+		$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();
+		try {
+			$response = Requests::get($url, array(), $options);
+			if ($response->success) {
+				$items = array();
+				$jellyfin = json_decode($response->body, true);
+				foreach ($jellyfin as $child) {
+					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
+						$items[] = $this->resolveJellyfinItem($child);
+					}
+				}
+				$api['content'] = array_filter($items);
+				$this->setAPIResponse('success', null, 200, $api);
+				return $api;
+			} else {
+				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
+				return false;
+			}
+		} catch (Requests_Exception $e) {
+			$this->writeLog('error', 'Jellyfin Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
+			$this->setAPIResponse('error', $e->getMessage(), 500);
+			return false;
+		}
+	}
+	
+	public function getJellyfinHomepageRecent()
+	{
+		if (!$this->homepageItemPermissions($this->jellyfinHomepagePermissions('recent'), true)) {
+			return false;
+		}
+		$url = $this->qualifyURL($this->config['jellyfinURL']);
+		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$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['jellyfinToken'];
+			$response = Requests::get($userIds, array(), $options);
+			if ($response->success) {
+				$jellyfin = json_decode($response->body, true);
+				foreach ($jellyfin as $value) { // Scan for admin user
+					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
+						$userId = $value['Id'];
+					}
+					if ($username && strtolower($value['Name']) == $username) {
+						$userId = $value['Id'];
+						$showPlayed = false;
+						break;
+					}
+				}
+				$url = $url . '/Users/' . $userId . '/Items/Latest?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['jellyfinToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
+			} else {
+				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
+				return false;
+			}
+			$response = Requests::get($url, array(), $options);
+			if ($response->success) {
+				$items = array();
+				$jellyfin = json_decode($response->body, true);
+				foreach ($jellyfin as $child) {
+					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
+						$items[] = $this->resolveJellyfinItem($child);
+					}
+				}
+				$api['content'] = array_filter($items);
+				$this->setAPIResponse('success', null, 200, $api);
+				return $api;
+			} else {
+				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
+				return false;
+			}
+		} catch (Requests_Exception $e) {
+			$this->writeLog('error', 'Jellyfin Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
+			$this->setAPIResponse('error', $e->getMessage(), 500);
+			return false;
+		}
+	}
+	
+	public function getJellyfinHomepageMetadata($array)
+	{
+		if (!$this->homepageItemPermissions($this->jellyfinHomepagePermissions('metadata'), true)) {
+			return false;
+		}
+		$key = $array['key'] ?? null;
+		if (!$key) {
+			$this->setAPIResponse('error', 'Jellyfin Metadata key is not defined', 422);
+			return false;
+		}
+		$url = $this->qualifyURL($this->config['jellyfinURL']);
+		$options = ($this->localURL($url)) ? array('verify' => false) : array();
+		$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['jellyfinToken'];
+			$response = Requests::get($userIds, array(), $options);
+			if ($response->success) {
+				$jellyfin = json_decode($response->body, true);
+				foreach ($jellyfin as $value) { // Scan for admin user
+					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
+						$userId = $value['Id'];
+					}
+					if ($username && strtolower($value['Name']) == $username) {
+						$userId = $value['Id'];
+						$showPlayed = false;
+						break;
+					}
+				}
+				$url = $url . '/Users/' . $userId . '/Items/' . $key . '?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['jellyfinToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
+			} else {
+				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
+				return false;
+			}
+			$response = Requests::get($url, array(), $options);
+			if ($response->success) {
+				$items = array();
+				$jellyfin = json_decode($response->body, true);
+				if (isset($jellyfin['NowPlayingItem']) || isset($jellyfin['Name'])) {
+					$items[] = $this->resolveJellyfinItem($jellyfin);
+				}
+				$api['content'] = array_filter($items);
+				$this->setAPIResponse('success', null, 200, $api);
+				return $api;
+			} else {
+				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
+				return false;
+			}
+		} catch (Requests_Exception $e) {
+			$this->writeLog('error', 'Jellyfin Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
+			$this->setAPIResponse('error', $e->getMessage(), 500);
+			return false;
+		}
+	}
+	
 	public function resolveJellyfinItem($itemDetails)
 	{
 		$item = isset($itemDetails['NowPlayingItem']['Id']) ? $itemDetails['NowPlayingItem'] : $itemDetails;
@@ -393,208 +627,4 @@ trait JellyfinHomepageItem
 		return $jellyfinItem;
 	}
 	
-	public function getJellyfinHomepageStreams()
-	{
-		if (!$this->config['homepageJellyfinEnabled']) {
-			$this->setAPIResponse('error', 'Jellyfin homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageJellyfinStreams']) {
-			$this->setAPIResponse('error', 'Jellyfin homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageJellyfinAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageJellyStreamsAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['jellyfinURL'])) {
-			$this->setAPIResponse('error', 'Jellyfin URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['jellyfinToken'])) {
-			$this->setAPIResponse('error', 'Jellyfin Token is not defined', 422);
-			return false;
-		}
-		$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();
-		try {
-			$response = Requests::get($url, array(), $options);
-			if ($response->success) {
-				$items = array();
-				$jellyfin = json_decode($response->body, true);
-				foreach ($jellyfin as $child) {
-					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
-						$items[] = $this->resolveJellyfinItem($child);
-					}
-				}
-				$api['content'] = array_filter($items);
-				$this->setAPIResponse('success', null, 200, $api);
-				return $api;
-			} else {
-				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
-				return false;
-			}
-		} catch (Requests_Exception $e) {
-			$this->writeLog('error', 'Jellyfin Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
-			$this->setAPIResponse('error', $e->getMessage(), 500);
-			return false;
-		}
-	}
-	
-	public function getJellyfinHomepageRecent()
-	{
-		if (!$this->config['homepageJellyfinEnabled']) {
-			$this->setAPIResponse('error', 'Jellyfin homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageJellyfinRecent']) {
-			$this->setAPIResponse('error', 'Jellyfin homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageJellyfinAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageJellyfinRecentAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['jellyfinURL'])) {
-			$this->setAPIResponse('error', 'Jellyfin URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['jellyfinToken'])) {
-			$this->setAPIResponse('error', 'Jellyfin Token is not defined', 422);
-			return false;
-		}
-		$url = $this->qualifyURL($this->config['jellyfinURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$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['jellyfinToken'];
-			$response = Requests::get($userIds, array(), $options);
-			if ($response->success) {
-				$jellyfin = json_decode($response->body, true);
-				foreach ($jellyfin as $value) { // Scan for admin user
-					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
-						$userId = $value['Id'];
-					}
-					if ($username && strtolower($value['Name']) == $username) {
-						$userId = $value['Id'];
-						$showPlayed = false;
-						break;
-					}
-				}
-				$url = $url . '/Users/' . $userId . '/Items/Latest?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['jellyfinToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
-			} else {
-				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
-				return false;
-			}
-			$response = Requests::get($url, array(), $options);
-			if ($response->success) {
-				$items = array();
-				$jellyfin = json_decode($response->body, true);
-				foreach ($jellyfin as $child) {
-					if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
-						$items[] = $this->resolveJellyfinItem($child);
-					}
-				}
-				$api['content'] = array_filter($items);
-				$this->setAPIResponse('success', null, 200, $api);
-				return $api;
-			} else {
-				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
-				return false;
-			}
-		} catch (Requests_Exception $e) {
-			$this->writeLog('error', 'Jellyfin Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
-			$this->setAPIResponse('error', $e->getMessage(), 500);
-			return false;
-		}
-	}
-	
-	public function getJellyfinHomepageMetadata($array)
-	{
-		if (!$this->config['homepageJellyfinEnabled']) {
-			$this->setAPIResponse('error', 'Jellyfin homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageJellyfinAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['jellyfinURL'])) {
-			$this->setAPIResponse('error', 'Jellyfin URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['jellyfinToken'])) {
-			$this->setAPIResponse('error', 'Jellyfin Token is not defined', 422);
-			return false;
-		}
-		$key = $array['key'] ?? null;
-		if (!$key) {
-			$this->setAPIResponse('error', 'Jellyfin Metadata key is not defined', 422);
-			return false;
-		}
-		$url = $this->qualifyURL($this->config['jellyfinURL']);
-		$options = ($this->localURL($url)) ? array('verify' => false) : array();
-		$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['jellyfinToken'];
-			$response = Requests::get($userIds, array(), $options);
-			if ($response->success) {
-				$jellyfin = json_decode($response->body, true);
-				foreach ($jellyfin as $value) { // Scan for admin user
-					if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
-						$userId = $value['Id'];
-					}
-					if ($username && strtolower($value['Name']) == $username) {
-						$userId = $value['Id'];
-						$showPlayed = false;
-						break;
-					}
-				}
-				$url = $url . '/Users/' . $userId . '/Items/' . $key . '?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['jellyfinToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
-			} else {
-				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
-				return false;
-			}
-			$response = Requests::get($url, array(), $options);
-			if ($response->success) {
-				$items = array();
-				$jellyfin = json_decode($response->body, true);
-				if (isset($jellyfin['NowPlayingItem']) || isset($jellyfin['Name'])) {
-					$items[] = $this->resolveJellyfinItem($jellyfin);
-				}
-				$api['content'] = array_filter($items);
-				$this->setAPIResponse('success', null, 200, $api);
-				return $api;
-			} else {
-				$this->setAPIResponse('error', 'Jellyfin Error Occurred', 500);
-				return false;
-			}
-		} catch (Requests_Exception $e) {
-			$this->writeLog('error', 'Jellyfin Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
-			$this->setAPIResponse('error', $e->getMessage(), 500);
-			return false;
-		}
-	}
-	
 }

+ 41 - 36
api/homepage/lidarr.php

@@ -194,30 +194,48 @@ trait LidarrHomepageItem
 		}
 	}
 	
-	public function getLidarrQueue()
+	public function lidarrHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageLidarrEnabled']) {
-			$this->setAPIResponse('error', 'Lidarr homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageLidarrQueueEnabled']) {
-			$this->setAPIResponse('error', 'Lidarr homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageLidarrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageLidarrQueueAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['lidarrURL'])) {
-			$this->setAPIResponse('error', 'Lidarr URL is not defined', 422);
-			return false;
+		$permissions = [
+			'calendar' => [
+				'enabled' => [
+					'homepageLidarrEnabled'
+				],
+				'auth' => [
+					'homepageLidarrAuth'
+				],
+				'not_empty' => [
+					'lidarrURL',
+					'lidarrToken'
+				]
+			],
+			'queue' => [
+				'enabled' => [
+					'homepageLidarrEnabled',
+					'homepageLidarrQueueEnabled'
+				],
+				'auth' => [
+					'homepageLidarrAuth',
+					'homepageLidarrQueueAuth'
+				],
+				'not_empty' => [
+					'lidarrURL',
+					'lidarrToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['lidarrToken'])) {
-			$this->setAPIResponse('error', 'Lidarr Token is not defined', 422);
+	}
+	
+	public function getLidarrQueue()
+	{
+		if (!$this->homepageItemPermissions($this->lidarrHomepagePermissions('queue'), true)) {
 			return false;
 		}
 		$queueItems = array();
@@ -250,20 +268,7 @@ trait LidarrHomepageItem
 	{
 		$startDate = ($startDate) ?? $_GET['start'];
 		$endDate = ($endDate) ?? $_GET['end'];
-		if (!$this->config['homepageLidarrEnabled']) {
-			$this->setAPIResponse('error', 'Lidarr homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageLidarrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['lidarrURL'])) {
-			$this->setAPIResponse('error', 'Lidarr URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['lidarrToken'])) {
-			$this->setAPIResponse('error', 'Lidarr Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->lidarrHomepagePermissions('calendar'), true)) {
 			return false;
 		}
 		$calendarItems = array();

+ 40 - 9
api/homepage/monitorr.php

@@ -69,18 +69,49 @@ trait MonitorrHomepageItem
 		);
 	}
 	
-	public function getMonitorrHomepageData()
+	public function monitorrHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageMonitorrEnabled']) {
-			$this->setAPIResponse('error', 'Monitorr homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageMonitorrEnabled'
+				],
+				'auth' => [
+					'homepageMonitorrAuth'
+				],
+				'not_empty' => [
+					'monitorrURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageMonitorrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrderMonitorr()
+	{
+		if ($this->homepageItemPermissions($this->monitorrHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Monitorr...</h2></div>
+					<script>
+						// Monitorr
+						homepageMonitorr("' . $this->config['homepageMonitorrRefresh'] . '");
+						// End Monitorr
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['monitorrURL'])) {
-			$this->setAPIResponse('error', 'Monitorr URL is not defined', 422);
+	}
+	
+	public function getMonitorrHomepageData()
+	{
+		if (!$this->homepageItemPermissions($this->monitorrHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api = [];

+ 41 - 10
api/homepage/netdata.php

@@ -4,16 +4,7 @@ trait NetDataHomepageItem
 {
 	public function getNetdataHomepageData()
 	{
-		if (!$this->config['homepageNetdataEnabled']) {
-			$this->setAPIResponse('error', 'NetData homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageNetdataAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['netdataURL'])) {
-			$this->setAPIResponse('error', 'NetData URL is not defined', 422);
+		if (!$this->homepageItemPermissions($this->netdataHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api = [];
@@ -293,6 +284,46 @@ trait NetDataHomepageItem
 		return $array;
 	}
 	
+	public function netdataHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageNetdataEnabled'
+				],
+				'auth' => [
+					'homepageNetdataAuth'
+				],
+				'not_empty' => [
+					'netdataURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderNetdata()
+	{
+		if ($this->homepageItemPermissions($this->netdataHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Netdata...</h2></div>
+					<script>
+						// Netdata
+						homepageNetdata("' . $this->config['homepageNetdataRefresh'] . '");
+						// End Netdata
+					</script>
+				</div>
+				';
+		}
+	}
+	
 	public function disk($dimension, $url)
 	{
 		$data = [];

+ 43 - 9
api/homepage/nzbget.php

@@ -109,18 +109,52 @@ trait NZBGetHomepageItem
 		}
 	}
 	
-	public function getNzbgetHomepageQueue()
+	public function nzbgetHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageNzbgetEnabled']) {
-			$this->setAPIResponse('error', 'NZBGet homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageNzbgetEnabled'
+				],
+				'auth' => [
+					'homepageNzbgetAuth'
+				],
+				'not_empty' => [
+					'nzbgetURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageNzbgetAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrdernzbget()
+	{
+		if ($this->homepageItemPermissions($this->nzbgetHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['nzbgetCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['nzbgetCombine']) ? 'buildDownloaderCombined(\'nzbget\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("nzbget"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrdernzbget
+		                ' . $builder . '
+		                homepageDownloader("nzbget", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrdernzbget
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['nzbgetURL'])) {
-			$this->setAPIResponse('error', 'NZBGet URL is not defined', 422);
+	}
+	
+	public function getNzbgetHomepageQueue()
+	{
+		if (!$this->homepageItemPermissions($this->nzbgetHomepagePermissions('main'), true)) {
 			return false;
 		}
 		try {

+ 41 - 13
api/homepage/octoprint.php

@@ -61,22 +61,50 @@ trait OctoPrintHomepageItem
 		);
 	}
 	
-	public function getOctoprintHomepageData()
+	public function octoprintHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageOctoprintEnabled']) {
-			$this->setAPIResponse('error', 'OctoPrint homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageOctoprintAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageOctoprintEnabled'
+				],
+				'auth' => [
+					'homepageOctoprintAuth'
+				],
+				'not_empty' => [
+					'octoprintURL',
+					'octoprintToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['octoprintURL'])) {
-			$this->setAPIResponse('error', 'OctoPrint URL is not defined', 422);
-			return false;
+	}
+	
+	public function homepageOrderOctoprint()
+	{
+		if ($this->homepageItemPermissions($this->octoprintHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading OctoPrint...</h2></div>
+					<script>
+						// Octoprint
+						homepageOctoprint("' . $this->config['homepageOctoprintRefresh'] . '");
+						// End Octoprint
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['octoprintToken'])) {
-			$this->setAPIResponse('error', 'OctoPrint Token is not defined', 422);
+	}
+	
+	public function getOctoprintHomepageData()
+	{
+		if (!$this->homepageItemPermissions($this->octoprintHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api = [];

+ 47 - 48
api/homepage/ombi.php

@@ -169,27 +169,51 @@ trait OmbiHomepageItem
 		};
 	}
 	
-	public function ombiTVDefault($type)
+	public function ombiHomepagePermissions($key = null)
 	{
-		return $type == $this->config['ombiTvDefault'];
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageOmbiEnabled'
+				],
+				'auth' => [
+					'homepageOmbiAuth'
+				],
+				'not_empty' => [
+					'ombiURL',
+					'ombiToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
 	}
 	
-	public function getOmbiRequests($type = "both", $limit = 50, $offset = 0)
+	public function homepageOrderombi()
 	{
-		if (!$this->config['homepageOmbiEnabled']) {
-			$this->setAPIResponse('error', 'Ombi homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageOmbiAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['ombiURL'])) {
-			$this->setAPIResponse('error', 'Ombi URL is not defined', 422);
-			return false;
+		if ($this->homepageItemPermissions($this->ombiHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Requests...</h2></div>
+					<script>
+						// Ombi Requests
+						homepageRequests("' . $this->config['ombiRefresh'] . '");
+						// End Ombi Requests
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['ombiToken'])) {
-			$this->setAPIResponse('error', 'Ombi Token is not defined', 422);
+	}
+	
+	
+	public function getOmbiRequests($type = "both", $limit = 50, $offset = 0)
+	{
+		if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api['count'] = array(
@@ -308,20 +332,7 @@ trait OmbiHomepageItem
 			$this->setAPIResponse('error', 'Type was not supplied', 422);
 			return false;
 		}
-		if (!$this->config['homepageOmbiEnabled']) {
-			$this->setAPIResponse('error', 'Ombi homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageOmbiAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['ombiURL'])) {
-			$this->setAPIResponse('error', 'Ombi URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['ombiToken'])) {
-			$this->setAPIResponse('error', 'Ombi Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['ombiURL']);
@@ -449,24 +460,7 @@ trait OmbiHomepageItem
 			$this->setAPIResponse('error', 'Action was not supplied', 422);
 			return false;
 		}
-		if (!$this->config['homepageOmbiEnabled']) {
-			$this->setAPIResponse('error', 'Ombi homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageOmbiAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest(1)) {
-			$this->setAPIResponse('error', 'User must be an admin', 401);
-			return false;
-		}
-		if (empty($this->config['ombiURL'])) {
-			$this->setAPIResponse('error', 'Ombi URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['ombiToken'])) {
-			$this->setAPIResponse('error', 'Ombi Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['ombiURL']);
@@ -526,4 +520,9 @@ trait OmbiHomepageItem
 			return false;
 		};
 	}
+	
+	public function ombiTVDefault($type)
+	{
+		return $type == $this->config['ombiTvDefault'];
+	}
 }

+ 40 - 9
api/homepage/pihole.php

@@ -112,18 +112,49 @@ trait PiHoleHomepageItem
 		}
 	}
 	
-	public function getPiholeHomepageStats()
+	public function piholeHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepagePiholeEnabled']) {
-			$this->setAPIResponse('error', 'Pihole homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepagePiholeEnabled'
+				],
+				'auth' => [
+					'homepagePiholeAuth'
+				],
+				'not_empty' => [
+					'piholeURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepagePiholeAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrderPihole()
+	{
+		if ($this->homepageItemPermissions($this->piholeHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Pihole...</h2></div>
+					<script>
+						// Pi-hole Stats
+						homepagePihole("' . $this->config['homepagePiholeRefresh'] . '");
+						// End Pi-hole Stats
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['piholeURL'])) {
-			$this->setAPIResponse('error', 'Pihole URL is not defined', 422);
+	}
+	
+	public function getPiholeHomepageStats()
+	{
+		if (!$this->homepageItemPermissions($this->piholeHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api = array();

+ 315 - 298
api/homepage/plex.php

@@ -231,6 +231,321 @@ trait PlexHomepageItem
 		}
 	}
 	
+	public function plexHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'streams' => [
+				'enabled' => [
+					'homepagePlexEnabled',
+					'homepagePlexStreams'
+				],
+				'auth' => [
+					'homepagePlexAuth',
+					'homepagePlexStreamsAuth'
+				],
+				'not_empty' => [
+					'plexURL',
+					'plexToken',
+					'plexID'
+				]
+			],
+			'recent' => [
+				'enabled' => [
+					'homepagePlexEnabled',
+					'homepagePlexRecent'
+				],
+				'auth' => [
+					'homepagePlexAuth',
+					'homepagePlexRecentAuth'
+				],
+				'not_empty' => [
+					'plexURL',
+					'plexToken',
+					'plexID'
+				]
+			],
+			'playlists' => [
+				'enabled' => [
+					'homepagePlexEnabled',
+					'homepagePlexPlaylist'
+				],
+				'auth' => [
+					'homepagePlexAuth',
+					'homepagePlexPlaylistAuth'
+				],
+				'not_empty' => [
+					'plexURL',
+					'plexToken',
+					'plexID'
+				]
+			],
+			'metadata' => [
+				'enabled' => [
+					'homepagePlexEnabled'
+				],
+				'auth' => [
+					'homepagePlexAuth'
+				],
+				'not_empty' => [
+					'plexURL',
+					'plexToken',
+					'plexID'
+				]
+			],
+			'search' => [
+				'enabled' => [
+					'homepagePlexEnabled',
+					'mediaSearch'
+				],
+				'auth' => [
+					'homepagePlexAuth',
+					'mediaSearchAuth'
+				],
+				'not_empty' => [
+					'plexURL',
+					'plexToken',
+					'plexID'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderplexnowplaying()
+	{
+		if ($this->homepageItemPermissions($this->plexHomepagePermissions('streams'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Now Playing...</h2></div>
+					<script>
+						// Plex Stream
+						homepageStream("plex", "' . $this->config['homepageStreamRefresh'] . '");
+						// End Plex Stream
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function homepageOrderplexrecent()
+	{
+		if ($this->homepageItemPermissions($this->plexHomepagePermissions('recent'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Recent...</h2></div>
+					<script>
+						// Plex Recent
+						homepageRecent("plex", "' . $this->config['homepageRecentRefresh'] . '");
+						// End Plex Recent
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function homepageOrderplexplaylist()
+	{
+		if ($this->homepageItemPermissions($this->plexHomepagePermissions('playlists'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Playlists...</h2></div>
+					<script>
+						// Plex Playlist
+						homepagePlaylist("plex");
+						// End Plex Playlist
+					</script>
+				</div>
+				';
+		}
+	}
+	
+	public function getPlexHomepageStreams()
+	{
+		if (!$this->homepageItemPermissions($this->plexHomepagePermissions('streams'), true)) {
+			return false;
+		}
+		$ignore = array();
+		$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);
+		libxml_use_internal_errors(true);
+		if ($response->success) {
+			$items = array();
+			$plex = simplexml_load_string($response->body);
+			foreach ($plex as $child) {
+				if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
+					$items[] = $this->resolvePlexItem($child);
+				}
+			}
+			$api['content'] = ($resolve) ? $items : $plex;
+			$api['plexID'] = $this->config['plexID'];
+			$api['showNames'] = true;
+			$api['group'] = '1';
+			$this->setAPIResponse('success', null, 200, $api);
+			return $api;
+		}
+	}
+	
+	public function getPlexHomepageRecent()
+	{
+		if (!$this->homepageItemPermissions($this->plexHomepagePermissions('recent'), true)) {
+			return false;
+		}
+		$ignore = array();
+		$resolve = true;
+		$url = $this->qualifyURL($this->config['plexURL']);
+		$urls['movie'] = $url . "/hubs/home/recentlyAdded?X-Plex-Token=" . $this->config['plexToken'] . "&X-Plex-Container-Start=0&X-Plex-Container-Size=" . $this->config['homepageRecentLimit'] . "&type=1";
+		$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);
+			libxml_use_internal_errors(true);
+			if ($response->success) {
+				$items = array();
+				$plex = simplexml_load_string($response->body);
+				foreach ($plex as $child) {
+					if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
+						$items[] = $this->resolvePlexItem($child);
+					}
+				}
+				if (isset($api)) {
+					$api['content'] = array_merge($api['content'], ($resolve) ? $items : $plex);
+				} else {
+					$api['content'] = ($resolve) ? $items : $plex;
+				}
+			}
+		}
+		if (isset($api['content'])) {
+			usort($api['content'], function ($a, $b) {
+				return $b['addedAt'] <=> $a['addedAt'];
+			});
+		}
+		$api['plexID'] = $this->config['plexID'];
+		$api['showNames'] = true;
+		$api['group'] = '1';
+		$this->setAPIResponse('success', null, 200, $api);
+		return $api;
+	}
+	
+	public function getPlexHomepagePlaylists()
+	{
+		if (!$this->homepageItemPermissions($this->plexHomepagePermissions('playlists'), true)) {
+			return false;
+		}
+		$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);
+		libxml_use_internal_errors(true);
+		if ($response->success) {
+			$items = array();
+			$plex = simplexml_load_string($response->body);
+			foreach ($plex as $child) {
+				if ($child['playlistType'] == "video" && strpos(strtolower($child['title']), 'private') === false) {
+					$playlistTitleClean = preg_replace("/(\W)+/", "", (string)$child['title']);
+					$playlistURL = $this->qualifyURL($this->config['plexURL']);
+					$playlistURL = $playlistURL . $child['key'] . "?X-Plex-Token=" . $this->config['plexToken'];
+					$options = ($this->localURL($url)) ? array('verify' => false) : array();
+					$playlistResponse = Requests::get($playlistURL, array(), $options);
+					if ($playlistResponse->success) {
+						$playlistResponse = simplexml_load_string($playlistResponse->body);
+						$items[$playlistTitleClean]['title'] = (string)$child['title'];
+						foreach ($playlistResponse->Video as $playlistItem) {
+							$items[$playlistTitleClean][] = $this->resolvePlexItem($playlistItem);
+						}
+					}
+				}
+			}
+			$api['content'] = $items;
+			$api['plexID'] = $this->config['plexID'];
+			$api['showNames'] = true;
+			$api['group'] = '1';
+			$this->setAPIResponse('success', null, 200, $api);
+			return $api;
+		} else {
+			$this->setAPIResponse('error', 'Plex API error', 500);
+			return false;
+		}
+		
+	}
+	
+	public function getPlexHomepageMetadata($array)
+	{
+		if (!$this->homepageItemPermissions($this->plexHomepagePermissions('metadata'), true)) {
+			return false;
+		}
+		$key = $array['key'] ?? null;
+		if (!$key) {
+			$this->setAPIResponse('error', 'Plex Metadata key is not defined', 422);
+			return false;
+		}
+		$ignore = array();
+		$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);
+		libxml_use_internal_errors(true);
+		if ($response->success) {
+			$items = array();
+			$plex = simplexml_load_string($response->body);
+			foreach ($plex as $child) {
+				if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
+					$items[] = $this->resolvePlexItem($child);
+				}
+			}
+			$api['content'] = ($resolve) ? $items : $plex;
+			$api['plexID'] = $this->config['plexID'];
+			$api['showNames'] = true;
+			$api['group'] = '1';
+			$this->setAPIResponse('success', null, 200, $api);
+			return $api;
+		}
+	}
+	
+	public function getPlexHomepageSearch($query)
+	{
+		if (!$this->homepageItemPermissions($this->plexHomepagePermissions('search'), true)) {
+			return false;
+		}
+		$query = $query ?? null;
+		if (!$query) {
+			$this->setAPIResponse('error', 'Plex Metadata key is not defined', 422);
+			return false;
+		}
+		$ignore = array('artist', 'episode');
+		$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);
+		libxml_use_internal_errors(true);
+		if ($response->success) {
+			$items = array();
+			$plex = simplexml_load_string($response->body);
+			foreach ($plex as $child) {
+				if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
+					$items[] = $this->resolvePlexItem($child);
+				}
+			}
+			$api['content'] = ($resolve) ? $items : $plex;
+			$api['plexID'] = $this->config['plexID'];
+			$api['showNames'] = true;
+			$api['group'] = '1';
+			$this->setAPIResponse('success', null, 200, $api);
+			return $api;
+		}
+	}
+	
 	public function resolvePlexItem($item)
 	{
 		// Static Height & Width
@@ -423,302 +738,4 @@ trait PlexHomepageItem
 		}
 		return $plexItem;
 	}
-	
-	public function getPlexHomepageStreams()
-	{
-		if (!$this->config['homepagePlexEnabled']) {
-			$this->setAPIResponse('error', 'Plex homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepagePlexStreams']) {
-			$this->setAPIResponse('error', 'Plex homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexStreamsAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['plexURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexID'])) {
-			$this->setAPIResponse('error', 'Plex Id is not defined', 422);
-			return false;
-		}
-		$ignore = array();
-		$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);
-		libxml_use_internal_errors(true);
-		if ($response->success) {
-			$items = array();
-			$plex = simplexml_load_string($response->body);
-			foreach ($plex as $child) {
-				if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
-					$items[] = $this->resolvePlexItem($child);
-				}
-			}
-			$api['content'] = ($resolve) ? $items : $plex;
-			$api['plexID'] = $this->config['plexID'];
-			$api['showNames'] = true;
-			$api['group'] = '1';
-			$this->setAPIResponse('success', null, 200, $api);
-			return $api;
-		}
-	}
-	
-	public function getPlexHomepageRecent()
-	{
-		if (!$this->config['homepagePlexEnabled']) {
-			$this->setAPIResponse('error', 'Plex homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepagePlexRecent']) {
-			$this->setAPIResponse('error', 'Plex homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexRecentAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['plexURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexID'])) {
-			$this->setAPIResponse('error', 'Plex Id is not defined', 422);
-			return false;
-		}
-		$ignore = array();
-		$resolve = true;
-		$url = $this->qualifyURL($this->config['plexURL']);
-		$urls['movie'] = $url . "/hubs/home/recentlyAdded?X-Plex-Token=" . $this->config['plexToken'] . "&X-Plex-Container-Start=0&X-Plex-Container-Size=" . $this->config['homepageRecentLimit'] . "&type=1";
-		$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);
-			libxml_use_internal_errors(true);
-			if ($response->success) {
-				$items = array();
-				$plex = simplexml_load_string($response->body);
-				foreach ($plex as $child) {
-					if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
-						$items[] = $this->resolvePlexItem($child);
-					}
-				}
-				if (isset($api)) {
-					$api['content'] = array_merge($api['content'], ($resolve) ? $items : $plex);
-				} else {
-					$api['content'] = ($resolve) ? $items : $plex;
-				}
-			}
-		}
-		if (isset($api['content'])) {
-			usort($api['content'], function ($a, $b) {
-				return $b['addedAt'] <=> $a['addedAt'];
-			});
-		}
-		$api['plexID'] = $this->config['plexID'];
-		$api['showNames'] = true;
-		$api['group'] = '1';
-		$this->setAPIResponse('success', null, 200, $api);
-		return $api;
-	}
-	
-	public function getPlexHomepageMetadata($array)
-	{
-		if (!$this->config['homepagePlexEnabled']) {
-			$this->setAPIResponse('error', 'Plex homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepagePlexStreams']) {
-			$this->setAPIResponse('error', 'Plex homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexStreamsAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['plexURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexID'])) {
-			$this->setAPIResponse('error', 'Plex Id is not defined', 422);
-			return false;
-		}
-		$key = $array['key'] ?? null;
-		if (!$key) {
-			$this->setAPIResponse('error', 'Plex Metadata key is not defined', 422);
-			return false;
-		}
-		$ignore = array();
-		$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);
-		libxml_use_internal_errors(true);
-		if ($response->success) {
-			$items = array();
-			$plex = simplexml_load_string($response->body);
-			foreach ($plex as $child) {
-				if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
-					$items[] = $this->resolvePlexItem($child);
-				}
-			}
-			$api['content'] = ($resolve) ? $items : $plex;
-			$api['plexID'] = $this->config['plexID'];
-			$api['showNames'] = true;
-			$api['group'] = '1';
-			$this->setAPIResponse('success', null, 200, $api);
-			return $api;
-		}
-	}
-	
-	public function getPlexHomepagePlaylists()
-	{
-		if (!$this->config['homepagePlexEnabled']) {
-			$this->setAPIResponse('error', 'Plex homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepagePlexPlaylist']) {
-			$this->setAPIResponse('error', 'Plex homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexPlaylistAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['plexURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexID'])) {
-			$this->setAPIResponse('error', 'Plex Id is not defined', 422);
-			return false;
-		}
-		$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);
-		libxml_use_internal_errors(true);
-		if ($response->success) {
-			$items = array();
-			$plex = simplexml_load_string($response->body);
-			foreach ($plex as $child) {
-				if ($child['playlistType'] == "video" && strpos(strtolower($child['title']), 'private') === false) {
-					$playlistTitleClean = preg_replace("/(\W)+/", "", (string)$child['title']);
-					$playlistURL = $this->qualifyURL($this->config['plexURL']);
-					$playlistURL = $playlistURL . $child['key'] . "?X-Plex-Token=" . $this->config['plexToken'];
-					$options = ($this->localURL($url)) ? array('verify' => false) : array();
-					$playlistResponse = Requests::get($playlistURL, array(), $options);
-					if ($playlistResponse->success) {
-						$playlistResponse = simplexml_load_string($playlistResponse->body);
-						$items[$playlistTitleClean]['title'] = (string)$child['title'];
-						foreach ($playlistResponse->Video as $playlistItem) {
-							$items[$playlistTitleClean][] = $this->resolvePlexItem($playlistItem);
-						}
-					}
-				}
-			}
-			$api['content'] = $items;
-			$api['plexID'] = $this->config['plexID'];
-			$api['showNames'] = true;
-			$api['group'] = '1';
-			$this->setAPIResponse('success', null, 200, $api);
-			return $api;
-		} else {
-			$this->setAPIResponse('error', 'Plex API error', 500);
-			return false;
-		}
-		
-	}
-	
-	public function getPlexHomepageSearch($query)
-	{
-		if (!$this->config['homepagePlexEnabled']) {
-			$this->setAPIResponse('error', 'Plex homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagePlexAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['plexURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['plexID'])) {
-			$this->setAPIResponse('error', 'Plex Id is not defined', 422);
-			return false;
-		}
-		$query = $query ?? null;
-		if (!$query) {
-			$this->setAPIResponse('error', 'Plex Metadata key is not defined', 422);
-			return false;
-		}
-		$ignore = array('artist', 'episode');
-		$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);
-		libxml_use_internal_errors(true);
-		if ($response->success) {
-			$items = array();
-			$plex = simplexml_load_string($response->body);
-			foreach ($plex as $child) {
-				if (!in_array($child['type'], $ignore) && isset($child['librarySectionID'])) {
-					$items[] = $this->resolvePlexItem($child);
-				}
-			}
-			$api['content'] = ($resolve) ? $items : $plex;
-			$api['plexID'] = $this->config['plexID'];
-			$api['showNames'] = true;
-			$api['group'] = '1';
-			$this->setAPIResponse('success', null, 200, $api);
-			return $api;
-		}
-	}
 }

+ 43 - 9
api/homepage/qbittorrent.php

@@ -161,18 +161,52 @@ trait QBitTorrentHomepageItem
 		}
 	}
 	
-	public function getQBittorrentHomepageQueue()
+	public function qBittorrentHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageqBittorrentEnabled']) {
-			$this->setAPIResponse('error', 'qBittorrent homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageqBittorrentEnabled'
+				],
+				'auth' => [
+					'homepageqBittorrentAuth'
+				],
+				'not_empty' => [
+					'qBittorrentURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageqBittorrentAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrderqBittorrent()
+	{
+		if ($this->homepageItemPermissions($this->qBittorrentHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['qBittorrentCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['qBittorrentCombine']) ? 'buildDownloaderCombined(\'qBittorrent\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("qBittorrent"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrderqBittorrent
+		                ' . $builder . '
+		                homepageDownloader("qBittorrent", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrderqBittorrent
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['qBittorrentURL'])) {
-			$this->setAPIResponse('error', 'qBittorrent URL is not defined', 422);
+	}
+	
+	public function getQBittorrentHomepageQueue()
+	{
+		if (!$this->homepageItemPermissions($this->qBittorrentHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$digest = $this->qualifyURL($this->config['qBittorrentURL'], true);

+ 59 - 35
api/homepage/radarr.php

@@ -222,30 +222,67 @@ trait RadarrHomepageItem
 		}
 	}
 	
-	public function getRadarrQueue()
+	public function radarrHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageRadarrEnabled']) {
-			$this->setAPIResponse('error', 'Radarr homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageRadarrQueueEnabled']) {
-			$this->setAPIResponse('error', 'Radarr homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageRadarrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageRadarrQueueAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
+		$permissions = [
+			'calendar' => [
+				'enabled' => [
+					'homepageRadarrEnabled'
+				],
+				'auth' => [
+					'homepageRadarrAuth'
+				],
+				'not_empty' => [
+					'radarrURL',
+					'lidarrToken'
+				]
+			],
+			'queue' => [
+				'enabled' => [
+					'homepageRadarrEnabled',
+					'homepageRadarrQueueEnabled'
+				],
+				'auth' => [
+					'homepageRadarrAuth',
+					'homepageRadarrQueueAuth'
+				],
+				'not_empty' => [
+					'radarrURL',
+					'radarrToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['radarrURL'])) {
-			$this->setAPIResponse('error', 'Radarr URL is not defined', 422);
-			return false;
+	}
+	
+	public function homepageOrderRadarrQueue()
+	{
+		if ($this->homepageItemPermissions($this->radarrHomepagePermissions('queue'))) {
+			$loadingBox = ($this->config['homepageRadarrQueueCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['homepageRadarrQueueCombine']) ? 'buildDownloaderCombined(\'radarr\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("radarr"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrderRadarrQueue
+		                ' . $builder . '
+		                homepageDownloader("radarr", "' . $this->config['homepageRadarrQueueRefresh'] . '");
+		                // End homepageOrderRadarrQueue
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['radarrToken'])) {
-			$this->setAPIResponse('error', 'Radarr Token is not defined', 422);
+	}
+	
+	public function getRadarrQueue()
+	{
+		if (!$this->homepageItemPermissions($this->radarrHomepagePermissions('queue'), true)) {
 			return false;
 		}
 		$queueItems = array();
@@ -278,20 +315,7 @@ trait RadarrHomepageItem
 	{
 		$startDate = ($startDate) ?? $_GET['start'];
 		$endDate = ($endDate) ?? $_GET['end'];
-		if (!$this->config['homepageRadarrEnabled']) {
-			$this->setAPIResponse('error', 'Radarr homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageRadarrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['radarrURL'])) {
-			$this->setAPIResponse('error', 'Radarr URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['radarrToken'])) {
-			$this->setAPIResponse('error', 'Radarr Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->radarrHomepagePermissions('calendar'), true)) {
 			return false;
 		}
 		$calendarItems = array();

+ 44 - 8
api/homepage/rtorrent.php

@@ -188,6 +188,47 @@ trait RTorrentHomepageItem
 		}
 	}
 	
+	public function rTorrentHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepagerTorrentEnabled'
+				],
+				'auth' => [
+					'homepagerTorrentAuth'
+				],
+				'not_empty' => []
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderrTorrent()
+	{
+		if ($this->homepageItemPermissions($this->rTorrentHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['rTorrentCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['rTorrentCombine']) ? 'buildDownloaderCombined(\'rTorrent\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("rTorrent"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrderrTorrent
+		                ' . $builder . '
+		                homepageDownloader("rTorrent", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrderrTorrent
+	                </script>
+				</div>
+				';
+		}
+	}
+	
 	public function checkOverrideURL($url, $override)
 	{
 		if (strpos($override, $url) !== false) {
@@ -213,18 +254,13 @@ trait RTorrentHomepageItem
 	
 	public function getRTorrentHomepageQueue()
 	{
-		if (!$this->config['homepagerTorrentEnabled']) {
-			$this->setAPIResponse('error', 'rTorrent homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepagerTorrentAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
 		if (empty($this->config['rTorrentURL']) && empty($this->config['rTorrentURLOverride'])) {
 			$this->setAPIResponse('error', 'rTorrent URL is not defined', 422);
 			return false;
 		}
+		if (!$this->homepageItemPermissions($this->rTorrentHomepagePermissions('main'), true)) {
+			return false;
+		}
 		try {
 			if ($this->config['rTorrentLimit'] == '0') {
 				$this->config['rTorrentLimit'] = '1000';

+ 46 - 41
api/homepage/sabnzbd.php

@@ -97,22 +97,53 @@ trait SabNZBdHomepageItem
 		}
 	}
 	
-	public function getSabNZBdHomepageQueue()
+	public function sabNZBdHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageSabnzbdEnabled']) {
-			$this->setAPIResponse('error', 'SabNZBd homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSabnzbdAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageSabnzbdEnabled'
+				],
+				'auth' => [
+					'homepageSabnzbdAuth'
+				],
+				'not_empty' => [
+					'sabnzbdURL',
+					'sabnzbdToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['sabnzbdURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
+	}
+	
+	public function homepageOrdersabnzbd()
+	{
+		if ($this->homepageItemPermissions($this->sabNZBdHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['sabnzbdCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['sabnzbdCombine']) ? 'buildDownloaderCombined(\'sabnzbd\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("sabnzbd"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrdersabnzbd
+		                ' . $builder . '
+		                homepageDownloader("sabnzbd", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrdersabnzbd
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['sabnzbdToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
+	}
+	
+	public function getSabNZBdHomepageQueue()
+	{
+		if (!$this->homepageItemPermissions($this->sabNZBdHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['sabnzbdURL']);
@@ -148,20 +179,7 @@ trait SabNZBdHomepageItem
 	
 	public function pauseSabNZBdQueue($target = null)
 	{
-		if (!$this->config['homepageSabnzbdEnabled']) {
-			$this->setAPIResponse('error', 'SabNZBd homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSabnzbdAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['sabnzbdURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['sabnzbdToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->sabNZBdHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['sabnzbdURL']);
@@ -185,20 +203,7 @@ trait SabNZBdHomepageItem
 	
 	public function resumeSabNZBdQueue($target = null)
 	{
-		if (!$this->config['homepageSabnzbdEnabled']) {
-			$this->setAPIResponse('error', 'SabNZBd homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSabnzbdAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['sabnzbdURL'])) {
-			$this->setAPIResponse('error', 'Plex URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['sabnzbdToken'])) {
-			$this->setAPIResponse('error', 'Plex Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->sabNZBdHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$url = $this->qualifyURL($this->config['sabnzbdURL']);

+ 25 - 18
api/homepage/sickrage.php

@@ -150,27 +150,34 @@ trait SickRageHomepageItem
 		}
 	}
 	
+	public function sickrageHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'calendar' => [
+				'enabled' => [
+					'homepageSickrageEnabled'
+				],
+				'auth' => [
+					'homepageSickrageAuth'
+				],
+				'not_empty' => [
+					'sickrageURL',
+					'sickrageToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
 	
 	public function getSickRageCalendar($startDate = null, $endDate = null)
 	{
-		if (!$this->config['homepageSickrageEnabled']) {
-			$this->setAPIResponse('error', 'SickRage homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSickrageAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageRadarrQueueAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
-		}
-		if (empty($this->config['sickrageURL'])) {
-			$this->setAPIResponse('error', 'SickRage URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['sickrageToken'])) {
-			$this->setAPIResponse('error', 'SickRage Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->sickrageHomepagePermissions('calendar'), true)) {
 			return false;
 		}
 		$calendarItems = array();

+ 59 - 35
api/homepage/sonarr.php

@@ -228,30 +228,67 @@ trait SonarrHomepageItem
 		}
 	}
 	
-	public function getSonarrQueue()
+	public function sonarrHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageSonarrEnabled']) {
-			$this->setAPIResponse('error', 'Sonarr homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->config['homepageSonarrQueueEnabled']) {
-			$this->setAPIResponse('error', 'Sonarr homepage module is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSonarrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSonarrQueueAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage module', 401);
-			return false;
+		$permissions = [
+			'calendar' => [
+				'enabled' => [
+					'homepageSonarrEnabled'
+				],
+				'auth' => [
+					'homepageSonarrAuth'
+				],
+				'not_empty' => [
+					'sonarrURL',
+					'sonarrToken'
+				]
+			],
+			'queue' => [
+				'enabled' => [
+					'homepageSonarrEnabled',
+					'homepageSonarrQueueEnabled'
+				],
+				'auth' => [
+					'homepageSonarrAuth',
+					'homepageSonarrQueueAuth'
+				],
+				'not_empty' => [
+					'sonarrURL',
+					'sonarrToken'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['sonarrURL'])) {
-			$this->setAPIResponse('error', 'Sonarr URL is not defined', 422);
-			return false;
+	}
+	
+	public function homepageOrderSonarrQueue()
+	{
+		if ($this->homepageItemPermissions($this->sonarrHomepagePermissions('queue'))) {
+			$loadingBox = ($this->config['homepageSonarrQueueCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['homepageSonarrQueueCombine']) ? 'buildDownloaderCombined(\'sonarr\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("sonarr"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrderSonarrQueue
+		                ' . $builder . '
+		                homepageDownloader("sonarr", "' . $this->config['homepageSonarrQueueRefresh'] . '");
+		                // End homepageOrderSonarrQueue
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['sonarrToken'])) {
-			$this->setAPIResponse('error', 'Sonarr Token is not defined', 422);
+	}
+	
+	public function getSonarrQueue()
+	{
+		if (!$this->homepageItemPermissions($this->sonarrHomepagePermissions('queue'), true)) {
 			return false;
 		}
 		$queueItems = array();
@@ -284,20 +321,7 @@ trait SonarrHomepageItem
 	{
 		$startDate = ($startDate) ?? $_GET['start'];
 		$endDate = ($endDate) ?? $_GET['end'];
-		if (!$this->config['homepageSonarrEnabled']) {
-			$this->setAPIResponse('error', 'Sonarr homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageSonarrAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['sonarrURL'])) {
-			$this->setAPIResponse('error', 'Sonarr URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['sonarrToken'])) {
-			$this->setAPIResponse('error', 'Sonarr Token is not defined', 422);
+		if (!$this->homepageItemPermissions($this->sonarrHomepagePermissions('calendar'), true)) {
 			return false;
 		}
 		$calendarItems = array();

+ 40 - 13
api/homepage/speedtest.php

@@ -60,18 +60,49 @@ trait SpeedTestHomepageItem
 		);
 	}
 	
-	public function getSpeedtestHomepageData()
+	public function speedTestHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageSpeedtestEnabled']) {
-			$this->setAPIResponse('error', 'SpeedTest homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageSpeedtestEnabled'
+				],
+				'auth' => [
+					'homepageSpeedtestAuth'
+				],
+				'not_empty' => [
+					'speedtestURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageSpeedtestAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrderSpeedtest()
+	{
+		if ($this->homepageItemPermissions($this->speedTestHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Speedtest...</h2></div>
+					<script>
+						// Speedtest
+						homepageSpeedtest("' . $this->config['homepageSpeedtestRefresh'] . '");
+						// End Speedtest
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['speedtestURL'])) {
-			$this->setAPIResponse('error', 'SpeedTest URL is not defined', 422);
+	}
+	
+	public function getSpeedtestHomepageData()
+	{
+		if (!$this->homepageItemPermissions($this->speedTestHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api = [];
@@ -81,18 +112,15 @@ trait SpeedTestHomepageItem
 			$response = Requests::get($dataUrl);
 			if ($response->success) {
 				$json = json_decode($response->body, true);
-
 				$api['data'] = [
 					'current' => $json['data'],
 				];
-
 				$keys = [
 					'average',
 					'max',
 					'maximum',
 					'minimum'
 				];
-
 				foreach ($keys as $key) {
 					if (array_key_exists($key, $json)) {
 						if ($key == 'max') {
@@ -102,7 +130,6 @@ trait SpeedTestHomepageItem
 						}
 					}
 				}
-
 				$api['options'] = [
 					'title' => $this->config['speedtestHeader'],
 					'titleToggle' => $this->config['speedtestHeaderToggle'],

+ 41 - 13
api/homepage/tautulli.php

@@ -187,22 +187,50 @@ trait TautulliHomepageItem
 		}
 	}
 	
-	public function getTautulliHomepageData()
+	public function tautulliHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageTautulliEnabled']) {
-			$this->setAPIResponse('error', 'Tautulli homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageTautulliAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageTautulliEnabled'
+				],
+				'auth' => [
+					'homepageTautulliAuth'
+				],
+				'not_empty' => [
+					'tautulliURL',
+					'tautulliApikey'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (empty($this->config['tautulliURL'])) {
-			$this->setAPIResponse('error', 'Tautulli URL is not defined', 422);
-			return false;
+	}
+	
+	public function homepageOrdertautulli()
+	{
+		if ($this->homepageItemPermissions($this->tautulliHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Tautulli...</h2></div>
+					<script>
+						// Tautulli
+						homepageTautulli("' . $this->config['homepageTautulliRefresh'] . '");
+						// End Tautulli
+					</script>
+				</div>
+				';
 		}
-		if (empty($this->config['tautulliApikey'])) {
-			$this->setAPIResponse('error', 'Tautulli Token is not defined', 422);
+	}
+	
+	public function getTautulliHomepageData()
+	{
+		if (!$this->homepageItemPermissions($this->tautulliHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api = [];

+ 43 - 9
api/homepage/transmission.php

@@ -137,18 +137,52 @@ trait TransmissionHomepageItem
 		}
 	}
 	
-	public function getTransmissionHomepageQueue()
+	public function transmissionHomepagePermissions($key = null)
 	{
-		if (!$this->config['homepageTransmissionEnabled']) {
-			$this->setAPIResponse('error', 'Transmission homepage item is not enabled', 409);
-			return false;
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageTransmissionEnabled'
+				],
+				'auth' => [
+					'homepageTransmissionAuth'
+				],
+				'not_empty' => [
+					'transmissionURL'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
 		}
-		if (!$this->qualifyRequest($this->config['homepageTransmissionAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
+	}
+	
+	public function homepageOrdertransmission()
+	{
+		if ($this->homepageItemPermissions($this->transmissionHomepagePermissions('main'))) {
+			$loadingBox = ($this->config['transmissionCombine']) ? '' : '<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Download Queue...</h2></div>';
+			$builder = ($this->config['transmissionCombine']) ? 'buildDownloaderCombined(\'transmission\');' : '$("#' . __FUNCTION__ . '").html(buildDownloader("transmission"));';
+			return '
+				<div id="' . __FUNCTION__ . '">
+					' . $loadingBox . '
+					<script>
+		                // homepageOrdertransmission
+		                ' . $builder . '
+		                homepageDownloader("transmission", "' . $this->config['homepageDownloadRefresh'] . '");
+		                // End homepageOrdertransmission
+	                </script>
+				</div>
+				';
 		}
-		if (empty($this->config['transmissionURL'])) {
-			$this->setAPIResponse('error', 'Transmission URL is not defined', 422);
+	}
+	
+	public function getTransmissionHomepageQueue()
+	{
+		if (!$this->homepageItemPermissions($this->transmissionHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$digest = $this->qualifyURL($this->config['transmissionURL'], true);

+ 43 - 18
api/homepage/unifi.php

@@ -93,6 +93,48 @@ trait UnifiHomepageItem
 		);
 	}
 	
+	public function unifiHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageUnifiEnabled'
+				],
+				'auth' => [
+					'homepageUnifiAuth'
+				],
+				'not_empty' => [
+					'unifiURL',
+					'unifiUsername',
+					'unifiPassword'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderunifi()
+	{
+		if ($this->homepageItemPermissions($this->unifiHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Unifi...</h2></div>
+					<script>
+						// Unifi
+						homepageUnifi("' . $this->config['homepageHealthChecksRefresh'] . '");
+						// End Unifi
+					</script>
+				</div>
+				';
+		}
+	}
+	
 	public function getUnifiSiteName()
 	{
 		if (empty($this->config['unifiURL'])) {
@@ -212,24 +254,7 @@ trait UnifiHomepageItem
 	
 	public function getUnifiHomepageData()
 	{
-		if (!$this->config['homepageUnifiEnabled']) {
-			$this->setAPIResponse('error', 'Unifi homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageUnifiAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['unifiURL'])) {
-			$this->setAPIResponse('error', 'Unifi URL is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['unifiUsername'])) {
-			$this->setAPIResponse('error', 'Unifi Username is not defined', 422);
-			return false;
-		}
-		if (empty($this->config['unifiPassword'])) {
-			$this->setAPIResponse('error', 'Unifi Password is not defined', 422);
+		if (!$this->homepageItemPermissions($this->unifiHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api['content']['unifi'] = array();

+ 42 - 10
api/homepage/weather.php

@@ -117,6 +117,47 @@ trait WeatherHomepageItem
 		);
 	}
 	
+	public function weatherHomepagePermissions($key = null)
+	{
+		$permissions = [
+			'main' => [
+				'enabled' => [
+					'homepageWeatherAndAirEnabled'
+				],
+				'auth' => [
+					'homepageWeatherAndAirAuth'
+				],
+				'not_empty' => [
+					'homepageWeatherAndAirLatitude',
+					'homepageWeatherAndAirLongitude'
+				]
+			]
+		];
+		if (array_key_exists($key, $permissions)) {
+			return $permissions[$key];
+		} elseif ($key == 'all') {
+			return $permissions;
+		} else {
+			return [];
+		}
+	}
+	
+	public function homepageOrderWeatherAndAir()
+	{
+		if ($this->homepageItemPermissions($this->weatherHomepagePermissions('main'))) {
+			return '
+				<div id="' . __FUNCTION__ . '">
+					<div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Weather...</h2></div>
+					<script>
+						// Weather And Air
+						homepageWeatherAndAir("' . $this->config['homepageWeatherAndAirRefresh'] . '");
+						// End Weather And Air
+					</script>
+				</div>
+				';
+		}
+	}
+	
 	public function searchCityForCoordinates($query)
 	{
 		try {
@@ -140,16 +181,7 @@ trait WeatherHomepageItem
 	
 	public function getWeatherAndAirData()
 	{
-		if (!$this->config['homepageWeatherAndAirEnabled']) {
-			$this->setAPIResponse('error', 'Weather homepage item is not enabled', 409);
-			return false;
-		}
-		if (!$this->qualifyRequest($this->config['homepageWeatherAndAirAuth'])) {
-			$this->setAPIResponse('error', 'User not approved to view this homepage item', 401);
-			return false;
-		}
-		if (empty($this->config['homepageWeatherAndAirLatitude']) && empty($this->config['homepageWeatherAndAirLongitude'])) {
-			$this->setAPIResponse('error', 'Weather Latitude and/or Longitude were not defined', 422);
+		if (!$this->homepageItemPermissions($this->weatherHomepagePermissions('main'), true)) {
 			return false;
 		}
 		$api['content'] = array(