Ejemplo n.º 1
0
 def __init__(self):
     super(YoutubeSkill, self).__init__(name="YoutubeSkill")
     self.nextpage_url = None
     self.previouspage_url = None
     self.live_category = None
     self.recentList = deque()
     self.recentPageObject = {}
     self.nextSongList = None
     self.lastSong = None
     self.videoPageObject = {}
     self.isTitle = None
     self.trendCategoryList = {}
     self.newsCategoryList = {}
     self.musicCategoryList = {}
     self.techCategoryList = {}
     self.polCategoryList = {}
     self.gamingCategoryList = {}
     self.searchCategoryList = {}
     self.recentCategoryList = {}
     self.recentWatchListObj = {}
     self.storeDB = dirname(__file__) + '-recent.db'
     self.recent_db = JsonStorage(self.storeDB)
     self.ytkey = base64.b64decode(
         "QUl6YVN5RE9tSXhSemI0RzFhaXFzYnBaQ3IwQTlFN1NrT0pVRURr")
     pafy.set_api_key(self.ytkey)
     self.quackAPIWorker = "J0dvb2dsZWJvdC8yLjEgKCtodHRwOi8vd3d3Lmdvb2dsZS5jb20vYm90Lmh0bWwpJw=="
     self.quackagent = {'User-Agent': base64.b64decode(self.quackAPIWorker)}
     self.yts = YoutubeSearcher()
Ejemplo n.º 2
0
    def __init__(self, config):
        super().__init__()
        if isinstance(config, dict):
            self.config = config
        elif isinstance(config, str):
            self.config = JsonStorage(config)

        model = self.config.get("model_folder")
        if not model or not isdir(model):
            raise ModelNotFound

        listener_config = self.config.get("listener") or \
                          {"vad_agressiveness": 2,
                           "sample_rate": 16000,
                           "start_thresh": 1,
                           "end_thresh": 3}
        self.vad_agressiveness = listener_config["vad_agressiveness"]
        self.sample_rate = listener_config["sample_rate"]
        self.start_thresh = listener_config["start_thresh"]
        self.end_thresh = listener_config["end_thresh"]

        self.model = KaldiModel(model)
        self.kaldi = KaldiRecognizer(self.model, self.sample_rate)
        self._hotwords = dict(self.config.get("hotwords", {}))

        self.running = False
        self.speaking = False
        self.result = None
 def __init__(self):
     super().__init__("Epic Horror Theatre")
     self.db = JsonStorage(join(dirname(__file__),
                                "res", "epichorrortheatre.json"))
     self.supported_media = [MediaType.GENERIC,
                             MediaType.RADIO_THEATRE,
                             MediaType.AUDIOBOOK]
     self.default_bg = join(dirname(__file__), "ui", "bg.jpg")
     self.skill_icon = join(dirname(__file__), "ui", "icon.png")
Ejemplo n.º 4
0
 def __init__(self):
     super().__init__("Wayne June Lovecraft Readings")
     self.supported_media = [
         MediaType.GENERIC, MediaType.AUDIOBOOK, MediaType.VISUAL_STORY,
         MediaType.VIDEO
     ]
     self.default_image = join(dirname(__file__), "ui", "wayne_june.png")
     self.skill_icon = join(dirname(__file__), "ui", "icon.png")
     self.default_bg = join(dirname(__file__), "ui", "bg.jpeg")
     self.db = JsonStorage(join(dirname(__file__), "res", "waynejune.json"))
Ejemplo n.º 5
0
    def initialize(self):
        self.add_event('pixabay-skill.aiix.home',
                       self.handle_pixabay_homescreen)
        self.gui.register_handler("pixabay.show.image",
                                  self.handle_pixabay_show_image)
        self.gui.register_handler("pixabay.show.video",
                                  self.handle_pixabay_show_video)
        self.gui.register_handler("pixabay.gallery.next",
                                  self.handle_gallery_next_page)
        self.gui.register_handler("pixabay.gallery.previous",
                                  self.handle_gallery_previous_page)
        self.gui.register_handler("pixabay.idle.set_idle",
                                  self.handle_set_idlescreen_type)
        self.gui.register_handler("pixabay.idle.enableTime",
                                  self.handle_idle_enable_time)
        self.gui.register_handler("pixabay.idle.disableTime",
                                  self.handle_idle_disable_time)
        self.gui.register_handler("pixabay.idle.updateTime",
                                  self.handle_idle_update_time)
        self.gui.register_handler("pixabay.idle.removeConfigPage",
                                  self.handle_remove_configure_idle_screen)
        self.entKey = base64.b64decode(
            "MTcyMjI5NDctYTlmNTQxNmQ2ODhkNDVmNmJkZmY4ZWEzYQ==")
        self.video = Video(self.entKey)
        self.image = Image(self.entKey)
        self.shownPageNumber = None
        self.numberOfAvailablePages = None
        self.previousQuery = None
        self.currentType = None
        self.currentDir = dirname(dirname(abspath(__file__)))
        self.wantedDir = "pixabayData"
        self.dataPath = join(self.currentDir, self.wantedDir)
        self.videoPath = join(self.dataPath, "video.mp4")

        # Set All Paths
        try:
            os.mkdir(self.dataPath)
        except OSError as error:
            print("Directory Already Exist Skipping")
        self.storeDB = join(self.dataPath, 'pixabay-idle.db')
        self.idle_db = JsonStorage(self.storeDB)
        self.configDB = join(self.dataPath, 'pixabay-config.db')
        self.idle_config_db = JsonStorage(self.configDB)

        # Make Import For TimeData
        try:
            time_date_path = "/opt/mycroft/skills/mycroft-date-time.mycroftai/__init__.py"
            time_date_id = "datetimeskill"
            datetimeskill = load_skill_module(time_date_path, time_date_id)
            from datetimeskill import TimeSkill
            self.dt_skill = TimeSkill()
        except:
            print("Failed To Import DateTime Skill")
Ejemplo n.º 6
0
 def __init__(self):
     super().__init__("LovecraftComics")
     self.supported_media = [MediaType.GENERIC,
                             MediaType.AUDIOBOOK,
                             MediaType.VISUAL_STORY,
                             MediaType.VIDEO]
     self.default_bg = join(dirname(__file__), "ui", "bg.png")
     self.default_image = join(dirname(__file__), "ui", "dagon.png")
     self.skill_icon = join(dirname(__file__), "ui", "icon.png")
     self.db = JsonStorage(join(dirname(__file__), "res",
                                "JeremyZahn_lovecraft_comics.json"))
     self.db2 = JsonStorage(join(dirname(__file__), "res",
                                 "TanabeGou_lovecraft_comics.json"))
Ejemplo n.º 7
0
def get_default_config():
    default = JsonStorage(_DEFAULT_CONFIG_PATH)
    default["lang"] = "en-us"
    default["host"] = "0.0.0.0"
    default["port"] = 5678
    default["data_dir"] = "~/jarbasHiveMind/recordings"
    default["tts"] = {"module": "responsive_voice"}
    default["stt"] = {
        "module": "google",
        "deepspeech_server": {
            "uri": "http://localhost:8080/stt"
        },
        "kaldi": {
            "uri": "http://localhost:8080/client/dynamic/recognize"
        }
    }
    default["listener"] = {
        "sample_rate": 16000,
        "channels": 1,
        "record_wake_words": False,
        "record_utterances": False,
        "phoneme_duration": 120,
        "multiplier": 1.0,
        "energy_ratio": 1.5,
        "stand_up_word": "wake up"
    }
    default["hotwords"] = {
        "hey mycroft": {
            "module": "pocketsphinx",
            "phonemes": "HH EY . M AY K R AO F T",
            "threshold": 1e-90,
            "lang": "en-us",
            "sound": "snd/start_listening.wav",
            "listen": True
        },
        "thank you": {
            "module": "pocketsphinx",
            "phonemes": "TH AE NG K . Y UW .",
            "threshold": 1e-1,
            "listen": False,
            "utterance": "thank you",
            "active": False,
            "sound": "",
            "lang": "en-us"
        },
        "wake up": {
            "module": "pocketsphinx",
            "phonemes": "W EY K . AH P",
            "threshold": 1e-20,
            "lang": "en-us"
        }
    }
    default["log_blacklist"] = []
    return default
Ejemplo n.º 8
0
 def __init__(self):
     super(YoutubeSkill, self).__init__(name="YoutubeSkill")
     self.nextpage_url = None
     self.previouspage_url = None
     self.live_category = None
     self.recentList = deque()
     self.recentPageObject = {}
     self.nextSongList = None
     self.lastSong = None
     self.videoPageObject = {}
     self.isTitle = None
     self.newsCategoryList = {}
     self.musicCategoryList = {}
     self.techCategoryList = {}
     self.polCategoryList = {}
     self.gamingCategoryList = {}
     self.searchCategoryList = {}
     self.storeDB = dirname(__file__) + '-recent.db'
     self.recent_db = JsonStorage(self.storeDB)
     self.ytkey = base64.b64decode("QUl6YVN5RE9tSXhSemI0RzFhaXFzYnBaQ3IwQTlFN1NrT0pVRURr")
     pafy.set_api_key(self.ytkey)
Ejemplo n.º 9
0
 def save(self, filename):
     """
     Saves Markov chain to filename
     :param filename: string - where to save chain
     :return: None
     """
     with JsonStorage(filename) as db:
         db["order"] = self.order
         db["START_OF_SEQ"] = self.START_OF_SEQ
         db["END_OF_SEQ"] = self.END_OF_SEQ
         db["reverse_modelling"] = self.reverse_modelling
         # convert tuple keys to strings
         db["records"] = {str(k): v for k, v in self.records.items()}
Ejemplo n.º 10
0
 def load(self, filename):
     """
     Saves Markov chain to filename
     :param filename: string - where to save chain
     :return: None
     """
     with JsonStorage(filename) as db:
         if self._current_state == [self.START_OF_SEQ] * self.order:
             self._current_state = [db["START_OF_SEQ"]] * db["order"]
         self.order = db["order"]
         self.START_OF_SEQ = db["START_OF_SEQ"]
         self.END_OF_SEQ = db["END_OF_SEQ"]
         self.reverse_modelling = db.get("reverse_modelling") or False
         # convert str keys back to tuples
         self.records = {
             tuple(k.replace("',)", "')")[2:-2].split("', '")): v
             for k, v in db["records"].items()
         }
     return self
Ejemplo n.º 11
0
def default_config():
    default = JsonStorage(DATA_PATH)

    DB_PATH = join(DATA_PATH, "database")

    default["port"] = 5678
    default["data_path"] = DATA_PATH
    default["ssl"] = {
        "enable": False,
        "ssl_certfile": join(DATA_PATH, "certs", "hivemind.crt"),
        "ssl_keyfile": join(DATA_PATH, "certs", "hivekey.crt")
    }
    default["database"] = {
        "clients": "sqlite:///" + join(DB_PATH, "clients.db")
    }
    default["log_blacklist"] = []
    default["mycroft_bus"] = {
        "host": "0.0.0.0",
        "port": 8181,
        "route": "/core",
        "ssl": False
    }

    return default
class EpicHorrorTheatreSkill(OVOSCommonPlaybackSkill):

    def __init__(self):
        super().__init__("Epic Horror Theatre")
        self.db = JsonStorage(join(dirname(__file__),
                                   "res", "epichorrortheatre.json"))
        self.supported_media = [MediaType.GENERIC,
                                MediaType.RADIO_THEATRE,
                                MediaType.AUDIOBOOK]
        self.default_bg = join(dirname(__file__), "ui", "bg.jpg")
        self.skill_icon = join(dirname(__file__), "ui", "icon.png")

    # common play
    def clean_vocs(self, phrase):
        phrase = self.remove_voc(phrase, "reading")
        phrase = self.remove_voc(phrase, "lovecraft")
        phrase = self.remove_voc(phrase, "atlanta")
        phrase = self.remove_voc(phrase, "epic_horror")
        phrase = self.remove_voc(phrase, "audio_theatre")
        phrase = self.remove_voc(phrase, "play")
        phrase = phrase.strip()
        return phrase

    def get_base_score(self, phrase, media_type):
        original = phrase
        score = 0

        if self.voc_match(original, "atlanta"):
            score += 15

        if self.voc_match(phrase, "audio_theatre") or \
                media_type == MediaType.RADIO_THEATRE:
            score += 35
        elif media_type == MediaType.AUDIOBOOK:
            score += 15

        if self.voc_match(original, "horror"):
            score += 15
        elif self.voc_match(original, "epic_horror"):
            score += 30

        if self.voc_match(original, "lovecraft"):
            score += 50

        return score

    @ocp_search()
    def ocp_epichorrortheatre_playlist(self, phrase, media_type):
        score = self.get_base_score(phrase, media_type)
        if self.voc_match(phrase, "atlanta"):
            score += 15
        if self.voc_match(phrase, "audio_theatre") or \
                media_type == MediaType.RADIO_THEATRE:
            score += 10
        pl = [
            {
                "match_confidence": score,
                "media_type": MediaType.AUDIOBOOK,
                "uri": entry["uri"],
                "playback": PlaybackType.AUDIO,
                "image": join(dirname(__file__), entry["image"]),
                "bg_image": self.default_bg,
                "skill_icon": self.skill_icon,
                "title": title,
                "author": "H. P. Lovecraft",
                "album": "by Atlanta Radio Theatre"
            } for title, entry in self.db.items()
        ]
        if pl:
            yield {
                "match_confidence": score,
                "media_type": MediaType.AUDIOBOOK,
                "playlist": pl,
                "playback": PlaybackType.AUDIO,
                "skill_icon": self.skill_icon,
                "image": self.default_bg,
                "bg_image": self.default_bg,
                "title": "Epic Horror Theatre (Atlanta Radio Theatre)",
                "author": "H. P. Lovecraft",
                "album": "by Atlanta Radio Theatre"
            }

    @ocp_search()
    def search(self, phrase, media_type):
        score = self.get_base_score(phrase, media_type)
        phrase = self.clean_vocs(phrase)
        scores = {k: score for k, v in self.db.items()}
        if self.voc_match(phrase, "color_out_of_space"):
            scores["The Color Out of Space"] += 70
        elif self.voc_match(phrase, "innsmouth"):
            scores["The Shadow Over Innsmouth"] += 70
        elif self.voc_match(phrase, "mountains_of_madness"):
            scores["At The Mountains of Madness"] += 70
        elif media_type not in [MediaType.RADIO_THEATRE, MediaType.AUDIOBOOK]:
            return

        if score >= MatchConfidence.AVERAGE:
            for k in scores:
                yield {
                    "match_confidence": min(100, scores[k]),
                    "media_type": MediaType.AUDIOBOOK,
                    "uri": self.db[k]["uri"],
                    "playback": PlaybackType.AUDIO,
                    "image": join(dirname(__file__), self.db[k]["image"]),
                    "bg_image": self.default_bg,
                    "skill_icon": self.skill_icon,
                    "title": k,
                    "author": "H. P. Lovecraft",
                    "album": "by Atlanta Radio Theatre"
                }
