Esempio n. 1
0
    def setup(self):
        # handle credentials
        uuid = None
        uuidlist = None
        credentials = self._load_credentials_store()
        if credentials is not None:
            uuid = credentials['uuid']
            uuidlist = credentials['list']
        else:
            login = self.settings.get("login", "")
            password = self.settings.get("password", "")
            if login:
                uuid, uuidlist = BringApi.login(login, password)

        if uuid is None:
            self.speak_dialog('bring.error.connect')
            self.log.warning(
                "Loading credentials failed, please check your credentials")
            return

        self.log.info("Loaded credentials")
        self._bring = BringApi(uuid, uuidlist)
        if self._bring is None:
            self.speak_dialog('bring.error.connect')
            self.log.warning("API connect failed")

        self.log.info("API connect succeeded")
        return
    def bring(self):
        if not self._bring:
            if not self._uuid or not self._uuidlist:
                self._uuid, self._uuidlist = BringApi.login(
                    self.getConfig('bringEmail'),
                    self.getConfig('bringPassword'))
                self.updateConfig('uuid', self._uuid)
                self.updateConfig('listUuid', self._uuidlist)

            self._bring = BringApi(self._uuid, self._uuidlist)
        return self._bring
Esempio n. 3
0
    def getList(self) -> str:
        uuid = self.skillInstance.getConfig('uuid')
        uuidList = self.skillInstance.getConfig('listUuid')
        bringList = BringApi(uuid, uuidList)
        translation = BringApi.loadTranslations(
            self.LanguageManager.activeLanguageAndCountryCode)

        items = bringList.get_items()['purchase']
        details = bringList.get_items_detail()
        itemList = [{
            "text": self.translate(item['name'], translation),
            "image": self.get_image(details, item['name'])
        } for item in items]

        return json.dumps(itemList)
    def __init__(self, hass, username, password, list_id, name, locale):
        """Initialize Bring data updater."""
        self.list_id = list_id
        self.locale = locale
        self.name = name
        self.api = BringApi(username, password, True)

        self.purchase = []
        self.recently = []

        super().__init__(
            hass,
            _LOGGER,
            name=name,
            update_interval=SCAN_INTERVAL,
        )
	def bring(self):
		# check if the credentials have changed. if so, get new login.
		if not self._bring:
			if not self._uuid or not self._uuidlist:
				self.logInfo('New Login required using mail and password')
				self._uuid, self._uuidlist = BringApi.login(self.getConfig('bringEmail'), self.getConfig('bringPassword'))
				self.updateConfig('uuid', self._uuid)
				self.updateConfig('listUuid', self._uuidlist)

			self.logInfo(f'Getting new instance of Bring! with uuid {self._uuid}, default list {self._uuidlist} and custom list {self._overwriteUuidlist}')

			if self._overwriteUuidlist:
				self._bring = BringApi(self._uuid, self._overwriteUuidlist)
			else:
				self._bring = BringApi(self._uuid, self._uuidlist)

			itemlist = ", ".join([f'{item["name"]} ({item["listUuid"]})' for item in self._bring.load_lists().json()["lists"]])
			self.logInfo(f'Available Bring! lists are {itemlist}. Currently using {self._bring.bringListUUID}')

		return self._bring
	def _addItemInt(self, items) -> Tuple[list, list]:
		"""
		internal method to add a list of items to the shopping list
		:returns: two splitted lists of successful adds and items that already existed.
		"""
		bringItems = self.bring().get_items(self.LanguageManager.activeLanguageAndCountryCode)['purchase']
		added = list()
		exist = list()
		for item in items:
			if not any(entr['name'].lower() == item.lower() for entr in bringItems):
				self.bring().purchase_item(BringApi.translateToCH(item, self.LanguageManager.activeLanguageAndCountryCode), "")
				added.append(item)
			else:
				exist.append(item)
		return added, exist
    def getList(self) -> dict:
        try:
            bringList = self.skillInstance.bring()
            translation = BringApi.loadTranslations(
                self.LanguageManager.activeLanguageAndCountryCode)

            items = bringList.get_items()['purchase']
            details = bringList.get_items_detail()
            itemList = [{
                "text": self.translate(item['name'], translation),
                "image": self.get_image(details, item['name'])
            } for item in items]

            return {'success': True, 'items': itemList}
        except Exception as e:
            return {'success': False, 'message': str(e)}
	def _deleteItemInt(self, items: list) -> Tuple[list, list]:
		"""
		internal method to delete a list of items from the shopping list
		:returns: two splitted lists of successful deletions and items that were not on the list
		"""
		bringItems = self.bring().get_items(self.LanguageManager.activeLanguageAndCountryCode)['purchase']
		removed = list()
		exist = list()
		for item in items:
			for entr in bringItems:
				if entr['name'].lower() == item.lower():
					self.bring().recent_item(BringApi.translateToCH(entr['name'], self.LanguageManager.activeLanguageAndCountryCode))
					removed.append(item)
					break
			else:
				exist.append(item)
		return removed, exist
