Skip to content

Commit

Permalink
Merge pull request #36 from Makhuta/master
Browse files Browse the repository at this point in the history
Change/Update
  • Loading branch information
mkanet authored Apr 15, 2024
2 parents ca44401 + a72535f commit 0cc5da9
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 115 deletions.
48 changes: 22 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,30 @@ Read through these two resources before posting issues to GitHub or the forums.

1. Install this component by copying [these files](https://github.com/custom-components/sensor.sonarr_upcoming_media/tree/master/custom_components/sonarr_upcoming_media) to `/custom_components/sonarr_upcoming_media/`.
2. Install the card: [Upcoming Media Card](https://github.com/custom-cards/upcoming-media-card)
3. Add the code to your `configuration.yaml` using the config options below.
4. Add the code for the card to your `ui-lovelace.yaml`.
5. **You will need to restart after installation for the component to start working.**

| key | default | required | description
| --- | --- | --- | ---
| api_key | | yes | Your Sonarr API key
| host | localhost | no | The host Sonarr is running on.
| port | 8989 | no | The port Sonarr is running on.
| urlbase | / | no | The base URL Sonarr is running under.
| days | 7 | no | How many days to look ahead for the upcoming sensor.
| ssl | false | no | Whether or not to use SSL for Sonarr.
| max | 5 | no | Max number of items in sensor.
</br>
3. Add the code for the card to your `ui-lovelace.yaml`.
4. **You will need to restart after installation for the component to start working.**

### Adding device
To add the **Sonarr Upcoming Media** integration to your Home Assistant, use this My button:

<a href="https://my.home-assistant.io/redirect/config_flow_start?domain=sonarr_upcoming_media" class="my badge" target="_blank"><img src="https://my.home-assistant.io/badges/config_flow_start.svg"></a>

<details><summary style="list-style: none"><h3><b style="cursor: pointer">Manual configuration steps</b></h3></summary>

If the above My button doesn’t work, you can also perform the following steps manually:

- Browse to your Home Assistant instance.

- Go to [Settings > Devices & Services](https://my.home-assistant.io/redirect/integrations/).

- In the bottom right corner, select the [Add Integration button.](https://my.home-assistant.io/redirect/config_flow_start?domain=sonarr_upcoming_media)

- From the list, select **Sonarr Upcoming Media**.

- Follow the instructions on screen to complete the setup.
</details>

**Do not just copy examples, please use config options above to build your own!**
### Sample for configuration.yaml:

```
sensor:
- platform: sonarr_upcoming_media
api_key: YOUR_API_KEY
host: 127.0.0.1
port: 8989
days: 7
ssl: false
max: 10
```

### Sample for ui-lovelace.yaml:

Expand Down
2 changes: 1 addition & 1 deletion custom_components/sonarr_upcoming_media/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def valid_max():
return lambda x: type(x) == int and x > 0

SONARR_SCHEMA = vol.Schema({
vol.Optional(CONF_NAME, default='Sonarr'): vol.All(str),
vol.Optional(CONF_NAME, default=''): vol.All(str),
vol.Optional(CONF_HOST, default='localhost'): vol.All(str),
vol.Optional(CONF_PORT, default=8989): vol.All(vol.Coerce(int), vol.Range(min=0)),
vol.Optional(CONF_URLBASE, default=''): vol.All(str),
Expand Down
12 changes: 11 additions & 1 deletion custom_components/sonarr_upcoming_media/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,14 @@

CONF_DAYS: Final = 'days'
CONF_URLBASE: Final = 'urlbase'
CONF_MAX: Final = 'max'
CONF_MAX: Final = 'max'


DEFAULT_PARSE_DICT: Final = {
'title_default': '$title',
'line1_default': '$episode',
'line2_default': '$release',
'line3_default': '$rating - $runtime',
'line4_default': '$number - $studio',
'icon': 'mdi:arrow-down-bold'
}
2 changes: 1 addition & 1 deletion custom_components/sonarr_upcoming_media/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/custom-components/sensor.sonarr_upcoming_media/issues",
"requirements": [],
"version": "0.4.0"
"version": "0.4.1"
}

81 changes: 81 additions & 0 deletions custom_components/sonarr_upcoming_media/parsing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import time
from datetime import date, datetime
from pytz import timezone

from .const import DEFAULT_PARSE_DICT

def days_until(date, tz):
from pytz import utc
date = datetime.strptime(date, '%Y-%m-%dT%H:%M:%SZ')
date = str(date.replace(tzinfo=utc).astimezone(tz))[:10]
date = time.strptime(date, '%Y-%m-%d')
date = time.mktime(date)
now = datetime.now().strftime('%Y-%m-%d')
now = time.strptime(now, '%Y-%m-%d')
now = time.mktime(now)
return int((date - now) / 86400)

def parse_data(data, tz, host, port, ssl):
import re
"""Return JSON for the sensor."""
attributes = {}
card_json = []
card_json.append(DEFAULT_PARSE_DICT)
for show in data:
card_item = {}
if 'series' not in show:
continue
card_item['airdate'] = show['airDateUtc']
if days_until(show['airDateUtc'], tz) <= 7:
card_item['release'] = '$day, $time'
else:
card_item['release'] = '$day, $date $time'
card_item['flag'] = show.get('hasFile', False)
if 'title' in show['series']:
card_item['title'] = show['series']['title']
else:
continue
card_item['episode'] = show.get('title', '')
if 'seasonNumber' and 'episodeNumber' in show:
card_item['number'] = 'S{:02d}E{:02d}'.format(show['seasonNumber'],
show['episodeNumber'])
else:
card_item['number'] = ''
if 'runtime' in show['series']:
card_item['runtime'] = show['series']['runtime']
else:
card_item['runtime'] = ''
if 'network' in show['series']:
card_item['studio'] = show['series']['network']
else:
card_item['studio'] = ''
if ('ratings' in show['series'] and
show['series']['ratings']['value'] > 0):
card_item['rating'] = ('\N{BLACK STAR} ' +
str(show['series']['ratings']['value']))
else:
card_item['rating'] = ''
if 'genres' in show['series']:
card_item['genres'] = ', '.join(show['series']['genres'])
else:
card_item['genres'] = ''
card_item['summary'] = show.get('overview', '')
try:
for img in show['series']['images']:
if img['coverType'] == 'poster':
card_item['poster'] = re.sub('.jpg', '_t.jpg', img['remoteUrl'])
except:
continue
try:
card_item['fanart'] = ''
for img in show['series']['images']:
if img['coverType'] == 'fanart':
card_item['fanart'] = re.sub('.jpg', '_t.jpg', img['remoteUrl'])
except:
pass
series_title_slug = show['series']['titleSlug']
protocol = 'https' if ssl else 'http'
card_item['deep_link'] = f'{protocol}://{host}:{port}/series/{series_title_slug}'
card_json.append(card_item)
attributes['data'] = card_json
return attributes
2 changes: 1 addition & 1 deletion custom_components/sonarr_upcoming_media/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class SonarrUpcomingMediaSensor(CoordinatorEntity[SonarrDataCoordinator], Sensor
def __init__(self, coordinator: SonarrDataCoordinator, config_entry: ConfigEntry):
super().__init__(coordinator)
self._coordinator = coordinator
self._name = f'{config_entry.data[CONF_NAME].capitalize()} Sonarr Upcoming Media'
self._name = f'{config_entry.data[CONF_NAME].capitalize() + " " if len(config_entry.data[CONF_NAME]) > 0 else ""}Sonarr Upcoming Media'
self._api_key = config_entry.data[CONF_API_KEY]

@property
Expand Down
88 changes: 3 additions & 85 deletions custom_components/sonarr_upcoming_media/sonarr_api.py
Original file line number Diff line number Diff line change
@@ -1,100 +1,18 @@
import time
from datetime import date, datetime
from datetime import datetime
from pytz import timezone
import requests
import json

from homeassistant.core import HomeAssistant

from .parsing import parse_data

def get_date(zone, offset=0):
"""Get date based on timezone and offset of days."""
return datetime.date(datetime.fromtimestamp(
time.time() + 86400 * offset, tz=zone))

def days_until(date, tz):
from pytz import utc
date = datetime.strptime(date, '%Y-%m-%dT%H:%M:%SZ')
date = str(date.replace(tzinfo=utc).astimezone(tz))[:10]
date = time.strptime(date, '%Y-%m-%d')
date = time.mktime(date)
now = datetime.now().strftime('%Y-%m-%d')
now = time.strptime(now, '%Y-%m-%d')
now = time.mktime(now)
return int((date - now) / 86400)

def parse_data(data, tz, host, port, ssl):
import re
"""Return JSON for the sensor."""
attributes = {}
default = {}
card_json = []
default['title_default'] = '$title'
default['line1_default'] = '$episode'
default['line2_default'] = '$release'
default['line3_default'] = '$rating - $runtime'
default['line4_default'] = '$number - $studio'
default['icon'] = 'mdi:arrow-down-bold'
card_json.append(default)
for show in data:
card_item = {}
if 'series' not in show:
continue
card_item['airdate'] = show['airDateUtc']
if days_until(show['airDateUtc'], tz) <= 7:
card_item['release'] = '$day, $time'
else:
card_item['release'] = '$day, $date $time'
card_item['flag'] = show.get('hasFile', False)
if 'title' in show['series']:
card_item['title'] = show['series']['title']
else:
continue
card_item['episode'] = show.get('title', '')
if 'seasonNumber' and 'episodeNumber' in show:
card_item['number'] = 'S{:02d}E{:02d}'.format(show['seasonNumber'],
show['episodeNumber'])
else:
card_item['number'] = ''
if 'runtime' in show['series']:
card_item['runtime'] = show['series']['runtime']
else:
card_item['runtime'] = ''
if 'network' in show['series']:
card_item['studio'] = show['series']['network']
else:
card_item['studio'] = ''
if ('ratings' in show['series'] and
show['series']['ratings']['value'] > 0):
card_item['rating'] = ('\N{BLACK STAR} ' +
str(show['series']['ratings']['value']))
else:
card_item['rating'] = ''
if 'genres' in show['series']:
card_item['genres'] = ', '.join(show['series']['genres'])
else:
card_item['genres'] = ''
card_item['summary'] = show.get('overview', '')
try:
for img in show['series']['images']:
if img['coverType'] == 'poster':
card_item['poster'] = re.sub('.jpg', '_t.jpg', img['remoteUrl'])
except:
continue
try:
card_item['fanart'] = ''
for img in show['series']['images']:
if img['coverType'] == 'fanart':
card_item['fanart'] = re.sub('.jpg', '_t.jpg', img['remoteUrl'])
except:
pass
series_title_slug = show['series']['titleSlug']
protocol = 'https' if ssl else 'http'
card_item['deep_link'] = f'{protocol}://{host}:{port}/series/{series_title_slug}'
card_json.append(card_item)
attributes['data'] = card_json
return attributes


class SonarrApi():
def __init__(
self,
Expand Down
27 changes: 27 additions & 0 deletions info.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
This component feeds [Upcoming Media Card](./146783593) with Sonarr's upcoming shows.

## Installation:

1. Install this component by copying [these files](https://github.com/custom-components/sensor.sonarr_upcoming_media/tree/master/custom_components/sonarr_upcoming_media) to `/custom_components/sonarr_upcoming_media/`.
2. Install the card: [Upcoming Media Card](https://github.com/custom-cards/upcoming-media-card)
3. Add the code for the card to your `ui-lovelace.yaml`.
4. **You will need to restart after installation for the component to start working.**

### Adding device
To add the **Sonarr Upcoming Media** integration to your Home Assistant, use this My button:

<a href="https://my.home-assistant.io/redirect/config_flow_start?domain=sonarr_upcoming_media" class="my badge" target="_blank"><img src="https://my.home-assistant.io/badges/config_flow_start.svg"></a>

<details><summary style="list-style: none"><h3><b style="cursor: pointer">Manual configuration steps</b></h3></summary>

If the above My button doesn’t work, you can also perform the following steps manually:

- Browse to your Home Assistant instance.

- Go to [Settings > Devices & Services](https://my.home-assistant.io/redirect/integrations/).

- In the bottom right corner, select the [Add Integration button.](https://my.home-assistant.io/redirect/config_flow_start?domain=sonarr_upcoming_media)

- From the list, select **Sonarr Upcoming Media**.

- Follow the instructions on screen to complete the setup.
</details>

## Supporting Development
- :coffee: [Buy me a coffee](https://www.buymeacoffee.com/FgwNR2l)
- :red_circle: [Tip some Crypto](https://github.com/sponsors/maykar)
Expand Down

0 comments on commit 0cc5da9

Please sign in to comment.