Ejemplo n.º 13
0
class OVOSGuiControl(MycroftSkill):
    """
    The OVOSGuiControl skill handles much of the gui activities related to Mycroft's
    core functionality. This includes showing "speaking" faces as well as
    more complicated things such as switching to the selected resting face
    and handling system signals.

    # TODO move most things to enclosure / HAL. Only voice interaction should
      reside in the Skill.
    """
    def __init__(self):
        super().__init__("OVOSGuiControl")

        self.settings["auto_brightness"] = False
        self.settings["use_listening_beep"] = True

        self.has_show_page = False  # resets with each handler
        self.override_animations = False
        self.resting_screen = None
        self.auto_brightness = None

    def initialize(self):
        """Perform initalization.

        Registers messagebus handlers and sets default gui values.
        """
        self.resting_screen = RestingScreen(self.bus, self.gui, self.log,
                                            self.settings)

        self.brightness_dict = self.translate_namedvalues("brightness.levels")
        self.gui["volume"] = 0

        # Prepare GUI Viseme structure
        self.gui["viseme"] = {"start": 0, "visemes": []}

        store_conf = join(self.file_system.path, 'skill_conf.json')
        if not self.file_system.exists("skill_conf.json"):
            self.skill_conf = JsonStorage(store_conf)
            self.skill_conf["selected_backend"] = "unknown"
            self.skill_conf.store()
        else:
            self.skill_conf = JsonStorage(store_conf)

        try:
            # Handle network connection events
            self.add_event("mycroft.internet.connected",
                           self.handle_internet_connected)

            # Handle the 'busy' visual
            self.bus.on("mycroft.skill.handler.start", self.on_handler_started)

            self.bus.on("recognizer_loop:sleep", self.on_handler_sleep)
            self.bus.on("mycroft.awoken", self.on_handler_awoken)
            self.bus.on("enclosure.mouth.reset", self.on_handler_mouth_reset)
            self.bus.on("recognizer_loop:audio_output_end",
                        self.on_handler_mouth_reset)
            self.bus.on("enclosure.mouth.viseme_list",
                        self.on_handler_speaking)
            self.bus.on("gui.page.show", self.on_gui_page_show)
            self.bus.on("gui.page_interaction", self.on_gui_page_interaction)

            self.bus.on("mycroft.skills.initialized", self.reset_face)
            self.bus.on("ovos.pairing.process.completed",
                        self.start_homescreen_process)
            self.bus.on("ovos.pairing.set.backend", self.set_backend_type)
            self.bus.on("mycroft.mark2.register_idle",
                        self.resting_screen.on_register)

            self.add_event("mycroft.mark2.reset_idle",
                           self.resting_screen.restore)
            # TODO move resting screen to Enclosure
            # TODO consolidate bus message format
            # - this message is set to be consistent with a handler below.
            self.add_event("mycroft.device.show.idle",
                           self.resting_screen.show)

            # Handle device settings events
            self.add_event("mycroft.device.settings",
                           self.handle_device_settings)

            # Handle GUI release events
            self.add_event("mycroft.gui.screen.close",
                           self.handle_remove_namespace)

            # Use Legacy for QuickSetting delegate
            self.gui.register_handler("mycroft.device.settings",
                                      self.handle_device_settings)
            self.gui.register_handler("mycroft.device.settings.homescreen",
                                      self.handle_device_homescreen_settings)

            self.gui.register_handler('mycroft.device.settings.ssh',
                                      self.handle_device_ssh_settings)

            self.gui.register_handler("mycroft.device.settings.restart",
                                      self.handle_device_restart_action)
            self.gui.register_handler("mycroft.device.settings.poweroff",
                                      self.handle_device_poweroff_action)
            self.gui.register_handler("mycroft.device.show.idle",
                                      self.resting_screen.show)

            # Handle idle selection
            self.gui.register_handler("mycroft.device.set.idle",
                                      self.resting_screen.set)

            # System events
            self.add_event("system.reboot", self.handle_system_reboot)
            self.add_event("system.shutdown", self.handle_system_shutdown)

            # Show loading screen while starting up skills.
            # self.gui['state'] = 'loading'
            # self.gui.show_page('all.qml')

            # Collect Idle screens and display if skill is restarted
            self.device_paired = is_paired()
            self.device_backend = self.skill_conf["selected_backend"]

            if not self.device_backend == "local":
                if self.device_paired:
                    self.resting_screen.collect()
            else:
                self.resting_screen.collect()
                self.bus.emit(Message("ovos.shell.status.ok"))

        except Exception:
            LOG.exception("In OVOSGuiControl Skill")

        # Update use of wake-up beep
        self._sync_wake_beep_setting()

        self.settings_change_callback = self.on_websettings_changed

    ###################################################################
    # System events
    def handle_system_reboot(self, _):
        self.speak_dialog("rebooting", wait=True)
        subprocess.call(["/usr/bin/systemctl", "reboot"])

    def handle_system_shutdown(self, _):
        subprocess.call(["/usr/bin/systemctl", "poweroff"])

    def handle_remove_namespace(self, message):
        self.log.info("Got Clear Namespace Event In Mark 2 Skill")
        get_skill_namespace = message.data.get("skill_id", "")
        if get_skill_namespace:
            self.bus.emit(
                Message("gui.clear.namespace",
                        {"__from": get_skill_namespace}))
        self.resting_screen.cancel_override()
        self.cancel_scheduled_event("IdleCheck")

    ###################################################################
    # Idle screen mechanism

    def set_backend_type(self, message):
        backend = message.data.get("backend", "unknown")
        if not backend == "unknown":
            self.skill_conf["selected_backend"] = backend
            self.skill_conf.store()
            self.device_backend = self.skill_conf["selected_backend"]

    def start_homescreen_process(self, _):
        self.device_paired = is_paired()
        self.resting_screen.collect()

    def reset_face(self, _):
        """Triggered after skills are initialized.

        Sets switches from resting "face" to a registered resting screen.
        """
        time.sleep(1)
        if self.device_paired or self.device_backend == "local":
            self.resting_screen.collect()

    def stop(self, _=None):
        """Clear override_idle and stop visemes."""
        self.log.debug("Stop received")
        self.resting_screen.stop()
        self.gui["viseme"] = {"start": 0, "visemes": []}
        return False

    def shutdown(self):
        """Cleanly shutdown the Skill removing any manual event handlers"""
        # Gotta clean up manually since not using add_event()
        self.bus.remove("mycroft.skill.handler.start", self.on_handler_started)
        self.bus.remove("recognizer_loop:sleep", self.on_handler_sleep)
        self.bus.remove("mycroft.awoken", self.on_handler_awoken)
        self.bus.remove("enclosure.mouth.reset", self.on_handler_mouth_reset)
        self.bus.remove("recognizer_loop:audio_output_end",
                        self.on_handler_mouth_reset)
        self.bus.remove("enclosure.mouth.viseme_list",
                        self.on_handler_speaking)
        self.bus.remove("gui.page.show", self.on_gui_page_show)
        self.bus.remove("gui.page_interaction", self.on_gui_page_interaction)
        self.bus.remove("mycroft.mark2.register_idle",
                        self.resting_screen.on_register)
        self.bus.remove("ovos.pairing.process.completed",
                        self.start_homescreen_process)
        self.bus.remove("ovos.pairing.set.backend", self.set_backend_type)

    #####################################################################
    # Manage "busy" visual

    def on_handler_started(self, message):
        handler = message.data.get("handler", "")
        # Ignoring handlers from this skill and from the background clock
        if "OVOSGuiControl" in handler:
            return
        if "TimeSkill.update_display" in handler:
            return

    def on_gui_page_interaction(self, _):
        """ Reset idle timer to 30 seconds when page is flipped. """
        self.log.debug("Resetting idle counter to 30 seconds")
        self.start_idle_event(30)

    def on_gui_page_show(self, message):
        self.log.info(message.data.get("__from", ""))
        if "skill-ovos-mycroftgui" not in message.data.get("__from", ""):
            # Some skill other than the handler is showing a page
            self.has_show_page = True

            # If a skill overrides the animations do not show any
            override_animations = message.data.get("__animations", False)
            if override_animations:
                # Disable animations
                self.log.debug("Disabling all animations for page")
                self.override_animations = True
            else:
                self.log.debug("Displaying all animations for page")
                self.override_animations = False

            # If a skill overrides the idle do not switch page
            override_idle = message.data.get("__idle")
            if override_idle is True:
                # Disable idle screen
                self.log.debug("Cancelling Idle screen")
                self.cancel_idle_event()
                self.resting_screen.override(message)
            elif isinstance(override_idle, int) and override_idle is not False:
                self.log.info("Overriding idle timer to"
                              " {} seconds".format(override_idle))
                self.resting_screen.override(None)
                self.start_idle_event(override_idle)
            elif message.data["page"] and not message.data["page"][0].endswith(
                    "idle.qml"):
                # Check if the show_page deactivates a previous idle override
                # This is only possible if the page is from the same skill
                self.log.info("Cancelling idle override")
                if override_idle is False and compare_origin(
                        message, self.resting_screen.override_idle[0]):
                    # Remove the idle override page if override is set to false
                    self.resting_screen.cancel_override()
                # Set default idle screen timer
                self.start_idle_event(30)

    def on_handler_mouth_reset(self, _):
        """ Restore viseme to a smile. """
        pass

    def on_handler_sleep(self, _):
        """ Show resting face when going to sleep. """
        self.gui["state"] = "resting"
        self.gui.show_page("all.qml")

    def on_handler_awoken(self, _):
        """ Show awake face when sleep ends. """
        self.gui["state"] = "awake"
        self.gui.show_page("all.qml")

    def on_handler_complete(self, message):
        """ When a skill finishes executing clear the showing page state. """
        handler = message.data.get("handler", "")
        # Ignoring handlers from this skill and from the background clock
        if "OVOSGuiControl" in handler:
            return
        if "TimeSkill.update_display" in handler:
            return

        self.has_show_page = False

        try:
            if self.hourglass_info[handler] == -1:
                self.enclosure.reset()
            del self.hourglass_info[handler]
        except Exception:
            # There is a slim chance the self.hourglass_info might not
            # be populated if this skill reloads at just the right time
            # so that it misses the mycroft.skill.handler.start but
            # catches the mycroft.skill.handler.complete
            pass

    #####################################################################
    # Manage "speaking" visual

    def on_handler_speaking(self, message):
        """Show the speaking page if no skill has registered a page
        to be shown in it's place.
        """
        if self.device_paired or self.device_backend == "local":
            self.gui["viseme"] = message.data
            if not self.has_show_page:
                self.gui["state"] = "speaking"
                self.gui.show_page("all.qml")
                # Show idle screen after the visemes are done (+ 2 sec).
                viseme_time = message.data["visemes"][-1][1] + 5
                self.start_idle_event(viseme_time)

    #####################################################################
    # Manage resting screen visual state
    def cancel_idle_event(self):
        """Cancel the event monitoring current system idle time."""
        self.resting_screen.next = 0
        self.cancel_scheduled_event("IdleCheck")

    def start_idle_event(self, offset=60, weak=False):
        """Start an event for showing the idle screen.

        Arguments:
            offset: How long until the idle screen should be shown
            weak: set to true if the time should be able to be overridden
        """
        with self.resting_screen.lock:
            if time.monotonic() + offset < self.resting_screen.next:
                self.log.info("No update, before next time")
                return

            self.log.debug("Starting idle event")
            try:
                if not weak:
                    self.resting_screen.next = time.monotonic() + offset
                # Clear any existing checker
                self.cancel_scheduled_event("IdleCheck")
                time.sleep(0.5)
                self.schedule_event(self.resting_screen.show,
                                    int(offset),
                                    name="IdleCheck")
                self.log.debug("Showing idle screen in "
                               "{} seconds".format(offset))
            except Exception as e:
                self.log.exception(repr(e))

    #####################################################################
    # Manage network

    def handle_internet_connected(self, _):
        """ System came online later after booting. """
        self.enclosure.mouth_reset()

    #####################################################################
    # Web settings

    def on_websettings_changed(self):
        """ Update use of wake-up beep. """
        self._sync_wake_beep_setting()

    def _sync_wake_beep_setting(self):
        """ Update "use beep" global config from skill settings. """
        config = Configuration.get()
        use_beep = self.settings.get("use_listening_beep", False)
        if not config["confirm_listening"] == use_beep:
            # Update local (user) configuration setting
            new_config = {"confirm_listening": use_beep}
            user_config = LocalConf(USER_CONFIG)
            user_config.merge(new_config)
            user_config.store()
            self.bus.emit(Message("configuration.updated"))

    #####################################################################
    # Brightness intent interaction

    def percent_to_level(self, percent):
        """Converts the brigtness value from percentage to a
        value the Arduino can read

        Arguments:
            percent (int): interger value from 0 to 100

        return:
            (int): value form 0 to 30
        """
        return int(float(percent) / float(100) * 30)

    def parse_brightness(self, brightness):
        """Parse text for brightness percentage.

        Arguments:
            brightness (str): string containing brightness level

        Returns:
            (int): brightness as percentage (0-100)
        """

        try:
            # Handle "full", etc.
            name = normalize(brightness)
            if name in self.brightness_dict:
                return self.brightness_dict[name]

            if "%" in brightness:
                brightness = brightness.replace("%", "").strip()
                return int(brightness)
            if "percent" in brightness:
                brightness = brightness.replace("percent", "").strip()
                return int(brightness)

            i = int(brightness)
            if i < 0 or i > 100:
                return None

            if i < 30:
                # Assmume plain 0-30 is "level"
                return int((i * 100.0) / 30.0)

            # Assume plain 31-100 is "percentage"
            return i
        except Exception:
            return None  # failed in an int() conversion

    def set_screen_brightness(self, level, speak=True):
        """Actually change screen brightness.

        Arguments:
            level (int): 0-30, brightness level
            speak (bool): when True, speak a confirmation
        """
        # TODO CHANGE THE BRIGHTNESS
        if speak:
            percent = int(float(level) * float(100) / float(30))
            self.speak_dialog("brightness.set",
                              data={"val": str(percent) + "%"})

    def _set_brightness(self, brightness):
        # brightness can be a number or word like "full", "half"
        percent = self.parse_brightness(brightness)
        if percent is None:
            self.speak_dialog("brightness.not.found.final")
        elif int(percent) == -1:
            self.handle_auto_brightness(None)
        else:
            self.auto_brightness = False
            self.set_screen_brightness(self.percent_to_level(percent))

    @intent_handler("brightness.intent")
    def handle_brightness(self, message):
        """Intent handler to set custom screen brightness.

        Arguments:
            message (dict): messagebus message from intent parser
        """
        brightness = message.data.get(
            "brightness", None) or self.get_response("brightness.not.found")
        if brightness:
            self._set_brightness(brightness)

    def _get_auto_time(self):
        """Get dawn, sunrise, noon, sunset, and dusk time.

        Returns:
            times (dict): dict with associated (datetime, level)
        """
        tz_code = self.location["timezone"]["code"]
        lat = self.location["coordinate"]["latitude"]
        lon = self.location["coordinate"]["longitude"]
        ast_loc = astral.Location()
        ast_loc.timezone = tz_code
        ast_loc.lattitude = lat
        ast_loc.longitude = lon

        user_set_tz = timezone(tz_code).localize(datetime.now()).strftime("%Z")
        device_tz = time.tzname

        if user_set_tz in device_tz:
            sunrise = ast_loc.sun()["sunrise"]
            noon = ast_loc.sun()["noon"]
            sunset = ast_loc.sun()["sunset"]
        else:
            secs = int(self.location["timezone"]["offset"]) / -1000
            sunrise = (arrow.get(ast_loc.sun()["sunrise"]).shift(
                seconds=secs).replace(tzinfo="UTC").datetime)
            noon = (arrow.get(ast_loc.sun()["noon"]).shift(
                seconds=secs).replace(tzinfo="UTC").datetime)
            sunset = (arrow.get(ast_loc.sun()["sunset"]).shift(
                seconds=secs).replace(tzinfo="UTC").datetime)

        return {
            "Sunrise": (sunrise, 20),  # high
            "Noon": (noon, 30),  # full
            "Sunset": (sunset, 5),  # dim
        }

    def schedule_brightness(self, time_of_day, pair):
        """Schedule auto brightness with the event scheduler.

        Arguments:
            time_of_day (str): Sunrise, Noon, Sunset
            pair (tuple): (datetime, brightness)
        """
        d_time = pair[0]
        brightness = pair[1]
        now = arrow.now()
        arw_d_time = arrow.get(d_time)
        data = (time_of_day, brightness)
        if now.timestamp > arw_d_time.timestamp:
            d_time = arrow.get(d_time).shift(hours=+24)
            self.schedule_event(
                self._handle_screen_brightness_event,
                d_time,
                data=data,
                name=time_of_day,
            )
        else:
            self.schedule_event(
                self._handle_screen_brightness_event,
                d_time,
                data=data,
                name=time_of_day,
            )

    @intent_handler("brightness.auto.intent")
    def handle_auto_brightness(self, _):
        """brightness varies depending on time of day

        Arguments:
            message (Message): messagebus message from intent parser
        """
        self.auto_brightness = True
        auto_time = self._get_auto_time()
        nearest_time_to_now = (float("inf"), None, None)
        for time_of_day, pair in auto_time.items():
            self.schedule_brightness(time_of_day, pair)
            now = arrow.now().timestamp
            timestamp = arrow.get(pair[0]).timestamp
            if abs(now - timestamp) < nearest_time_to_now[0]:
                nearest_time_to_now = (abs(now - timestamp), pair[1],
                                       time_of_day)
        self.set_screen_brightness(nearest_time_to_now[1], speak=False)

    def _handle_screen_brightness_event(self, message):
        """Wrapper for setting screen brightness from eventscheduler

        Arguments:
            message (Message): messagebus message
        """
        if self.auto_brightness:
            time_of_day = message.data[0]
            level = message.data[1]
            self.cancel_scheduled_event(time_of_day)
            self.set_screen_brightness(level, speak=False)
            pair = self._get_auto_time()[time_of_day]
            self.schedule_brightness(time_of_day, pair)

    #####################################################################
    # Device Settings

    @intent_handler("device.settings.intent")
    def handle_device_settings(self, message):
        """ Display device settings page. """
        self.gui["state"] = "settings/settingspage"
        self.gui.show_page("all.qml")

    @intent_handler("device.homescreen.settings.intent")
    def handle_device_homescreen_settings(self, message):
        """
        display homescreen settings page
        """
        screens = [{
            "screenName": s,
            "screenID": self.resting_screen.screens[s]
        } for s in self.resting_screen.screens]
        self.gui["idleScreenList"] = {"screenBlob": screens}
        self.gui["selectedScreen"] = self.gui["selected"]
        self.gui["state"] = "settings/homescreen_settings"
        self.gui.show_page("all.qml")

    @intent_handler('device.ssh.settings.intent')
    def handle_device_ssh_settings(self, message):
        """ Display ssh settings page. """
        self.gui['state'] = 'settings/ssh_settings'
        self.gui.show_page('all.qml')

    def handle_device_set_ssh(self, message):
        """ Set ssh settings """
        enable_ssh = message.data.get("enable_ssh", False)
        if enable_ssh:
            ssh_enable()
        elif not enable_ssh:
            ssh_disable()

    def handle_device_restart_action(self, message):
        """ Device restart action. """
        self.log.info("Going Down For Restart")
        system_reboot()

    def handle_device_poweroff_action(self, message):
        """ Device poweroff action. """
        self.log.info("Powering Off")
        system_shutdown()