def get_bring(conf):
    return BringApi(conf['secret']['uuid'], conf['secret']['bringlistuuid'])
class BringShoppingList(AliceSkill):
	"""
	Author: philipp2310
	Description: maintaines a Bring! shopping list
	"""


	def __init__(self):
		super().__init__()
		self._uuid = None
		self._uuidlist = None
		self._overwriteUuidlist = None
		self._bring = None


	def onStart(self):
		super().onStart()
		self.reloadConfig()
		self._connectAccount()


	def reloadConfig(self, dummy = None):
		self.logInfo('Bring! config reloading...')
		self._uuid = self.getConfig('uuid')
		self._uuidlist = self.getConfig('listUuid')
		self._overwriteUuidlist = self.getConfig('overwriteListUuid')
		self._bring = None
		self.bring()
		self.logInfo('Bring! config reload done!')
		return True


	def bring(self):
		# check if the credentials have changed. if so, get new login.
		if not self._bring:
			if not self._uuid or not self._uuidlist:
				self.logInfo('New Login required using mail and password')
				self._uuid, self._uuidlist = BringApi.login(self.getConfig('bringEmail'), self.getConfig('bringPassword'))
				self.updateConfig('uuid', self._uuid)
				self.updateConfig('listUuid', self._uuidlist)

			self.logInfo(f'Getting new instance of Bring! with uuid {self._uuid}, default list {self._uuidlist} and custom list {self._overwriteUuidlist}')

			if self._overwriteUuidlist:
				self._bring = BringApi(self._uuid, self._overwriteUuidlist)
			else:
				self._bring = BringApi(self._uuid, self._uuidlist)

			itemlist = ", ".join([f'{item["name"]} ({item["listUuid"]})' for item in self._bring.load_lists().json()["lists"]])
			self.logInfo(f'Available Bring! lists are {itemlist}. Currently using {self._bring.bringListUUID}')

		return self._bring


	@Online
	def _connectAccount(self):
		try:
			self._bring = self.bring()
		except BringApi.AuthentificationFailed:
			raise SkillStartingFailed(skillName=self._name, error='Please check your account login and password')


	def _deleteCompleteList(self):
		"""
		perform the deletion of the complete list
		-> load all and delete item by item
		"""
		items = self.bring().get_items()['purchase']
		for item in items:
			self.bring().recent_item(item['name'])


	def _addItemInt(self, items) -> Tuple[list, list]:
		"""
		internal method to add a list of items to the shopping list
		:returns: two splitted lists of successful adds and items that already existed.
		"""
		bringItems = self.bring().get_items(self.LanguageManager.activeLanguageAndCountryCode)['purchase']
		added = list()
		exist = list()
		for item in items:
			if not any(entr['name'].lower() == item.lower() for entr in bringItems):
				self.bring().purchase_item(BringApi.translateToCH(item, self.LanguageManager.activeLanguageAndCountryCode), "")
				added.append(item)
			else:
				exist.append(item)
		return added, exist


	def _deleteItemInt(self, items: list) -> Tuple[list, list]:
		"""
		internal method to delete a list of items from the shopping list
		:returns: two splitted lists of successful deletions and items that were not on the list
		"""
		bringItems = self.bring().get_items(self.LanguageManager.activeLanguageAndCountryCode)['purchase']
		removed = list()
		exist = list()
		for item in items:
			for entr in bringItems:
				if entr['name'].lower() == item.lower():
					self.bring().recent_item(BringApi.translateToCH(entr['name'], self.LanguageManager.activeLanguageAndCountryCode))
					removed.append(item)
					break
			else:
				exist.append(item)
		return removed, exist


	def _checkListInt(self, items: list) -> Tuple[list, list]:
		"""
		internal method to check if a list of items is on the shopping list
		:returns: two splitted lists, one with the items on the list, one with the missing ones
		"""
		bringItems = self.bring().get_items(self.LanguageManager.activeLanguageAndCountryCode)['purchase']
		found = list()
		missing = list()
		for item in items:
			if any(entr['name'].lower() == item.lower() for entr in bringItems):
				found.append(item)
			else:
				missing.append(item)
		return found, missing


	def _getShopItems(self, answer: str, session: DialogSession) -> list:
		"""get the values of shopItem as a list of strings"""
		intent = session.intentName
		if intent == Intent('SpellWord'):
			item = ''.join([slot.value['value'] for slot in session.slotsAsObjects['Letters']])
			return [item.capitalize()]

		items = [x.value['value'] for x in session.slotsAsObjects.get('shopItem', list()) if x.value['value'] != 'unknownword']

		if not items:
			self.continueDialog(
				sessionId=session.sessionId,
				text=self.randomTalk(f'{answer}_what'),
				intentFilter=[Intent('Bring_whatItem')],
				currentDialogState=intent.split(':')[-1].split('/')[-1],
				slot='buyable',
				probabilityThreshold=0.1
			)
		return items


	### INTENTS ###
	@IntentHandler('Bring_deleteList')
	@Online
	def delListIntent(self, session: DialogSession):
		self.continueDialog(
			sessionId=session.sessionId,
			text=self.randomTalk('chk_del_all'),
			intentFilter=[Intent('AnswerYesOrNo')],
			currentDialogState='confDelList_Bring')


	@AnyExcept(exceptions=BringApi.AuthentificationFailed, text='authFailed')
	@Online
	@IntentHandler('AnswerYesOrNo', requiredState='confDelList_Bring')
	def confDelIntent(self, session: DialogSession):
		if self.Commons.isYes(session):
			self._deleteCompleteList()
			self.endDialog(session.sessionId, text=self.randomTalk('del_all'))
		else:
			self.endDialog(session.sessionId, text=self.randomTalk('nodel_all'))


	@AnyExcept(exceptions=BringApi.AuthentificationFailed, text='authFailed')
	@Online
	@IntentHandler('Bring_addItem')
	@IntentHandler('Bring_whatItem', requiredState='Bring_addItem')
	@IntentHandler('SpellWord', requiredState='Bring_addItem')
	def addItemIntent(self, session: DialogSession):
		items = self._getShopItems('add', session)
		if items:
			added, exist = self._addItemInt(items)
			self.endDialog(session.sessionId, text=self._combineLists('add', added, exist))


	@AnyExcept(exceptions=BringApi.AuthentificationFailed, text='authFailed')
	@Online
	@IntentHandler('Bring_deleteItem')
	@IntentHandler('Bring_whatItem', requiredState='Bring_deleteItem')
	@IntentHandler('SpellWord', requiredState='Bring_deleteItem')
	def delItemIntent(self, session: DialogSession):
		items = self._getShopItems('rem', session)
		if items:
			removed, exist = self._deleteItemInt(items)
			self.endDialog(session.sessionId, text=self._combineLists('rem', removed, exist))


	@AnyExcept(exceptions=BringApi.AuthentificationFailed, text='authFailed')
	@Online
	@IntentHandler('Bring_checkList')
	@IntentHandler('Bring_whatItem', requiredState='Bring_checkList')
	@IntentHandler('SpellWord', requiredState='Bring_checkList')
	def checkListIntent(self, session: DialogSession):
		items = self._getShopItems('chk', session)
		if items:
			found, missing = self._checkListInt(items)
			self.endDialog(session.sessionId, text=self._combineLists('chk', found, missing))


	@AnyExcept(exceptions=BringApi.AuthentificationFailed, text='authFailed')
	@Online
	@IntentHandler('Bring_readList')
	def readListIntent(self, session: DialogSession):
		"""read the content of the list"""
		items = self.bring().get_items(self.LanguageManager.activeLanguageAndCountryCode)['purchase']
		itemlist = [item['name'] for item in items]
		self.endDialog(session.sessionId, text=self._getTextForList('read', itemlist))


	#### List/Text operations
	def _combineLists(self, answer: str, first: list, second: list) -> str:
		firstAnswer = self._getTextForList(answer, first) if first else ''
		secondAnswer = self._getTextForList(f'{answer}_f', second) if second else ''
		combinedAnswer = self.randomTalk('state_con', [firstAnswer, secondAnswer]) if first and second else ''

		return combinedAnswer or firstAnswer or secondAnswer


	def _getTextForList(self, pref: str, items: list) -> str:
		"""Combine entries of list into wrapper sentence"""
		if not items:
			return self.randomTalk(f'{pref}_none')
		elif len(items) == 1:
			return self.randomTalk(f'{pref}_one', [items[0]])

		value = self.randomTalk(text='gen_list', replace=[', '.join(items[:-1]), items[-1]])
		return self.randomTalk(f'{pref}_multi', [value])
