示例#1
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'sickbeard_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS, host={}, apikey={})

    def validate_host(self, field, value):
        if not value:
            return value
        url = PING_URL % {'host':value, 'apikey':1234}
        response = utils.http_request(url, timeout=2).get('response')
        if not response:
            raise ValidationError('Host not reachable.')
        if response.status != 200:
            raise ValidationError('Invalid response from server: %s' % response.status)
        return value

    def validate_apikey(self, field, value):
        if not value:
            return value
        host = self.fields.host.value
        if host is None:
            host = self.pkconfig.get(self.namespace, 'host')
        url = PING_URL % {'host':host, 'apikey':value}
        response = utils.http_request(url, timeout=2).get('response')
        if not response:
            raise ValidationError('Host not reachable.')
        if response.status != 200:
            raise ValidationError('Invalid response from server: %s' % response.status)
        content = json.loads(response.read().decode('utf-8'))
        if content.get('result') != 'success':
            raise ValidationError('Invalid API key specified.')
        return value
示例#2
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'sonarr_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS, host={}, apikey={})

    def validate_host(self, field, value):
        if not value:
            return value
        url = UPDATE_URL % {'host': value, 'apikey': 1234, 'end': '2000-01-01'}
        response = utils.http_request(url, timeout=2)
        if utils.rget(response, 'error.code') != 401:
            raise ValidationError('Host not reachable.')
        return value

    def validate_apikey(self, field, value):
        if not value:
            return value
        host = self.fields.host.value
        if host is None:
            host = self.pkconfig.get(self.namespace, 'host')
        url = UPDATE_URL % {'host': host, 'apikey': value, 'end': '2000-01-01'}
        response = utils.http_request(url, timeout=2).get('response')
        if utils.rget(response, 'error.code') == 401:
            raise ValidationError('Invalid API key specified.')
        content = json.loads(response.read().decode('utf-8'))
        if not isinstance(content, list):
            raise ValidationError('Invalid response from server.')
        return value
示例#3
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'plexserver_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS,
                         host={},
                         username={'save_to_keyring': True},
                         password={'save_to_keyring': True})

    def validate_password(self, field, value):
        if not value:
            return value
        try:
            MyPlexAccount.signin(self.fields.username.value, value)
            return value
        except Unauthorized:
            raise ValidationError('Invalid username or password.')

    def validate_host(self, field, value):
        if not value:
            return value
        try:
            username = self.fields.username.value
            password = self.fields.password.value
            fetch_plex_instance(self.pkmeter, username, password, value)
            return value
        except Unauthorized:
            raise ValidationError('Invalid username or password.')
        except NotFound:
            raise ValidationError('Server host or name not found.')
        except:
            raise ValidationError('Invalid server.')
示例#4
0
 def _init(self, etree, control, parent=None):
     self.etree = etree  # Element tree to parse
     self.control = control  # Control class (for callback connect)
     self.parent = parent  # Parent widget
     self.id = None  # ID of this widget (if specified)
     self.data = utils.Bunch()  # Metadata to append to object
     self.actions = []  # List of actions
     self.manifest = utils.Bunch()  # Dict of element ids
     self.bgimage = None  # Background image
     self.bgpos = (0, 0)  # Background position 'x,y' or 'center,top' etc..
     self.bgsize = 'fit'  # Background size 'x,y' or 'fit'
     self.bgfade = 0  # Fade bgimage when changed (0 to disable)
     self.bgopacity = 1.0  # Current bgopacity (used during transition)
     self.click_enabled = False  # Set True when click event enabled
     self.dblclick_enabled = False  # Set True when dblclick event enabled
     self.installEventFilter(self)  # Capture events for interactions
     self._init_attributes()  # Process all attributes (and actions)
     self.children = self._append_children()  # Build all Chiuldren
     if parent is not None:
         parent.layout().addWidget(self)
示例#5
0
 def __init__(self, pkmeter, pkconfig):
     self.name = utils.name(self.__module__)  # Name of this Plugin
     self.namespace = utils.namespace(
         self.__module__)  # Namespace of this Config
     self.template = self._init_template()  # Template for config settings
     self.fields = utils.Bunch()  # Fields in this Config
     PKVFrame.__init__(self, self.template, self)  # Init parent widget
     self.pkmeter = pkmeter  # Reference to PKMeter
     self.pkconfig = pkconfig  # Reference to Main Config
     self._init_default_interval()
     self._init_fields()
