__init__.py 8.35 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ##############################################################################
#  Author: echel0n <[email protected]>
#  URL: https://sickrage.ca/
#  Git: https://git.sickrage.ca/SiCKRAGE/sickrage.git
#  -
#  This file is part of SiCKRAGE.
#  -
#  SiCKRAGE is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  -
#  SiCKRAGE is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  -
#  You should have received a copy of the GNU General Public License
#  along with SiCKRAGE.  If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
import os
from abc import ABC

from tornado.escape import json_decode

import sickrage
from sickrage.core.queues.search import ManualSearchTask
28
29
from sickrage.core.tv.episode.helpers import find_episode_by_slug, find_episode
from sickrage.core.tv.show.helpers import find_show_by_slug
echel0n's avatar
echel0n committed
30
31
from sickrage.core.webserver.handlers.api import APIBaseHandler
from sickrage.core.webserver.handlers.api.v2.episode.schemas import EpisodesManualSearchSchema, EpisodesRenameSchema, EpisodesManualSearchPath
32
33
34
from sickrage.core.websocket import WebSocketMessage


echel0n's avatar
echel0n committed
35
class EpisodesManualSearchHandler(APIBaseHandler, ABC):
36
    def get(self, episode_slug):
echel0n's avatar
echel0n committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
        """Episode Manual Search"
        ---
        tags: [Episodes]
        summary: Manually search for episode on search providers
        description: Manually search for episode on search providers
        parameters:
        - in: path
          schema:
            EpisodesManualSearchPath
        - in: query
          schema:
            EpisodesManualSearchSchema
        responses:
          200:
            description: Success payload
            content:
              application/json:
                schema:
                  EpisodesManualSearchSuccessSchema
          400:
            description: Bad request; Check `errors` for any validation errors
            content:
              application/json:
                schema:
                  BadRequestSchema
          401:
            description: Returned if your JWT token is missing or expired
            content:
              application/json:
                schema:
                  NotAuthorizedSchema
          404:
            description: Returned if the given episode slug does not exist or the search returns no results.
            content:
              application/json:
                schema:
                  NotFoundSchema
        """
        use_existing_quality = self.get_argument('useExistingQuality', None) or False

        validation_errors = self._validate_schema(EpisodesManualSearchPath, self.request.path)
        if validation_errors:
            return self.send_error(400, errors=validation_errors)

        validation_errors = self._validate_schema(EpisodesManualSearchSchema, self.request.arguments)
        if validation_errors:
            return self.send_error(400, errors=validation_errors)
84

85
        episode = find_episode_by_slug(episode_slug)
86
        if episode is None:
87
            return self.send_error(404, error=f"Unable to find the specified episode using slug: {episode_slug}")
88
89

        # make a queue item for it and put it on the queue
90
91
92
93
94
        ep_queue_item = ManualSearchTask(int(episode.show.series_id),
                                         episode.show.series_provider_id,
                                         int(episode.season),
                                         int(episode.episode),
                                         bool(use_existing_quality))
95
96
97

        sickrage.app.search_queue.put(ep_queue_item)
        if not all([ep_queue_item.started, ep_queue_item.success]):
echel0n's avatar
echel0n committed
98
            return self.write_json({'success': True})
99

echel0n's avatar
echel0n committed
100
101
102
103
        return self.send_error(
            status_code=404,
            error=_(f"Unable to find season {episode.season} episode {episode.episode} for show {episode.show.name} on search providers")
        )
104
105


echel0n's avatar
echel0n committed
106
class EpisodesRenameHandler(APIBaseHandler, ABC):
107
    def get(self):
echel0n's avatar
echel0n committed
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
        """Get list of episodes to rename"
        ---
        tags: [Episodes]
        summary: Get list of episodes to rename
        description: Get list of episodes to rename
        parameters:
        - in: query
          schema:
            EpisodesRenameSchema
        responses:
          200:
            description: Success payload
            content:
              application/json:
                schema:
                  EpisodesRenameSuccessSchema
          400:
            description: Bad request; Check `errors` for any validation errors
            content:
              application/json:
                schema:
                  BadRequestSchema
          401:
            description: Returned if your JWT token is missing or expired
            content:
              application/json:
                schema:
                  NotAuthorizedSchema
        """
137
        series_slug = self.get_argument('seriesSlug', None)
echel0n's avatar
echel0n committed
138
139
140
141
142

        validation_errors = self._validate_schema(EpisodesRenameSchema, self.request.arguments)
        if validation_errors:
            return self.send_error(400, error=validation_errors)

143
144
        if not series_slug:
            return self.send_error(400, error="Missing series slug")
145
146
147

        rename_data = []

148
        series = find_show_by_slug(series_slug)
149
        if series is None:
150
            return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
151
152

        if not os.path.isdir(series.location):
153
            return self.send_error(400, error="Can't rename episodes when the show location does not exist")
154
155
156
157
158
159
160
161
162
163

        for episode in series.episodes:
            if not episode.location:
                continue

            current_location = episode.location[len(episode.show.location) + 1:]
            new_location = "{}.{}".format(episode.proper_path(), current_location.split('.')[-1])

            if current_location != new_location:
                rename_data.append({
164
                    'episodeId': episode.episode_id,
165
166
                    'season': episode.season,
                    'episode': episode.episode,
167
168
                    'currentLocation': current_location,
                    'newLocation': new_location,
169
170
171
172
173
                })

        return self.write_json(rename_data)

    def post(self):
echel0n's avatar
echel0n committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
        """Rename list of episodes"
        ---
        tags: [Episodes]
        summary: Rename list of episodes
        description: Rename list of episodes
        # parameters:
        # - in: query
        #   schema:
        #     EpisodesRenameSchema
        responses:
          200:
            description: Success payload
            content:
              application/json:
                schema:
                  EpisodesRenameSuccessSchema
          400:
            description: Bad request; Check `errors` for any validation errors
            content:
              application/json:
                schema:
                  BadRequestSchema
          401:
            description: Returned if your JWT token is missing or expired
            content:
              application/json:
                schema:
                  NotAuthorizedSchema
        """
203
204
205
206
        data = json_decode(self.request.body)

        renamed_episodes = []

207
208
209
        series_slug = data.get('seriesSlug', None)
        if not series_slug:
            return self.send_error(400, error="Missing series id")
210

211
        series = find_show_by_slug(series_slug)
212
        if series is None:
213
            return self.send_error(404, error=f"Unable to find the specified series using slug: {series_slug}")
214
215

        if not os.path.isdir(series.location):
216
            return self.send_error(400, error="Can't rename episodes when the show location does not exist")
217

218
219
        for episode_id in data.get('episodeIdList', []):
            episode = find_episode(episode_id, series.series_provider_id)
220
221
            if episode:
                episode.rename()
222
                renamed_episodes.append(episode.episode_id)
223
224

        if len(renamed_episodes) > 0:
225
            WebSocketMessage('SHOW_RENAMED', {'seriesSlug': series.slug}).push()
226
227

        return self.write_json(renamed_episodes)