def on_task_output(self, task, config): """ Configuration:: notify_xmpp: title: Message title, supports jinja templating, default {{task.name}} text: Message text, suports jinja templating, default {{title}} """ if not config or not task.accepted: return title = config['title'] try: title = render_from_task(title, task) log.debug('Setting message title to :%s', title) except RenderError as e: log.error('Error setting title message: %s' % e) items = [] for entry in task.accepted: try: items.append(entry.render(config['text'])) except RenderError as e: log.error('Error setting text message: %s' % e) text = '%s\n%s' % (title, '\n'.join(items)) log.verbose('Send XMPP notification about: %s', ' - '.join(items)) logging.getLogger('sleekxmpp').setLevel(logging.CRITICAL) recipients = config.get('recipients', []) if not isinstance(recipients, list): recipients = [recipients] xmpp = SendMsgBot(config['sender'], config['password'], recipients, text) if xmpp.connect(): xmpp.process(block=True)
def on_task_exit(self, task, config): """Send email at exit.""" config = prepare_config(config) if not config['active']: return # don't send mail when learning if task.manager.options.learn: return # generate email content if config.get('subject'): subject = config['subject'] else: subject = '[FlexGet] {{task.name}}: ' if task.aborted: subject += 'Aborted' elif task.failed: subject += '{{task.failed|length}} failed entries' else: subject += '{{task.accepted|length}} new entries downloaded' try: subject = render_from_task(subject, task) except RenderError, e: log.error('Error rendering email subject: %s' % e) return
def execute(self, task, phase_name, config): config = self.prepare_config(config) if not phase_name in config: log.debug('phase %s not configured' % phase_name) return name_map = {'for_entries': task.entries, 'for_accepted': task.accepted, 'for_rejected': task.rejected, 'for_failed': task.failed} allow_background = config.get('allow_background') for operation, entries in name_map.iteritems(): if not operation in config[phase_name]: continue log.debug('running phase_name: %s operation: %s entries: %s' % (phase_name, operation, len(entries))) for entry in entries: cmd = config[phase_name][operation] entrydict = EscapingDict(entry) if config.get('auto_escape') else entry # Do string replacement from entry, but make sure quotes get escaped try: cmd = render_from_entry(cmd, entrydict) except RenderError as e: log.error('Could not set exec command for %s: %s' % (entry['title'], e)) # fail the entry if configured to do so if config.get('fail_entries'): entry.fail('Entry `%s` does not have required fields for string replacement.' % entry['title']) continue log.debug('phase_name: %s operation: %s cmd: %s' % (phase_name, operation, cmd)) if task.options.test: log.info('Would execute: %s' % cmd) else: # Make sure the command can be encoded into appropriate encoding, don't actually encode yet, # so logging continues to work. try: cmd.encode(config['encoding']) except UnicodeEncodeError: log.error('Unable to encode cmd `%s` to %s' % (cmd, config['encoding'])) if config.get('fail_entries'): entry.fail('cmd `%s` could not be encoded to %s.' % (cmd, config['encoding'])) continue # Run the command, fail entries with non-zero return code if configured to if self.execute_cmd(cmd, allow_background, config['encoding']) != 0 and config.get('fail_entries'): entry.fail('exec return code was non-zero') # phase keyword in this if 'phase' in config[phase_name]: cmd = config[phase_name]['phase'] try: cmd = render_from_task(cmd, task) except RenderError as e: log.error('Error rendering `%s`: %s' % (cmd, e)) else: log.debug('phase cmd: %s' % cmd) if task.options.test: log.info('Would execute: %s' % cmd) else: self.execute_cmd(cmd, allow_background, config['encoding'])
def on_task_exit(self, task, config): """Send email at exit.""" config = prepare_config(config) if not config['active']: return # don't send mail when learning if task.options.learn: return # generate email content if config.get('subject'): subject = config['subject'] else: subject = '[FlexGet] {{task.name}}: ' if task.aborted: subject += 'Aborted' elif task.failed: subject += '{{task.failed|length}} failed entries' else: subject += '{{task.accepted|length}} new entries downloaded' try: subject = render_from_task(subject, task) except RenderError as e: log.error('Error rendering email subject: %s' % e) return try: content = render_from_task( get_template(config['template'], 'email'), task) except RenderError as e: log.error('Error rendering email body: %s' % e) return if not content.strip(): log.verbose( 'No content generated from template, not sending email.') return if config.get('global'): # Email plugin was configured at root, save the email output log.debug('Saving email content for task %s' % task.name) task_content[task.name] = content else: send_email(subject, content, config)
def on_task_exit(self, task, config): """Send email at exit.""" config = prepare_config(config) if not config['active']: return # don't send mail when learning if task.manager.options.learn: return # generate email content if config.get('subject'): subject = config['subject'] else: subject = '[FlexGet] {{task.name}}: ' if task.aborted: subject += 'Aborted' elif task.failed: subject += '{{task.failed|length}} failed entries' else: subject += '{{task.accepted|length}} new entries downloaded' try: subject = render_from_task(subject, task) except RenderError as e: log.error('Error rendering email subject: %s' % e) return try: content = render_from_task(get_template(config['template'], 'email'), task) except RenderError as e: log.error('Error rendering email body: %s' % e) return if not content.strip(): log.verbose('No content generated from template, not sending email.') return if config.get('global'): # Email plugin was configured at root, save the email output log.debug('Saving email content for task %s' % task.name) task_content[task.name] = content else: send_email(subject, content, config)
def on_task_output(self, task, config): config = prepare_config(config) if not config["active"]: return # don't send mail when learning if task.options.learn: return # generate email content if config.get("subject"): subject = config["subject"] else: subject = "[FlexGet] {{task.name}}: " if task.aborted: subject += "Aborted" elif task.failed: subject += "{{task.failed|length}} failed entries" else: subject += "{{task.accepted|length}} new entries downloaded" try: subject = render_from_task(subject, task) except RenderError as e: log.error("Error rendering email subject: %s" % e) return try: content = render_from_task(get_template(config["template"], "email"), task) except RenderError as e: log.error("Error rendering email body: %s" % e) return if not content.strip(): log.verbose("No content generated from template, not sending email.") return if config.get("global"): # Email plugin was configured at root, save the email output log.debug("Saving email content for task %s" % task.name) task_content[task.name] = content else: send_email(subject, content, config)
def render(self, template): """ Renders a template string based on fields in the entry. :param template: A template string or FlexGetTemplate that uses jinja2 or python string replacement format. :return: The result of the rendering. :rtype: string :raises RenderError: If there is a problem. """ if not isinstance(template, (str, FlexGetTemplate)): raise ValueError( 'Trying to render non string template or unrecognized template format, got %s' % repr(template)) log.trace('rendering: %s', template) return render_from_task(template, self)
def on_task_output(self, task, config): # Use the default template if none is specified if not config.get('template'): config['template'] = 'default.template' filename = os.path.expanduser(config['template']) output = os.path.expanduser(config['file']) # Output to config directory if absolute path has not been specified if not os.path.isabs(output): output = os.path.join(task.manager.config_base, output) # create the template template = render_from_task(get_template(filename, PLUGIN_NAME), task) log.verbose('Writing output html to %s' % output) with open(output, 'w') as f: f.write(template.encode('utf-8'))
def on_task_output(self, task, config): # Use the default template if none is specified if not config.get("template"): config["template"] = "default.template" filename = os.path.expanduser(config["template"]) output = os.path.expanduser(config["file"]) # Output to config directory if absolute path has not been specified if not os.path.isabs(output): output = os.path.join(task.manager.config_base, output) # create the template template = render_from_task(get_template(filename, PLUGIN_NAME), task) log.verbose("Writing output html to %s" % output) f = open(output, "w") f.write(template.encode("utf-8")) f.close()
def on_task_output(self, task, config): # Use the default template if none is specified if not config.get('template'): config['template'] = 'default.template' filename = os.path.expanduser(config['template']) output = os.path.expanduser(config['file']) # Output to config directory if absolute path has not been specified if not os.path.isabs(output): output = os.path.join(task.manager.config_base, output) # create the template try: template = render_from_task(get_template(filename, PLUGIN_NAME), task) log.verbose('Writing output html to %s' % output) with open(output, 'w') as f: f.write(template.encode('utf-8')) except RenderError as e: log.error('Error while rendering task %s, Error: %s' % (task, e)) raise plugin.PluginError('There was an error rendering the specified template')
def on_task_output(self, task, config): """ Configuration:: notify_osd: title_template: Notification title, supports jinja templating, default {{task.name}} item_template: Notification body, suports jinja templating, default {{title}} timeout: Set how long the Notification is displayed, this is an integer default = 4 seconds, Default: 4 """ from gi.repository import Notify if not config or not task.accepted: return config = self.prepare_config(config) body_items = [] for entry in task.accepted: try: body_items.append(entry.render(config['item_template'])) except RenderError as e: log.error('Error setting body message: %s' % e) log.verbose("Send Notify-OSD notification about: %s", " - ".join(body_items)) title = config['title_template'] try: title = render_from_task(title, task) log.debug('Setting bubble title to :%s', title) except RenderError as e: log.error('Error setting title Notify-osd message: %s' % e) if not Notify.init("Flexget"): log.error('Unable to init libnotify.') return n = Notify.Notification.new(title, '\n'.join(body_items), None) timeout = (config['timeout'] * 1000) n.set_timeout(timeout) if not n.show(): log.error('Unable to send notification for %s', title) return
def on_task_output(self, task, config): if not task.accepted: log.debug('nothing accepted, aborting') return rooms = [s.encode('utf8').lower() for s in config.get('feeds', [])] if task.options.test: log.info('Test posting to feed(s): ' + ','.join(rooms)) else: from flexget.plugins.local.friendfeed2 import FriendFeed, fetch_installed_app_access_token consumer_token = {'key': config['app_key'], 'secret': config['app_secret']} access_token = fetch_installed_app_access_token(consumer_token, config['username'], config['password']) ff = FriendFeed(oauth_consumer_token=consumer_token, oauth_access_token=access_token) if config['mode'] == 'posts': for entry in task.accepted: try: fftext = entry.render(config['text']) fflink = entry.render(config['link']) if 'link' in config else None ffcomm = entry.render(config['comment']) if 'comment' in config else None ffpict = entry.render(config['image']) if 'image' in config else None except RenderError as e: log.error('Error rendering data: %s' % e) if task.options.test: log.info('Test run for entry ' + entry['title']) log.info('- Text would be: ' + fftext) if fflink: log.info('- Link would be: ' + fflink) if ffpict: log.info('- Image would be: ' + ffpict) if ffcomm: log.info('- Comment would be: ' + ffcomm) else: try: res = ff.post_entry(fftext, link=fflink, comment=ffcomm, to=','.join(rooms), image_url=ffpict) log.info('Published id: %s' % res['id']) except Exception as err: log.info('post_entry() failed with %s' % str(err)) else: if not config.get('comment'): raise plugin.PluginError('"comment" option is required when "mode"=="comments".') try: fftext = render_from_task(config['text'], task) fflink = render_from_task(config['link'], task) if 'link' in config else None ffpict = render_from_task(config['image'], task) if 'image' in config else None except RenderError as e: log.error('Error rendering data: %s' % e) if task.options.test: log.info('Test run for task.') log.info('- Text would be: ' + fftext) if fflink: log.info('- Link would be: ' + fflink) if ffpict: log.info('- Image would be: ' + ffpict) else: res = ff.post_entry(fftext, link=fflink, to=','.join(rooms), image_url=ffpict) log.info('Published id: %s' % res['id']) for entry in task.accepted: try: ffcomm = entry.render(config['comment']) except RenderError as e: log.error('Error rendering data: %s' % e) if task.options.test: log.info('- Comment would be: ' + ffcomm) else: try: time.sleep(1) rcm = ff.post_comment(res['id'], ffcomm) log.verbose('Published comment id: %s' % rcm['id']) except Exception as err: log.info('post_comment() failed with %s' % str(err))
def execute(self, task, phase_name, config): config = self.prepare_config(config) if phase_name not in config: log.debug("phase %s not configured" % phase_name) return name_map = { "for_entries": task.entries, "for_accepted": task.accepted, "for_rejected": task.rejected, "for_failed": task.failed, } allow_background = config.get("allow_background") for operation, entries in name_map.items(): if operation not in config[phase_name]: continue log.debug("running phase_name: %s operation: %s entries: %s" % (phase_name, operation, len(entries))) for entry in entries: for cmd in config[phase_name][operation]: entrydict = EscapingEntry(entry) if config.get("auto_escape") else entry # Do string replacement from entry, but make sure quotes get escaped try: cmd = render_from_entry(cmd, entrydict) except RenderError as e: log.error("Could not set exec command for %s: %s" % (entry["title"], e)) # fail the entry if configured to do so if config.get("fail_entries"): entry.fail( "Entry `%s` does not have required fields for string replacement." % entry["title"] ) continue log.debug("phase_name: %s operation: %s cmd: %s" % (phase_name, operation, cmd)) if task.options.test: log.info("Would execute: %s" % cmd) else: # Make sure the command can be encoded into appropriate encoding, don't actually encode yet, # so logging continues to work. try: cmd.encode(config["encoding"]) except UnicodeEncodeError: log.error("Unable to encode cmd `%s` to %s" % (cmd, config["encoding"])) if config.get("fail_entries"): entry.fail("cmd `%s` could not be encoded to %s." % (cmd, config["encoding"])) continue # Run the command, fail entries with non-zero return code if configured to if self.execute_cmd(cmd, allow_background, config["encoding"]) != 0 and config.get( "fail_entries" ): entry.fail("exec return code was non-zero") # phase keyword in this if "phase" in config[phase_name]: for cmd in config[phase_name]["phase"]: try: cmd = render_from_task(cmd, task) except RenderError as e: log.error("Error rendering `%s`: %s" % (cmd, e)) else: log.debug("phase cmd: %s" % cmd) if task.options.test: log.info("Would execute: %s" % cmd) else: self.execute_cmd(cmd, allow_background, config["encoding"])
def execute(self, task, phase_name, config): config = self.prepare_config(config) if phase_name not in config: log.debug('phase %s not configured' % phase_name) return name_map = { 'for_entries': task.entries, 'for_accepted': task.accepted, 'for_rejected': task.rejected, 'for_failed': task.failed } allow_background = config.get('allow_background') for operation, entries in name_map.items(): if operation not in config[phase_name]: continue log.debug('running phase_name: %s operation: %s entries: %s' % (phase_name, operation, len(entries))) for entry in entries: for cmd in config[phase_name][operation]: entrydict = EscapingEntry(entry) if config.get( 'auto_escape') else entry # Do string replacement from entry, but make sure quotes get escaped try: cmd = render_from_entry(cmd, entrydict) except RenderError as e: log.error('Could not set exec command for %s: %s' % (entry['title'], e)) # fail the entry if configured to do so if config.get('fail_entries'): entry.fail( 'Entry `%s` does not have required fields for string replacement.' % entry['title']) continue log.debug('phase_name: %s operation: %s cmd: %s' % (phase_name, operation, cmd)) if task.options.test: log.info('Would execute: %s' % cmd) else: # Make sure the command can be encoded into appropriate encoding, don't actually encode yet, # so logging continues to work. try: cmd.encode(config['encoding']) except UnicodeEncodeError: log.error('Unable to encode cmd `%s` to %s' % (cmd, config['encoding'])) if config.get('fail_entries'): entry.fail( 'cmd `%s` could not be encoded to %s.' % (cmd, config['encoding'])) continue # Run the command, fail entries with non-zero return code if configured to if (self.execute_cmd(cmd, allow_background, config['encoding']) != 0 and config.get('fail_entries')): entry.fail('exec return code was non-zero') # phase keyword in this if 'phase' in config[phase_name]: for cmd in config[phase_name]['phase']: try: cmd = render_from_task(cmd, task) except RenderError as e: log.error('Error rendering `%s`: %s' % (cmd, e)) else: log.debug('phase cmd: %s' % cmd) if task.options.test: log.info('Would execute: %s' % cmd) else: self.execute_cmd(cmd, allow_background, config['encoding'])
class OutputEmail(object): """ Send an e-mail with the list of all succeeded (downloaded) entries. Configuration options =============== =================================================================== Option Description =============== =================================================================== from The email address from which the email will be sent (required) to The email address of the recipient (required) smtp_host The host of the smtp server smtp_port The port of the smtp server smtp_username The username to use to connect to the smtp server smtp_password The password to use to connect to the smtp server smtp_tls Should we use TLS to connect to the smtp server smtp_ssl Should we use SSL to connect to the smtp server Due to a bug in python, this only works in python 2.6.3 and up active Is this plugin active or not =============== =================================================================== Config basic example:: email: from: [email protected] to: [email protected] smtp_host: smtp.host.com Config example with smtp login:: email: from: [email protected] to: [email protected] smtp_host: smtp.host.com smtp_port: 25 smtp_login: true smtp_username: my_smtp_login smtp_password: my_smtp_password smtp_tls: true Config multi-task example:: global: email: from: [email protected] to: [email protected] smtp_host: smtp.host.com tasks: task1: rss: http://xxx task2: rss: http://yyy email: active: False task3: rss: http://zzz email: to: [email protected] GMAIL example:: from: [email protected] to: [email protected] smtp_host: smtp.gmail.com smtp_port: 587 smtp_login: true smtp_username: gmailUser smtp_password: gmailPassword smtp_tls: true Default values for the config elements:: email: active: True smtp_host: localhost smtp_port: 25 smtp_login: False smtp_username: smtp_password: smtp_tls: False smtp_ssl: False """ def validator(self): v = options_validator() v.accept('boolean', key='global') return v def on_task_output(self, task, config): """Count the email as an output""" def on_task_exit(self, task, config): """Send email at exit.""" config = prepare_config(config) if not config['active']: return # don't send mail when learning if task.manager.options.learn: return # generate email content if config.get('subject'): subject = config['subject'] else: subject = '[FlexGet] {{task.name}}: ' if task.aborted: subject += 'Aborted' elif task.failed: subject += '{{task.failed|length}} failed entries' else: subject += '{{task.accepted|length}} new entries downloaded' try: subject = render_from_task(subject, task) except RenderError, e: log.error('Error rendering email subject: %s' % e) return try: content = render_from_task(get_template(config['template'], 'email'), task) except RenderError, e: log.error('Error rendering email body: %s' % e) return