Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/show sub original release #7955

Merged
merged 19 commits into from
Apr 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#### Improvements
- Add show names with dashes to guessit expected titles ([#7918](https://github.com/pymedusa/Medusa/pull/7918))
- Provider YggTorrents: Add 'saison' as a season pack search keyword ([#7920](https://github.com/pymedusa/Medusa/pull/7920))
- Show Snatched or Downloaded release name when manually picking a subtitle ([#7955](https://github.com/pymedusa/Medusa/pull/7955))

#### Fixes
- Fixed root dirs not always shown on Home page ([#7921](https://github.com/pymedusa/Medusa/pull/7921))
Expand Down
156 changes: 154 additions & 2 deletions dredd/api-description.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ paths:
The Episode endpoint returns information about the Episodes from a given Series.
parameters:
- $ref: '#/parameters/series-id'
name: seriesid
- name: season
in: query
required: false
Expand Down Expand Up @@ -995,6 +994,91 @@ paths:
400:
$ref: '#/responses/error'
x-disabled: true
/history:
get:
summary: Return history entries to a specific show
description: |
The history endpoint returns logged activities stored in the history table, like episodes snatched and downloaded. Or downloaded subtitles for an episode.
parameters:
- $ref: '#/parameters/page'
- $ref: '#/parameters/limit'
- $ref: '#/parameters/sort'
responses:
200:
$ref: '#/responses/pagination_history'
x-disabled: true
400:
$ref: '#/responses/error'
description: Invalid series id or pagination parameters
x-request:
path-params:
seriesid: asdf
x-disabled: true
404:
$ref: '#/responses/error'
description: Series not found
x-request:
path-params:
seriesid: tvdb999999999
x-disabled: true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@medariox @sharkykh yes i'm disabling these.
I'm not getting it to work. If some of you want to spend time on this, feel free.

/history/{seriesid}:
get:
summary: Return history entries to a specific show
description: |
The history endpoint returns logged activities stored in the history table, like episodes snatched and downloaded. Or downloaded subtitles for an episode.
parameters:
- $ref: '#/parameters/series-id'
- $ref: '#/parameters/page'
- $ref: '#/parameters/limit'
- $ref: '#/parameters/sort'
responses:
200:
$ref: '#/responses/pagination_history'
x-disabled: true
400:
$ref: '#/responses/error'
description: Invalid series id or pagination parameters
x-request:
path-params:
seriesid: asdf
x-disabled: true
404:
$ref: '#/responses/error'
description: Series not found
x-request:
path-params:
seriesid: tvdb999999999
x-disabled: true
/history/{seriesid}/episode/{episodeid}:
get:
summary: Return history entries for a specific episode
description: |
The histories episode endpoint returns history entries for a specific episode
parameters:
- $ref: '#/parameters/series-id'
- $ref: '#/parameters/episode-id'
responses:
200:
description: Array of History entries
schema:
type: array
items:
$ref: '#/definitions/History'
x-disabled: true
400:
$ref: '#/responses/error'
description: Invalid series id or pagination parameters
x-request:
path-params:
seriesid: asdf
x-disabled: true
404:
$ref: '#/responses/error'
description: Series not found
x-request:
path-params:
seriesid: tvdb999999999
x-disabled: true

definitions:
Series:
Expand Down Expand Up @@ -2721,6 +2805,51 @@ definitions:
overview:
type: string
description: Episode status/quality overview string

History:
description: History object
type: object
properties:
id:
type: integer
format: int32
description: Internal id for the history row
series:
type: string
description: Series slug (if available)
status:
type: integer
format: int32
description: Status (numberic)
statusName:
type: string
description: Status description
actionDate:
type: integer
format: int32
description: Date of when the history entrie was stored
resource:
type: string
description: Description of what was stored
example:
- The release name for a statusName of "Downloaded" or "Snatched"
- The language of a subitle downloaded fo ra statusName of "Subtitled"
size:
type: integer
description: Snatched or Downloaded filesize
season:
type: integer
description: Season number
episode:
type: integer
description: Episode number
manuallySearched:
type: boolean
description: Specifies if an episode was snatched or downloaded through a manual search
provider:
type: string
description: Provider of the history record. For example, the provider id if origin from snatch/download.

parameters:
detailed:
name: detailed
Expand Down Expand Up @@ -2762,7 +2891,7 @@ parameters:
x-example: tvdb301824
type: string
episode-id:
name: episode-id
name: episodeid
in: path
required: true
description: The episode id to retrieve. E.g. s02e03, e34 or 2016-12-31
Expand Down Expand Up @@ -2925,3 +3054,26 @@ responses:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
pagination_history:
description: A paged array of history records
headers:
X-Pagination-Page:
type: integer
format: int32
description: The page number
X-Pagination-Limit:
type: integer
format: int32
description: The pagination limit
X-Pagination-Count:
type: integer
format: int32
description: The total items count
Link:
type: string
description: "The pagination links: next, last, first and previous"
schema:
type: array
items:
$ref: '#/definitions/History'

99 changes: 99 additions & 0 deletions medusa/server/api/v2/episode_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# coding=utf-8
"""Request handler for series and episodes."""
from __future__ import unicode_literals

import logging
from os.path import basename

from medusa import db
from medusa.common import statusStrings
from medusa.logger.adapters.style import BraceAdapter
from medusa.server.api.v2.base import BaseRequestHandler
from medusa.server.api.v2.history import HistoryHandler
from medusa.tv.episode import Episode, EpisodeNumber
from medusa.tv.series import Series, SeriesIdentifier


log = BraceAdapter(logging.getLogger(__name__))
log.logger.addHandler(logging.NullHandler())


class EpisodeHistoryHandler(BaseRequestHandler):
"""Episode history request handler."""

#: parent resource handler
parent_handler = HistoryHandler
#: resource name
name = 'episode'
#: identifier
identifier = ('episode_slug', r'[\w-]+')
#: path param
path_param = ('path_param', r'\w+')
#: allowed HTTP methods
allowed_methods = ('GET',)

def get(self, series_slug, episode_slug, path_param):
"""Query episode's history information.

:param series_slug: series slug. E.g.: tvdb1234
:param episode_slug: episode slug. E.g.: s01e01
:param path_param:
"""
series_identifier = SeriesIdentifier.from_slug(series_slug)
if not series_identifier:
return self._bad_request('Invalid series slug')

series = Series.find_by_identifier(series_identifier)
if not series:
return self._not_found('Series not found')

if not episode_slug:
return self._bad_request('Invalid episode slug')

episode_number = EpisodeNumber.from_slug(episode_slug)
if not episode_number:
return self._not_found('Invalid episode number')

episode = Episode.find_by_series_and_episode(series, episode_number)
if not episode:
return self._not_found('Episode not found')

sql_base = """
SELECT rowid, date, action, quality,
provider, version, resource, size, proper_tags,
indexer_id, showid, season, episode, manually_searched
FROM history
WHERE showid = ? AND indexer_id = ? AND season = ? AND episode = ?
"""

params = [series.series_id, series.indexer, episode.season, episode.episode]

sql_base += ' ORDER BY date DESC'
results = db.DBConnection().select(sql_base, params)

def data_generator():
"""Read history data and normalize key/value pairs."""
for item in results:
d = {}
d['id'] = item['rowid']
d['series'] = SeriesIdentifier.from_id(item['indexer_id'], item['showid']).slug
d['status'] = item['action']
d['actionDate'] = item['date']

d['resource'] = basename(item['resource'])
d['size'] = item['size']
d['properTags'] = item['proper_tags']
d['statusName'] = statusStrings.get(item['action'])
d['season'] = item['season']
d['episode'] = item['episode']
d['manuallySearched'] = bool(item['manually_searched'])
d['provider'] = item['provider']

yield d

if not results:
return self._not_found('History data not found for show {show} and episode {episode}'.format(
show=series.identifier.slug, episode=episode.slug
))

return self._ok(data=list(data_generator()))
92 changes: 92 additions & 0 deletions medusa/server/api/v2/history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# coding=utf-8
"""Request handler for alias (scene exceptions)."""
from __future__ import unicode_literals

from os.path import basename

from medusa import db
from medusa.common import statusStrings
from medusa.server.api.v2.base import BaseRequestHandler
from medusa.tv.series import SeriesIdentifier


class HistoryHandler(BaseRequestHandler):
"""History request handler."""

#: resource name
name = 'history'
#: identifier
identifier = ('series_slug', r'\w+')
#: path param
path_param = ('path_param', r'\w+')
#: allowed HTTP methods
allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')

def get(self, series_slug, path_param):
"""
Get history records.

History records can be specified using a show slug.
"""
sql_base = """
SELECT rowid, date, action, quality,
provider, version, proper_tags, manually_searched,
resource, size, indexer_id, showid, season, episode
FROM history
"""
params = []

arg_page = self._get_page()
arg_limit = self._get_limit(default=50)

if series_slug is not None:
series_identifier = SeriesIdentifier.from_slug(series_slug)
if not series_identifier:
return self._bad_request('Invalid series')

sql_base += ' WHERE indexer_id = ? AND showid = ?'
params += [series_identifier.indexer.id, series_identifier.id]

sql_base += ' ORDER BY date DESC'
results = db.DBConnection().select(sql_base, params)

def data_generator():
"""Read and paginate history records."""
start = arg_limit * (arg_page - 1)

for item in results[start:start + arg_limit]:
d = {}
d['id'] = item['rowid']
d['series'] = SeriesIdentifier.from_id(item['indexer_id'], item['showid']).slug
d['status'] = item['action']
d['actionDate'] = item['date']

d['resource'] = basename(item['resource'])
d['size'] = item['size']
d['properTags'] = item['proper_tags']
d['statusName'] = statusStrings.get(item['action'])
d['season'] = item['season']
d['episode'] = item['episode']
d['manuallySearched'] = bool(item['manually_searched'])
d['provider'] = item['provider']

yield d

if not results:
return self._not_found('History data not found')

return self._paginate(data_generator=data_generator)

def delete(self, identifier, **kwargs):
"""Delete a history record."""
identifier = self._parse(identifier)
if not identifier:
return self._bad_request('Invalid history id')

main_db_con = db.DBConnection()
last_changes = main_db_con.connection.total_changes
main_db_con.action('DELETE FROM history WHERE row_id = ?', [identifier])
if main_db_con.connection.total_changes - last_changes <= 0:
return self._not_found('History row not found')

return self._no_content()
Loading