'Plex',
'enabled' => strpos('personal', $this->config['license']) !== false,
'image' => 'plugins/images/tabs/plex.png',
'category' => 'Media Server',
'settingsArray' => __FUNCTION__
];
if ($infoOnly) {
return $homepageInformation;
}
$libraryList = [['name' => 'Refresh page to update List', 'value' => '', 'disabled' => true]];
if ($this->config['plexID'] !== '' && $this->config['plexToken'] !== '') {
$loop = $this->plexLibraryList('key');
if ($loop) {
$loop = $loop['libraries'];
foreach ($loop as $key => $value) {
$libraryList[] = ['name' => $key, 'value' => $value];
}
}
}
$homepageSettings = [
'docs' => $this->docs('features/homepage/plex-homepage-item'),
'debug' => true,
'settings' => [
'Enable' => [
$this->settingsOption('enable', 'homepagePlexEnabled'),
$this->settingsOption('auth', 'homepagePlexAuth'),
],
'Connection' => [
$this->settingsOption('url', 'plexURL'),
$this->settingsOption('blank'),
$this->settingsOption('disable-cert-check', 'plexDisableCertCheck'),
$this->settingsOption('use-custom-certificate', 'plexUseCustomCertificate'),
$this->settingsOption('token', 'plexToken'),
$this->settingsOption('button', '', ['label' => 'Get Plex Token', 'icon' => 'fa fa-ticket', 'text' => 'Retrieve', 'attr' => 'onclick="PlexOAuth(oAuthSuccess,oAuthError, null, \'#homepage-Plex-form [name=plexToken]\')"']),
$this->settingsOption('password-alt', 'plexID', ['label' => 'Plex Machine']),
$this->settingsOption('button', '', ['label' => 'Get Plex Machine', 'icon' => 'fa fa-id-badge', 'text' => 'Retrieve', 'attr' => 'onclick="showPlexMachineForm(\'#homepage-Plex-form [name=plexID]\')"']),
],
'Active Streams' => [
$this->settingsOption('enable', 'homepagePlexStreams'),
$this->settingsOption('auth', 'homepagePlexStreamsAuth'),
$this->settingsOption('switch', 'homepageShowStreamNames', ['label' => 'User Information', 'help' => 'Show user and IP information']),
$this->settingsOption('auth', 'homepageShowStreamNamesAuth'),
$this->settingsOption('switch', 'homepageShowStreamNamesWithoutIp', ['label' => 'User Information Without IP', 'help' => 'Only shows username and no IP information']),
$this->settingsOption('auth', 'homepageShowStreamNamesWithoutIpAuth'),
$this->settingsOption('refresh', 'homepageStreamRefresh'),
$this->settingsOption('plex-library-exclude', 'homepagePlexStreamsExclude', ['options' => $libraryList]),
],
'Recent Items' => [
$this->settingsOption('enable', 'homepagePlexRecent'),
$this->settingsOption('auth', 'homepagePlexRecentAuth'),
$this->settingsOption('plex-library-exclude', 'homepagePlexRecentExclude', ['options' => $libraryList]),
$this->settingsOption('limit', 'homepageRecentLimit'),
$this->settingsOption('refresh', 'homepageRecentRefresh'),
],
'Media Search' => [
$this->settingsOption('enable', 'mediaSearch'),
$this->settingsOption('auth', 'mediaSearchAuth'),
$this->settingsOption('plex-library-exclude', 'homepagePlexSearchExclude', ['options' => $libraryList]),
$this->settingsOption('media-search-server', 'mediaSearchType'),
],
'Playlists' => [
$this->settingsOption('enable', 'homepagePlexPlaylist'),
$this->settingsOption('auth', 'homepagePlexPlaylistAuth'),
],
'Misc Options' => [
$this->settingsOption('input', 'plexTabName', ['label' => 'Plex Tab Name', 'placeholder' => 'Only use if you have Plex in a reverse proxy']),
$this->settingsOption('input', 'plexTabURL', ['label' => 'Plex Tab WAN URL', 'placeholder' => 'http(s)://domain.com/plex']),
$this->settingsOption('image-cache-quality', 'cacheImageSize'),
$this->settingsOption('blank'),
$this->settingsOption('switch', 'homepageUseCustomStreamNames', ['label' => 'Use Tautulli custom names for users']),
],
'Test Connection' => [
$this->settingsOption('blank', null, ['label' => 'Please Save before Testing']),
$this->settingsOption('test', 'plex'),
]
]
];
return array_merge($homepageInformation, $homepageSettings);
}
public function testConnectionPlex()
{
if (!empty($this->config['plexURL']) && !empty($this->config['plexToken'])) {
$url = $this->qualifyURL($this->config['plexURL']) . "/servers?X-Plex-Token=" . $this->config['plexToken'];
try {
$options = $this->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
$response = Requests::get($url, [], $options);
libxml_use_internal_errors(true);
if ($response->success) {
$this->setAPIResponse('success', 'API Connection succeeded', 200);
return true;
} else {
$this->setAPIResponse('error', 'URL and/or Token not setup correctly', 422);
return false;
}
} catch (Requests_Exception $e) {
$this->setResponse(500, $e->getMessage());
return false;
}
} else {
$this->setAPIResponse('error', 'URL and/or Token not setup', 422);
return 'URL and/or Token not setup';
}
}
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'
]
]
];
return $this->homepageCheckKeyPermissions($key, $permissions);
}
public function homepageOrderplexnowplaying()
{
if ($this->homepageItemPermissions($this->plexHomepagePermissions('streams'))) {
return '
';
}
}
public function homepageOrderplexrecent()
{
if ($this->homepageItemPermissions($this->plexHomepagePermissions('recent'))) {
return '
';
}
}
public function homepageOrderplexplaylist()
{
if ($this->homepageItemPermissions($this->plexHomepagePermissions('playlists'))) {
return '
';
}
}
public function getPlexHomepageStreams()
{
if (!$this->homepageItemPermissions($this->plexHomepagePermissions('streams'), true)) {
return false;
}
if ($this->demo) {
return $this->demoData('plex/plex-streams.json');
}
$this->setTautulliFriendlyNames();
$ignore = array();
$exclude = explode(',', $this->config['homepagePlexStreamsExclude']);
$resolve = true;
$url = $this->qualifyURL($this->config['plexURL']);
$url = $url . "/status/sessions?X-Plex-Token=" . $this->config['plexToken'];
$options = $this->requestOptions($url, $this->config['homepageStreamRefresh'], $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
try {
$response = Requests::get($url, [], $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) && !in_array($child['librarySectionID'], $exclude) && 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;
} else {
$this->setAPIResponse('error', null, 401, []);
return [];
}
} catch (Exception $e) {
$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
return false;
}
}
public function getPlexHomepageRecent()
{
if (!$this->homepageItemPermissions($this->plexHomepagePermissions('recent'), true)) {
return false;
}
$ignore = array();
$exclude = explode(',', $this->config['homepagePlexRecentExclude']);
$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";
try {
foreach ($urls as $k => $v) {
$options = $this->requestOptions($url, $this->config['homepageRecentRefresh'], $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
$response = Requests::get($v, [], $options);
libxml_use_internal_errors(true);
if ($response->success) {
$items = array();
$plex = simplexml_load_string($response->body);
foreach ($plex as $child) {
if (!in_array($child['type'], $ignore) && !in_array($child['librarySectionID'], $exclude) && 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;
} catch (Exception $e) {
$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
return false;
}
}
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->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
try {
$response = Requests::get($url, [], $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;
}
} catch (Exception $e) {
$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
return false;
}
}
public function getPlexHomepageMetadata($array)
{
if (!$this->homepageItemPermissions($this->plexHomepagePermissions('metadata'), true)) {
return false;
}
if ($this->demo) {
return $this->demoData('plex/plex-metadata.json');
}
$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->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
try {
$response = Requests::get($url, [], $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;
}
} catch (Exception $e) {
$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
return false;
}
}
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');
$exclude = explode(',', $this->config['homepagePlexSearchExclude']);
$resolve = true;
$url = $this->qualifyURL($this->config['plexURL']);
$url = $url . "/search?query=" . rawurlencode($query) . "&X-Plex-Token=" . $this->config['plexToken'];
$options = $this->requestOptions($url, null, $this->config['plexDisableCertCheck'], $this->config['plexUseCustomCertificate']);
try {
$response = Requests::get($url, [], $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) && !in_array($child['librarySectionID'], $exclude) && 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;
}
} catch (Exception $e) {
$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
return false;
}
}
public function resolvePlexItem($item)
{
// Static Height & Width
$height = $this->getCacheImageSize('h');
$width = $this->getCacheImageSize('w');
$nowPlayingHeight = $this->getCacheImageSize('nph');
$nowPlayingWidth = $this->getCacheImageSize('npw');
// Cache Directories
$cacheDirectory = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
$cacheDirectoryWeb = 'data/cache/';
// Types
switch ($item['type']) {
case 'show':
$plexItem['type'] = 'tv';
$plexItem['title'] = (string)$item['title'];
$plexItem['secondaryTitle'] = (string)$item['year'];
$plexItem['summary'] = (string)$item['summary'];
$plexItem['ratingKey'] = (string)$item['ratingKey'];
$plexItem['thumb'] = (string)$item['thumb'];
$plexItem['key'] = (string)$item['ratingKey'] . "-list";
$plexItem['nowPlayingThumb'] = (string)$item['art'];
$plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
$plexItem['nowPlayingTitle'] = (string)$item['title'];
$plexItem['nowPlayingBottom'] = (string)$item['year'];
$plexItem['metadataKey'] = (string)$item['ratingKey'];
break;
case 'season':
$plexItem['type'] = 'tv';
$plexItem['title'] = (string)$item['parentTitle'];
$plexItem['secondaryTitle'] = (string)$item['title'];
$plexItem['summary'] = (string)$item['parentSummary'];
$plexItem['ratingKey'] = (string)$item['parentRatingKey'];
$plexItem['thumb'] = (string)$item['thumb'];
$plexItem['key'] = (string)$item['ratingKey'] . "-list";
$plexItem['nowPlayingThumb'] = (string)$item['art'];
$plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
$plexItem['metadataKey'] = (string)$item['parentRatingKey'];
break;
case 'episode':
$useImage = (isset($item['live']) ? 'plugins/images/homepage/livetv.png' : null);
$plexItem['type'] = 'tv';
$plexItem['title'] = (string)$item['grandparentTitle'];
$plexItem['secondaryTitle'] = (string)$item['parentTitle'] . ' - Episode ' . (string)$item['index'];
$plexItem['summary'] = (string)$item['title'];
$plexItem['ratingKey'] = (string)($item['parentRatingKey'] ?? $item['ratingKey']);
$plexItem['thumb'] = ($item['parentThumb'] ? (string)$item['parentThumb'] : (string)$item['grandparentThumb']);
$plexItem['key'] = (string)$item['ratingKey'] . "-list";
$plexItem['nowPlayingThumb'] = (string)$item['grandparentArt'];
$plexItem['nowPlayingKey'] = (string)$item['grandparentRatingKey'] . "-np";
$plexItem['nowPlayingTitle'] = (string)$item['grandparentTitle'] . ' - ' . (string)$item['title'];
$plexItem['nowPlayingBottom'] = 'S' . (string)$item['parentIndex'] . ' ยท E' . (string)$item['index'];
$plexItem['metadataKey'] = (string)($item['grandparentRatingKey'] ?? $item['parentRatingKey'] ?? $item['ratingKey']);
break;
case 'clip':
$useImage = (isset($item['live']) ? "plugins/images/homepage/livetv.png" : null);
$plexItem['type'] = 'clip';
$plexItem['title'] = (isset($item['live']) ? 'Live TV' : (string)$item['title']);
$plexItem['secondaryTitle'] = '';
$plexItem['summary'] = (string)$item['summary'];
$plexItem['ratingKey'] = (string)$item['parentRatingKey'];
$plexItem['thumb'] = (string)$item['thumb'];
$plexItem['key'] = (string)$item['ratingKey'] . "-list";
$plexItem['nowPlayingThumb'] = (string)$item['art'];
$plexItem['nowPlayingKey'] = isset($item['ratingKey']) ? (string)$item['ratingKey'] . "-np" : (isset($item['live']) ? "livetv.png" : ":)");
$plexItem['nowPlayingTitle'] = $plexItem['title'];
$plexItem['nowPlayingBottom'] = isset($item['extraType']) ? "Trailer" : (isset($item['live']) ? "Live TV" : ":)");
break;
case 'album':
case 'track':
$plexItem['type'] = 'music';
$plexItem['title'] = (string)$item['parentTitle'];
$plexItem['secondaryTitle'] = (string)$item['title'];
$plexItem['summary'] = (string)$item['title'];
$plexItem['ratingKey'] = (string)$item['parentRatingKey'];
$plexItem['thumb'] = (string)$item['thumb'];
$plexItem['key'] = (string)$item['ratingKey'] . "-list";
$plexItem['nowPlayingThumb'] = ($item['parentThumb']) ? (string)$item['parentThumb'] : (string)$item['art'];
$plexItem['nowPlayingKey'] = (string)$item['parentRatingKey'] . "-np";
$plexItem['nowPlayingTitle'] = (string)$item['grandparentTitle'] . ' - ' . (string)$item['title'];
$plexItem['nowPlayingBottom'] = (string)$item['parentTitle'];
$plexItem['metadataKey'] = isset($item['grandparentRatingKey']) ? (string)$item['grandparentRatingKey'] : (string)$item['parentRatingKey'];
break;
default:
$useImage = (isset($item['live']) ? 'plugins/images/homepage/livetv.png' : null);
$plexItem['type'] = 'movie';
$plexItem['title'] = (string)$item['title'];
$plexItem['secondaryTitle'] = (string)$item['year'];
$plexItem['summary'] = (string)$item['summary'];
$plexItem['ratingKey'] = (string)$item['ratingKey'];
$plexItem['thumb'] = (string)$item['thumb'];
$plexItem['key'] = (string)$item['ratingKey'] . "-list";
$plexItem['nowPlayingThumb'] = (string)$item['art'];
$plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
$plexItem['nowPlayingTitle'] = (string)$item['title'];
$plexItem['nowPlayingBottom'] = (string)$item['year'];
$plexItem['metadataKey'] = (string)$item['ratingKey'];
}
$plexItem['originalType'] = $item['type'];
$plexItem['uid'] = (string)$item['ratingKey'];
$plexItem['elapsed'] = isset($item['viewOffset']) && $item['viewOffset'] !== '0' ? (int)$item['viewOffset'] : null;
$plexItem['duration'] = isset($item['duration']) ? (int)$item['duration'] : (int)$item->Media['duration'];
$plexItem['addedAt'] = isset($item['addedAt']) ? (int)$item['addedAt'] : null;
$plexItem['watched'] = ($plexItem['elapsed'] && $plexItem['duration'] ? floor(($plexItem['elapsed'] / $plexItem['duration']) * 100) : 0);
$plexItem['transcoded'] = isset($item->TranscodeSession['progress']) ? floor((int)$item->TranscodeSession['progress'] - $plexItem['watched']) : '';
$plexItem['stream'] = isset($item->Media->Part->Stream['decision']) ? (string)$item->Media->Part->Stream['decision'] : '';
$plexItem['id'] = str_replace('"', '', (string)$item->Player['machineIdentifier']);
$plexItem['session'] = (string)$item->Session['id'];
$plexItem['bandwidth'] = (string)$item->Session['bandwidth'];
$plexItem['bandwidthType'] = (string)$item->Session['location'];
$plexItem['sessionType'] = isset($item->TranscodeSession['progress']) ? 'Transcoding' : 'Direct Playing';
$plexItem['state'] = (((string)$item->Player['state'] == "paused") ? "pause" : "play");
$plexItem['user'] = $this->formatPlexUserName($item);
$plexItem['userThumb'] = (($this->config['homepageShowStreamNames'] && $this->qualifyRequest($this->config['homepageShowStreamNamesAuth'])) || ($this->config['homepageShowStreamNamesWithoutIp'] && $this->qualifyRequest($this->config['homepageShowStreamNamesWithoutIpAuth']))) ? (string)$item->User['thumb'] : "";
$plexItem['userAddress'] = ($this->config['homepageShowStreamNames'] && $this->qualifyRequest($this->config['homepageShowStreamNamesAuth'])) ? (string)$item->Player['address'] : "x.x.x.x";
$plexItem['address'] = $this->config['plexTabURL'] ? $this->config['plexTabURL'] . "/web/index.html#!/server/" . $this->config['plexID'] . "/details?key=/library/metadata/" . $item['ratingKey'] : "https://app.plex.tv/web/app#!/server/" . $this->config['plexID'] . "/details?key=/library/metadata/" . $item['ratingKey'];
$plexItem['nowPlayingOriginalImage'] = 'api/v2/homepage/image?source=plex&img=' . $plexItem['nowPlayingThumb'] . '&height=' . $nowPlayingHeight . '&width=' . $nowPlayingWidth . '&key=' . $plexItem['nowPlayingKey'] . '$' . $this->randString();
$plexItem['originalImage'] = 'api/v2/homepage/image?source=plex&img=' . $plexItem['thumb'] . '&height=' . $height . '&width=' . $width . '&key=' . $plexItem['key'] . '$' . $this->randString();
$plexItem['openTab'] = $this->config['plexTabURL'] && $this->config['plexTabName'] ? true : false;
$plexItem['tabName'] = $this->config['plexTabName'] ? $this->config['plexTabName'] : '';
// Stream info
$plexItem['userStream'] = array(
'platform' => (string)$item->Player['platform'],
'product' => (string)$item->Player['product'],
'device' => (string)$item->Player['device'],
'stream' => isset($item->Media) ? (string)$item->Media->Part['decision'] . ($item->TranscodeSession['throttled'] == '1' ? ' (Throttled)' : '') : '',
'videoResolution' => (string)$item->Media['videoResolution'],
'throttled' => ($item->TranscodeSession['throttled'] == 1) ? true : false,
'sourceVideoCodec' => (string)$item->TranscodeSession['sourceVideoCodec'],
'videoCodec' => (string)$item->TranscodeSession['videoCodec'],
'audioCodec' => (string)$item->TranscodeSession['audioCodec'],
'sourceAudioCodec' => (string)$item->TranscodeSession['sourceAudioCodec'],
'videoDecision' => $this->streamType((string)$item->TranscodeSession['videoDecision']),
'audioDecision' => $this->streamType((string)$item->TranscodeSession['audioDecision']),
'container' => (string)$item->TranscodeSession['container'],
'audioChannels' => (string)$item->TranscodeSession['audioChannels']
);
// Genre catch all
if ($item->Genre) {
$genres = array();
foreach ($item->Genre as $key => $value) {
$genres[] = (string)$value['tag'];
}
}
// Actor catch all
if ($item->Role) {
$actors = array();
foreach ($item->Role as $key => $value) {
if ($value['thumb']) {
$actors[] = array(
'name' => (string)$value['tag'],
'role' => (string)$value['role'],
'thumb' => (string)$value['thumb']
);
}
}
}
// Metadata information
$plexItem['metadata'] = array(
'guid' => (string)$item['guid'],
'summary' => (string)$item['summary'],
'rating' => (string)$item['rating'],
'duration' => (string)$item['duration'],
'originallyAvailableAt' => (string)$item['originallyAvailableAt'],
'year' => (string)$item['year'],
'studio' => (string)$item['studio'],
'tagline' => (string)$item['tagline'],
'genres' => ($item->Genre) ? $genres : '',
'actors' => ($item->Role) ? $actors : ''
);
if (file_exists($cacheDirectory . $plexItem['nowPlayingKey'] . '.jpg')) {
$plexItem['nowPlayingImageURL'] = $cacheDirectoryWeb . $plexItem['nowPlayingKey'] . '.jpg';
}
if (file_exists($cacheDirectory . $plexItem['key'] . '.jpg')) {
$plexItem['imageURL'] = $cacheDirectoryWeb . $plexItem['key'] . '.jpg';
}
if (file_exists($cacheDirectory . $plexItem['nowPlayingKey'] . '.jpg') && (time() - 604800) > filemtime($cacheDirectory . $plexItem['nowPlayingKey'] . '.jpg') || !file_exists($cacheDirectory . $plexItem['nowPlayingKey'] . '.jpg')) {
$plexItem['nowPlayingImageURL'] = 'api/v2/homepage/image?source=plex&img=' . $plexItem['nowPlayingThumb'] . '&height=' . $nowPlayingHeight . '&width=' . $nowPlayingWidth . '&key=' . $plexItem['nowPlayingKey'] . '';
}
if (file_exists($cacheDirectory . $plexItem['key'] . '.jpg') && (time() - 604800) > filemtime($cacheDirectory . $plexItem['key'] . '.jpg') || !file_exists($cacheDirectory . $plexItem['key'] . '.jpg')) {
$plexItem['imageURL'] = 'api/v2/homepage/image?source=plex&img=' . $plexItem['thumb'] . '&height=' . $height . '&width=' . $width . '&key=' . $plexItem['key'] . '';
}
if (!$plexItem['nowPlayingThumb']) {
$plexItem['nowPlayingOriginalImage'] = $plexItem['nowPlayingImageURL'] = "plugins/images/homepage/no-np.png";
$plexItem['nowPlayingKey'] = "no-np";
}
if (!$plexItem['thumb'] || $plexItem['addedAt'] >= (time() - 300)) {
$plexItem['originalImage'] = $plexItem['imageURL'] = "plugins/images/homepage/no-list.png";
$plexItem['key'] = "no-list";
}
if (isset($useImage)) {
$plexItem['useImage'] = $useImage;
}
return $plexItem;
}
public function getTautulliFriendlyNames($bypass = null)
{
$names = [];
if (!$this->qualifyRequest(1) && !$bypass) {
return false;
}
$url = $this->qualifyURL($this->config['tautulliURL']);
$url .= '/api/v2?apikey=' . $this->config['tautulliApikey'];
$url .= '&cmd=get_users';
$options = $this->requestOptions($url, null, $this->config['tautulliDisableCertCheck'], $this->config['tautulliUseCustomCertificate']);
try {
$response = Requests::get($url, [], $options);
if ($response->success) {
$response = json_decode($response->body, true);
foreach ($response['response']['data'] as $user) {
if ($user['user_id'] != 0) {
$names[$user['username']] = $user['friendly_name'];
}
}
}
} catch (Exception $e) {
$this->setAPIResponse('error', null, 422, [$e->getMessage()]);
}
$this->setAPIResponse('success', null, 200, $names);
return $names;
}
public function setTautulliFriendlyNames()
{
if ($this->config['tautulliURL'] && $this->config['tautulliApikey'] && $this->config['homepageUseCustomStreamNames']) {
$names = $this->getTautulliFriendlyNames(true);
$names = json_encode($names);
if ($names !== $this->config['homepageCustomStreamNames']) {
$this->updateConfig(array('homepageCustomStreamNames' => $names));
$this->config['homepageCustomStreamNames'] = $names;
$this->setLoggerChannel('Tautulli');
$this->logger->debug('Updating Tautulli custom names config item', $names);
}
}
}
private function formatPlexUserName($item)
{
$name = (($this->config['homepageShowStreamNames'] && $this->qualifyRequest($this->config['homepageShowStreamNamesAuth'])) || ($this->config['homepageShowStreamNamesWithoutIp'] && $this->qualifyRequest($this->config['homepageShowStreamNamesWithoutIpAuth']))) ? (string)$item->User['title'] : "";
try {
if ($this->config['homepageUseCustomStreamNames']) {
$customNames = json_decode($this->config['homepageCustomStreamNames'], true);
if (array_key_exists($name, $customNames)) {
$name = $customNames[$name];
}
}
} catch (Exception $e) {
// don't do anythig if it goes wrong, like if the JSON is badly formatted
}
return $name;
}
public function plexLibraryList($value = 'id')
{
if (!empty($this->config['plexToken']) && !empty($this->config['plexID'])) {
$url = 'https://plex.tv/api/servers/' . $this->config['plexID'];
try {
$headers = array(
"Accept" => "application/json",
"X-Plex-Token" => $this->config['plexToken']
);
$response = Requests::get($url, $headers, array());
libxml_use_internal_errors(true);
if ($response->success) {
$libraryList = array();
$plex = simplexml_load_string($response->body);
foreach ($plex->Server->Section as $child) {
$libraryList['libraries'][(string)$child['title']] = (string)$child[$value];
}
$libraryList = array_change_key_case($libraryList, CASE_LOWER);
return $libraryList;
}
} catch (Requests_Exception $e) {
$this->setLoggerChannel('Plex')->error($e);
return false;
};
}
return false;
}
}