Ejemplo n.º 1
0
 def persist(self):
     # noinspection PyBroadException
     try:
         __class__.persist_cache(self.clients)
     except Exception:
         logger.exception('Query cache failed to persist')
     else:
         self.last_persist_time = time.time()
         self.unpersisted_count = 0
         logger.debug('Query cache persisted successfully')
Ejemplo n.º 2
0
 def on_speech_downloaded(self, query: str, path: str):
     logger.debug('on_speech_downloaded: query=%s, path=%s', repr(query),
                  repr(path))
     if not self.auto_play:
         return
     # 若窗口未显示,或查询内容已改变,不发音
     if not self.is_visible(
     ) or not self.current_query_result or self.current_query_result.query != query:
         return
     # 避免重复发音
     if not self.current_query_result.speech_path:
         self.pronounce(path)
         self.current_query_result.speech_path = path
Ejemplo n.º 3
0
    def query(self, text: str) -> Optional[QueryResult]:
        start_time = time.time()
        logger.debug('[%s] Query started for query=%s', self.client.id,
                     repr(text))

        # noinspection PyBroadException
        try:
            result = self.cache.get(self.client.id, text)
            if result:
                # TODO 完善路径的协议检查
                if result.speech_path and result.speech_path.startswith(
                        '/') and not os.path.exists(result.speech_path):
                    result.speech_path = None
                logger.debug('[%s] Cache hit for query=%s, result=%s',
                             self.client.id, repr(text), repr(result))
                return result

            result = self.client.query(text)
            logger.debug('[%s] Query finished for query=%s, result=%s',
                         self.client.id, repr(text), repr(result))
            if result:
                self.cache.put(self.client.id, text, result)
            return result
        except Exception:
            logger.exception('[%s] Query failed for query=%s', self.client.id,
                             repr(text))
        finally:
            time_spent = (time.time() - start_time) * 1000
            logger.debug('[%s] Time spent: %fms', self.client.id, time_spent)
Ejemplo n.º 4
0
 def load_cache():
     if not os.path.exists(
             __class__.CACHE_VERSION_FILE) or not os.path.exists(
                 __class__.CACHE_FILE):
         return
     # noinspection PyBroadException
     try:
         with open(__class__.CACHE_VERSION_FILE, 'r') as f:
             query_result_version = int(f.read().strip())
             if query_result_version != QueryResult.VERSION:
                 logger.debug(
                     'Ignore cache for version %d, current version is %d',
                     query_result_version, QueryResult.VERSION)
                 return
         with open(__class__.CACHE_FILE, 'rb') as f:
             data = pickle.load(f)
             return data
     except Exception:
         return
Ejemplo n.º 5
0
 def redraw(self, selection: Selection, query_result: QueryResult):
     if not query_result:
         logger.debug('Redraw canceled, since query_result is invalid: %s',
                      repr(query_result))
         return
     # 若选中文本已经变化,不再显示旧的查询结果
     if selection.text != Selection.current.text:
         logger.debug(
             'Redraw canceled, since selection has changed: original=%s, current=%s',
             repr(selection.text), repr(Selection.current.text))
         return
     logger.debug('Redraw started for query=%s', repr(selection.text))
     self.current_query_result = query_result
     self.widgets.draw(query_result)
     minimum_height, natural_height = self.box.get_preferred_height()
     # Avoid warning: Allocating size to window without calling gtk_widget_get_preferred_width/height()
     # self.get_preferred_width()
     # self.get_preferred_height()
     self.resize(self.WINDOW_WIDTH, minimum_height)
     self.move_window(selection)
     self.show()
     self.time_to_hide = time.time() + self.popup_timeout
     if self.auto_play and query_result.speech_path:
         self.pronounce(query_result.speech_path)
Ejemplo n.º 6
0
    def query(self, text: str) -> Optional[QueryResult]:
        try:
            res = requests.get(self.API,
                               params=self._params(text),
                               timeout=self.config.request_timeout)
            if not res.ok:
                logger.error(
                    '[%s] Request failed for query=%s: status_code=%s, reason=%s, content=%s',
                    self.id, repr(text), res.status_code, res.reason,
                    repr(res.text))
                return

            try:
                result = res.json()
            except json.decoder.JSONDecodeError:
                logger.error('[%s] Invalid JSON response for query=%s: ',
                             self.id, repr(text), repr(res.text))
                return

            if result['errorCode'] != '0':
                logger.error('[%s] Query failed for query=%s: errorCode=%s',
                             self.id, repr(text), str(result['errorCode']))
                return

            logger.debug('[%s] Request success for query=%s: %s', self.id,
                         repr(text), result)

            language = result['l'].replace('2zh-CHS', '').lower()
            translation = result['translation'] != [
                result['query']
            ] and '; '.join(result['translation']) or None
            basic = result.get('basic')
            phrases = result.get('web') or None

            # 检查有无有效翻译结果。translation 和 explanations 至少要有其一
            # 特例:
            #   * 无 translation, 有 explanations: alt, github
            #   * 有 translation, 无 explanations: 除英语外的其它语种
            if not translation and (not basic or not basic.get('explains')):
                logger.debug('[%s] No translation for query=%s', self.id,
                             repr(text))
                return

            if phrases is not None:
                for phrase in phrases:
                    phrase['value'] = '; '.join(phrase['value'])
                    phrase['dict_link'] = __class__.dict_link(
                        language, phrase['key'])

            # 小语种查询结果没有 'query'
            query_result = QueryResult(
                result.get('query', text),
                translation,
                dict_link=__class__.dict_link(language,
                                              result.get('query', text)),
                phonetic=basic
                and (basic.get('us-phonetic') or basic.get('uk-phonetic')
                     or basic.get('phonetic')),
                explanations=basic and basic.get('explains'),
                phrases=phrases)
            return query_result
        except requests.exceptions.RequestException:
            logger.exception('[%s] Request failed for query=%s', self.id,
                             repr(text))