Ejemplo n.º 14
0
#!/usr/bin/env python3
from json_database import JsonStorage
import os
import cryptography

data = JsonStorage("data.json")
contacts = []


class user:
    filename = "user.data"
    signer = None
    decrypt_cipher = None
    key = None
    chats = None
    username = ""

    def __init__(self):
        None

    def retrieve(self):
        self.filename = self.username + ".data"
        if not os.path.isfile(self.filename):
            return False
        cryptography.get_data(self)
        return True

    def create(self):
        self.filename = self.username + ".data"
        if os.path.isfile(self.filename):
            return False
from json_database import JsonStorage

save_path = "my_dict.conf"

with JsonStorage(save_path) as my_config:
    my_config["lang"] = "pt"
    my_config["secondary_lang"] = "en"
    my_config["email"] = "*****@*****.**"

# auto saved
Ejemplo n.º 16
0
    default = JsonStorage(DATA_PATH)

    DB_PATH = join(DATA_PATH, "database")

    default["port"] = 5678
    default["data_path"] = DATA_PATH
    default["ssl"] = {
        "enable": False,
        "ssl_certfile": join(DATA_PATH, "certs", "hivemind.crt"),
        "ssl_keyfile": join(DATA_PATH, "certs", "hivekey.crt")
    }
    default["database"] = {
        "clients": "sqlite:///" + join(DB_PATH, "clients.db")
    }
    default["log_blacklist"] = []
    default["mycroft_bus"] = {
        "host": "0.0.0.0",
        "port": 8181,
        "route": "/core",
        "ssl": False
    }

    return default


if not exists(DATA_PATH):
    CONFIGURATION = default_config()
    CONFIGURATION.store()
else:
    CONFIGURATION = JsonStorage(DATA_PATH)
Ejemplo n.º 17
0
class LovecraftComicsSkill(OVOSCommonPlaybackSkill):

    def __init__(self):
        super().__init__("LovecraftComics")
        self.supported_media = [MediaType.GENERIC,
                                MediaType.AUDIOBOOK,
                                MediaType.VISUAL_STORY,
                                MediaType.VIDEO]
        self.default_bg = join(dirname(__file__), "ui", "bg.png")
        self.default_image = join(dirname(__file__), "ui", "dagon.png")
        self.skill_icon = join(dirname(__file__), "ui", "icon.png")
        self.db = JsonStorage(join(dirname(__file__), "res",
                                   "JeremyZahn_lovecraft_comics.json"))
        self.db2 = JsonStorage(join(dirname(__file__), "res",
                                    "TanabeGou_lovecraft_comics.json"))

    def get_base_score(self, original, media_type):
        score = 0
        if media_type == MediaType.AUDIOBOOK:
            score += 10
        elif media_type == MediaType.VIDEO:
            score += 5
        elif media_type == MediaType.VISUAL_STORY:
            score += 30

        if self.voc_match(original, "reading") or \
                self.voc_match(original, "audio_theatre"):
            score += 10

        if self.voc_match(original, "lovecraft"):
            score += 30
            if self.voc_match(original, "video"):
                score += 10

        if self.voc_match(original, "comic"):
            score += 10
        return score

    @ocp_search()
    def ocp_motioncomics_lovecraft_playlist(self, phrase, media_type):
        score = self.get_base_score(phrase, media_type)
        if self.voc_match(phrase, "comic") or \
                media_type == MediaType.VISUAL_STORY:
            score += 10
            if self.voc_match(phrase, "lovecraft"):
                score += 30
        pl = [
            {
                "match_confidence": score,
                "media_type": MediaType.VISUAL_STORY,
                "uri": entry["uri"],
                "playback": PlaybackType.VIDEO,
                "image": entry["image"],
                "bg_image": self.default_bg,
                "skill_icon": self.skill_icon,
                "title": entry["title"],
                "author": "H. P. Lovecraft",
                "album": "Lovecraft Motion Comics by Jeremy Zahn"
            } for title, entry in self.db.items()
        ]
        pl2 = [
            {
                "match_confidence": score,
                "media_type": MediaType.VISUAL_STORY,
                "uri": entry["uri"],
                "playback": PlaybackType.VIDEO,
                "image": entry["image"],
                "bg_image": self.default_bg,
                "skill_icon": self.skill_icon,
                "title": entry["title"],
                "author": "H. P. Lovecraft",
                "album": "Lovecraft Illustrated by Tanabe Gou"
            } for title, entry in self.db2.items()
        ]

        return [{
            "match_confidence": score,
            "media_type": MediaType.VISUAL_STORY,
            "playlist": pl,
            "playback": PlaybackType.VIDEO,
            "skill_icon": self.skill_icon,
            "image": "https://img.youtube.com/vi/Gv1I0y6PHfg/hqdefault.jpg",
            "bg_image": self.default_image,
            "title": "Lovecraft Comics by Jeremy Zahn (Playlist)",
            "author": "H. P. Lovecraft",
            "album": "Lovecraft Motion Comics by Jeremy Zahn"
        }, {
            "match_confidence": score,
            "media_type": MediaType.VISUAL_STORY,
            "playlist": pl2,
            "playback": PlaybackType.VIDEO,
            "skill_icon": self.skill_icon,
            "image": "https://img.youtube.com/vi/jW_G7cGxCWY/hqdefault.jpg",
            "bg_image": self.default_image,
            "title": "Lovecraft Illustrated by Tanabe Gou (Playlist)",
            "author": "H. P. Lovecraft",
            "album": "Lovecraft Illustrated by Tanabe Gou"
        }]

    @ocp_featured_media()
    def featured_media(self):
        pl = [
            {
                "media_type": MediaType.VISUAL_STORY,
                "uri": entry["uri"],
                "playback": PlaybackType.VIDEO,
                "image": entry["image"],
                "bg_image": self.default_bg,
                "skill_icon": self.skill_icon,
                "title": entry["title"],
                "author": "H. P. Lovecraft",
                "album": "Lovecraft Motion Comics by Jeremy Zahn"
            } for title, entry in self.db.items()
        ]
        pl2 = [
            {
                "media_type": MediaType.VISUAL_STORY,
                "uri": entry["uri"],
                "playback": PlaybackType.VIDEO,
                "image": entry["image"],
                "bg_image": self.default_bg,
                "skill_icon": self.skill_icon,
                "title": entry["title"],
                "author": "H. P. Lovecraft",
                "album": "Lovecraft Illustrated by Tanabe Gou"
            } for title, entry in self.db2.items()
        ]
        return pl + pl2
Ejemplo n.º 18
0
    def initialize(self):
        """Perform initalization.

        Registers messagebus handlers and sets default gui values.
        """
        self.resting_screen = RestingScreen(self.bus, self.gui, self.log,
                                            self.settings)

        self.brightness_dict = self.translate_namedvalues("brightness.levels")
        self.gui["volume"] = 0

        # Prepare GUI Viseme structure
        self.gui["viseme"] = {"start": 0, "visemes": []}

        store_conf = join(self.file_system.path, 'skill_conf.json')
        if not self.file_system.exists("skill_conf.json"):
            self.skill_conf = JsonStorage(store_conf)
            self.skill_conf["selected_backend"] = "unknown"
            self.skill_conf.store()
        else:
            self.skill_conf = JsonStorage(store_conf)

        try:
            # Handle network connection events
            self.add_event("mycroft.internet.connected",
                           self.handle_internet_connected)

            # Handle the 'busy' visual
            self.bus.on("mycroft.skill.handler.start", self.on_handler_started)

            self.bus.on("recognizer_loop:sleep", self.on_handler_sleep)
            self.bus.on("mycroft.awoken", self.on_handler_awoken)
            self.bus.on("enclosure.mouth.reset", self.on_handler_mouth_reset)
            self.bus.on("recognizer_loop:audio_output_end",
                        self.on_handler_mouth_reset)
            self.bus.on("enclosure.mouth.viseme_list",
                        self.on_handler_speaking)
            self.bus.on("gui.page.show", self.on_gui_page_show)
            self.bus.on("gui.page_interaction", self.on_gui_page_interaction)

            self.bus.on("mycroft.skills.initialized", self.reset_face)
            self.bus.on("ovos.pairing.process.completed",
                        self.start_homescreen_process)
            self.bus.on("ovos.pairing.set.backend", self.set_backend_type)
            self.bus.on("mycroft.mark2.register_idle",
                        self.resting_screen.on_register)

            self.add_event("mycroft.mark2.reset_idle",
                           self.resting_screen.restore)
            # TODO move resting screen to Enclosure
            # TODO consolidate bus message format
            # - this message is set to be consistent with a handler below.
            self.add_event("mycroft.device.show.idle",
                           self.resting_screen.show)

            # Handle device settings events
            self.add_event("mycroft.device.settings",
                           self.handle_device_settings)

            # Handle GUI release events
            self.add_event("mycroft.gui.screen.close",
                           self.handle_remove_namespace)

            # Use Legacy for QuickSetting delegate
            self.gui.register_handler("mycroft.device.settings",
                                      self.handle_device_settings)
            self.gui.register_handler("mycroft.device.settings.homescreen",
                                      self.handle_device_homescreen_settings)

            self.gui.register_handler('mycroft.device.settings.ssh',
                                      self.handle_device_ssh_settings)

            self.gui.register_handler("mycroft.device.settings.restart",
                                      self.handle_device_restart_action)
            self.gui.register_handler("mycroft.device.settings.poweroff",
                                      self.handle_device_poweroff_action)
            self.gui.register_handler("mycroft.device.show.idle",
                                      self.resting_screen.show)

            # Handle idle selection
            self.gui.register_handler("mycroft.device.set.idle",
                                      self.resting_screen.set)

            # System events
            self.add_event("system.reboot", self.handle_system_reboot)
            self.add_event("system.shutdown", self.handle_system_shutdown)

            # Show loading screen while starting up skills.
            # self.gui['state'] = 'loading'
            # self.gui.show_page('all.qml')

            # Collect Idle screens and display if skill is restarted
            self.device_paired = is_paired()
            self.device_backend = self.skill_conf["selected_backend"]

            if not self.device_backend == "local":
                if self.device_paired:
                    self.resting_screen.collect()
            else:
                self.resting_screen.collect()
                self.bus.emit(Message("ovos.shell.status.ok"))

        except Exception:
            LOG.exception("In OVOSGuiControl Skill")

        # Update use of wake-up beep
        self._sync_wake_beep_setting()

        self.settings_change_callback = self.on_websettings_changed
Ejemplo n.º 19
0
from json_database import JsonStorage
from json_database.exceptions import DatabaseNotCommitted
from os.path import exists

save_path = "my_dict.conf"

my_config = JsonStorage(save_path)

my_config["lang"] = "pt"
my_config["secondary_lang"] = "en"
my_config["email"] = "*****@*****.**"

# my_config is a python dict
assert isinstance(my_config, dict)

# save to file
my_config.store()

my_config["lang"] = "pt-pt"

# revert to previous saved file
my_config.reload()

assert my_config["lang"] == "pt"

# clear all fields
my_config.clear()

assert my_config == {}

