def on_task_input(self, task, config): session = requests.Session() data = { 'username': config['username'], 'password': config['password'], 'sub_login': '******' } try: r = session.post('http://www.pogdesign.co.uk/cat/', data=data) if 'U / P Invalid' in r.text: raise plugin.PluginError( 'Invalid username/password for pogdesign.') page = session.get('http://www.pogdesign.co.uk/cat/showselect.php') except requests.RequestException as e: raise plugin.PluginError('Error retrieving source: %s' % e) soup = get_soup(page.text) entries = [] for row in soup.find_all('label', {'class': 'label_check'}): if row.find(attrs={'checked': 'checked'}): t = row.find('strong').text if t.endswith('[The]'): t = 'The ' + t[:-6] # Make certain names friendlier if t in self.name_map: t = self.name_map[t] e = Entry() e['title'] = t url = row.find_next('a', {'class': 'slink'}) e['url'] = 'http://www.pogdesign.co.uk' + url['href'] entries.append(e) return entries
def _login(self, config): """Authenicate with the myepisodes service and return a requests session Return: requests session Raises: PluginWarning if login fails PluginError if http communication fails """ url = "https://www.myepisodes.com/login.php" session = requests.Session() payload = { 'username': config['username'], 'password': config['password'], 'action': 'Login', } try: response = session.post(url, data=payload) if 'login' in response.url: raise plugin.PluginWarning( ( 'Login to myepisodes.com failed, please see if the site is down and verify ' 'your credentials.' ), log, ) except requests.RequestException as e: raise plugin.PluginError('Error logging in to myepisodes: %s' % e) return session
def on_task_output(self, task, config): session = requests.Session() auth = (config.get('user'), config.get('pass')) url = config['url'] + '/' + phpFile for entry in task.accepted: path = entry.get('path', config.get('path', '')) try: path = os.path.normcase(os.path.expanduser(entry.render(path))) except RenderError as e: log.error( 'Could not render path for `%s` downloading to default directory.' % entry['title']) # Add to default folder path = '' payload = {'dir_edit': path, 'url': entry['url']} if (config['autostart'] == False): payload.update({'torrents_start_stopped': '1'}) if task.options.test: log.info('Would add `%s` to rutorrent' % entry['title']) continue result = session.get(url, params=payload, auth=auth) if (result.json()['result'] == 'Success'): log.info('Added `%s` to rutorrent' % entry['title']) log.info('in folder %s ' % path) else: entry.fail('Fail to add `%s` to rutorrent' % entry['url'])
def on_task_input(self, task, config): sess = requests.Session() if config.get('username') and config.get('password'): log.verbose('Logging in ...') # Log in to imdb with our handler params = { 'login': config['username'], 'password': config['password'] } try: # First get the login page so we can get the hidden input value soup = get_soup( sess.get( 'https://secure.imdb.com/register-imdb/login').content) tag = soup.find('input', attrs={'name': '49e6c'}) if tag: params['49e6c'] = tag['value'] else: log.warning( 'Unable to find required info for imdb login, maybe their login method has changed.' ) # Now we do the actual login with appropriate parameters r = sess.post('https://secure.imdb.com/register-imdb/login', data=params, raise_status=False) except requests.RequestException, e: raise PluginError('Unable to login to imdb: %s' % e.message) # IMDb redirects us upon a successful login. if r.status_code != 302: log.warning('It appears logging in to IMDb was unsuccessful.') # try to automatically figure out user_id from watchlist redirect url if not 'user_id' in config: log.verbose('Getting user_id ...') response = sess.get('http://www.imdb.com/list/watchlist') log.debug('redirected to %s' % response.url) user_id = response.url.split('/')[-2] if re.match(USER_ID_RE, user_id): config['user_id'] = user_id else: raise PluginError( 'Couldn\'t figure out user_id, please configure it manually.' )
def on_task_input(self, task, config): session = requests.Session() data = { 'username': config['username'], 'password': config['password'], 'sub_login': '******', } try: r = session.post('https://www.pogdesign.co.uk/cat/login', data=data) if 'Login to Your Account' in r.text: raise plugin.PluginError( 'Invalid username/password for pogdesign.') page = session.get('https://www.pogdesign.co.uk/cat/show-select') except requests.RequestException as e: raise plugin.PluginError('Error retrieving source: %s' % e) soup = get_soup(page.text) entries = [] for row in soup.find_all('li', {'class': 'selectgrp checked'}): # Get name t = row.find('strong') # Remove <span> tags spantags = t.find_all('span') for s in spantags: s.extract() t = row.text # remove newlines and whitepsace t = t.replace('\n', '').strip() if t.endswith('[The]'): t = 'The ' + t[:-6] # Make certain names friendlier if t in self.name_map: t = self.name_map[t] e = Entry() e['title'] = t e['url'] = 'https://www.pogdesign.co.uk/{0}'.format( row.find_next('a')['href'].lstrip('/')) entries.append(e) return entries
def get_session(account=None, token=None): """ Creates a requests session ready to talk to trakt API with FlexGet's api key. Can also add user level authentication if `account` parameter is given. :param account: An account authorized via `flexget trakt auth` CLI command. If given, returned session will be authenticated for that account. """ # default to username if account name is not specified session = requests.Session() session.headers = { 'Content-Type': 'application/json', 'trakt-api-version': 2, 'trakt-api-key': CLIENT_ID, } if account: access_token = get_access_token(account, token) if account else None if access_token: session.headers.update({'Authorization': 'Bearer %s' % access_token}) return session
def _reset(self): """Reset task state""" log.debug('resetting %s' % self.name) self.enabled = not self.name.startswith('_') self.session = None self.priority = 65535 self.requests = requests.Session() # List of all entries in the task self._all_entries = EntryContainer() self.disabled_phases = [] self._abort = False self._abort_reason = None self._silent_abort = False self._rerun = False # current state self.current_phase = None self.current_plugin = None
def _reset(self): """Reset task state""" log.debug('resetting %s' % self.name) self.enabled = True self.session = None self.priority = 65535 self.requests = requests.Session() # List of all entries in the task self._all_entries = EntryContainer(task=self) self.disabled_phases = [] # TODO: task.abort() should be done by using exception? not a flag that has to be checked everywhere self._abort = False self._abort_reason = None self._silent_abort = False self._rerun = False # current state self.current_phase = None self.current_plugin = None
from builtins import * from future.moves.urllib.parse import quote_plus import logging import re from flexget import plugin from flexget.entry import Entry from flexget.event import event from flexget.utils import requests from flexget.utils.soup import get_soup from flexget.utils.search import normalize_unicode log = logging.getLogger('search_cpasbien') session = requests.Session() class SearchCPASBIEN(object): schema = { 'type': 'object', 'properties': { 'category': { 'type': 'string', 'enum': [ 'films', 'series', 'musique', 'films-french', '720p', 'series-francaise', 'films-dvdrip', 'all', 'films-vostfr', '1080p', 'series-vostfr', 'ebook' ] },
def on_task_output(self, task, config): if not config.get('enabled', True): return if not task.accepted: return session = requests.Session() url = config['url'] if not url.endswith('/'): url += '/' auth = (config['username'], config['password']) # Login try: response = session.get(url + 'token.html', auth=auth) except requests.RequestException as e: if hasattr(e, 'response') and e.response.status_code == '401': raise plugin.PluginError( 'Invalid credentials, check your utorrent webui username and password.', log) raise plugin.PluginError('%s' % e, log) token = get_soup(response.text).find('div', id='token').text result = session.get(url, auth=auth, params={ 'action': 'list-dirs', 'token': token }).json() download_dirs = dict((os.path.normcase(dir['path']), i) for i, dir in enumerate(result['download-dirs'])) for entry in task.accepted: # http://[IP]:[PORT]/gui/?action=add-url&s=[TORRENT URL] # bunch of urls now going to check folder = 0 path = entry.get('path', config.get('path', '')) try: path = os.path.normcase(os.path.expanduser(entry.render(path))) except RenderError as e: log.error( 'Could not render path for `%s` downloading to default directory.' % entry['title']) # Add to default folder path = '' if path: for dir in download_dirs: if path.startswith(dir): folder = download_dirs[dir] path = path[len(dir):].lstrip('\\') break else: log.error( 'path `%s` (or one of its parents)is not added to utorrent webui allowed download ' 'directories. You must add it there before you can use it from flexget. ' 'Adding to default download directory instead.') path = '' # Add torrent data = { "action": "add-url", "s": entry['url'], "token": token, "download_dir": folder, "path": path } result = session.get(url, params=data, auth=auth) if 'build' in result.json(): log.info("Added `%s` to utorrent" % entry['url']) log.info("in folder %s " % folder + path) else: entry.fail("Fail to add '%s' to utorrent" % entry['url'])
def on_task_output(self, task, config): if not config.get('enabled', True): return if not task.accepted: return # don't add when learning if task.options.learn: return session = requests.Session() url = config['url'] if not url.endswith('/'): url += '/' auth = (config['username'], config['password']) # Login try: response = session.get(url + 'token.html', auth=auth) except requests.RequestException as e: if hasattr(e, 'response') and e.response.status_code == '401': raise plugin.PluginError( 'Invalid credentials, check your utorrent webui username and password.', log) raise plugin.PluginError('%s' % e, log) token = get_soup(response.text).find('div', id='token').text result = session.get(url, auth=auth, params={ 'action': 'list-dirs', 'token': token }).json() download_dirs = dict((os.path.normcase(dir['path']), i) for i, dir in enumerate(result['download-dirs'])) for entry in task.accepted: # bunch of urls now going to check folder = 0 path = entry.get('path', config.get('path', '')) try: path = os.path.expanduser(entry.render(path)) except RenderError as e: log.error( 'Could not render path for `%s` downloading to default directory.' % entry['title']) # Add to default folder path = '' if path: path_normcase = os.path.normcase(path) for dir in download_dirs: if path_normcase.startswith(dir): folder = download_dirs[dir] path = path[len(dir):].lstrip('\\') break else: log.error( 'path `%s` (or one of its parents)is not added to utorrent webui allowed download ' 'directories. You must add it there before you can use it from flexget. ' 'Adding to default download directory instead.' % path) path = '' if task.options.test: log.info('Would add `%s` to utorrent' % entry['title']) continue # Get downloaded downloaded = not entry['url'].startswith('magnet:') # Check that file is downloaded if downloaded and 'file' not in entry: entry.fail('file missing?') continue # Verify the temp file exists if downloaded and not os.path.exists(entry['file']): tmp_path = os.path.join(task.manager.config_base, 'temp') log.debug('entry: %s' % entry) log.debug('temp: %s' % ', '.join(os.listdir(tmp_path))) entry.fail("Downloaded temp file '%s' doesn't exist!?" % entry['file']) continue # Add torrent if downloaded: # HTTP://[IP]:[PORT]/GUI/?ACTION=ADD-FILE files = {'torrent_file': open(entry['file'], 'rb')} data = { 'action': 'add-file', 'token': token, 'download_dir': folder, 'path': path } result = session.post(url, params=data, auth=auth, files=files) else: # http://[IP]:[PORT]/gui/?action=add-url&s=[TORRENT URL] data = { 'action': 'add-url', 's': entry['url'], 'token': token, 'download_dir': folder, 'path': path } result = session.get(url, params=data, auth=auth) # Check result if 'build' in result.json(): log.info('Added `%s` to utorrent' % entry['url']) log.info('in folder %s ' % folder + path) else: entry.fail('Fail to add `%s` to utorrent' % entry['url'])
def __init__(self, manager, name, config=None, options=None, output=None, priority=None): """ :param Manager manager: Manager instance. :param string name: Name of the task. :param dict config: Task configuration. :param options: dict or argparse namespace with options for this task :param output: A filelike that all logs and stdout will be sent to for this task. :param priority: If multiple tasks are waiting to run, the task with the lowest priority will be run first. The default is 0, if the cron option is set though, the default is lowered to 10. """ self.name = unicode(name) self.manager = manager if config is None: config = manager.config['tasks'].get(name, {}) self.config = copy.deepcopy(config) self.prepared_config = None if options is None: options = copy.copy(self.manager.options.execute) elif isinstance(options, dict): options_namespace = copy.copy(self.manager.options.execute) options_namespace.__dict__.update(options) options = options_namespace self.options = options self.output = output if priority is None: self.priority = 10 if self.options.cron else 0 else: self.priority = priority self.priority = priority self._count = next(self._counter) self.finished_event = threading.Event() # simple persistence self.simple_persistence = SimpleTaskPersistence(self) # not to be reset self._rerun_count = 0 self.config_modified = None self.enabled = not self.name.startswith('_') # These are just to query what happened in task. Call task.abort to set. self.aborted = False self.abort_reason = None self.silent_abort = False self.session = None self.requests = requests.Session() # List of all entries in the task self._all_entries = EntryContainer() self._rerun = False self.disabled_phases = [] # current state self.current_phase = None self.current_plugin = None
import logging import re from datetime import datetime from sqlalchemy import Column, Unicode, Integer from flexget import plugin from flexget.event import event from flexget.utils import requests from flexget.utils.soup import get_soup from flexget.utils.titles.series import SeriesParser from flexget.db_schema import versioned_base log = logging.getLogger('pogcal_acquired') Base = versioned_base('pogcal_acquired', 0) session = requests.Session(max_retries=3) series_parser = SeriesParser() class PogcalShow(Base): __tablename__ = 'pogcal_shows' id = Column(Integer, primary_key=True, autoincrement=False, nullable=False) name = Column(Unicode) class PogcalAcquired(object): schema = { 'type': 'object', 'properties': { 'username': {
def __init__( self, manager, name, config=None, options=None, output=None, loglevel=None, priority=None, suppress_warnings=None, ): """ :param Manager manager: Manager instance. :param string name: Name of the task. :param dict config: Task configuration. :param options: dict or argparse namespace with options for this task :param output: A filelike that all logs and stdout will be sent to for this task. :param loglevel: Custom loglevel, only log messages at this level will be sent to `output` :param priority: If multiple tasks are waiting to run, the task with the lowest priority will be run first. The default is 0, if the cron option is set though, the default is lowered to 10. :param suppress_warnings: Allows suppressing log warning about missing plugin in key phases """ self.name = str(name) self.id = ''.join(random.choice(string.digits) for _ in range(6)) self.manager = manager if config is None: config = manager.config['tasks'].get(name, {}) self.config = copy.deepcopy(config) self.prepared_config = None if options is None: options = copy.copy(self.manager.options.execute) elif isinstance(options, dict): options_namespace = copy.copy(self.manager.options.execute) options_namespace.__dict__.update(options) options = options_namespace # If execution hasn't specifically set the `allow_manual` flag, set it to False by default if not hasattr(options, 'allow_manual'): setattr(options, 'allow_manual', False) self.options = options self.output = output self.loglevel = loglevel self.suppress_warnings = suppress_warnings or [] if priority is None: self.priority = 10 if self.options.cron else 0 else: self.priority = priority self.priority = priority self._count = next(self._counter) self.finished_event = threading.Event() # simple persistence self.simple_persistence = SimpleTaskPersistence(self) # rerun related flags and values self._rerun_count = 0 self._max_reruns = Task.RERUN_DEFAULT self._reruns_locked = False self.config_modified = None self.enabled = not self.name.startswith('_') # These are just to query what happened in task. Call task.abort to set. self.aborted = False self.abort_reason = None self.silent_abort = False self.session = None self.requests = requests.Session() # List of all entries in the task self._all_entries = EntryContainer() self._rerun = False self.disabled_phases = [] # current state self.current_phase = None self.current_plugin = None
def on_task_input(self, task, config): sess = requests.Session() if config.get('username') and config.get('password'): log.verbose('Logging in ...') # Log in to imdb with our handler params = { 'login': config['username'], 'password': config['password'] } try: # First get the login page so we can get the hidden input value soup = get_soup( sess.get( 'https://secure.imdb.com/register-imdb/login').content) # Fix for bs4 bug. see #2313 and github#118 auxsoup = soup.find('div', id='nb20').next_sibling.next_sibling tag = auxsoup.find('input', attrs={'name': '49e6c'}) if tag: params['49e6c'] = tag['value'] else: log.warning( 'Unable to find required info for imdb login, maybe their login method has changed.' ) # Now we do the actual login with appropriate parameters r = sess.post('https://secure.imdb.com/register-imdb/login', data=params, raise_status=False) except requests.RequestException as e: raise plugin.PluginError('Unable to login to imdb: %s' % e.message) # IMDb redirects us upon a successful login. # removed - doesn't happen always? # if r.status_code != 302: # log.warning('It appears logging in to IMDb was unsuccessful.') # try to automatically figure out user_id from watchlist redirect url if not 'user_id' in config: log.verbose('Getting user_id ...') try: response = sess.get('http://www.imdb.com/list/watchlist') except requests.RequestException as e: log.error('Error retrieving user ID from imdb: %s' % e.message) user_id = '' else: log.debug('redirected to %s' % response.url) user_id = response.url.split('/')[-2] if re.match(USER_ID_RE, user_id): config['user_id'] = user_id else: raise plugin.PluginError( 'Couldn\'t figure out user_id, please configure it manually.' ) if not 'user_id' in config: raise plugin.PluginError( 'Configuration option `user_id` required.') log.verbose('Retrieving list %s ...' % config['list']) # Get the imdb list in csv format try: url = 'http://www.imdb.com/list/export' params = { 'list_id': config['list'], 'author_id': config['user_id'] } log.debug('Requesting %s' % url) opener = sess.get(url, params=params) mime_type = parse_header(opener.headers['content-type'])[0] log.debug('mime_type: %s' % mime_type) if mime_type != 'text/csv': raise plugin.PluginError( 'Didn\'t get CSV export as response. Probably specified list `%s` ' 'does not exist.' % config['list']) csv_rows = csv.reader(opener.iter_lines()) except requests.RequestException as e: raise plugin.PluginError('Unable to get imdb list: %s' % e.message) # Create an Entry for each movie in the list entries = [] for row in csv_rows: if not row or row[0] == 'position': # Don't use blank rows or the headings row continue try: title = decode_html(row[5]).decode('utf-8') entries.append( Entry(title=title, url=make_url(row[1]), imdb_id=row[1], imdb_name=title)) except IndexError: log.critical('IndexError! Unable to handle row: %s' % row) return entries
def search(self, entry, config): login_sess = requests.Session() login_params = { 'username': config['username'], 'password': config['password'], 'loginkey': config['login_key'] } try: login_sess.post('https://piratethenet.org/takelogin.php', data=login_params, verify=False) except requests.RequestException as e: log.error('Error while logging in to PtN: %s', e) download_auth = CookieAuth(login_sess.cookies) # Default to searching by title (0=title 3=imdb_id) search_by = 0 if 'imdb_id' in entry: searches = [entry['imdb_id']] search_by = 3 elif 'movie_name' in entry: search = entry['movie_name'] if 'movie_year' in entry: search += ' %s' % entry['movie_year'] searches = [search] else: searches = entry.get('search_strings', [entry['title']]) params = {'_by': search_by} if config.get('categories'): for cat in config['categories']: params[categories[cat]] = 1 results = set() for search in searches: params['search'] = search try: r = login_sess.get('http://piratethenet.org/browse.php', params=params) except requests.RequestException as e: log.error('Error searching ptn: %s' % e) continue soup = get_soup(r.text) if 'login' in soup.head.title.text.lower(): log.error('PtN cookie info invalid') raise plugin.PluginError('PTN cookie info invalid') try: results_table = soup.find_all('table', attrs={'class': 'main'}, limit=2)[1] except IndexError: log.debug('no results found for `%s`' % search) continue for row in results_table.find_all('tr')[1:]: columns = row.find_all('td') entry = Entry() links = columns[1].find_all('a', recursive=False, limit=2) entry['title'] = links[0].text if len(links) > 1: entry['imdb_id'] = extract_id(links[1].get('href')) entry['url'] = 'http://piratethenet.org/' + columns[2].a.get( 'href') entry['download_auth'] = download_auth entry['torrent_seeds'] = int(columns[8].text) entry['torrent_leeches'] = int(columns[9].text) entry['search_sort'] = torrent_availability( entry['torrent_seeds'], entry['torrent_leeches']) size = columns[6].find('br').previous_sibling unit = columns[6].find('br').next_sibling if unit == 'GB': entry['content_size'] = int(float(size) * 1024) elif unit == 'MB': entry['content_size'] = int(float(size)) elif unit == 'KB': entry['content_size'] = int(float(size) / 1024) results.add(entry) return results