def loop(self): checkins = get_plugin('foursquare').get_checkins().output if not checkins: return last_checkin = checkins[0] last_checkin_created_at = last_checkin.get('createdAt', 0) if self._last_created_at and last_checkin_created_at <= self._last_created_at: return self.bus.post(FoursquareCheckinEvent(checkin=last_checkin)) self._last_created_at = last_checkin_created_at get_plugin('variable').set( **{self._last_created_at_varname: self._last_created_at})
def __init__(self, boards: List[str], token: str, **kwargs): """ :param boards: List of boards to subscribe, by ID or name. :param token: Trello web client API token. """ super().__init__(**kwargs) self._plugin: TrelloPlugin = get_plugin('trello') self.token = token self._req_id = 0 self._boards_by_id = {} self._boards_by_name = {} for b in boards: b = self._plugin.get_board(b).board # noinspection PyUnresolvedReferences self._boards_by_id[b.id] = b # noinspection PyUnresolvedReferences self._boards_by_name[b.name] = b self.url = self._websocket_url_base.format(token=self.token) self._connected = Event() self._items = {} self._event_handled = False
def get_or_create_ngrok_tunnel() -> str: """ This method creates an ngrok tunnel for the local web application, useful to register public HTTPS callback URLs on the fly from plugins and backends. """ global _app_tunnel_url with _app_tunnel_lock: if _app_tunnel_url: return _app_tunnel_url local_port = _get_http_port() ngrok = None if Config.get('ngrok'): ngrok = get_plugin('ngrok') assert ngrok, 'The ngrok plugin is required in order to subscribe to notifications' tunnel_response = ngrok.create_tunnel( resource=local_port, protocol='http', bind_tls=True, ).output _app_tunnel_url = tunnel_response.get('url') assert _app_tunnel_url, 'Unable to create an ngrok tunnel' return _app_tunnel_url
def loop(self): last_seen_id = int(self.last_seen_id) new_last_seen_id = int(last_seen_id) plugin: NextcloudPlugin = get_plugin('nextcloud') # noinspection PyUnresolvedReferences activities = plugin.get_activities(sort='desc', url=self.url, username=self.username, password=self.password, object_type=self.object_type, object_id=self.object_id).output events = [] for activity in activities: if last_seen_id and activity['activity_id'] <= last_seen_id: break events.append(self._activity_to_event(activity)) if not new_last_seen_id or activity[ 'activity_id'] > new_last_seen_id: new_last_seen_id = int(activity['activity_id']) for evt in events[::-1]: self.bus.post(evt) if new_last_seen_id and last_seen_id != new_last_seen_id: self.last_seen_id = new_last_seen_id
def _get_direction_from_sensors(self): if Direction.DIR_AUTO.value not in self.directions: raise RuntimeError( "Can't start auto pilot: " + "no sensor configured in gpio.zeroborg.directions.auto") direction = None for sensor in self.directions[Direction.DIR_AUTO.value]['sensors']: plugin = get_plugin(sensor['plugin']) if not sensor: raise RuntimeError('No such sensor: ' + sensor['plugin']) value = self._get_measurement(plugin=plugin, timeout=sensor['timeout']) threshold = sensor['threshold'] if value >= threshold and 'above_threshold_direction' in sensor: direction = sensor['above_threshold_direction'] elif 'below_threshold_direction' in sensor: direction = sensor['below_threshold_direction'] logging.info('Sensor: {}\tMeasurement: {}\tDirection: {}'.format( sensor['plugin'], value, direction)) return direction
def __init__(self, queue='platypush_bus_mq', redis_args={}, *args, **kwargs): """ :param queue: Queue name to listen on (default: ``platypush_bus_mq``) :type queue: str :param redis_args: Arguments that will be passed to the redis-py constructor (e.g. host, port, password), see http://redis-py.readthedocs.io/en/latest/ :type redis_args: dict """ super().__init__(*args, **kwargs) self.queue = queue self.redis_args = redis_args if not redis_args: try: redis_plugin = get_plugin('redis') if redis_plugin and redis_plugin.kwargs: self.redis_args = redis_plugin.kwargs except: pass self.redis = Redis(**self.redis_args)
def _stop_torrent(self): # noinspection PyBroadException try: torrents = get_plugin(self.torrent_plugin) torrents.quit() except Exception as e: self.logger.warning(f'Could not stop torrent plugin: {str(e)}')
def __init__(self): db_plugin = get_plugin('db') if not db_plugin: raise ModuleNotFoundError( 'Please enable/configure the db plugin for multi-user support') self._engine = db_plugin._get_engine()
def _status(self, host, port): sock = self._connect(host, port) request = { 'id': self._get_req_id(), 'jsonrpc': '2.0', 'method': 'Server.GetStatus' } get_plugin('music.snapcast')._send(sock, request) try: return self._recv(sock).get('result', {}).get('server', {}) except Exception as e: self.logger.warning('Unable to connect to {}:{}: {}'.format( host, port, str(e))) self._socks[host] = None
def get_measurement(self): """ Wrapper around ``plugin.get_measurement()`` that can filter events on specified enabled sensors data or on specified tolerance values. It can be overridden by derived classes. """ if not self.plugin: raise NotImplementedError('No plugin specified') reload = False success = False data = None while not success: try: plugin = get_plugin(self.plugin, reload=reload) data = plugin.get_data(**self.plugin_args).output if reload: self.logger.info('Backend successfully restored') success = True except Exception as e: self.logger.warning('Unexpected exception while getting data: {}'.format(str(e))) self.logger.exception(e) reload = True time.sleep(5) if self.enabled_sensors and data is not None: data = { sensor: data[sensor] for sensor, enabled in self.enabled_sensors.items() if enabled and sensor in data } return data
def on_stop(self): if not self.plugin: return plugin = get_plugin(self.plugin) if plugin and hasattr(plugin, 'close'): plugin.close()
def search(self, query): self.logger.info('Searching torrents for "{}"'.format(query)) torrents = get_plugin('torrent') if not torrents: raise RuntimeError('Torrent plugin not available/configured') return torrents.search(query, ).output
def _stop_torrent(self): # noinspection PyBroadException try: torrents = get_plugin(self.torrent_plugin) torrents.quit() except: pass
def _youtube_search_api(query): return [{ 'url': 'https://www.youtube.com/watch?v=' + item['id']['videoId'], **item.get('snippet', {}), } for item in get_plugin('google.youtube').search(query=query).output if item.get('id', {}).get('kind') == 'youtube#video']
def run(self): super().run() plugin: WeatherBuienradarPlugin = get_plugin('weather.buienradar') self.logger.info('Initialized weather forecast backend') while not self.should_stop(): weather = plugin.get_weather().output precip = plugin.get_precipitation().output del weather['measured'] if precip != self.last_precip: self.bus.post( NewPrecipitationForecastEvent( plugin_name='weather.buienradar', average=precip.get('average'), total=precip.get('total'), time_frame=precip.get('time_frame'))) if weather != self.last_weather: self.bus.post( NewWeatherConditionEvent( **{ **weather, 'plugin_name': 'weather.buienradar', })) self.last_weather = weather self.last_precip = precip time.sleep(self.poll_seconds)
def _process_devices(self, client, msg): devices_info = { device.get('friendly_name', device.get('ieee_address')): device for device in msg } # noinspection PyProtectedMember event_args = {'host': client._host, 'port': client._port} client.subscribe( * [self.base_topic + '/' + device for device in devices_info.keys()]) for name, device in devices_info.items(): if name not in self._devices: self.bus.post( ZigbeeMqttDeviceConnectedEvent(device=name, **event_args)) exposes = (device.get('definition', {}) or {}).get('exposes', []) client.publish( self.base_topic + '/' + name + '/get', json.dumps( get_plugin('zigbee.mqtt').build_device_get_request( exposes))) devices_copy = [*self._devices.keys()] for name in devices_copy: if name not in devices_info: self.bus.post( ZigbeeMqttDeviceRemovedEvent(device=name, **event_args)) del self._devices[name] self._devices = {device: {} for device in devices_info.keys()}
def _get_feed_latest_timestamp(cls, url: str) -> Optional[datetime.datetime]: t = get_plugin('variable').get( cls._get_feed_latest_timestamp_varname(url) ).output.get(cls._get_feed_latest_timestamp_varname(url)) if t: return dateutil.parser.isoparse(t)
def _init_models(self, models): if not models: raise AttributeError('Please specify at least one voice model') self.models = {} for name, conf in models.items(): if name in self.models: raise AttributeError('Duplicate model key {}'.format(name)) model_file = conf.get('voice_model_file') detect_sound = conf.get('detect_sound') if not model_file: raise AttributeError('No voice_model_file specified for model {}'.format(name)) model_file = os.path.abspath(os.path.expanduser(model_file)) assistant_plugin_name = conf.get('assistant_plugin') if detect_sound: detect_sound = os.path.abspath(os.path.expanduser(detect_sound)) if not os.path.isfile(model_file): raise FileNotFoundError('Voice model file {} does not exist or it not a regular file'. format(model_file)) self.models[name] = { 'voice_model_file': model_file, 'sensitivity': conf.get('sensitivity', 0.5), 'detect_sound': detect_sound, 'assistant_plugin': get_plugin(assistant_plugin_name) if assistant_plugin_name else None, 'assistant_language': conf.get('assistant_language'), }
def get_measurement(self): plugin = get_plugin('system') battery = plugin.sensors_battery().output return { 'battery_percent': battery.get('percent'), 'battery_power_plugged': bool(battery.get('power_plugged')), }
def get_all_backends(): manifests = {mf.component_name for mf in get_manifests(Backend)} return { backend_name: backend_info for backend_name, backend_info in get_plugin( 'inspect').get_all_backends().output.items() if backend_name in manifests }
def get_all_plugins(): manifests = {mf.component_name for mf in get_manifests(Plugin)} return { plugin_name: plugin_info for plugin_name, plugin_info in get_plugin( 'inspect').get_all_plugins().output.items() if plugin_name in manifests }
def _thread_func(_n_tries, errors=None): response = None if self.action.startswith('procedure.'): context['n_tries'] = _n_tries response = self._execute_procedure(**context) if response is not None: self._send_response(response) return response else: action = self.expand_value_from_context(self.action, **context) (module_name, method_name) = get_module_and_method_from_action(action) plugin = get_plugin(module_name) try: # Run the action args = self._expand_context(**context) args = self.expand_value_from_context(args, **context) response = plugin.run(method=method_name, **args) if response and response.is_error(): logger.warning(('Response processed with errors from ' + 'action {}: {}').format( action, str(response))) elif not response.disable_logging: logger.info('Processed response from action {}: {}'. format(action, str(response))) except Exception as e: # Retry mechanism plugin.logger.exception(e) logger.warning(('Uncaught exception while processing response ' + 'from action [{}]: {}').format(action, str(e))) errors = errors or [] if str(e) not in errors: errors.append(str(e)) response = Response(output=None, errors=errors) if _n_tries-1 > 0: logger.info('Reloading plugin {} and retrying'.format(module_name)) get_plugin(module_name, reload=True) response = _thread_func(_n_tries=_n_tries - 1, errors=errors) finally: self._send_response(response) return response
def get_chromecast(self, chromecast): from .lib.plexcast import PlexController hndl = PlexController() hndl.namespace = 'urn:x-cast:com.google.cast.sse' cast = get_plugin('media.chromecast').get_chromecast(chromecast) cast.register_handler(hndl) return (cast, hndl)
def last_seen_id(self) -> Optional[int]: if self._last_seen_id is None: variables: VariablePlugin = get_plugin('variable') last_seen_id = variables.get( self._LAST_ACTIVITY_VARNAME).output.get( self._LAST_ACTIVITY_VARNAME) self._last_seen_id = last_seen_id return self._last_seen_id
def _addr_tracker(self, addr): with self._bt_lock: name = get_plugin('bluetooth').lookup_name( addr, timeout=self.scan_duration).name if name is None: self._remove_last_seen_device(addr) else: self._add_last_seen_device({'addr': addr, 'name': name})
def __init__(self, **kwargs): """ The plugin will create a table named ``variable`` on the database configured in the :mod:`platypush.plugins.db` plugin. You'll have to specify a default ``engine`` in your ``db`` plugin configuration. """ super().__init__(**kwargs) self.db_plugin = get_plugin('db') self.redis_plugin = get_plugin('redis') db = Config.get('db') self.db_config = { 'engine': db.get('engine'), 'args': db.get('args', []), 'kwargs': db.get('kwargs', {}) } self._create_tables()
def loop(self): builds = get_plugin('travisci').builds(limit=1).output if not builds: return last_build = builds[0] last_build_finished_at = self._convert_iso_date(last_build.get('finished_at', 0)) if not last_build_finished_at: return if self._last_build_finished_at and last_build_finished_at <= self._last_build_finished_at: return if last_build.get('state') == 'passed': evt_type = TravisciBuildPassedEvent elif last_build.get('state') == 'failed': evt_type = TravisciBuildFailedEvent else: return evt = evt_type(repository_id=last_build.get('repository', {}).get('id'), repository_name=last_build.get('repository', {}).get('name'), repository_slug=last_build.get('repository').get('slug'), build_id=int(last_build.get('id')), build_number=int(last_build.get('number')), duration=last_build.get('duration'), previous_state=last_build.get('previous_state'), private=last_build.get('private'), tag=last_build.get('tag'), branch=last_build.get('branch', {}).get('name'), commit_id=last_build.get('commit', {}).get('id'), commit_sha=last_build.get('commit', {}).get('sha'), commit_message=last_build.get('commit', {}).get('message'), committed_at=self._convert_iso_date( last_build.get('commit', {}).get('committed_at')), created_by=last_build.get('created_by', {}).get('login'), started_at=self._convert_iso_date(last_build.get('started_at')), finished_at=self._convert_iso_date(last_build.get('finished_at'))) self.bus.post(evt) self._last_build_finished_at = last_build_finished_at get_plugin('variable').set(**{self._last_build_finished_at_varname: self._last_build_finished_at})
def __init__(self, authorized_chat_ids: Optional[List[Union[str, int]]] = None, **kwargs): """ :param authorized_chat_ids: Optional list of chat_id/user_id which are authorized to send messages to the bot. If nothing is specified then no restrictions are applied. """ super().__init__(**kwargs) self.authorized_chat_ids = set(authorized_chat_ids or []) self._plugin: ChatTelegramPlugin = get_plugin('chat.telegram')
def _get_playing_plugin(self): if self.plugin: status = self.plugin.status() if status['state'] == PlayerState.PLAY.value or state['state'] == PlayerState.PAUSE.value: return self.plugin for plugin in self._supported_plugins: try: player = get_plugin(plugin) except: try: player = get_plugin(plugin, reload=True) except: continue status = player.status().output if status['state'] == PlayerState.PLAY.value or status['state'] == PlayerState.PAUSE.value: return player return None
def send_message(self, msg): websocket = get_plugin('websocket') websocket_args = {} if self.ssl_context: url = 'wss://localhost:{}'.format(self.port) websocket_args['ssl'] = self.ssl_context else: url = 'ws://localhost:{}'.format(self.port) websocket.send(url=url, msg=msg, **websocket_args)