# load from a specific path
Ejemplo n.º 20
0
class YoutubeSkill(MycroftSkill):
    def __init__(self):
        super(YoutubeSkill, self).__init__(name="YoutubeSkill")
        self.nextpage_url = None
        self.previouspage_url = None
        self.live_category = None
        self.recentList = deque()
        self.recentPageObject = {}
        self.nextSongList = None
        self.lastSong = None
        self.videoPageObject = {}
        self.isTitle = None
        self.newsCategoryList = {}
        self.musicCategoryList = {}
        self.techCategoryList = {}
        self.polCategoryList = {}
        self.gamingCategoryList = {}
        self.searchCategoryList = {}
        self.storeDB = dirname(__file__) + '-recent.db'
        self.recent_db = JsonStorage(self.storeDB)
        self.ytkey = base64.b64decode("QUl6YVN5RE9tSXhSemI0RzFhaXFzYnBaQ3IwQTlFN1NrT0pVRURr")
        pafy.set_api_key(self.ytkey)

    def initialize(self):
        self.load_data_files(dirname(__file__))
        
        self.bus.on('youtube-skill.aiix.home', self.launcherId)
        
        youtubepause = IntentBuilder("YoutubePauseKeyword"). \
            require("YoutubePauseKeyword").build()
        self.register_intent(youtubepause, self.youtubepause)

        youtuberesume = IntentBuilder("YoutubeResumeKeyword"). \
            require("YoutubeResumeKeyword").build()
        self.register_intent(youtuberesume, self.youtuberesume)

        youtubesearchpage = IntentBuilder("YoutubeSearchPageKeyword"). \
            require("YoutubeSearchPageKeyword").build()
        self.register_intent(youtubesearchpage, self.youtubesearchpage)

        youtubelauncherId = IntentBuilder("YoutubeLauncherId"). \
            require("YoutubeLauncherIdKeyword").build()
        self.register_intent(youtubelauncherId, self.launcherId)
        
        self.add_event('aiix.youtube-skill.playvideo_id', self.play_event)
        
        self.gui.register_handler('YoutubeSkill.SearchLive',
                                  self.searchLive)
        
        self.gui.register_handler('YoutubeSkill.NextPage', self.searchNextPage)
        self.gui.register_handler('YoutubeSkill.PreviousPage', self.searchPreviousPage)
        self.gui.register_handler('YoutubeSkill.NextAutoPlaySong', self.nextSongForAutoPlay)
        self.gui.register_handler('YoutubeSkill.RefreshWatchList', self.refreshWatchList)
        self.gui.register_handler('YoutubeSkill.ClearDB', self.clear_db)
        
    def launcherId(self, message):
        self.show_homepage({})

    def getListSearch(self, text):
        query = quote(text)
        url = "https://www.youtube.com/results?search_query=" + quote(query)
        response = urlopen(url)
        html = response.read()
        a_tag = SoupStrainer('a')
        soup = BeautifulSoup(html, 'html.parser', parse_only=a_tag)
        for vid in soup.findAll(attrs={'class': 'yt-uix-tile-link'}):
            if "googleads" not in vid['href'] and not vid['href'].startswith(
                    u"/user") and not vid['href'].startswith(u"/channel"):
                id = vid['href'].split("v=")[1].split("&")[0]
                return id

    def moreRandomListSearch(self, text):
        LOG.info(text)
        query = quote(text)
        try:
            querySplit = text.split()
            LOG.info(querySplit)
            searchQuery = "*," + quote(querySplit[0]) + quote(querySplit[1]) + ",*"
        
        except:
            LOG.info("fail")
            searchQuery = "*," + quote(query) + ",*"

        LOG.info(searchQuery)
        return searchQuery    
    

    def searchLive(self, message):
        videoList = []
        videoList.clear()
        videoPageObject = {}
        try:
            query = message.data["Query"]
            LOG.info("I am in search Live")
            self.searchCategoryList["videoList"] = self.build_category_list(quote(query))
            self.gui["searchListBlob"] = self.searchCategoryList
            self.gui["previousAvailable"] = False
            self.gui["nextAvailable"] = True
            self.gui["bgImage"] = quote(query)
            self.gui.show_page("YoutubeLiveSearch.qml", override_idle=True)
        except:
            LOG.debug("error")
        
    def searchNextPage(self, message):
        getCategory = message.data["Category"]
        LOG.info(getCategory)
        if getCategory == "News":
            LOG.info("In Category News")
            newsAdditionalPages = self.process_additional_pages("news")
            self.newsCategoryList['videoList'] = self.build_category_list_from_url("https://www.youtube.com" + newsAdditionalPages[0])
            self.gui["newsNextAvailable"] = False
            self.gui["newsListBlob"] = self.newsCategoryList
        if getCategory == "Music":
            LOG.info("In Category Music")
            musicAdditionalPages = self.process_additional_pages("music")
            self.musicCategoryList['videoList'] = self.build_category_list_from_url("https://www.youtube.com" + musicAdditionalPages[0])
            self.gui["musicNextAvailable"] = False
            self.gui["musicListBlob"] = self.musicCategoryList
        if getCategory == "Technology":
            LOG.info("In Category Technology")
            technologyAdditionalPages = self.process_additional_pages("technology")
            self.techCategoryList['videoList'] = self.build_category_list_from_url("https://www.youtube.com" + technologyAdditionalPages[0])
            self.gui["techNextAvailable"] = False
            self.gui["techListBlob"] = self.techCategoryList
        if getCategory == "Politics":
            LOG.info("In Category Politics")
            politicsAdditionalPages = self.process_additional_pages("politics")
            self.polCategoryList['videoList'] = self.build_category_list_from_url("https://www.youtube.com" + politicsAdditionalPages[0])
            self.gui["polNextAvailable"] = False
            self.gui["polListBlob"] = self.polCategoryList
        if getCategory == "Gaming":
            LOG.info("In Category Gaming")
            gamingAdditionalPages = self.process_additional_pages("gaming")
            self.gamingCategoryList['videoList'] = self.build_category_list_from_url("https://www.youtube.com" + gamingAdditionalPages[0])
            self.gui["gamingNextAvailable"] = False
            self.gui["gamingListBlob"] = self.gamingCategoryList
        if getCategory == "Search":
            LOG.info("In Search")
        
    def searchPreviousPage(self, message):
        getCategory = message.data["Category"]
        LOG.info(getCategory)
        if getCategory == "News":
            LOG.info("In Category News")
            newsAdditionalPages = self.process_additional_pages("news")
            self.newsCategoryList['videoList'] = self.build_category_list_from_url(newsAdditionalPages[1])
            self.gui["newsNextAvailable"] = True
            self.gui["newsListBlob"] = self.newsCategoryList
        if getCategory == "Music":
            LOG.info("In Category Music")
            musicAdditionalPages = self.process_additional_pages("music")
            self.musicCategoryList['videoList'] = self.build_category_list_from_url(musicAdditionalPages[1])
            self.gui["musicNextAvailable"] = True
            self.gui["musicListBlob"] = self.musicCategoryList
        if getCategory == "Technology":
            LOG.info("In Category Technology")
            technologyAdditionalPages = self.process_additional_pages("technology")
            self.techCategoryList['videoList'] = self.build_category_list_from_url(technologyAdditionalPages[1])
            self.gui["techNextAvailable"] = True
            self.gui["techListBlob"] = self.techCategoryList
        if getCategory == "Politics":
            LOG.info("In Category Politics")
            politicsAdditionalPages = self.process_additional_pages("politics")
            self.polCategoryList['videoList'] = self.build_category_list_from_url(politicsAdditionalPages[1])
            self.gui["polNextAvailable"] = True
            self.gui["polListBlob"] = self.polCategoryList
        if getCategory == "Gaming":
            LOG.info("In Category Gaming")
            gamingAdditionalPages = self.process_additional_pages("gaming")
            self.gamingCategoryList['videoList'] = self.build_category_list_from_url(gamingAdditionalPages[1])
            self.gui["gamingNextAvailable"] = True
            self.gui["gamingListBlob"] = self.gamingCategoryList
        if getCategory == "Search":
            LOG.info("In Search")
            
    def getTitle(self, text):
        query = quote(text)
        url = "https://www.youtube.com/results?search_query=" + quote(query)
        response = urlopen(url)
        html = response.read()
        soup = BeautifulSoup(html)
        for vid in soup.findAll(attrs={'class': 'yt-uix-tile-link'}):
            if "googleads" not in vid['href'] and not vid['href'].startswith(
                    u"/user") and not vid['href'].startswith(u"/channel"):
                videoTitle = vid['title']
                return videoTitle


    @intent_file_handler('youtube.intent')
    def youtube(self, message):
        self.stop()
        self.gui.clear()
        self.enclosure.display_manager.remove_active()
        utterance = message.data['videoname'].lower()
        self.youtube_play_video(utterance)
    
    def youtube_play_video(self, utterance):
        self.gui["setTitle"] = ""
        self.gui["video"] = ""
        self.gui["status"] = "stop"
        self.gui["currenturl"] = ""
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["videoThumb"] = ""
        url = "https://www.youtube.com/results?search_query=" + quote(utterance)
        response = urlopen(url)
        html = response.read()
        a_tag = SoupStrainer('a')
        soup = BeautifulSoup(html, 'html.parser', parse_only=a_tag)
        self.gui["video"] = ""
        self.gui["status"] = "stop"
        self.gui["currenturl"] = ""
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["videoThumb"] = ""
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"], 0, override_idle=True)
        rfind = soup.findAll(attrs={'class': 'yt-uix-tile-link'})
        try:
            vid = str(rfind[0].attrs['href'])
            veid = "https://www.youtube.com{0}".format(vid)
            LOG.info(veid)
            getvid = vid.split("v=")[1].split("&")[0]
        except:
            vid = str(rfind[1].attrs['href'])
            veid = "https://www.youtube.com{0}".format(vid)
            LOG.info(veid)
            getvid = vid.split("v=")[1].split("&")[0]
        thumb = "https://img.youtube.com/vi/{0}/maxresdefault.jpg".format(getvid)
        self.gui["videoThumb"] = thumb
        self.lastSong = veid
        video = pafy.new(veid)
        playstream = video.streams[0]
        playurl = playstream.url
        self.gui["status"] = str("play")
        self.gui["video"] = str(playurl)
        self.gui["currenturl"] = str(vid)
        self.gui["currenttitle"] = video.title
        self.gui["setTitle"] = video.title
        self.gui["viewCount"] = video.viewcount
        self.gui["publishedDate"] = video.published
        self.gui["videoAuthor"] = video.username
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["nextSongTitle"] = ""
        self.gui["nextSongImage"] = ""
        self.gui["nextSongID"] = ""
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"], 0, override_idle=True)
        self.gui["currenttitle"] = self.getTitle(utterance)
        if 'recentList' in self.recent_db.keys():
            recentVideoList = self.recent_db['recentList']
        else:
            recentVideoList = []
        recentVideoList.insert(0, {"videoID": getvid, "videoTitle": video.title, "videoImage": video.thumb})
        self.recent_db['recentList'] = recentVideoList
        self.recent_db.store()
        self.gui["recentListBlob"] = self.recent_db
        self.youtubesearchpagesimple(utterance)
        self.isTitle = video.title
        self.gui["recentListBlob"] = self.recent_db
        
    def youtubepause(self, message):
        self.gui["status"] = str("pause")
        self.gui.show_page("YoutubePlayer.qml")
    
    def youtuberesume(self, message):
        self.gui["status"] = str("play")
        self.gui.show_page("YoutubePlayer.qml")
        
    def youtubesearchpage(self, message):
        self.stop()
        videoList = []
        videoList.clear()
        videoPageObject = {}
        utterance = message.data.get('utterance').lower()
        utterance = utterance.replace(
            message.data.get('YoutubeSearchPageKeyword'), '')
        vid = self.getListSearch(utterance)
        url = "https://www.youtube.com/results?search_query=" + vid
        response = urlopen(url)
        html = response.read()
        videoList = self.process_soup_additional(html)
        videoPageObject['videoList'] = videoList
        self.gui["videoListBlob"] = videoPageObject
        self.gui["recentListBlob"] = self.recent_db
        self.gui.show_page("YoutubeSearch.qml")
        
    def youtubesearchpagesimple(self, query):
        LOG.info(query)
        videoList = []
        videoList.clear()
        videoPageObject = {}
        vid = self.moreRandomListSearch(query)
        url = "https://www.youtube.com/results?search_query=" + vid
        response = urlopen(url)
        html = response.read()
        videoList = self.process_soup_additional(html)        
        videoPageObject['videoList'] = videoList
        self.gui["videoListBlob"] = videoPageObject
        self.gui["recentListBlob"] = self.recent_db
        
    def show_homepage(self, message):
        LOG.info("I AM IN HOME PAGE FUNCTION")
        self.gui.clear()
        self.enclosure.display_manager.remove_active()
        self.gui["loadingStatus"] = ""
        self.gui.show_page("YoutubeLogo.qml")
        self.process_home_page()

    def process_home_page(self):
        LOG.info("I AM IN HOME PROCESS PAGE FUNCTION")
        self.gui.show_page("YoutubeLogo.qml")
        self.gui["loadingStatus"] = "Fetching News"
        self.newsCategoryList['videoList'] = self.build_category_list("news")
        self.gui["loadingStatus"] = "Fetching Music"
        self.musicCategoryList['videoList'] = self.build_category_list("music")
        self.gui.clear()
        self.enclosure.display_manager.remove_active()
        self.show_search_page()
        self.techCategoryList['videoList'] = self.build_category_list("technology")
        self.gui["techListBlob"] = self.techCategoryList
        self.polCategoryList['videoList'] = self.build_category_list("politics")
        self.gui["polListBlob"] = self.polCategoryList
        self.gamingCategoryList['videoList'] = self.build_category_list("gaming")
        self.gui["gamingListBlob"] = self.gamingCategoryList     
        LOG.info("I AM NOW IN REMOVE LOGO PAGE FUNCTION")

    def show_search_page(self):
        LOG.info("I AM NOW IN SHOW SEARCH PAGE FUNCTION")
        LOG.info(self.techCategoryList)
        self.gui["newsListBlob"] = self.newsCategoryList
        self.gui["newsNextAvailable"] = True
        self.gui["musicListBlob"] = self.musicCategoryList
        self.gui["musicNextAvailable"] = True
        self.gui["techListBlob"] = self.techCategoryList
        self.gui["techNextAvailable"] = True
        self.gui["polListBlob"] = self.polCategoryList
        self.gui["polNextAvailable"] = True
        self.gui["gamingListBlob"] = self.gamingCategoryList
        self.gui["gamingNextAvailable"] = True
        self.gui["searchListBlob"] = ""
        self.gui["previousAvailable"] = False
        self.gui["nextAvailable"] = True
        self.gui["bgImage"] = self.live_category
        self.gui.show_page("YoutubeLiveSearch.qml", override_idle=True)
        

    def play_event(self, message):
        urlvideo = "http://www.youtube.com/watch?v={0}".format(message.data['vidID'])
        self.lastSong = message.data['vidID']
        video = pafy.new(urlvideo)
        playstream = video.getbest(preftype="mp4", ftypestrict=True)
        playurl = playstream.url
        self.speak("Playing")
        self.gui["video"] = str(playurl)
        self.gui["status"] = str("play")
        self.gui["currenturl"] = str(message.data['vidID'])
        self.gui["currenttitle"] = str(message.data['vidTitle'])
        self.gui["setTitle"] = video.title
        self.gui["viewCount"] = video.viewcount
        self.gui["publishedDate"] = video.published
        self.gui["videoAuthor"] = video.username
        self.gui["nextSongTitle"] = ""
        self.gui["nextSongImage"] = ""
        self.gui["nextSongID"] = ""
        videoTitleSearch = str(message.data['vidTitle']).join(str(message.data['vidTitle']).split()[:-1])
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"], 0, override_idle=True)
        thumb = "https://img.youtube.com/vi/{0}/maxresdefault.jpg".format(message.data['vidID'])
        if 'recentList' in self.recent_db.keys():
            recentVideoList = self.recent_db['recentList']
        else:
            recentVideoList = []
        recentVideoList.insert(0, {"videoID": str(message.data['vidID']), "videoTitle": str(message.data['vidTitle']), "videoImage": video.thumb})
        self.recent_db['recentList'] = recentVideoList
        self.recent_db.store()
        self.gui["recentListBlob"] = self.recent_db
        self.isTitle = video.title

    def stop(self):
        self.enclosure.bus.emit(Message("metadata", {"type": "stop"}))
        pass
    
    def process_soup(self, htmltype):
        videoList = []
        videoList.clear()
        soup = BeautifulSoup(htmltype)
        for vid in soup.findAll(attrs={'class': 'yt-uix-tile-link'}):
            if "googleads" not in vid['href'] and not vid['href'].startswith(
                    u"/user") and not vid['href'].startswith(u"/channel"):
                LOG.info(vid)
                videoID = vid['href'].split("v=")[1].split("&")[0]
                videoTitle = vid['title']
                videoImage = "https://i.ytimg.com/vi/{0}/hqdefault.jpg".format(videoID)
                videoList.append({"videoID": videoID, "videoTitle": videoTitle, "videoImage": videoImage})
                
        if len(videoList) > 1:
            self.nextSongList = videoList[1]
        else:
            self.nextSongList = videoList[0]
            
        return videoList
    
    def process_soup_additional(self, htmltype):
        videoList = []
        videoList.clear()
        soup = BeautifulSoup(htmltype)
        getVideoDetails = zip(soup.findAll(attrs={'class': 'yt-uix-tile-link'}), soup.findAll(attrs={'class': 'yt-lockup-byline'}), soup.findAll(attrs={'class': 'yt-lockup-meta-info'}), soup.findAll(attrs={'class': 'video-time'}))
        for vid in getVideoDetails:
            if "googleads" not in vid[0]['href'] and not vid[0]['href'].startswith(
                u"/user") and not vid[0]['href'].startswith(u"/channel"):
                videoID = vid[0]['href'].split("v=")[1].split("&")[0]
                videoTitle = vid[0]['title']
                videoImage = "https://i.ytimg.com/vi/{0}/hqdefault.jpg".format(videoID)
                videoChannel = vid[1].contents[0].string
                videoUploadDate = vid[2].contents[0].string
                videoDuration = vid[3].contents[0].string
                if "watching" in vid[2].contents[0].string:
                    videoViews = "Live"
                else:
                    try:
                        videoViews = vid[2].contents[1].string
                    except:
                        videoViews = "Playlist"

                videoList.append({"videoID": videoID, "videoTitle": videoTitle, "videoImage": videoImage, "videoChannel": videoChannel, "videoViews": videoViews, "videoUploadDate": videoUploadDate, "videoDuration": videoDuration})

        #if len(videoList) > 1:
            #self.nextSongList = videoList[1]
        #else:
            #self.nextSongList = videoList[0]               
                
        return videoList
    
    def process_additional_pages(self, category):
        url = "https://www.youtube.com/results?search_query={0}".format(category)
        response = urlopen(url)
        html = response.read()
        soup = BeautifulSoup(html)
        buttons = soup.findAll('a', attrs={'class':"yt-uix-button vve-check yt-uix-sessionlink yt-uix-button-default yt-uix-button-size-default"})
        try:
            nPage = buttons[0]['href']
        except:
            nPage = self.process_additional_pages_fail(category)
        pPage = url
        addPgObj = [nPage, pPage]
        
        return addPgObj
    
    def process_additional_pages_fail(self, category):
        url = None
        if category == "news":
            url = "/results?search_query=world+news"
        if category == "music":
            url = "/results?search_query=latest+music"
        if category == "technology":
            url = "/results?search_query=latest+tech"
        if category == "politics":
            url = "/results?search_query=latest+politics"
        if category == "gaming":
            url = "/results?search_query=latest+games"

        return url
                    
    
    def nextSongForAutoPlay(self):
        self.gui["nextSongTitle"] = self.nextSongList["videoTitle"]
        self.gui["nextSongImage"] = self.nextSongList["videoImage"]
        self.gui["nextSongID"] = self.nextSongList["videoID"]
    
    def refreshWatchList(self, message):
        try:
            self.youtubesearchpagesimple(message.data["title"])
        except:
            self.youtubesearchpagesimple(self.isTitle)
        
    @intent_file_handler('youtube-repeat.intent')
    def youtube_repeat_last(self):
        video = pafy.new(self.lastSong)
        thumb = video.thumb
        playstream = video.streams[0]
        playurl = playstream.url
        self.gui["status"] = str("play")
        self.gui["video"] = str(playurl)
        self.gui["currenturl"] = ""
        self.gui["currenttitle"] = video.title
        self.gui["setTitle"] = video.title
        self.gui["viewCount"] = video.viewcount
        self.gui["publishedDate"] = video.published
        self.gui["videoAuthor"] = video.username
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["nextSongTitle"] = ""
        self.gui["nextSongImage"] = ""
        self.gui["nextSongID"] = ""
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"], 0, override_idle=True)
        self.youtubesearchpagesimple(video.title)
        self.isTitle = video.title

    def build_category_list(self, category):
        url = "https://www.youtube.com/results?search_query={0}".format(category)
        response = urlopen(url)
        html = response.read()
        videoList = self.process_soup_additional(html)
        return videoList
    
    def build_category_list_from_url(self, link):
        url = link
        print(url)
        response = urlopen(url)
        html = response.read()
        videoList = self.process_soup_additional(html)
        return videoList
    
    def clear_db(self):
        LOG.info("In DB Clear")
        self.recent_db.clear()
        self.recent_db.store()
        self.gui["recentListBlob"] = ""