示例#6
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'wunderground_config.html')
    FIELDS = utils.Bunch(
        BaseConfig.FIELDS,
        apikey={},
        query={},
        location={'default': 'autoip'},
    )

    def validate_apikey(self, field, value):
        if not value:
            return value
        url = UPDATE_URL % {'apikey': value, 'location': 'autoip'}
        response = utils.http_request(url, timeout=2).get('response')
        if not response:
            raise ValidationError('No response from Weather Underground.')
        content = json.loads(response.read().decode('utf-8'))
        if 'response' not in content:
            raise ValidationError('Invalid response from Weather Underground.')
        if 'current_observation' not in content:
            raise ValidationError('Invalid API key specified.')
        return value

    def validate_query(self, field, value):
        if not value or value == 'autoip':
            self.fields.location.value = 'autoip'
            field.help.setText(field.help_default)
            return value
        url = QUERY_URL % {'query': value}
        response = utils.http_request(url, timeout=2).get('response')
        if not response:
            raise ValidationError('No response from Weather Underground.')
        content = json.loads(response.read().decode('utf-8'))
        if not content.get('RESULTS'):
            raise ValidationError('Unable to determine specified location.')
        result = content['RESULTS'][0]
        self.fields.location.value = result['ll'].replace(' ', ',')
        field.help.setText(result['name'])
        return value
示例#7
0
 def _init_field(self, name, meta):
     field = utils.Bunch(meta)  # Convert to Bunch
     field.name = name  # Name of this field
     field.input = self.manifest.get(name)  # QT input element
     field.controlgroup = self.manifest.get('controlgroup_%s' %
                                            name)  # QT control group
     field.status = self.manifest.get('status_%s' % name)  # QT status label
     field.help = self.manifest.get('help_%s' % name)  # QT help label
     field.help_default = field.help.text(
     ) if field.help else None  # Default help text
     field.default = field.get('default', '')  # Default value
     field.value = self._get_value(field)  # Current value (to be saved)
     field.lastchecked = field.value  # Last value verified
     field.validator = getattr(self, 'validate_%s' % name,
                               None)  # Validator callback
     if name in self.manifest:
         if getattr(field.input, 'textEdited', None):
             field.input.textEdited.connect(
                 lambda txt, field=field: self._editing(field, txt))
         if getattr(field.input, 'editingFinished', None):
             field.input.editingFinished.connect(
                 lambda field=field: self._validate(field))
         field.input.set_value(field.value)
     self.fields[name] = field
示例#8
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'externalip_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS, url={'default': DEFUALT_URL})
示例#9
0
 def _iter_calendars(self):
     for i in range(6):
         baseurl = self.pkmeter.config.get(self.namespace, 'cal%s' % i)
         url = Plugin.build_url(baseurl)
         color = self.pkmeter.config.get(self.namespace, 'color%s' % i)
         if baseurl: yield utils.Bunch({'url': url, 'color': color})
示例#10
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'gcal_config.html')
    FIELDS = utils.Bunch(
        BaseConfig.FIELDS,
        cal1={'default': ''},
        color1={'default': '#4986E7'},
        cal2={'default': ''},
        color2={'default': '#CD74E6'},
        cal3={'default': ''},
        color3={'default': '#F83A22'},
        cal4={'default': ''},
        color4={'default': '#FFAD46'},
        cal5={'default': ''},
        color5={'default': '#7BD148'},
    )

    def __init__(self, *args, **kwargs):
        super(Config, self).__init__(*args, **kwargs)
        self._button = None
        self.colorpicker = self._init_colorpicker()

    def _init_colorpicker(self):
        colorpicker = QtWidgets.QColorDialog()
        colorpicker.finished.connect(self.colorpicker_finished)
        return colorpicker

    def btn_color(self, widget):
        self._button = widget
        self.colorpicker.setCurrentColor(utils.hex_to_qcolor(
            widget.data.color))
        self.colorpicker.open()

    def colorpicker_finished(self):
        field = self.fields[self._button.id]
        color = self.colorpicker.currentColor().name()
        self._button.set_value(color)
        self._validate(field)

    def _validate_cal(self, field, value):
        if not value:
            field.help.setText(field.help_default)
            return value
        url = Plugin.build_url(value)
        response = utils.http_request(url, timeout=2).get('response')
        if not response:
            raise ValidationError('No response from Google.')
        ical = Calendar.from_ical(response.read().decode('utf-8'))
        title = ical.get('x-wr-calname', ical.get('version', ''))
        if not title:
            raise ValidationError('Invalid response from Google.')
        field.help.setText(title)
        return value

    def validate_cal1(self, field, value):
        return self._validate_cal(field, value)

    def validate_cal2(self, field, value):
        return self._validate_cal(field, value)

    def validate_cal3(self, field, value):
        return self._validate_cal(field, value)

    def validate_cal4(self, field, value):
        return self._validate_cal(field, value)

    def validate_cal5(self, field, value):
        return self._validate_cal(field, value)
