Compare commits

..

8 Commits

Author SHA1 Message Date
Antoine Bertin f264092e74 Release v0.3 2011-08-18 08:55:19 +02:00
Antoine Bertin 052481c0a1 Add more checks before adjusting permissions 2011-08-18 08:55:05 +02:00
Antoine Bertin 4e3f622de0 Add possibility to choose mode of created files (chmod) 2011-08-17 22:15:10 +02:00
Antoine Bertin 143c46fff0 Fix encoding issues with logging 2011-08-17 21:16:47 +02:00
Antoine Bertin bc8b0c762d Add a script to ease subtitles download 2011-07-31 19:42:58 +02:00
Antoine Bertin 9ec92d1be4 Fix dependencies failure when installing package 2011-07-31 19:42:25 +02:00
Antoine Bertin 29ee43a67d Fix a bug when series is not guessed by guessit 2011-07-23 13:39:11 +02:00
Antoine Bertin 0f15f8f52d Revert to development version 2011-07-23 13:24:30 +02:00
13 changed files with 154 additions and 24 deletions
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Subliminal - Subtitles, faster than your thoughts
# Copyright (c) 2008-2011 Patrick Dessalle <patrick@dessalle.be>
# Copyright (c) 2011 Antoine Bertin <diaoulael@gmail.com>
#
# This file is part of Subliminal.
#
# Subliminal is free software; you can redistribute it and/or modify it under
# the terms of the Lesser GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Subliminal 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
# Lesser GNU General Public License for more details.
#
# You should have received a copy of the Lesser GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from optparse import OptionParser
import subliminal
import logging
import mimetypes
import os
import sys
def main():
'''Download subtitles'''
# parse command line options
parser = OptionParser("usage: %prog [options] file1 file2", version=subliminal.__version__)
parser.add_option("-l", "--language", action="append", dest="languages", help="wanted language (ISO 639-1 two chars) for the subtitles (e.g. fr, en). Multiple uses allowed such that `%prog -l fr -l en file1`")
parser.add_option("-m", "--multi", action="store_true", dest="multi", help="download one subtitle per specified language (instead of one of them) and name them accordingly (e.g. .fr.srt, .en.srt)")
parser.add_option("-p", "--plugin", action="append", dest="plugins", help="plugins to activate")
parser.add_option("-f", "--force", action="store_true", dest="force", help="force download of a subtitle even there is already one present")
parser.add_option("-C", "--no-config-file", action="store_false", dest="config", help="do not use configuration file (requires -l to be specified)")
parser.add_option("-c", "--config-file", action="store", dest="config", help="configuration file to use")
parser.add_option("-w", "--workers", action="store", dest="workers", help="specify the number of threads to use")
parser.add_option("--cache-dir", action="store", dest="cache_dir", help="cache directory to use")
parser.add_option("--no-cache-dir", action="store_false", dest="cache_dir", help="do not use cache directory (some plugins may not work)")
parser.add_option("--list-all-plugins", action="store_true", dest="list_all_plugins", help="list all plugins available")
parser.add_option("--list-api-plugins", action="store_true", dest="list_api_plugins", help="list api-based plugins")
parser.add_option("--list-active-plugins", action="store_true", dest="list_active_plugins", help="list currently active plugins")
parser.add_option("-v", "--verbose", action="count", dest="verbose", help="increase verbosity (maximum 2 times)")
parser.set_defaults(verbose=0, cache_dir=True, config=True, workers=4)
(options, args) = parser.parse_args()
if not args:
print parser.print_help()
exit(1)
if options.verbose == 2:
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-24s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
elif options.verbose == 1:
logging.basicConfig(level=logging.WARN, format='%(levelname)s: %(name)s %(message)s')
else:
logging.basicConfig(level=logging.ERROR)
if not options.config and not options.languages:
parser.error("Option -C (--no-config-file) is used without -l (--language)")
subliminal_client = subliminal.Subliminal(config=options.config, cache_dir=options.cache_dir, workers=options.workers, multi=options.multi, force=options.force, max_depth=3, autostart=False)
if options.plugins:
subliminal_client.plugins = options.plugins
if options.list_all_plugins:
plugins = subliminal_client.listExistingPlugins()
print ', '.join(subliminal_client.listExistingPlugins())
exit(0)
if options.list_api_plugins:
plugins = subliminal_client.list_api_plugins()
print ', '.join(subliminal_client.listExistingPlugins())
exit(0)
if options.list_active_plugins:
plugins = subliminal_client.plugins
print ', '.join(subliminal_client.listExistingPlugins())
exit(0)
if options.languages:
subliminal_client.languages = options.languages
else:
logging.info(u"No language given, looking into configuration file")
languages = subliminal_client.languages
if not languages:
logging.error(u"No language found in configuration file")
sys.stderr.write("No language found in configuration file")
exit(1)
parser.exit
subliminal_client.startWorkers()
subtitles = subliminal_client.downloadSubtitles(args)
subliminal_client.stopWorkers()
if len(subtitles) == 0:
sys.stderr.write("No subtitles found")
exit(1)
print "*" * 50
print "Downloaded %s subtitles" % len(subtitles)
for s in subtitles:
print s['lang'] + " - " + s['subtitlepath']
print "*" * 50
if __name__ == "__main__":
main()
+10 -9
View File
@@ -21,13 +21,13 @@
#
from setuptools import setup
from subliminal import __version__
execfile('subliminal/version.py')
setup(name='subliminal',
version=__version__,
license="LGPLv3",
description="Subliminal - Subtitles, faster than your thoughts",
license='LGPLv3',
description='Subliminal - Subtitles, faster than your thoughts',
classifiers=['Development Status :: 4 - Beta',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
'Intended Audience :: Developers',
@@ -36,9 +36,10 @@ setup(name='subliminal',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Multimedia :: Video'],
keywords='subliminal video movie subtitle python library',
author="Antoine Bertin",
author_email="diaoulael@gmail.com",
url="https://github.com/Diaoul/subliminal",
packages=["subliminal", "subliminal/plugins"],
py_modules=["subliminal"],
install_requires=["BeautifulSoup>=3.2.0", "guessit>=0.2"])
author='Antoine Bertin',
author_email='diaoulael@gmail.com',
url='https://github.com/Diaoul/subliminal',
packages=['subliminal', 'subliminal/plugins'],
scripts=['scripts/subliminal'],
py_modules=['subliminal'],
install_requires=['BeautifulSoup>=3.2.0', 'guessit>=0.2'])
+3 -3
View File
@@ -54,10 +54,10 @@ class PluginWorker(threading.Thread):
while task['subtitle']:
subtitle = task['subtitle'].pop(0)
# get the corresponding plugin
plugin = getattr(plugins, subtitle["plugin"])(task['config'])
plugin = getattr(plugins, subtitle['plugin'])(task['config'])
path = plugin.download(subtitle)
if path:
subtitle["subtitlepath"] = path
subtitle['subtitlepath'] = path
result = subtitle
break
else:
@@ -68,4 +68,4 @@ class PluginWorker(threading.Thread):
finally:
self.resultQueue.put(result)
self.taskQueue.task_done()
self.logger.debug(u"Thread %s terminated" % self.name)
self.logger.debug(u'Thread %s terminated' % self.name)
+2 -4
View File
@@ -19,7 +19,5 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__version__ = '0.2'
from subliminal import *
from subliminal import Subliminal
from version import __version__
+1 -1
View File
@@ -94,7 +94,7 @@ class Addic7ed(PluginBase.PluginBase):
release_group.add(guess['title'])
if 'screenSize' in guess:
release_group.add(guess['screenSize'])
if len(release_group) == 0:
if 'series' not in guess or len(release_group) == 0:
return []
self.release_group = release_group # used to sort results
return self.query(guess['series'], guess['season'], guess['episodeNumber'], release_group, filepath, languages)
+1 -1
View File
@@ -88,7 +88,7 @@ class BierDopje(PluginBase.PluginBase):
release_group.add(guess['title'].lower())
if 'screenSize' in guess:
release_group.add(guess['screenSize'].lower())
if len(release_group) == 0:
if 'series' not in guess or len(release_group) == 0:
return []
self.release_group = release_group # used to sort results
return self.query(guess['series'], guess['season'], guess['episodeNumber'], release_group, filepath, languages)
+3 -2
View File
@@ -33,7 +33,7 @@ class OpenSubtitles(PluginBase.PluginBase):
site_url = 'http://www.opensubtitles.org'
site_name = 'OpenSubtitles'
server_url = 'http://api.opensubtitles.org/xml-rpc'
user_agent = 'Subliminal v0.2'
user_agent = 'Subliminal v0.3'
multi_languages_queries = True
multi_filename_queries = False
api_based = True
@@ -112,6 +112,7 @@ class OpenSubtitles(PluginBase.PluginBase):
f = ek.ek(gzip.open, subtitleFilename + ".gz")
dump = ek.ek(open, subtitleFilename, "wb")
dump.write(f.read())
self.adjustPermissions(subtitleFilename)
dump.close()
f.close()
ek.ek(os.remove, subtitleFilename + ".gz")
@@ -133,7 +134,7 @@ class OpenSubtitles(PluginBase.PluginBase):
if not imdbID and not moviehash and not bytesize:
self.logger.debug(u"No search term, we'll use the filename")
guess = guessit.guess_file_info(filepath, 'autodetect')
if guess['type'] == 'episode':
if guess['type'] == 'episode' and 'series' in guess:
search['query'] = guess['series']
elif guess['type'] == 'movie':
search['query'] = guess['title']
+5
View File
@@ -95,6 +95,7 @@ class PluginBase(object):
f = urllib2.urlopen(req, data=data)
dump = ek.ek(open, filename, "wb")
dump.write(f.read())
self.adjustPermissions(filename)
dump.close()
f.close()
self.logger.debug(u"Download finished for file %s. Size: %s" % (filename, ek.ek(os.path.getsize, filename)))
@@ -103,6 +104,10 @@ class PluginBase(object):
except urllib2.URLError, e:
self.logger.error(u"URL Error:", e.reason, url)
def adjustPermissions(self, filepath):
if self.config_dict and 'files_mode' in self.config_dict and self.config_dict['files_mode'] != -1:
ek.ek(os.chmod, filepath, self.config_dict['files_mode'])
@abc.abstractmethod
def list(self, filenames, languages):
"""Main method to call when you want to list subtitles"""
+1
View File
@@ -113,6 +113,7 @@ class SubScene(PluginBase.PluginBase):
outfile = ek.ek(open, subtitlefilename, "wb")
outfile.write(zf.read(el.orig_filename))
outfile.flush()
self.adjustPermissions(subtitlefilename)
outfile.close()
else:
self.logger.info(u"File %s does not seem to be valid " % el.orig_filename)
+1 -1
View File
@@ -75,7 +75,7 @@ class SubsWiki(PluginBase.PluginBase):
release_group.add(guess['title'])
if 'screenSize' in guess:
release_group.add(guess['screenSize'])
if len(release_group) == 0:
if 'series' not in guess or len(release_group) == 0:
return []
self.release_group = release_group # used to sort results
return self.query(guess['series'], guess['season'], guess['episodeNumber'], release_group, filepath, languages)
+1 -1
View File
@@ -75,7 +75,7 @@ class Subtitulos(PluginBase.PluginBase):
release_group.add(guess['title'].lower())
if 'screenSize' in guess:
release_group.add(guess['screenSize'].lower())
if len(release_group) == 0:
if 'series' not in guess or len(release_group) == 0:
return []
self.release_group = release_group # used to sort results
return self.query(guess['series'], guess['season'], guess['episodeNumber'], release_group, filepath, languages)
+4 -2
View File
@@ -50,7 +50,7 @@ if not SYS_ENCODING or SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
class Subliminal(object):
"""Main Subliminal class"""
def __init__(self, config=True, cache_dir=True, workers=4, multi=False, force=False, max_depth=3, autostart=False, plugins_config=None):
def __init__(self, config=True, cache_dir=True, workers=4, multi=False, force=False, max_depth=3, autostart=False, plugins_config=None, files_mode=-1):
# set default values
self.multi = multi
self.force = force
@@ -64,6 +64,7 @@ class Subliminal(object):
self._plugins = self.listAPIPlugins()
self.workers = workers
self.plugins_config = plugins_config
self.files_mode = files_mode
if autostart:
self.startWorkers()
# handle configuration file preferences
@@ -193,7 +194,7 @@ class Subliminal(object):
def set_plugins(self, value):
"""Set plugins and save to configuration file if specified by the constructor"""
logger.debug(u"Setting plugins to %s" % value)
logger.debug(u'Setting plugins to %r' % value)
self._plugins = filter(self.isValidPlugin, value)
if self.config:
self._savePluginsToConfig()
@@ -422,4 +423,5 @@ class Subliminal(object):
if self.plugins_config and 'subtitlesource_key' in self.plugins_config:
config['subtitlesource_key'] = self.plugins_config['subtitlesource_key']
config['force'] = self.force
config['files_mode'] = self.files_mode
return config
+22
View File
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#
# Subliminal - Subtitles, faster than your thoughts
# Copyright (c) 2011 Antoine Bertin <diaoulael@gmail.com>
#
# This file is part of Subliminal.
#
# Subliminal is free software; you can redistribute it and/or modify it under
# the terms of the Lesser GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Subliminal 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
# Lesser GNU General Public License for more details.
#
# You should have received a copy of the Lesser GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__version__ = '0.3'