Ejemplo n.º 21
0
class WayneJuneLovecraftReadingsSkill(OVOSCommonPlaybackSkill):
    def __init__(self):
        super().__init__("Wayne June Lovecraft Readings")
        self.supported_media = [
            MediaType.GENERIC, MediaType.AUDIOBOOK, MediaType.VISUAL_STORY,
            MediaType.VIDEO
        ]
        self.default_image = join(dirname(__file__), "ui", "wayne_june.png")
        self.skill_icon = join(dirname(__file__), "ui", "icon.png")
        self.default_bg = join(dirname(__file__), "ui", "bg.jpeg")
        self.db = JsonStorage(join(dirname(__file__), "res", "waynejune.json"))

    def get_base_score(self, phrase):
        score = 0
        if self.voc_match(phrase, "reading"):
            score += 10

        if self.voc_match(phrase, "audio_theatre"):
            score += 10

        if self.voc_match(phrase, "lovecraft"):
            score += 50

        if self.voc_match(phrase, "wayne_june"):
            score += 35
            if self.voc_match(phrase, "lovecraft"):
                score += 10

        if self.voc_match(phrase, "horror"):
            score += 10
        if self.voc_match(phrase, "cthulhu"):
            score += 10
        return score

    @ocp_search()
    def ocp_waynejune_lovecraft_playlist(self, phrase):
        score = self.get_base_score(phrase)
        if self.voc_match(phrase, "wayne_june"):
            score += 50
        yield {
            "match_confidence": score,
            "media_type": MediaType.AUDIOBOOK,
            "playlist": self.featured_media(),
            "playback": PlaybackType.AUDIO,
            "skill_icon": self.skill_icon,
            "image": self.default_bg,
            "bg_image": self.default_bg,
            "title": "Lovecraft - read by Wayne June (Compilation Playlist)",
            "author": "H. P. Lovecraft",
            "album": "read by Wayne June"
        }

    def clean_vocs(self, phrase):
        phrase = self.remove_voc(phrase, "reading")
        phrase = self.remove_voc(phrase, "audio_theatre")
        phrase = self.remove_voc(phrase, "play")
        phrase = phrase.strip()
        return phrase

    @ocp_search()
    def search(self, phrase, media_type):
        """Analyze phrase to see if it is a play-able phrase with this skill.

        Arguments:
            phrase (str): User phrase uttered after "Play", e.g. "some music"
            media_type (MediaType): requested CPSMatchType to media for

        Returns:
            search_results (list): list of dictionaries with result entries
            {
                "match_confidence": MatchConfidence.HIGH,
                "media_type":  CPSMatchType.MUSIC,
                "uri": "https://audioservice.or.gui.will.play.this",
                "playback": PlaybackType.VIDEO,
                "image": "http://optional.audioservice.jpg",
                "bg_image": "http://optional.audioservice.background.jpg"
            }
        """
        score = self.get_base_score(phrase)
        if media_type != MediaType.AUDIOBOOK:
            score -= 20

        phrase = self.clean_vocs(phrase)

        # calculate scores for individual stories
        # NOTE: each match is designed to be 70 for exact match,
        # the other 30 are reserved for author/media type
        # NOTE2: all my lovecraft skills are designed to return confidence
        # of 40 if the query only contains the author, this is important to
        # ensure all stories are equal without extra information
        scores = {}
        for k in self.db:
            scores[k] = score

        if self.voc_match(phrase, "horror"):
            scores["The Horror At Red Hook"] += 10
            scores["The Dunwich Horror"] += 10

        if self.voc_match(phrase, "red_hook"):
            scores["The Horror At Red Hook"] += 40
            if self.voc_match(phrase, "horror"):
                scores["The Horror At Red Hook"] += 20

        if self.voc_match(phrase, "dunwich"):
            scores["The Dunwich Horror"] += 40
            if self.voc_match(phrase, "horror"):
                scores["The Dunwich Horror"] += 20

        if self.voc_match(phrase, "lurking_fear"):
            scores["The Lurking Fear"] += 70

        if self.voc_match(phrase, "mountains"):
            scores["At The Mountains Of Madness"] += 70

        if self.voc_match(phrase, "tomb"):
            scores["The Tomb"] += 70
        #  if self.voc_match(phrase, "virgin_finlay"):
        #      scores["To Virgil Finlay"] += 70

        if self.voc_match(phrase, "reanimator"):
            scores["Herbert West–Reanimator"] += 40
            if self.voc_match(phrase, "herbert_west"):
                scores["Herbert West–Reanimator"] += 30

        if self.voc_match(phrase, "innsmouth"):
            scores["The Shadow Over Innsmouth"] += 40
            if self.voc_match(phrase, "shadow"):
                scores["The Shadow Over Innsmouth"] += 30

        if self.voc_match(phrase, "cthulhu"):
            scores["The Call Of Cthulhu"] += 40
            if self.voc_match(phrase, "call"):
                scores["The Call Of Cthulhu"] += 20

        if self.voc_match(phrase, "doorstep"):
            scores["The Thing On The Doorstep"] += 10
        if self.voc_match(phrase, "thing"):
            scores["The Thing On The Doorstep"] += 10
        if self.voc_match(phrase, "thing") and \
                self.voc_match(phrase, "doorstep"):
            scores["The Thing On The Doorstep"] += 50

        if self.voc_match(phrase, "house"):
            scores["The Shunned House"] += 10
        if self.voc_match(phrase, "shunned"):
            scores["The Shunned House"] += 10
        if self.voc_match(phrase, "shunned") and \
                self.voc_match(phrase, "house"):
            scores["The Shunned House"] += 50

        for k, v in scores.items():
            if v >= MatchConfidence.AVERAGE_LOW:
                yield {
                    "match_confidence": min(100, v),
                    "media_type": MediaType.AUDIOBOOK,
                    "uri": self.db[k]["uri"],
                    "playback": PlaybackType.AUDIO,
                    "image": join(dirname(__file__), self.db[k]["image"]),
                    "bg_image": self.default_bg,
                    "skill_icon": self.skill_icon,
                    "length": self.db[k]["length"],
                    "title": k,
                    "author": "H. P. Lovecraft",
                    "album": "read by Wayne June"
                }

    @ocp_featured_media()
    def featured_media(self):
        return [{
            "media_type": MediaType.AUDIOBOOK,
            "uri": entry["uri"],
            "playback": PlaybackType.AUDIO,
            "image": join(dirname(__file__), entry["image"]),
            "bg_image": self.default_bg,
            "skill_icon": self.skill_icon,
            "length": entry["length"],
            "title": title,
            "author": "H. P. Lovecraft",
            "album": "read by Wayne June"
        } for title, entry in self.db.items()]
