~ubuntu-branches/ubuntu/vivid/subliminal/vivid

« back to all changes in this revision

Viewing changes to .pc/python3.patch/subliminal/providers/opensubtitles.py

  • Committer: Package Import Robot
  • Author(s): Etienne Millon
  • Date: 2013-11-16 14:25:31 UTC
  • Revision ID: package-import@ubuntu.com-20131116142531-q6rwjrfa3mjmpule
Tags: 0.7.4-1
Initial release. (Closes: #729781)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
from __future__ import unicode_literals
 
3
import base64
 
4
import logging
 
5
import os
 
6
import re
 
7
import xmlrpclib
 
8
import zlib
 
9
import babelfish
 
10
import chardet as charade
 
11
import guessit
 
12
from . import Provider
 
13
from .. import __version__
 
14
from ..exceptions import ProviderError, ProviderNotAvailable, InvalidSubtitle
 
15
from ..subtitle import Subtitle, is_valid_subtitle, compute_guess_matches
 
16
from ..video import Episode, Movie
 
17
 
 
18
 
 
19
logger = logging.getLogger(__name__)
 
20
 
 
21
 
 
22
class OpenSubtitlesSubtitle(Subtitle):
 
23
    provider_name = 'opensubtitles'
 
24
    series_re = re.compile('^"(?P<series_name>.*)" (?P<series_title>.*)$')
 
25
 
 
26
    def __init__(self, language, hearing_impaired, id, matched_by, movie_kind, hash, movie_name, movie_release_name,  # @ReservedAssignment
 
27
                 movie_year, movie_imdb_id, series_season, series_episode):
 
28
        super(OpenSubtitlesSubtitle, self).__init__(language, hearing_impaired)
 
29
        self.id = id
 
30
        self.matched_by = matched_by
 
31
        self.movie_kind = movie_kind
 
32
        self.hash = hash
 
33
        self.movie_name = movie_name
 
34
        self.movie_release_name = movie_release_name
 
35
        self.movie_year = movie_year
 
36
        self.movie_imdb_id = movie_imdb_id
 
37
        self.series_season = series_season
 
38
        self.series_episode = series_episode
 
39
 
 
40
    @property
 
41
    def series_name(self):
 
42
        return self.series_re.match(self.movie_name).group('series_name')
 
43
 
 
44
    @property
 
45
    def series_title(self):
 
46
        return self.series_re.match(self.movie_name).group('series_title')
 
47
 
 
48
    def compute_matches(self, video):
 
49
        matches = set()
 
50
        # episode
 
51
        if isinstance(video, Episode) and self.movie_kind == 'episode':
 
52
            # series
 
53
            if video.series and self.series_name.lower() == video.series.lower():
 
54
                matches.add('series')
 
55
            # season
 
56
            if video.season and self.series_season == video.season:
 
57
                matches.add('season')
 
58
            # episode
 
59
            if video.episode and self.series_episode == video.episode:
 
60
                matches.add('episode')
 
61
            # guess
 
62
            matches |= compute_guess_matches(video, guessit.guess_episode_info(self.movie_release_name + '.mkv'))
 
63
        # movie
 
64
        elif isinstance(video, Movie) and self.movie_kind == 'movie':
 
65
            # year
 
66
            if video.year and self.movie_year == video.year:
 
67
                matches.add('year')
 
68
            # guess
 
69
            matches |= compute_guess_matches(video, guessit.guess_movie_info(self.movie_release_name + '.mkv'))
 
70
        else:
 
71
            logger.info('%r is not a valid movie_kind for %r', self.movie_kind, video)
 
72
            return matches
 
73
        # hash
 
74
        if 'opensubtitles' in video.hashes and self.hash == video.hashes['opensubtitles']:
 
75
            matches.add('hash')
 
76
        # imdb_id
 
77
        if video.imdb_id and self.movie_imdb_id == video.imdb_id:
 
78
            matches.add('imdb_id')
 
79
        # title
 
80
        if video.title and self.movie_name.lower() == video.title.lower():
 
81
            matches.add('title')
 
82
        return matches
 
83
 
 
84
 
 
85
class OpenSubtitlesProvider(Provider):
 
86
    languages = {babelfish.Language.fromopensubtitles(l) for l in babelfish.get_language_converter('opensubtitles').codes}
 
87
 
 
88
    def __init__(self):
 
89
        self.server = xmlrpclib.ServerProxy('http://api.opensubtitles.org/xml-rpc')
 
90
        self.token = None
 
91
 
 
92
    def initialize(self):
 
93
        try:
 
94
            response = self.server.LogIn('', '', 'eng', 'subliminal v%s' % __version__)
 
95
        except xmlrpclib.ProtocolError:
 
96
            raise ProviderNotAvailable
 
97
        if response['status'] != '200 OK':
 
98
            raise ProviderError('Login failed with status %r' % response['status'])
 
99
        self.token = response['token']
 
100
 
 
101
    def terminate(self):
 
102
        try:
 
103
            response = self.server.LogOut(self.token)
 
104
        except xmlrpclib.ProtocolError:
 
105
            raise ProviderNotAvailable
 
106
        if response['status'] != '200 OK':
 
107
            raise ProviderError('Logout failed with status %r' % response['status'])
 
108
 
 
109
    def query(self, languages, hash=None, size=None, imdb_id=None, query=None):  # @ReservedAssignment
 
110
        searches = []
 
111
        if hash and size:
 
112
            searches.append({'moviehash': hash, 'moviebytesize': str(size)})
 
113
        if imdb_id:
 
114
            searches.append({'imdbid': imdb_id})
 
115
        if query:
 
116
            searches.append({'query': query})
 
117
        if not searches:
 
118
            raise ValueError('One or more parameter missing')
 
119
        for search in searches:
 
120
            search['sublanguageid'] = ','.join(l.opensubtitles for l in languages)
 
121
        logger.debug('Searching subtitles %r', searches)
 
122
        try:
 
123
            response = self.server.SearchSubtitles(self.token, searches)
 
124
        except xmlrpclib.ProtocolError:
 
125
            raise ProviderNotAvailable
 
126
        if response['status'] != '200 OK':
 
127
            raise ProviderError('Search failed with status %r' % response['status'])
 
128
        if not response['data']:
 
129
            logger.debug('No subtitle found')
 
130
            return []
 
131
        return [OpenSubtitlesSubtitle(babelfish.Language.fromopensubtitles(r['SubLanguageID']),
 
132
                                      bool(int(r['SubHearingImpaired'])), r['IDSubtitleFile'], r['MatchedBy'],
 
133
                                      r['MovieKind'], r['MovieHash'], r['MovieName'], r['MovieReleaseName'],
 
134
                                      int(r['MovieYear']) if r['MovieYear'] else None, int(r['IDMovieImdb']),
 
135
                                      int(r['SeriesSeason']) if r['SeriesSeason'] else None,
 
136
                                      int(r['SeriesEpisode']) if r['SeriesEpisode'] else None)
 
137
                for r in response['data']]
 
138
 
 
139
    def list_subtitles(self, video, languages):
 
140
        query = None
 
141
        if ('opensubtitles' not in video.hashes or not video.size) and not video.imdb_id:
 
142
            query = video.name.split(os.sep)[-1]
 
143
        return self.query(languages, hash=video.hashes.get('opensubtitles'), size=video.size, imdb_id=video.imdb_id,
 
144
                          query=query)
 
145
 
 
146
    def download_subtitle(self, subtitle):
 
147
        try:
 
148
            response = self.server.DownloadSubtitles(self.token, [subtitle.id])
 
149
        except xmlrpclib.ProtocolError:
 
150
            raise ProviderNotAvailable
 
151
        if response['status'] != '200 OK':
 
152
            raise ProviderError('Download failed with status %r' % response['status'])
 
153
        if not response['data']:
 
154
            raise ProviderError('Nothing to download')
 
155
        subtitle_bytes = zlib.decompress(base64.b64decode(response['data'][0]['data']), 47)
 
156
        subtitle_text = subtitle_bytes.decode(charade.detect(subtitle_bytes)['encoding'], 'replace')
 
157
        if not is_valid_subtitle(subtitle_text):
 
158
            raise InvalidSubtitle
 
159
        return subtitle_text