class BringDataUpdateCoordinator(DataUpdateCoordinator[int]):
    """Class to manage fetching shopping list data from endpoint."""
    def __init__(self, hass, username, password, list_id, name, locale):
        """Initialize Bring data updater."""
        self.list_id = list_id
        self.locale = locale
        self.name = name
        self.api = BringApi(username, password, True)

        self.purchase = []
        self.recently = []

        super().__init__(
            hass,
            _LOGGER,
            name=name,
            update_interval=SCAN_INTERVAL,
        )

    async def _async_update_data(self) -> Optional[int]:
        """Fetch new state data for the sensor.
        This is the only method that should fetch new data for Home Assistant.
        """

        catalog = self.api.loadCatalog(self.locale)
        details = self.api.get_items_detail()
        data = self.api.get_items(self.locale)

        purchase = data["purchase"]
        recently = data["recently"]

        self.purchase = self._get_list(purchase, details, catalog)
        self.recently = self._get_list(recently, details, catalog)

        return len(purchase)

    def _get_list(self, source=None, details=None, articles=None):
        if articles is None:
            articles = []
        items = []
        for p in source:
            found = False
            for d in details:
                if p["name"] == d["itemId"]:
                    found = True
                    break

            item = {
                "image": p["name"],
                "name": p["name"],
                "specification": p["specificitemation"]
            }

            if found:
                item["image"] = d["userIconItemId"]

            item["key"] = item["image"]

            if item["name"] in articles:
                item["name"] = articles[item["name"]]
            else:
                if found == 0:
                    item["image"] = item["name"][0]

            item["image"] = self._purge(item["image"])

            if "+" in item["specification"]:
                specs = item["specification"].split("+")

                for spec in specs:
                    temp = dict(item.items())
                    temp["specification"] = spec.strip()
                    items.append(temp)

            else:
                items.append(item)

        return items

    @staticmethod
    def _purge(item):
        return item.lower() \
            .replace("é", "e") \
            .replace("ä", "ae") \
            .replace("-", "_") \
            .replace("ö", "oe") \
            .replace("ü", "ue") \
            .replace(" ", "_")
	def _getBring(self) -> BringApi:
		"""get an instance of the BringApi"""
		return BringApi(self._uuid, self._uuidlist)