Ejemplo n.º 22
0
class PixabaySkill(MycroftSkill):

    # The constructor of the skill, which calls MycroftSkill's constructor
    def __init__(self):
        super(PixabaySkill, self).__init__(name="PixabaySkill")

    def initialize(self):
        self.add_event('pixabay-skill.aiix.home',
                       self.handle_pixabay_homescreen)
        self.gui.register_handler("pixabay.show.image",
                                  self.handle_pixabay_show_image)
        self.gui.register_handler("pixabay.show.video",
                                  self.handle_pixabay_show_video)
        self.gui.register_handler("pixabay.gallery.next",
                                  self.handle_gallery_next_page)
        self.gui.register_handler("pixabay.gallery.previous",
                                  self.handle_gallery_previous_page)
        self.gui.register_handler("pixabay.idle.set_idle",
                                  self.handle_set_idlescreen_type)
        self.gui.register_handler("pixabay.idle.enableTime",
                                  self.handle_idle_enable_time)
        self.gui.register_handler("pixabay.idle.disableTime",
                                  self.handle_idle_disable_time)
        self.gui.register_handler("pixabay.idle.updateTime",
                                  self.handle_idle_update_time)
        self.gui.register_handler("pixabay.idle.removeConfigPage",
                                  self.handle_remove_configure_idle_screen)
        self.entKey = base64.b64decode(
            "MTcyMjI5NDctYTlmNTQxNmQ2ODhkNDVmNmJkZmY4ZWEzYQ==")
        self.video = Video(self.entKey)
        self.image = Image(self.entKey)
        self.shownPageNumber = None
        self.numberOfAvailablePages = None
        self.previousQuery = None
        self.currentType = None
        self.currentDir = dirname(dirname(abspath(__file__)))
        self.wantedDir = "pixabayData"
        self.dataPath = join(self.currentDir, self.wantedDir)
        self.videoPath = join(self.dataPath, "video.mp4")

        # Set All Paths
        try:
            os.mkdir(self.dataPath)
        except OSError as error:
            print("Directory Already Exist Skipping")
        self.storeDB = join(self.dataPath, 'pixabay-idle.db')
        self.idle_db = JsonStorage(self.storeDB)
        self.configDB = join(self.dataPath, 'pixabay-config.db')
        self.idle_config_db = JsonStorage(self.configDB)

        # Make Import For TimeData
        try:
            time_date_path = "/opt/mycroft/skills/mycroft-date-time.mycroftai/__init__.py"
            time_date_id = "datetimeskill"
            datetimeskill = load_skill_module(time_date_path, time_date_id)
            from datetimeskill import TimeSkill
            self.dt_skill = TimeSkill()
        except:
            print("Failed To Import DateTime Skill")

    def handle_pixabay_homescreen(self, message):
        self.handle_pixabay_display("Homescreen")

    @intent_file_handler("PixabaySearchImage.intent")
    def handle_pixabay_search_image_type(self, message):
        query = message.data["query"]
        self.previousQuery = query
        self.shownPageNumber = 1
        self.currentType = "Image"
        ims = self.image.search(q=query,
                                lang='en',
                                image_type='photo',
                                orientation='vertical',
                                category='all',
                                safesearch='true',
                                order='latest',
                                page=1,
                                per_page=6)
        totalImages = ims['total']
        totalHits = ims['totalHits']
        self.handle_number_of_pages(totalImages, totalHits)
        self.gui["currentPageNumber"] = self.shownPageNumber
        self.gui["showMoreAvailable"] = self.handle_show_more_available(
            self.shownPageNumber)
        self.gui["imageGalleryModel"] = ims['hits']
        self.handle_pixabay_display("ImageGallery")

    def handle_pixabay_show_image(self, message):
        self.gui["imageURL"] = message.data["largeImageURL"]
        self.handle_pixabay_display("Image")

    @intent_file_handler("PixabaySearchVideo.intent")
    def handle_pixabay_search_video_type(self, message):
        query = message.data["query"]
        self.previousQuery = query
        self.shownPageNumber = 1
        self.currentType = "Video"
        vis = self.video.search(q=query,
                                lang='en',
                                video_type='all',
                                category='all',
                                page=1,
                                per_page=6)
        totalImages = vis['total']
        totalHits = vis['totalHits']
        print(totalImages)
        print(totalHits)
        self.handle_number_of_pages(totalImages, totalHits)
        self.gui["currentPageNumber"] = self.shownPageNumber
        self.gui["showMoreAvailable"] = self.handle_show_more_available(
            self.shownPageNumber)
        self.gui["videoGalleryModel"] = vis['hits']
        addr = vis['hits']
        print(addr)
        self.handle_pixabay_display("VideoGallery")

    def handle_pixabay_show_video(self, message):
        orignalurl = message.data['videourl']
        videoURL = self.handle_pixabay_extract_video(orignalurl)
        self.gui["videoURL"] = videoURL
        self.handle_pixabay_display("Video")

    def handle_pixabay_extract_video(self, videoURL):
        extractvideofromloc = requests.get(videoURL, allow_redirects=False)
        actualVideoUrl = extractvideofromloc.headers['location']
        r = requests.get(actualVideoUrl, stream=True)
        with open(self.videoPath, 'wb') as f:
            for chunk in r.iter_content(chunk_size=1024 * 1024):
                if chunk:
                    f.write(chunk)
        videoURL = self.videoPath
        return videoURL

    def handle_pixabay_display(self, state):
        if state is "Image":
            self.gui["setMessage"] = ""
            self.gui.show_page("Image.qml", override_idle=True)
        elif state is "Video":
            self.gui["setMessage"] = ""
            self.gui.show_page("Video.qml", override_idle=True)
        elif state is "Homescreen":
            self.gui.show_page("Homepage.qml", override_idle=True)
        else:
            self.gui["pageState"] = state
            self.gui.show_page("pixabayLoader.qml", override_idle=True)

    def handle_gallery_next_page(self, message):
        galleryType = message.data["galleryType"]
        pageNumber = message.data["currentPageNumber"]
        if pageNumber < self.numberOfAvailablePages:
            pageNumber = self.shownPageNumber + 1
            self.shownPageNumber = pageNumber
            if galleryType == "Image":
                ims = self.image.search(q=self.previousQuery,
                                        lang='en',
                                        image_type='all',
                                        orientation='vertical',
                                        category='all',
                                        safesearch='true',
                                        order='latest',
                                        page=self.shownPageNumber,
                                        per_page=6)
                self.gui["currentPageNumber"] = self.shownPageNumber
                self.gui[
                    "showMoreAvailable"] = self.handle_show_more_available(
                        self.shownPageNumber)
                self.gui["imageGalleryModel"] = ims['hits']
            elif galleryType == "Video":
                vis = self.video.search(q=self.previousQuery,
                                        lang='en',
                                        video_type='all',
                                        category='all',
                                        page=self.shownPageNumber,
                                        per_page=6)
                self.gui["currentPageNumber"] = self.shownPageNumber
                self.gui[
                    "showMoreAvailable"] = self.handle_show_more_available(
                        self.shownPageNumber)
                self.gui["videoGalleryModel"] = vis['hits']
                self.handle_pixabay_display("VideoGallery")
            else:
                print("Valid Type Not Found")

    def handle_gallery_previous_page(self, message):
        galleryType = message.data["galleryType"]
        pageNumber = message.data["currentPageNumber"]
        if pageNumber > 1:
            pageNumber = self.shownPageNumber - 1
            self.shownPageNumber = pageNumber
            if galleryType == "Image":
                ims = self.image.search(q=self.previousQuery,
                                        lang='en',
                                        image_type='all',
                                        orientation='all',
                                        category='all',
                                        safesearch='true',
                                        order='latest',
                                        page=self.shownPageNumber,
                                        per_page=6)
                self.gui["currentPageNumber"] = self.shownPageNumber
                self.gui[
                    "showMoreAvailable"] = self.handle_show_more_available(
                        self.shownPageNumber)
                self.gui["imageGalleryModel"] = ims['hits']
            elif galleryType == "Video":
                vis = self.video.search(q=self.previousQuery,
                                        lang='en',
                                        video_type='all',
                                        category='all',
                                        page=self.shownPageNumber,
                                        per_page=6)
                self.gui["currentPageNumber"] = self.shownPageNumber
                self.gui[
                    "showMoreAvailable"] = self.handle_show_more_available(
                        self.shownPageNumber)
                self.gui["videoGalleryModel"] = vis['hits']
                self.handle_pixabay_display("VideoGallery")
            else:
                print("Valid Type Not Found")

    @intent_handler(
        IntentBuilder("HandleAudioGalleryNext").require(
            "PixabayGalleryNextKeyword").build())
    def handle_audio_gallery_next(self):
        currentPageNumber = self.shownPageNumber
        self.handle_gallery_next_page(
            Message(
                "data", {
                    "currentPageNumber": currentPageNumber,
                    "galleryType": self.currentType
                }))

    @intent_handler(
        IntentBuilder("HandleAudioGalleryNext").require(
            "PixabayGalleryPreviousKeyword").build())
    def handle_audio_gallery_previous(self):
        currentPageNumber = self.shownPageNumber
        self.handle_gallery_previous_page(
            Message(
                "data", {
                    "currentPageNumber": currentPageNumber,
                    "galleryType": self.currentType
                }))

    def handle_number_of_pages(self, total, totalhits):
        if total > totalhits:
            orgNumPage = totalhits / 6
            if orgNumPage > 10:
                self.numberOfAvailablePages = 10
                return 10
            else:
                orgNumPage = totalhits / 6
                self.numberOfAvailablePages = orgNumPage
                return orgNumPage

        elif total < totalhits:
            orgNumPage = total / 6
            if orgNumPage > 10:
                self.numberOfAvailablePages = 10
                return 10
            else:
                orgNumPage = totalhits / 6
                self.numberOfAvailablePages = orgNumPage
                return orgNumPage

        elif total == totalhits:
            orgNumPage = total / 6
            if orgNumPage > 10:
                self.numberOfAvailablePages = 10
                return 10
            else:
                self.numberOfAvailablePages = orgNumPage
                return orgNumPage

    def handle_show_more_available(self, currentPage):
        if currentPage < self.numberOfAvailablePages:
            return True
        else:
            return False

    def handle_set_idlescreen_type(self, message):
        idleType = message.data["idleType"]
        self.idle_db.clear()
        if idleType == "Image":
            idleImageURL = message.data["idleImageURL"]
            imageType = idleImageURL.split('.')[-1]
            imagePath = join(self.dataPath,
                             str("pixabay-idle" + "." + imageType))
            self.extract_image_for_idle(idleImageURL, imagePath)
            self.gui["idleType"] = "ImageIdle"
            self.gui["idleGenericURL"] = imagePath
            self.idle_db["idleInfo"] = {
                "idleType": "ImageIdle",
                "idleGenericURL": imagePath
            }
            self.idle_db.store()
            self.gui["setMessage"] = "New Homescreen Set"
        if idleType == "Video":
            idleVideoURL = message.data["idleVideoURL"]
            self.gui["idleType"] = "VideoIdle"
            self.gui["idleGenericURL"] = idleVideoURL
            self.idle_db["idleInfo"] = {
                "idleType": "VideoIdle",
                "idleGenericURL": idleVideoURL
            }
            self.idle_db.store()
            self.gui["setMessage"] = "New Homescreen Set"

    def handle_idlescreen_first_run(self):
        # Check If Idle Screen DB Exist and Not Empty
        # Retrive and Set Idle Screen if Available
        # If idle unset, get random and store
        if 'idleInfo' in self.idle_db.keys():
            self.gui["idleType"] = self.idle_db["idleInfo"]["idleType"]
            self.gui["idleGenericURL"] = self.idle_db["idleInfo"][
                "idleGenericURL"]

        else:
            imageURL = self.generate_random_idle()
            imageType = imageURL.split('.')[-1]
            imagePath = join(self.dataPath,
                             str("pixabay-idle" + "." + imageType))
            self.extract_image_for_idle(imageURL, imagePath)
            self.idle_db["idleInfo"] = {
                "idleType": "ImageIdle",
                "idleGenericURL": imagePath
            }
            self.idle_db.store()
            self.gui["idleType"] = "ImageIdle"
            self.gui["idleGenericURL"] = imagePath

        if 'showTime' in self.idle_config_db.keys():
            if self.idle_config_db["showTime"] == True:
                self.gui["showTime"] = True
                self.gui[
                    'time_string'] = self.dt_skill.get_display_current_time()
            else:
                self.gui["showTime"] = False
                self.gui["time_string"] = ""
        else:
            self.gui["showTime"] = False
            self.gui["time_string"] = ""

    def generate_random_idle(self):
        ims = self.image.search(q="galaxy",
                                lang='en',
                                image_type='photo',
                                orientation='vertical',
                                category='all',
                                safesearch='true',
                                order='latest',
                                page=4,
                                per_page=6)
        randomImageUrl = ims['hits'][4]["largeImageURL"]
        return randomImageUrl

    @resting_screen_handler('Pixabay')
    def handle_idle(self, message):
        self.gui.clear()
        self.log.debug('Activating Time/Date resting page')
        self.handle_idlescreen_first_run()
        self.gui.show_page('pixabayIdleLoader.qml')

    def extract_image_for_idle(self, url, localpath):
        try:
            image = requests.get(url)
        except OSError:
            return False
        if image.status_code == 200:
            with open(localpath, "wb") as k:
                k.write(image.content)
        else:
            print("Saving Image Failed")

    def handle_idle_enable_time(self):
        self.speak("I am enabling time")
        self.idle_config_db["showTime"] = True
        self.gui["showTime"] = True
        self.idle_config_db.store()
        # Send Time Data Here First
        self.handle_idle_update_time()

    def handle_idle_disable_time(self):
        self.speak("I am disabling time")
        self.idle_config_db["showTime"] = False
        self.gui["showTime"] = False
        self.idle_config_db.store()

    def handle_idle_update_time(self):
        self.gui['time_string'] = self.dt_skill.get_display_current_time()

    @intent_handler(
        IntentBuilder("PixabayIdleConfigure").require(
            "PixabayIdleConfigure").build())
    def handle_configure_idle_screen(self):
        self.gui.show_page("ConfigurePixabayIdle.qml")

    def handle_remove_configure_idle_screen(self):
        self.gui.remove_page("ConfigurePixabayIdle.qml")

    def stop(self):
        pass
Ejemplo n.º 23
0
            "lang": "en-us"
        }
    }
    default["log_blacklist"] = []
    return default


DEFAULT_CONFIGURATION = get_default_config()


def merge_dict(base, delta):
    """
        Recursively merging configuration dictionaries.

        Args:
            base:  Target for merge
            delta: Dictionary to merge into base
    """

    for k, dv in delta.items():
        bv = base.get(k)
        if isinstance(dv, dict) and isinstance(bv, dict):
            merge_dict(bv, dv)
        else:
            base[k] = dv
    return base


CONFIGURATION = JsonStorage(_DEFAULT_CONFIG_PATH)
CONFIGURATION = merge_dict(DEFAULT_CONFIGURATION, CONFIGURATION)
Ejemplo n.º 24
0
class KaldiWWSpotter(EventEmitter):
    def __init__(self, config):
        super().__init__()
        if isinstance(config, dict):
            self.config = config
        elif isinstance(config, str):
            self.config = JsonStorage(config)

        model = self.config.get("model_folder")
        if not model or not isdir(model):
            raise ModelNotFound

        listener_config = self.config.get("listener") or \
                          {"vad_agressiveness": 2,
                           "sample_rate": 16000,
                           "start_thresh": 1,
                           "end_thresh": 3}
        self.vad_agressiveness = listener_config["vad_agressiveness"]
        self.sample_rate = listener_config["sample_rate"]
        self.start_thresh = listener_config["start_thresh"]
        self.end_thresh = listener_config["end_thresh"]

        self.model = KaldiModel(model)
        self.kaldi = KaldiRecognizer(self.model, self.sample_rate)
        self._hotwords = dict(self.config.get("hotwords", {}))

        self.running = False
        self.speaking = False
        self.result = None

    def add_hotword(self, name, config=None):
        config = config or {"transcriptions": [name], "intent": name}
        self._hotwords[name] = config

    def remove_hotword(self, name):
        if name in self._hotwords.keys():
            self._hotwords.pop(name)

    @property
    def hotwords(self):
        return self._hotwords

    def emit_detection_event(self, message_type, message_data=None):
        message_data = message_data or self.result
        serialized_message = json.dumps(message_data)
        logging.debug(serialized_message)
        self.emit(message_type, serialized_message)

    def _process_transcription(self):
        user_utt = self.result.get("text")

        for hotw in self.hotwords:
            if not self.hotwords[hotw].get("active"):
                continue
            rule = self.hotwords[hotw].get("rule", "sensitivity")
            s = 1 - self.hotwords[hotw].get("sensitivity", 0.2)
            confidence = (self.confidence + s) / 2

            for w in self.hotwords[hotw]["transcriptions"]:
                found = False

                if w in user_utt and rule == "in":
                    found = True
                elif user_utt.startswith(w) and rule == "start":
                    found = True
                elif user_utt.endswith(w) and rule == "end":
                    found = True
                elif w == user_utt and rule == "equal":
                    found = True
                elif rule == "sensitivity" and fuzzy_match(w, user_utt) >= s:
                    found = True

                if found:
                    yield {
                        "hotword": hotw,
                        "utterance": user_utt,
                        "confidence": confidence,
                        "intent": self.hotwords[hotw]["intent"]
                    }

    def _hotword_events(self):
        for hw_data in self._process_transcription():
            sound = self.hotwords[hw_data["hotword"]].get("sound")
            if sound and isfile(sound):
                play_sound(sound)
            self.emit_detection_event("hotword", hw_data)

    def feed_chunk(self, chunk):
        if self.kaldi.AcceptWaveform(chunk):
            self.result = json.loads(self.kaldi.Result())
        else:
            transcript_data = json.loads(self.kaldi.PartialResult())
            if transcript_data != self.result:
                self.result = transcript_data
                if transcript_data["partial"]:
                    self.emit_detection_event("transcription.partial")

    def finalize(self):
        final = json.loads(self.kaldi.FinalResult())
        if final["text"]:
            self.result = final
        if self.result.get("text"):
            self.emit_detection_event("transcription")
            self._hotword_events()
        else:
            self.emit_detection_event("transcription.failure",
                                      {"error": "empty text transcription"})
        data = dict(self.result)
        self.result = {}
        self.speaking = False
        return data

    @property
    def confidence(self):
        try:
            return sum([w["conf"] for w in self.result["result"]]) / len(
                self.result["result"])
        except:
            return 0

    def run(self):

        p = pyaudio.PyAudio()
        stream = p.open(format=pyaudio.paInt16,
                        channels=1,
                        rate=16000,
                        input=True,
                        frames_per_buffer=8000)
        stream.start_stream()
        logging.info("Listening")

        counter = 0
        silence_counter = 0

        prev_chunk = None
        self.running = True
        while self.running:
            data = stream.read(4000)
            if len(data) == 0:
                continue
            is_speaking = vad_collector(data, self.sample_rate,
                                        self.vad_agressiveness)
            if is_speaking:
                counter += 1
                silence_counter = 0
                if counter >= self.start_thresh and not self.speaking:
                    self.speaking = True
                    event_data = {
                        "thresh": self.start_thresh,
                        "agressiveness": self.vad_agressiveness
                    }
                    self.emit_detection_event("vad.start", event_data)
                    self.feed_chunk(prev_chunk)
                if self.speaking:
                    self.feed_chunk(data)
            else:
                if self.speaking and silence_counter >= self.end_thresh:
                    event_data = {
                        "timesteps": counter,
                        "agressiveness": self.vad_agressiveness
                    }
                    self.emit_detection_event("vad.end", event_data)
                    self.finalize()

                silence_counter += 1
                counter = 0
            prev_chunk = data

    def stop(self):
        # TODO close pyaudio stream
        self.running = False