示例#11
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'network_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS,
                         ignores={'default': DEFAULT_IGNORES})
示例#12
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'plexmedia_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS, ignores={})
示例#13
0
class BaseConfig(PKVFrame):
    STATUS_OK = '✔'
    STATUS_ERROR = '✘'
    STATUS_LOADING = '…'
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'default_config.html')
    FIELDS = utils.Bunch(enabled={'default': True}, interval={'default': 60})

    def __init__(self, pkmeter, pkconfig):
        self.name = utils.name(self.__module__)  # Name of this Plugin
        self.namespace = utils.namespace(
            self.__module__)  # Namespace of this Config
        self.template = self._init_template()  # Template for config settings
        self.fields = utils.Bunch()  # Fields in this Config
        PKVFrame.__init__(self, self.template, self)  # Init parent widget
        self.pkmeter = pkmeter  # Reference to PKMeter
        self.pkconfig = pkconfig  # Reference to Main Config
        self._init_default_interval()
        self._init_fields()

    def _init_template(self):
        with open(self.TEMPLATE) as tmpl:
            template = ElementTree.fromstring(tmpl.read())
        return template

    def _init_default_interval(self):
        if 'interval' in self.FIELDS:
            module = self.pkmeter.modules[self.namespace]
            default_interval = module.Plugin.DEFAULT_INTERVAL
            self.FIELDS.interval['default'] = default_interval

    def _init_fields(self):
        for name, meta in self.FIELDS.items():
            self._init_field(name, meta)

    def _init_field(self, name, meta):
        field = utils.Bunch(meta)  # Convert to Bunch
        field.name = name  # Name of this field
        field.input = self.manifest.get(name)  # QT input element
        field.controlgroup = self.manifest.get('controlgroup_%s' %
                                               name)  # QT control group
        field.status = self.manifest.get('status_%s' % name)  # QT status label
        field.help = self.manifest.get('help_%s' % name)  # QT help label
        field.help_default = field.help.text(
        ) if field.help else None  # Default help text
        field.default = field.get('default', '')  # Default value
        field.value = self._get_value(field)  # Current value (to be saved)
        field.lastchecked = field.value  # Last value verified
        field.validator = getattr(self, 'validate_%s' % name,
                                  None)  # Validator callback
        if name in self.manifest:
            if getattr(field.input, 'textEdited', None):
                field.input.textEdited.connect(
                    lambda txt, field=field: self._editing(field, txt))
            if getattr(field.input, 'editingFinished', None):
                field.input.editingFinished.connect(
                    lambda field=field: self._validate(field))
            field.input.set_value(field.value)
        self.fields[name] = field

    def _get_value(self, field):
        from_keyring = field.get('save_to_keyring', False)
        return self.pkconfig.get(self.namespace, field.name, field.default,
                                 from_keyring)

    def _editing(self, field, text):
        self._set_field_status(field, self.STATUS_LOADING, '')

    @threaded_method
    def _validate(self, field, force=False):
        if not field.input:
            return
        try:
            #self._set_field_status(field, self.STATUS_LOADING, '')
            value = field.input.get_value()
            if field.validator:
                result = field.validator(field, value)
                value = value if result is None else result
                log.info('Validation passed for %s.%s', self.namespace,
                         field.name)
            self._set_field_status(field, self.STATUS_OK, '')
        except Exception as err:
            log.warn('Validation Error for %s.%s: %s', self.namespace,
                     field.name, err)
            self._set_field_status(field, self.STATUS_ERROR, str(err))
        finally:
            log.info('Setting value %s.%s: %s', self.namespace, field.name,
                     value)
            field.value = value

    def _set_field_status(self, field, status, errmsg):
        if field.controlgroup: field.controlgroup.setToolTip(errmsg)
        if field.status: field.status.setText(status)

    def validate_interval(self, field, value):
        try:
            interval = int(value)
            assert 1 <= interval <= 3600, 'Value out of bounds.'
            return interval
        except:
            raise ValidationError('Interval seconds must be a number 1-3600.')
示例#14
0
class Config(BaseConfig):
    TEMPLATE = os.path.join(SHAREDIR, 'templates', 'filesystem_config.html')
    FIELDS = utils.Bunch(BaseConfig.FIELDS,
                         fstypes={'default': DEFAULT_FSTYPES})