| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- <?php
- namespace Kryptonit3\Sonarr;
- use GuzzleHttp\Client;
- use Kryptonit3\Sonarr\Exceptions\InvalidException;
- class Sonarr
- {
- protected $url;
- protected $apiKey;
- protected $httpAuthUsername;
- protected $httpAuthPassword;
- public function __construct($url, $apiKey, $httpAuthUsername = null, $httpAuthPassword = null)
- {
- $this->url = rtrim($url, '/\\'); // Example: http://127.0.0.1:8989 (no trailing forward-backward slashes)
- $this->apiKey = $apiKey;
- $this->httpAuthUsername = $httpAuthUsername;
- $this->httpAuthPassword = $httpAuthPassword;
- }
- /**
- * Gets upcoming episodes, if start/end are not supplied episodes airing today and tomorrow will be returned
- * When supplying start and/or end date you must supply date in format yyyy-mm-dd
- * Example: $sonarr->getCalendar('2015-01-25', '2016-01-15');
- * 'start' and 'end' not required. You may supply, one or both.
- *
- * @param string|null $start
- * @param string|null $end
- * @return array|object|string
- * @throws InvalidException
- */
- public function getCalendar($start = null, $end = null, $sonarrUnmonitored = 'false')
- {
- $uriData = [];
- if ( $start ) {
- if ( $this->validateDate($start) ) {
- $uriData['start'] = $start;
- } else {
- throw new InvalidException('Start date string was not recognized as a valid DateTime. Format must be yyyy-mm-dd.');
- }
- }
- if ( $end ) {
- if ( $this->validateDate($end) ) {
- $uriData['end'] = $end;
- } else {
- throw new InvalidException('End date string was not recognized as a valid DateTime. Format must be yyyy-mm-dd.');
- }
- }
- if ( $sonarrUnmonitored == 'true' ) {
- $uriData['unmonitored'] = 'true';
- }
-
- try {
- $response = $this->_request(
- [
- 'uri' => 'calendar',
- 'type' => 'get',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Queries the status of a previously started command, or all currently started commands.
- *
- * @param null $id Unique ID of the command
- * @return array|object|string
- * @throws InvalidException
- */
- public function getCommand($id = null)
- {
- $uri = ($id) ? 'command/' . $id : 'command';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Publish a new command for Sonarr to run.
- * These commands are executed asynchronously; use GET to retrieve the current status.
- *
- * Commands and their parameters can be found here:
- * https://github.com/Sonarr/Sonarr/wiki/Command#commands
- *
- * @param $name
- * @param array|null $params
- * @return string
- * @throws InvalidException
- */
- public function postCommand($name, array $params = null)
- {
- $uri = 'command';
- $uriData = [
- 'name' => $name
- ];
- if ( array_key_exists('seriesId', $params) ) { $uriData['seriesId'] = $params['seriesId']; }
- if ( array_key_exists('episodeIds', $params) ) { $uriData['episodeIds'] = $params['episodeIds']; }
- if ( array_key_exists('seasonNumber', $params) ) { $uriData['seasonNumber'] = $params['seasonNumber']; }
- if ( array_key_exists('path', $params) ) { $uriData['path'] = $params['path']; }
- if ( array_key_exists('downloadClientId', $params) ) { $uriData['downloadClientId'] = $params['downloadClientId']; }
- if ( array_key_exists('files', $params) ) { $uriData['files'] = $params['files']; }
- if ( array_key_exists('seriesIds', $params) ) { $uriData['seriesIds'] = $params['seriesIds']; }
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'post',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Gets Diskspace
- *
- * @return array|object|string
- * @throws InvalidException
- */
- public function getDiskspace()
- {
- $uri = 'diskspace';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Returns all episodes for the given series
- *
- * @param $seriesId
- * @return array|object|string
- * @throws InvalidException
- */
- public function getEpisodes($seriesId)
- {
- $uri = 'episode';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => [
- 'SeriesId' => $seriesId
- ]
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Returns the episode with the matching id
- *
- * @param $id
- * @return string
- * @throws InvalidException
- */
- public function getEpisode($id)
- {
- $uri = 'episode';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri . '/' . $id,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Update the given episodes, currently only monitored is changed, all other modifications are ignored.
- *
- * Required: All parameters; You should perform a getEpisode(id)
- * and submit the full body with the changes, as other values may be editable in the future.
- *
- * @param array $data
- * @return string
- * @throws InvalidException
- */
- public function updateEpisode(array $data)
- {
- $uri = 'episode';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'put',
- 'data' => $data
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Returns all episode files for the given series
- *
- * @param $seriesId
- * @return array|object|string
- * @throws InvalidException
- */
- public function getEpisodeFiles($seriesId)
- {
- $uri = 'episodefile';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => [
- 'SeriesId' => $seriesId
- ]
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Returns the episode file with the matching id
- *
- * @param $id
- * @return string
- * @throws InvalidException
- */
- public function getEpisodeFile($id)
- {
- $uri = 'episodefile';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri . '/' . $id,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Delete the given episode file
- *
- * @param $id
- * @return string
- * @throws InvalidException
- */
- public function deleteEpisodeFile($id)
- {
- $uri = 'episodefile';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri . '/' . $id,
- 'type' => 'delete',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Gets history (grabs/failures/completed).
- *
- * @param int $page Page Number
- * @param int $pageSize Results per Page
- * @param string $sortKey 'series.title' or 'date'
- * @param string $sortDir 'asc' or 'desc'
- * @return array|object|string
- * @throws InvalidException
- */
- public function getHistory($page = 1, $pageSize = 10, $sortKey = 'series.title', $sortDir = 'asc')
- {
- $uri = 'history';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => [
- 'page' => $page,
- 'pageSize' => $pageSize,
- 'sortKey' => $sortKey,
- 'sortDir' => $sortDir
- ]
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Gets missing episode (episodes without files).
- *
- * @param int $page Page Number
- * @param int $pageSize Results per Page
- * @param string $sortKey 'series.title' or 'airDateUtc'
- * @param string $sortDir 'asc' or 'desc'
- * @return array|object|string
- * @throws InvalidException
- */
- public function getWantedMissing($page = 1, $pageSize = 10, $sortKey = 'series.title', $sortDir = 'asc')
- {
- $uri = 'wanted/missing';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => [
- 'page' => $page,
- 'pageSize' => $pageSize,
- 'sortKey' => $sortKey,
- 'sortDir' => $sortDir
- ]
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Displays currently downloading info
- *
- * @return array|object|string
- * @throws InvalidException
- */
- public function getQueue()
- {
- $uri = 'queue';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Gets all quality profiles
- *
- * @return array|object|string
- * @throws InvalidException
- */
- public function getProfiles()
- {
- $uri = 'profile';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Get release by episode id
- *
- * @param $episodeId
- * @return string
- * @throws InvalidException
- */
- public function getRelease($episodeId)
- {
- $uri = 'release';
- $uriData = [
- 'episodeId' => $episodeId
- ];
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Adds a previously searched release to the download client,
- * if the release is still in Sonarr's search cache (30 minute cache).
- * If the release is not found in the cache Sonarr will return a 404.
- *
- * @param $guid
- * @return string
- * @throws InvalidException
- */
- public function postRelease($guid)
- {
- $uri = 'release';
- $uriData = [
- 'guid' => $guid
- ];
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'post',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Push a release to download client
- *
- * @param $title
- * @param $downloadUrl
- * @param $downloadProtocol (Usenet or Torrent)
- * @param $publishDate (ISO8601 Date)
- * @return string
- * @throws InvalidException
- */
- public function postReleasePush($title, $downloadUrl, $downloadProtocol, $publishDate)
- {
- $uri = 'release';
- $uriData = [
- 'title' => $title,
- 'downloadUrl' => $downloadUrl,
- 'downloadProtocol' => $downloadProtocol,
- 'publishDate' => $publishDate
- ];
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'post',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Gets root folder
- *
- * @return array|object|string
- * @throws InvalidException
- */
- public function getRootFolder()
- {
- $uri = 'rootfolder';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Returns all series in your collection
- *
- * @return array|object|string
- * @throws InvalidException
- */
- public function getSeries()
- {
- $uri = 'series';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Adds a new series to your collection
- *
- * NOTE: if you do not add the required params, then the series wont function.
- * Some of these without the others can indeed make a "series". But it wont function properly in Sonarr.
- *
- * Required: tvdbId (int) title (string) qualityProfileId (int) titleSlug (string) seasons (array)
- * See GET output for format
- *
- * path (string) - full path to the series on disk or rootFolderPath (string)
- * Full path will be created by combining the rootFolderPath with the series title
- *
- * Optional: tvRageId (int) seasonFolder (bool) monitored (bool)
- *
- * @param array $data
- * @param bool|true $onlyFutureEpisodes It can be used to control which episodes Sonarr monitors
- * after adding the series, setting to true (default) will only monitor future episodes.
- *
- * @return array|object|string
- * @throws InvalidException
- */
- public function postSeries(array $data, $onlyFutureEpisodes = true)
- {
- $uri = 'series';
- $uriData = [];
- // Required
- $uriData['tvdbId'] = $data['tvdbId'];
- $uriData['title'] = $data['title'];
- $uriData['qualityProfileId'] = $data['qualityProfileId'];
- if ( array_key_exists('titleSlug', $data) ) { $uriData['titleSlug'] = $data['titleSlug']; }
- if ( array_key_exists('seasons', $data) ) { $uriData['seasons'] = $data['seasons']; }
- if ( array_key_exists('path', $data) ) { $uriData['path'] = $data['path']; }
- if ( array_key_exists('rootFolderPath', $data) ) { $uriData['rootFolderPath'] = $data['rootFolderPath']; }
- if ( array_key_exists('tvRageId', $data) ) { $uriData['tvRageId'] = $data['tvRageId']; }
- $uriData['seasonFolder'] = ( array_key_exists('seasonFolder', $data) ) ? $data['seasonFolder'] : true;
- if ( array_key_exists('monitored', $data) ) { $uriData['monitored'] = $data['monitored']; }
- if ( $onlyFutureEpisodes ) {
- $uriData['addOptions'] = [
- 'ignoreEpisodesWithFiles' => true,
- 'ignoreEpisodesWithoutFiles' => true
- ];
- }
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'post',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Delete the series with the given ID
- *
- * @param int $id
- * @param bool|true $deleteFiles
- * @return string
- * @throws InvalidException
- */
- public function deleteSeries($id, $deleteFiles = true)
- {
- $uri = 'series';
- $uriData = [];
- $uriData['deleteFiles'] = ($deleteFiles) ? 'true' : 'false';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri . '/' . $id,
- 'type' => 'delete',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Searches for new shows on trakt
- * Search by name or tvdbid
- * Example: 'The Blacklist' or 'tvdb:266189'
- *
- * @param string $searchTerm query string for the search (Use tvdb:12345 to lookup TVDB ID 12345)
- * @return string
- * @throws InvalidException
- */
- public function getSeriesLookup($searchTerm)
- {
- $uri = 'series/lookup';
- $uriData = [
- 'term' => $searchTerm
- ];
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => $uriData
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Get System Status
- *
- * @return string
- * @throws InvalidException
- */
- public function getSystemStatus()
- {
- $uri = 'system/status';
- try {
- $response = $this->_request(
- [
- 'uri' => $uri,
- 'type' => 'get',
- 'data' => []
- ]
- );
- } catch ( \Exception $e ) {
- throw new InvalidException($e->getMessage());
- }
- return $response->getBody()->getContents();
- }
- /**
- * Process requests with Guzzle
- *
- * @param array $params
- * @return \Psr\Http\Message\ResponseInterface
- */
- protected function _request(array $params)
- {
- $client = new Client();
- $options = [
- 'headers' => [
- 'X-Api-Key' => $this->apiKey
- ]
- ];
-
- if ( $this->httpAuthUsername && $this->httpAuthPassword ) {
- $options['auth'] = [
- $this->httpAuthUsername,
- $this->httpAuthPassword
- ];
- }
- if ( $params['type'] == 'get' ) {
- $url = $this->url . '/api/' . $params['uri'] . '?' . http_build_query($params['data']);
- return $client->get($url, $options);
- }
- if ( $params['type'] == 'put' ) {
- $url = $this->url . '/api/' . $params['uri'];
- $options['json'] = $params['data'];
-
- return $client->put($url, $options);
- }
- if ( $params['type'] == 'post' ) {
- $url = $this->url . '/api/' . $params['uri'];
- $options['json'] = $params['data'];
-
- return $client->post($url, $options);
- }
- if ( $params['type'] == 'delete' ) {
- $url = $this->url . '/api/' . $params['uri'] . '?' . http_build_query($params['data']);
- return $client->delete($url, $options);
- }
- }
- /**
- * Verify date is in proper format
- *
- * @param $date
- * @param string $format
- * @return bool
- */
- private function validateDate($date, $format = 'Y-m-d')
- {
- $d = \DateTime::createFromFormat($format, $date);
- return $d && $d->format($format) == $date;
- }
- }
|