Esempio n. 13
0
class BringlistSkill(MycroftSkill):
    def __init__(self):
        MycroftSkill.__init__(self)
        self._bring = None
        self._regex = {}

    def initialize(self):
        self.settings_change_callback = self.on_websettings_changed
        self.setup()

    def on_websettings_changed(self):
        self.setup()

    def setup(self):
        # handle credentials
        uuid = None
        uuidlist = None
        credentials = self._load_credentials_store()
        if credentials is not None:
            uuid = credentials['uuid']
            uuidlist = credentials['list']
        else:
            login = self.settings.get("login", "")
            password = self.settings.get("password", "")
            if login:
                uuid, uuidlist = BringApi.login(login, password)

        if uuid is None:
            self.speak_dialog('bring.error.connect')
            self.log.warning(
                "Loading credentials failed, please check your credentials")
            return

        self.log.info("Loaded credentials")
        self._bring = BringApi(uuid, uuidlist)
        if self._bring is None:
            self.speak_dialog('bring.error.connect')
            self.log.warning("API connect failed")

        self.log.info("API connect succeeded")
        return

    @intent_handler(
        IntentBuilder("AddToBringlist").require("bring.list").require(
            "bring.add"))
    def handle_bringlist_add(self, message):
        self.log.info("Bringlist add")
        if self._bring is None:
            self.speak_dialog('bring.error.connect')

        item, desc = self._get_item(message.data.get('utterance'),
                                    'bring.add.regex')
        if item is not None:
            self._bring.purchase_item(item.capitalize(), desc)
            self.speak_dialog('bring.success.add', data={"Item": item})
            return
        self.speak_dialog('bring.error.add', data={"Item": item})

    @intent_handler(
        IntentBuilder("RemoveFromBringlist").require("bring.list").require(
            "bring.remove"))
    def handle_bringlist_remove(self, message):
        self.log.info("Bringlist remove")
        if self._bring is None:
            self.speak_dialog('bring.error.connect')

        item, desc = self._get_item(message.data.get('utterance'),
                                    'bring.remove.regex')
        if item:
            self._bring.recent_item(item.capitalize())
            self.speak_dialog('bring.success.remove', data={"Item": item})
            return
        self.speak_dialog('bring.error.remove', data={"Item": item})

    @intent_handler(
        IntentBuilder("ClearBringlist").require("bring.list").require(
            "bring.clear"))
    def handle_bringlist_clear(self, message):
        self.log.info("Bringlist clear")
        if self._bring is None:
            self.speak_dialog('bring.error.connect')

        items = self._bring.get_items()['purchase']
        if items:
            for item in items:
                self._bring.recent_item(item['name'])
            self.speak_dialog('bring.success.clear',
                              data={"Count": len(items)})
            return
        self.speak_dialog('bring.error.clear')

    def _load_credentials_store(self):
        credentials = None
        credentials_file = 'credentials.store'
        if self.file_system.exists(credentials_file):
            with self.file_system.open(credentials_file, 'rb') as f:
                credentials = pickle.load(f)
        return credentials

    def _get_item(self, text, regfile):
        match = self._get_regex(regfile).match(text)
        if match:
            return match.group('Item'), match.group('Desc') if match.group(
                'Desc') is not None else ""
        else:
            return None, None

    def _get_regex(self, regfile):
        if regfile in self._regex:
            return self._regex[regfile]
        with open(self.find_resource(regfile, 'regex')) as f:
            matcher = f.readline().rstrip('\n')
            regex = re.compile(matcher)
            self._regex[regfile] = regex
            return regex