Ejemplo n.º 25
0
class YoutubeSkill(MycroftSkill):
    def __init__(self):
        super(YoutubeSkill, self).__init__(name="YoutubeSkill")
        self.nextpage_url = None
        self.previouspage_url = None
        self.live_category = None
        self.recentList = deque()
        self.recentPageObject = {}
        self.nextSongList = None
        self.lastSong = None
        self.videoPageObject = {}
        self.isTitle = None
        self.trendCategoryList = {}
        self.newsCategoryList = {}
        self.musicCategoryList = {}
        self.techCategoryList = {}
        self.polCategoryList = {}
        self.gamingCategoryList = {}
        self.searchCategoryList = {}
        self.recentCategoryList = {}
        self.recentWatchListObj = {}
        self.storeDB = dirname(__file__) + '-recent.db'
        self.recent_db = JsonStorage(self.storeDB)
        self.ytkey = base64.b64decode(
            "QUl6YVN5RE9tSXhSemI0RzFhaXFzYnBaQ3IwQTlFN1NrT0pVRURr")
        pafy.set_api_key(self.ytkey)
        self.quackAPIWorker = "J0dvb2dsZWJvdC8yLjEgKCtodHRwOi8vd3d3Lmdvb2dsZS5jb20vYm90Lmh0bWwpJw=="
        self.quackagent = {'User-Agent': base64.b64decode(self.quackAPIWorker)}
        self.yts = YoutubeSearcher()

    def initialize(self):
        self.load_data_files(dirname(__file__))

        self.bus.on('youtube-skill.aiix.home', self.launcherId)

        youtubepause = IntentBuilder("YoutubePauseKeyword"). \
            require("YoutubePauseKeyword").build()
        self.register_intent(youtubepause, self.youtubepause)

        youtuberesume = IntentBuilder("YoutubeResumeKeyword"). \
            require("YoutubeResumeKeyword").build()
        self.register_intent(youtuberesume, self.youtuberesume)

        youtubesearchpage = IntentBuilder("YoutubeSearchPageKeyword"). \
            require("YoutubeSearchPageKeyword").build()
        self.register_intent(youtubesearchpage, self.youtubesearchpage)

        youtubelauncherId = IntentBuilder("YoutubeLauncherId"). \
            require("YoutubeLauncherIdKeyword").build()
        self.register_intent(youtubelauncherId, self.launcherId)

        self.add_event('aiix.youtube-skill.playvideo_id', self.play_event)

        self.gui.register_handler('YoutubeSkill.SearchLive', self.searchLive)

        self.gui.register_handler('YoutubeSkill.NextPage', self.searchNextPage)
        self.gui.register_handler('YoutubeSkill.PreviousPage',
                                  self.searchPreviousPage)
        self.gui.register_handler('YoutubeSkill.NextAutoPlaySong',
                                  self.nextSongForAutoPlay)
        self.gui.register_handler('YoutubeSkill.RefreshWatchList',
                                  self.refreshWatchList)
        self.gui.register_handler('YoutubeSkill.ClearDB', self.clear_db)
        self.gui.register_handler('YoutubeSkill.ReplayLast',
                                  self.youtube_repeat_last)

    def launcherId(self, message):
        self.show_homepage({})

    @intent_file_handler('youtubeopenapp.intent')
    def launch_home_and_search_category(self, message):
        self.speak("Loading Up Youtube For You")
        self.show_homepage({})

    def getListSearch(self, text):
        query = quote(text)
        url = "https://www.youtube.com/results?search_query=" + quote(query)
        response = requests.get(url, headers=self.quackagent)
        html = response.text
        a_tag = SoupStrainer('a')
        soup = BeautifulSoup(html, 'html.parser', parse_only=a_tag)
        for vid in soup.findAll(attrs={'class': 'yt-uix-tile-link'}):
            if "googleads" not in vid['href'] and not vid['href'].startswith(
                    u"/user") and not vid['href'].startswith(u"/channel"):
                id = vid['href'].split("v=")[1].split("&")[0]
                return id

    def moreRandomListSearch(self, text):
        LOG.info(text)
        query = quote(text)
        try:
            querySplit = text.split()
            LOG.info(querySplit)
            searchQuery = "*," + quote(querySplit[0]) + quote(
                querySplit[1]) + ",*"

        except:
            LOG.info("fail")
            searchQuery = "*," + quote(query) + ",*"

        LOG.info(searchQuery)
        return searchQuery

    def searchLive(self, message):
        videoList = []
        videoList.clear()
        videoPageObject = {}
        try:
            query = message.data["Query"]
            LOG.info("I am in search Live")
            self.searchCategoryList["videoList"] = self.build_category_list(
                quote(query))
            self.gui["searchListBlob"] = self.searchCategoryList
            self.gui["previousAvailable"] = False
            self.gui["nextAvailable"] = True
            self.gui["bgImage"] = quote(query)
            self.gui.show_page("YoutubeLiveSearch.qml", override_idle=True)
        except:
            LOG.debug("error")

    def searchNextPage(self, message):
        getCategory = message.data["Category"]
        LOG.info(getCategory)
        if getCategory == "News":
            LOG.info("In Category News")
            newsAdditionalPages = self.process_additional_pages("news")
            self.newsCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    "https://www.youtube.com" + newsAdditionalPages[0])
            self.gui["newsNextAvailable"] = False
            self.gui["newsListBlob"] = self.newsCategoryList
        if getCategory == "Music":
            LOG.info("In Category Music")
            musicAdditionalPages = self.process_additional_pages("music")
            self.musicCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    "https://www.youtube.com" + musicAdditionalPages[0])
            self.gui["musicNextAvailable"] = False
            self.gui["musicListBlob"] = self.musicCategoryList
        if getCategory == "Technology":
            LOG.info("In Category Technology")
            technologyAdditionalPages = self.process_additional_pages(
                "technology")
            self.techCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    "https://www.youtube.com" + technologyAdditionalPages[0])
            self.gui["techNextAvailable"] = False
            self.gui["techListBlob"] = self.techCategoryList
        if getCategory == "Politics":
            LOG.info("In Category Politics")
            politicsAdditionalPages = self.process_additional_pages("politics")
            self.polCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    "https://www.youtube.com" + politicsAdditionalPages[0])
            self.gui["polNextAvailable"] = False
            self.gui["polListBlob"] = self.polCategoryList
        if getCategory == "Gaming":
            LOG.info("In Category Gaming")
            gamingAdditionalPages = self.process_additional_pages("gaming")
            self.gamingCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    "https://www.youtube.com" + gamingAdditionalPages[0])
            self.gui["gamingNextAvailable"] = False
            self.gui["gamingListBlob"] = self.gamingCategoryList
        if getCategory == "Search":
            LOG.info("In Search")

    def searchPreviousPage(self, message):
        getCategory = message.data["Category"]
        LOG.info(getCategory)
        if getCategory == "News":
            LOG.info("In Category News")
            newsAdditionalPages = self.process_additional_pages("news")
            self.newsCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    newsAdditionalPages[1])
            self.gui["newsNextAvailable"] = True
            self.gui["newsListBlob"] = self.newsCategoryList
        if getCategory == "Music":
            LOG.info("In Category Music")
            musicAdditionalPages = self.process_additional_pages("music")
            self.musicCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    musicAdditionalPages[1])
            self.gui["musicNextAvailable"] = True
            self.gui["musicListBlob"] = self.musicCategoryList
        if getCategory == "Technology":
            LOG.info("In Category Technology")
            technologyAdditionalPages = self.process_additional_pages(
                "technology")
            self.techCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    technologyAdditionalPages[1])
            self.gui["techNextAvailable"] = True
            self.gui["techListBlob"] = self.techCategoryList
        if getCategory == "Politics":
            LOG.info("In Category Politics")
            politicsAdditionalPages = self.process_additional_pages("politics")
            self.polCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    politicsAdditionalPages[1])
            self.gui["polNextAvailable"] = True
            self.gui["polListBlob"] = self.polCategoryList
        if getCategory == "Gaming":
            LOG.info("In Category Gaming")
            gamingAdditionalPages = self.process_additional_pages("gaming")
            self.gamingCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    gamingAdditionalPages[1])
            self.gui["gamingNextAvailable"] = True
            self.gui["gamingListBlob"] = self.gamingCategoryList
        if getCategory == "Search":
            LOG.info("In Search")

    def getTitle(self, text):
        query = quote(text)
        url = "https://www.youtube.com/results?search_query=" + quote(query)
        response = requests.get(url, headers=self.quackagent)
        html = response.text
        soup = BeautifulSoup(html)
        for vid in soup.findAll(attrs={'class': 'yt-uix-tile-link'}):
            if "googleads" not in vid['href'] and not vid['href'].startswith(
                    u"/user") and not vid['href'].startswith(u"/channel"):
                videoTitle = vid['title']
                return videoTitle

    @intent_file_handler('youtube.intent')
    def youtube(self, message):
        self.stop()
        self.gui.clear()
        self.enclosure.display_manager.remove_active()
        utterance = message.data['videoname'].lower()
        self.youtube_play_video(utterance)

    def youtube_play_video(self, utterance):
        self.gui["setTitle"] = ""
        self.gui["video"] = ""
        self.gui["status"] = "stop"
        self.gui["currenturl"] = ""
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["videoThumb"] = ""
        url = "https://www.youtube.com/results?search_query=" + quote(
            utterance)
        response = requests.get(url, headers=self.quackagent)
        html = response.text
        a_tag = SoupStrainer('a')
        soup = BeautifulSoup(html, 'html.parser', parse_only=a_tag)
        self.gui["video"] = ""
        self.gui["status"] = "stop"
        self.gui["currenturl"] = ""
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["videoThumb"] = ""
        video_query_str = str(quote(utterance))
        print(video_query_str)
        abc = self.yts.search_youtube(video_query_str, render="videos")
        vid = abc['videos'][0]['url']
        ydl = youtube_dl.YoutubeDL({'outtmpl': '%(id)s%(ext)s'})
        with ydl:
            ytresult = ydl.extract_info(
                vid,
                download=False  # We just want to extract the info
            )
            if 'entries' in ytresult:
                ytvideo = ytresult['entries'][0]
            else:
                ytvideo = ytresult

            stream_url = self.process_ytl_stream(ytvideo["formats"])
        getvid = vid.split("v=")[1].split("&")[0]
        thumb = "https://img.youtube.com/vi/{0}/0.jpg".format(getvid)
        self.gui["videoThumb"] = thumb
        self.lastSong = vid
        self.gui["status"] = str("play")
        self.gui["video"] = str(stream_url)
        self.gui["currenturl"] = str(vid)
        self.gui["currenttitle"] = abc['videos'][0]['title']
        self.gui["setTitle"] = abc['videos'][0]['title']
        self.gui["viewCount"] = abc['videos'][0]['views']
        self.gui["publishedDate"] = abc['videos'][0]['published_time']
        self.gui["videoAuthor"] = abc['videos'][0]['channel_name']
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["nextSongBlob"] = ""
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"],
                            0,
                            override_idle=True)
        self.gui["currenttitle"] = self.getTitle(utterance)
        LOG.info("Video Published On")
        recentVideoDict = {
            "videoID": getvid,
            "videoTitle": abc['videos'][0]['title'],
            "videoImage": thumb,
            "videoChannel": abc['videos'][0]['channel_name'],
            "videoViews": abc['videos'][0]['views'],
            "videoUploadDate": abc['videos'][0]['published_time'],
            "videoDuration": abc['videos'][0]['length']
        }
        self.buildHistoryModel(recentVideoDict)
        self.gui["recentListBlob"] = self.recent_db
        self.youtubesearchpagesimple(getvid)
        self.isTitle = abc['videos'][0]['title']
        self.gui["recentListBlob"] = self.recent_db

    def process_ytl_stream(self, streams):
        _videostreams = []
        for z in range(len(streams)):
            if streams[z].get("vcodec") != "none":
                if streams[z].get("acodec") != "none":
                    _videostreams.append(streams[z])

        for a in range(len(_videostreams)):
            if _videostreams[a]["format_note"] == "720p":
                return _videostreams[a]["url"]
            elif _videostreams[a]["format_note"] == "480p":
                return _videostreams[a]["url"]
            elif _videostreams[a]["format_note"] == "360p":
                return _videostreams[a]["url"]
            elif _videostreams[a]["format_note"] == "240p":
                return _videostreams[a]["url"]
            elif _videostreams[a]["format_note"] == "144p":
                return _videostreams[a]["url"]

    def youtubepause(self, message):
        self.gui["status"] = str("pause")
        self.gui.show_page("YoutubePlayer.qml")

    def youtuberesume(self, message):
        self.gui["status"] = str("play")
        self.gui.show_page("YoutubePlayer.qml")

    def youtubesearchpage(self, message):
        self.stop()
        videoList = []
        videoList.clear()
        videoPageObject = {}
        utterance = message.data.get('utterance').lower()
        utterance = utterance.replace(
            message.data.get('YoutubeSearchPageKeyword'), '')
        vid = self.getListSearch(utterance)
        url = "https://www.youtube.com/results?search_query=" + vid
        response = requests.get(url, headers=self.quackagent)
        html = response.text
        videoList = self.process_soup_additional(html)
        videoPageObject['videoList'] = videoList
        self.gui["videoListBlob"] = videoPageObject
        self.gui["recentListBlob"] = self.recent_db
        self.gui.show_page("YoutubeSearch.qml")

    def youtubesearchpagesimple(self, query):
        LOG.info(query)
        videoList = []
        videoList.clear()
        videoPageObject = {}
        yts = YoutubeSearcher()
        vidslist = yts.watchlist_search(video_id=query)
        for x in range(len(vidslist['watchlist_videos'])):
            videoID = vidslist['watchlist_videos'][x]['videoId']
            videoTitle = vidslist['watchlist_videos'][x]['title']
            videoImage = "https://img.youtube.com/vi/{0}/0.jpg".format(videoID)
            videoUploadDate = vidslist['watchlist_videos'][x]['published_time']
            videoDuration = vidslist['watchlist_videos'][x]['length']
            videoViews = vidslist['watchlist_videos'][x]['views']
            videoChannel = vidslist['watchlist_videos'][x]['channel_name']
            videoList.append({
                "videoID": videoID,
                "videoTitle": videoTitle,
                "videoImage": videoImage,
                "videoChannel": videoChannel,
                "videoViews": videoViews,
                "videoUploadDate": videoUploadDate,
                "videoDuration": videoDuration
            })

        videoPageObject['videoList'] = videoList
        self.gui["videoListBlob"] = videoPageObject
        self.gui["recentListBlob"] = self.recent_db

    def show_homepage(self, message):
        LOG.info("I AM IN HOME PAGE FUNCTION")
        self.gui.clear()
        self.enclosure.display_manager.remove_active()
        self.gui["loadingStatus"] = ""
        self.gui.show_page("YoutubeLogo.qml")
        self.process_home_page()

    def process_home_page(self):
        LOG.info("I AM IN HOME PROCESS PAGE FUNCTION")
        self.gui["loadingStatus"] = "Fetching Trends"
        self.trendCategoryList[
            'videoList'] = self.build_category_list_from_url(
                "https://www.youtube.com/feed/trending")
        if self.trendCategoryList['videoList']:
            LOG.info("Trends Not Empty")
        else:
            LOG.info("Trying To Rebuild Trends List")
            self.trendCategoryList[
                'videoList'] = self.build_category_list_from_url(
                    "https://www.youtube.com/feed/trending")
        self.gui["loadingStatus"] = "Fetching News"
        self.newsCategoryList['videoList'] = self.build_category_list("news")
        if self.newsCategoryList['videoList']:
            LOG.info("News Not Empty")
        else:
            LOG.info("Trying To Rebuild News List")
            self.newsCategoryList['videoList'] = self.build_category_list(
                "news")

        self.build_recent_watch_list(20)
        self.gui.clear()
        self.enclosure.display_manager.remove_active()
        self.show_search_page()

        self.musicCategoryList['videoList'] = self.build_category_list("music")
        if self.musicCategoryList['videoList']:
            LOG.info("Music Not Empty")
        else:
            LOG.info("Trying To Rebuild Music List")
            self.musicCategoryList['videoList'] = self.build_category_list(
                "music")
        self.gui["musicListBlob"] = self.musicCategoryList

        self.techCategoryList['videoList'] = self.build_category_list(
            "technology")
        if self.techCategoryList['videoList']:
            LOG.info("Tech Not Empty")
        else:
            LOG.info("Trying To Rebuild Tech List")
            self.techCategoryList['videoList'] = self.build_category_list(
                "technology")
        self.gui["techListBlob"] = self.techCategoryList

        self.polCategoryList['videoList'] = self.build_category_list(
            "politics")
        if self.polCategoryList['videoList']:
            LOG.info("Pol Not Empty")
        else:
            LOG.info("Trying To Rebuild Pol List")
            self.polCategoryList['videoList'] = self.build_category_list(
                "politics")
        self.gui["polListBlob"] = self.polCategoryList

        self.gamingCategoryList['videoList'] = self.build_category_list(
            "gaming")
        if self.gamingCategoryList['videoList']:
            LOG.info("Gaming Not Empty")
        else:
            LOG.info("Trying To Rebuild Pol List")
            self.gamingCategoryList['videoList'] = self.build_category_list(
                "gaming")
        self.gui["gamingListBlob"] = self.gamingCategoryList

        LOG.info("I AM NOW IN REMOVE LOGO PAGE FUNCTION")

    def show_search_page(self):
        LOG.info("I AM NOW IN SHOW SEARCH PAGE FUNCTION")
        LOG.info(self.techCategoryList)
        self.gui["recentHomeListBlob"] = self.recentWatchListObj
        self.gui["recentListBlob"] = self.recent_db
        self.gui["trendListBlob"] = self.trendCategoryList
        self.gui["newsListBlob"] = self.newsCategoryList
        self.gui["newsNextAvailable"] = True
        self.gui["musicListBlob"] = self.musicCategoryList
        self.gui["musicNextAvailable"] = True
        self.gui["techListBlob"] = self.techCategoryList
        self.gui["techNextAvailable"] = True
        self.gui["polListBlob"] = self.polCategoryList
        self.gui["polNextAvailable"] = True
        self.gui["gamingListBlob"] = self.gamingCategoryList
        self.gui["gamingNextAvailable"] = True
        self.gui["searchListBlob"] = ""
        self.gui["previousAvailable"] = False
        self.gui["nextAvailable"] = True
        self.gui["bgImage"] = self.live_category
        self.gui.show_page("YoutubeLiveSearch.qml", override_idle=True)

    def play_event(self, message):
        urlvideo = "http://www.youtube.com/watch?v={0}".format(
            message.data['vidID'])
        self.lastSong = message.data['vidID']
        video = pafy.new(urlvideo)
        playstream = video.getbest(preftype="mp4", ftypestrict=True)
        playurl = playstream.url
        self.speak("Playing")
        self.gui["video"] = str(playurl)
        self.gui["status"] = str("play")
        self.gui["currenturl"] = str(message.data['vidID'])
        self.gui["currenttitle"] = str(message.data['vidTitle'])
        self.gui["setTitle"] = video.title
        self.gui["viewCount"] = video.viewcount
        self.gui["publishedDate"] = video.published
        self.gui["videoAuthor"] = video.username
        self.gui["nextSongBlob"] = ""
        videoTitleSearch = str(message.data['vidTitle']).join(
            str(message.data['vidTitle']).split()[:-1])
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"],
                            0,
                            override_idle=True)
        thumb = "https://img.youtube.com/vi/{0}/maxresdefault.jpg".format(
            message.data['vidID'])
        recentVideoDict = {
            "videoID": message.data['vidID'],
            "videoTitle": message.data['vidTitle'],
            "videoImage": message.data['vidImage'],
            "videoChannel": message.data['vidChannel'],
            "videoViews": message.data['vidViews'],
            "videoUploadDate": message.data['vidUploadDate'],
            "videoDuration": message.data['vidDuration']
        }
        self.buildHistoryModel(recentVideoDict)
        self.gui["recentListBlob"] = self.recent_db
        self.isTitle = video.title

    def stop(self):
        self.enclosure.bus.emit(Message("metadata", {"type": "stop"}))
        pass

    def process_soup(self, htmltype):
        videoList = []
        videoList.clear()
        soup = BeautifulSoup(htmltype)
        for vid in soup.findAll(attrs={'class': 'yt-uix-tile-link'}):
            if "googleads" not in vid['href'] and not vid['href'].startswith(
                    u"/user") and not vid['href'].startswith(u"/channel"):
                LOG.info(vid)
                videoID = vid['href'].split("v=")[1].split("&")[0]
                videoTitle = vid['title']
                videoImage = "https://i.ytimg.com/vi/{0}/hqdefault.jpg".format(
                    videoID)
                videoList.append({
                    "videoID": videoID,
                    "videoTitle": videoTitle,
                    "videoImage": videoImage
                })

        if len(videoList) > 1:
            self.nextSongList = videoList[1]
        else:
            self.nextSongList = videoList[0]

        return videoList

    def process_soup_additional(self, htmltype):
        videoList = []
        videoList.clear()
        soup = BeautifulSoup(htmltype)
        getVideoDetails = zip(
            soup.findAll(attrs={'class': 'yt-uix-tile-link'}),
            soup.findAll(attrs={'class': 'yt-lockup-byline'}),
            soup.findAll(attrs={'class': 'yt-lockup-meta-info'}),
            soup.findAll(attrs={'class': 'video-time'}))
        for vid in getVideoDetails:
            if "googleads" not in vid[0][
                    'href'] and not vid[0]['href'].startswith(
                        u"/user") and not vid[0]['href'].startswith(
                            u"/channel") and not vid[0]['href'].startswith(
                                '/news') and not vid[0]['href'].startswith(
                                    '/music'
                                ) and not vid[0]['href'].startswith(
                                    '/technology'
                                ) and not vid[0]['href'].startswith(
                                    '/politics'
                                ) and not vid[0]['href'].startswith('/gaming'):
                videoID = vid[0]['href'].split("v=")[1].split("&")[0]
                videoTitle = vid[0]['title']
                videoImage = "https://i.ytimg.com/vi/{0}/hqdefault.jpg".format(
                    videoID)
                videoChannel = vid[1].contents[0].string
                videoUploadDate = vid[2].contents[0].string
                videoDuration = vid[3].contents[0].string
                if "watching" in vid[2].contents[0].string:
                    videoViews = "Live"
                else:
                    try:
                        videoViews = vid[2].contents[1].string
                    except:
                        videoViews = "Playlist"

                videoList.append({
                    "videoID": videoID,
                    "videoTitle": videoTitle,
                    "videoImage": videoImage,
                    "videoChannel": videoChannel,
                    "videoViews": videoViews,
                    "videoUploadDate": videoUploadDate,
                    "videoDuration": videoDuration
                })

        return videoList

    def process_additional_pages(self, category):
        url = "https://www.youtube.com/results?search_query={0}".format(
            category)
        response = requests.get(url, headers=self.quackagent)
        html = response.text
        soup = BeautifulSoup(html)
        buttons = soup.findAll(
            'a',
            attrs={
                'class':
                "yt-uix-button vve-check yt-uix-sessionlink yt-uix-button-default yt-uix-button-size-default"
            })
        try:
            nPage = buttons[0]['href']
        except:
            nPage = self.process_additional_pages_fail(category)
        pPage = url
        addPgObj = [nPage, pPage]

        return addPgObj

    def process_additional_pages_fail(self, category):
        url = None
        if category == "news":
            url = "/results?search_query=world+news"
        if category == "music":
            url = "/results?search_query=latest+music"
        if category == "technology":
            url = "/results?search_query=latest+tech"
        if category == "politics":
            url = "/results?search_query=latest+politics"
        if category == "gaming":
            url = "/results?search_query=latest+games"

        return url

    def nextSongForAutoPlay(self):
        self.gui["nextSongBlob"] = self.nextSongList

    def refreshWatchList(self, message):
        print("Currently Disabled, Skipping Step")
        #try:
        #print("todo")
        #self.youtubesearchpagesimple(self.lastSong)
        #except:
        #self.youtubesearchpagesimple(self.lastSong)

    @intent_file_handler('youtube-repeat.intent')
    def youtube_repeat_last(self):
        video = pafy.new(self.lastSong)
        thumb = video.thumb
        playstream = video.streams[0]
        playurl = playstream.url
        self.gui["status"] = str("play")
        self.gui["video"] = str(playurl)
        self.gui["currenturl"] = ""
        self.gui["currenttitle"] = video.title
        self.gui["setTitle"] = video.title
        self.gui["viewCount"] = video.viewcount
        self.gui["publishedDate"] = video.published
        self.gui["videoAuthor"] = video.username
        self.gui["videoListBlob"] = ""
        self.gui["recentListBlob"] = ""
        self.gui["nextSongTitle"] = ""
        self.gui["nextSongImage"] = ""
        self.gui["nextSongID"] = ""
        self.gui.show_pages(["YoutubePlayer.qml", "YoutubeSearch.qml"],
                            0,
                            override_idle=True)
        self.youtubesearchpagesimple(self.lastSong)
        self.isTitle = video.title

    def build_category_list(self, category):
        LOG.info("Building For Category" + category)
        videoList = []
        yts = YoutubeSearcher()
        vidslist = yts.search_youtube(category, render="videos")
        for x in range(len(vidslist['videos'])):
            videoID = vidslist['videos'][x]['videoId']
            videoTitle = vidslist['videos'][x]['title']
            videoImage = vidslist['videos'][x]['thumbnails'][0]['url']
            vidImgFix = str(videoImage).split("?")[0]
            videoUploadDate = vidslist['videos'][x]['published_time']
            videoDuration = vidslist['videos'][x]['length']
            videoViews = vidslist['videos'][x]['views']
            videoChannel = vidslist['videos'][x]['channel_name']
            videoList.append({
                "videoID": videoID,
                "videoTitle": videoTitle,
                "videoImage": vidImgFix,
                "videoChannel": videoChannel,
                "videoViews": videoViews,
                "videoUploadDate": videoUploadDate,
                "videoDuration": videoDuration
            })

        return videoList

    def build_category_list_from_url(self, category):
        videoList = []
        yts = YoutubeSearcher()
        vidslist = yts.page_search(page_type=category)
        for x in range(len(vidslist['page_videos'])):
            videoID = vidslist['page_videos'][x]['videoId']
            videoTitle = vidslist['page_videos'][x]['title']
            videoImage = vidslist['page_videos'][x]['thumbnails'][0]['url']
            vidImgFix = str(videoImage).split("?")[0]
            videoUploadDate = vidslist['page_videos'][x]['published_time']
            videoDuration = vidslist['page_videos'][x]['length']
            videoViews = vidslist['page_videos'][x]['views']
            videoChannel = vidslist['page_videos'][x]['channel_name']
            videoList.append({
                "videoID": videoID,
                "videoTitle": videoTitle,
                "videoImage": vidImgFix,
                "videoChannel": videoChannel,
                "videoViews": videoViews,
                "videoUploadDate": videoUploadDate,
                "videoDuration": videoDuration
            })

        return videoList

    def clear_db(self):
        LOG.info("In DB Clear")
        self.recent_db.clear()
        self.recent_db.store()
        self.gui["recentListBlob"] = ""

    def buildHistoryModel(self, dictItem):
        LOG.info("In Build History Model")
        if 'recentList' in self.recent_db.keys():
            myCheck = self.checkIfHistoryItem(dictItem)
            if myCheck == True:
                LOG.info("In true")
                LOG.info(dictItem)
                self.moveHistoryEntry(dictItem)
            elif myCheck == False:
                LOG.info("In false")
                LOG.info(dictItem)
                self.addHistoryEntry(dictItem)

        else:
            recentListItem = []
            recentListItem.insert(0, dictItem)
            self.recent_db['recentList'] = recentListItem
            LOG.info("In Build History Recent Not Found Creating")
            self.recent_db.store()
            self.build_recent_watch_list(20)
            self.gui["recentHomeListBlob"] = self.recentWatchListObj

    def checkIfHistoryItem(self, dictItem):
        hasHistoryItem = False
        for dict_ in [
                x for x in self.recent_db['recentList']
                if x["videoID"] == dictItem["videoID"]
        ]:
            hasHistoryItem = True
        return hasHistoryItem

    def moveHistoryEntry(self, dictItem):
        res = [
            i for i in self.recent_db['recentList']
            if not (i['videoID'] == dictItem["videoID"])
        ]
        self.recent_db['recentList'] = res
        self.recent_db['recentList'].insert(0, dictItem)
        self.recent_db.store()
        self.build_recent_watch_list(20)
        self.gui["recentHomeListBlob"] = self.recentWatchListObj

    def addHistoryEntry(self, dictItem):
        self.recent_db['recentList'].insert(0, dictItem)
        self.recent_db.store()
        self.build_recent_watch_list(20)
        self.gui["recentHomeListBlob"] = self.recentWatchListObj

    def build_recent_watch_list(self, count):
        if 'recentList' in self.recent_db.keys():
            recentWatchListRaw = self.recent_db['recentList']
            recentWatchListModded = recentWatchListRaw[0:count]
            self.recentWatchListObj['recentList'] = recentWatchListModded
        else:
            emptyList = []
            self.recentWatchListObj['recentList'] = emptyList

    def build_upload_date(self, update):
        now = datetime.datetime.now() + datetime.timedelta(seconds=60 * 3.4)
        date = dateutil.parser.parse(update)
        naive = date.replace(tzinfo=None)
        dtstring = timeago.format(naive, now)
        return dtstring

    def add_view_string(self, viewcount):
        val = viewcount
        count = re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
        views = count + " views"
        LOG.info(views)
        return views

    def process_soup_watchlist(self, html):
        videoList = []
        videoList.clear()
        soup = BeautifulSoup(html)
        currentVideoSection = soup.find('div',
                                        attrs={'class': 'watch-sidebar'})
        getVideoDetails = zip(
            currentVideoSection.findAll(attrs={'class': 'yt-uix-sessionlink'}),
            currentVideoSection.findAll(attrs={'class': 'attribution'}),
            currentVideoSection.findAll(
                attrs={'class': 'yt-uix-simple-thumb-wrap'}),
            currentVideoSection.findAll(attrs={'class': 'video-time'}),
            currentVideoSection.findAll(attrs={'class': 'view-count'}))
        for vid in getVideoDetails:
            if "googleads" not in vid[0][
                    'href'] and not vid[0]['href'].startswith(
                        u"/user") and not vid[0]['href'].startswith(
                            u"/channel") and not vid[0]['href'].startswith(
                                '/news') and not vid[0]['href'].startswith(
                                    '/music'
                                ) and not vid[0]['href'].startswith(
                                    '/technology'
                                ) and not vid[0]['href'].startswith(
                                    '/politics'
                                ) and not vid[0]['href'].startswith(
                                    '/gaming') and "title" in vid[0].attrs:
                videoID = vid[0]['href'].split("v=")[1].split("&")[0]
                videoTitle = vid[0]['title']
                videoImage = "https://i.ytimg.com/vi/{0}/hqdefault.jpg".format(
                    videoID)
                videoChannel = vid[1].contents[0].string
                videoUploadDate = " "
                videoDuration = vid[3].contents[0].string
                videoViews = vid[4].text

                videoList.append({
                    "videoID": videoID,
                    "videoTitle": videoTitle,
                    "videoImage": videoImage,
                    "videoChannel": videoChannel,
                    "videoViews": videoViews,
                    "videoUploadDate": videoUploadDate,
                    "videoDuration": videoDuration
                })

        return videoList