def keyboard_tap_callback(proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent, NSBundle NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] =\ dict(NSAllowsArbitraryLoads=True) if type_ < 0 or type_ > 0x7fffffff: LOG.error('Unkown mac event') run_event_loop() LOG.error('restart mac key board event loop') return event try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: ControllerApi.player.play_next() elif key_code is 20: ControllerApi.player.play_last() elif key_code is 16: ControllerApi.player.play_or_pause() return None return event
def load_user_infos(cls, data): avatar_url = data['avatar'] request = QNetworkRequest(QUrl(avatar_url)) cls.controller.network_manager.get(request) cls.controller.network_manager.network_queue.put(ViewOp.set_login_label_avatar) ViewOp.ui.MY_LIST_WIDGET.empty_layout() ViewOp.ui.COLLECTION_LIST_WIDGET.empty_layout() playlists = cls.controller.api.get_user_playlist() if not cls.controller.api.is_response_ok(playlists): return playlist_num = len(playlists) for playlist in playlists: pid = playlist['id'] w = PlaylistItem() w.set_playlist_item(playlist) w.signal_text_btn_clicked.connect(cls.on_playlist_btn_clicked) if cls.controller.api.is_playlist_mine(playlist): ViewOp.ui.MY_LIST_WIDGET.layout().addWidget(w) if pid == cls.controller.api.favorite_pid: favorite_playlist_detail = cls.controller.api.get_playlist_detail(pid) cls.controller.state["current_pid"] = pid ViewOp.ui.WEBVIEW.load_playlist(favorite_playlist_detail) else: if playlist_num <= 50: app_event_loop = asyncio.get_event_loop() app_event_loop.call_soon(cls.controller.api.get_playlist_detail, pid) else: ViewOp.ui.COLLECTION_LIST_WIDGET.layout().addWidget(w) LOG.info('load user infos finished')
def run_event_loop(): LOG.info("try to load mac hotkey event loop") import Quartz from AppKit import NSSystemDefined # Set up a tap, with type of tap, location, options and event mask tap = Quartz.CGEventTapCreate( Quartz.kCGSessionEventTap, # Session level is enough for our needs Quartz.kCGHeadInsertEventTap, # Insert wherever, we do not filter Quartz.kCGEventTapOptionDefault, # NSSystemDefined for media keys Quartz.CGEventMaskBit(NSSystemDefined), keyboard_tap_callback, None ) run_loop_source = Quartz.CFMachPortCreateRunLoopSource( None, tap, 0) Quartz.CFRunLoopAddSource( Quartz.CFRunLoopGetCurrent(), run_loop_source, Quartz.kCFRunLoopDefaultMode ) # Enable the tap Quartz.CGEventTapEnable(tap, True) # and run! This won't return until we exit or are terminated. Quartz.CFRunLoopRun() LOG.error('Mac hotkey event loop exit') return []
def keyboard_tap_callback(proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent if type_ < 0 or type_ > 0x7FFFFFFF: LOG.error("Unkown mac event") run_event_loop() LOG.error("restart mac key board event loop") return event try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: ControllerApi.player.play_next() elif key_code is 20: ControllerApi.player.play_last() elif key_code is 16: ControllerApi.player.play_or_pause() return None return event
def get_playlist_detail(self, pid, cache=True): '''update playlist detail in sqlite if cache is false''' if cache is False: app_event_loop = asyncio.get_event_loop() app_event_loop.run_in_executor( None, partial(self.update_playlist_detail, pid)) if PlaylistDb.exists(pid): LOG.info("Read playlist %d info from sqlite" % (pid)) return PlaylistDb.get_data(pid) else: return self.update_playlist_detail(pid)
def init(controller): LOG.info("NetEase Plugin init") ControllerApi.api = netease_normalize user = UserDb.get_last_login_user() if user is not None: netease_normalize.set_uid(user.uid) user_data = user.basic_info if user.cookies is not None: netease_normalize.ne.load_cookies(user.cookies) if netease_normalize.login_by_cookies(): ControllerApi.set_login() ViewOp.load_user_infos(user_data)
def update_user_playlists(self): user = UserDb.get_user(self.uid) data = self.ne.user_playlist(self.uid) if not self.is_response_avaible(data): return data playlist = data['playlist'] result_playlists = [] for i, brief_playlist in enumerate(playlist): brief_playlist['uid'] = brief_playlist['userId'] brief_playlist['type'] = brief_playlist['specialType'] result_playlists.append( BriefPlaylistModel(brief_playlist).get_dict()) self._set_favorite_pid(result_playlists) LOG.info('update user playlists info') user.update(_playlists=pickle.dumps(result_playlists)) return result_playlists
def on_set_favorite_btn_clicked(cls, checked=True): if not cls.controller.state["current_mid"]: return False data = cls.controller.api.set_music_to_favorite(cls.controller.state['current_mid'], checked) cls.controller.desktop_mini.content.is_song_like = checked if not cls.controller.api.is_response_ok(data): ViewOp.ui.LOVE_SONG_BTN.setChecked(not checked) cls.controller.desktop_mini.content.is_song_like = not checked return False playlist_detail = cls.controller.api.get_playlist_detail(cls.controller.api.favorite_pid, cache=False) if not cls.controller.api.is_response_ok(playlist_detail): ViewOp.ui.STATUS_BAR.showMessage("刷新 -喜欢列表- 失败") return False if cls.controller.state['current_pid'] == cls.controller.api.favorite_pid: LOG.info("喜欢列表的歌曲发生变化") ViewOp.ui.WEBVIEW.load_playlist(playlist_detail) return True
def __init__(self, parent=None): super().__init__(parent) ui = UiMainWidget() ViewOp.ui = ui ViewOp.controller = ControllerApi ui.setup_ui(self) engine = create_engine( 'sqlite:////%s' % DATABASE_SQLITE, connect_args={'check_same_thread': False}, echo=False) Base.metadata.create_all(engine) Session = sessionmaker() Session.configure(bind=engine) session = Session() LOG.info('db connected: %s' % DATABASE_SQLITE) ControllerApi.player = Player() ControllerApi.session = session ControllerApi.view = ViewOp ControllerApi.desktop_mini = DesktopMiniLayer() ControllerApi.lyric_widget = LyricWidget() ControllerApi.notify_widget = NotifyWidget() ControllerApi.network_manager = NetworkManager() ControllerApi.current_playlist_widget = MusicTableWidget() self._search_shortcut = QShortcut(QKeySequence('Ctrl+F'), self) self._minimize_shortcut = QShortcut(QKeySequence('Ctrl+M'), self) self._pre_focus = QShortcut(QKeySequence('Ctrl+['), self) self._next_focus = QShortcut(QKeySequence('Ctrl+]'), self) # self._switch_mode_shortcut = QShortcut(QKeySequence(Qt.Key_Escape), self) self.setAttribute(Qt.WA_MacShowFocusRect, False) self.setWindowIcon(QIcon(WINDOW_ICON)) self.setWindowTitle('FeelUOwn') self.resize(960, 600) self.mode_manager = ModesManger() self._init_signal_binding() app_event_loop = asyncio.get_event_loop() app_event_loop.call_later(1, self._init_plugins) app_event_loop.call_later(6, TipsManager.show_start_tip) asyncio.Task(VersionManager.check_release())
def http_request(self, method, action, query=None, urlencoded=None, callback=None, timeout=3): LOG.info('method=%s url=%s query=%s' % (method, action, query)) try: res = None if method == "GET": res = requests.get(action, headers=self.headers, cookies=self.cookies, timeout=timeout) elif method == "POST": res = requests.post(action, data=query, headers=self.headers, cookies=self.cookies, timeout=timeout) elif method == "POST_UPDATE": res = requests.post(action, data=query, headers=self.headers, cookies=self.cookies, timeout=timeout) self.cookies.update(res.cookies.get_dict()) content = show_requests_progress(res, self.signal_load_progress) content_str = content.decode('utf-8') content_dict = json.loads(content_str) return content_dict except Exception as e: LOG.error(str(e)) return {"code": 408}
def get_song_detail(self, mid): if SongDb.exists(mid): LOG.info("Read song %d from sqlite" % mid) return SongDb.get_data(mid) data = self.ne.song_detail(mid) if not self.is_response_avaible(data): return data songs = [] for each in data['songs']: song = self.access_music(each) songs.append(song) model = songs[0] song = SongDb(mid=mid, _data=pickle.dumps(model)) song.save() LOG.info('Save music %d info into sqlite' % mid) return model
def on_set_favorite_btn_clicked(cls, checked=True): if not cls.controller.state["current_mid"]: return False data = cls.controller.api.set_music_to_favorite( cls.controller.state['current_mid'], checked) cls.controller.desktop_mini.content.is_song_like = checked if not cls.controller.api.is_response_ok(data): ViewOp.ui.LOVE_SONG_BTN.setChecked(not checked) cls.controller.desktop_mini.content.is_song_like = not checked return False playlist_detail = cls.controller.api.get_playlist_detail( cls.controller.api.favorite_pid, cache=False) if not cls.controller.api.is_response_ok(playlist_detail): ViewOp.ui.STATUS_BAR.showMessage("刷新 -喜欢列表- 失败") return False if cls.controller.state[ 'current_pid'] == cls.controller.api.favorite_pid: LOG.info("喜欢列表的歌曲发生变化") ViewOp.ui.WEBVIEW.load_playlist(playlist_detail) return True
def update_playlist_detail(self, pid, data=None): data = self.ne.playlist_detail(pid) if data is None else data if not self.is_response_avaible(data): return data data = data['result'] data['uid'] = data['userId'] data['type'] = data['specialType'] for i, track in enumerate(data['tracks']): data['tracks'][i] = self.access_music(track) model = PlaylistModel(data).get_dict() if PlaylistDb.exists(pid): PlaylistDb.update_data(pid, model) else: playlist = PlaylistDb(pid=pid, _data=pickle.dumps(model)) playlist.save() LOG.info('Save playlist %d info to sqlite' % pid) return model
def check_release(cls): url = 'https://api.github.com/repos/cosven/FeelUOwn/releases' LOG.info('正在查找新版本...') try: loop = asyncio.get_event_loop() future = loop.run_in_executor(None, partial(requests.get, url, timeout=5)) res = yield from future if not res.status_code == 200: LOG.warning('connect to api.github.com timeout') return releases = res.json() for release in releases: if release['tag_name'] > cls.current_version: title = u'发现新版本 %s hoho' % release['tag_name'] LOG.info(title) content = release['name'] ControllerApi.notify_widget.show_message(title, content) ViewOp.ui.STATUS_BAR.showMessage(title, 5000) break except Exception as e: LOG.error(str(e))
def check_release(cls): url = 'https://api.github.com/repos/cosven/FeelUOwn/releases' LOG.info('正在查找新版本...') try: loop = asyncio.get_event_loop() future = loop.run_in_executor( None, partial(requests.get, url, timeout=5)) res = yield from future if not res.status_code == 200: LOG.warning('connect to api.github.com timeout') return releases = res.json() for release in releases: if release['tag_name'] > cls.current_version: title = u'发现新版本 %s hoho' % release['tag_name'] LOG.info(title) content = release['name'] ControllerApi.notify_widget.show_message(title, content) ViewOp.ui.STATUS_BAR.showMessage(title, 5000) break except Exception as e: LOG.error(str(e))
def load_user_infos(cls, data): avatar_url = data['avatar'] request = QNetworkRequest(QUrl(avatar_url)) cls.controller.network_manager.get(request) cls.controller.network_manager.network_queue.put( ViewOp.set_login_label_avatar) ViewOp.ui.MY_LIST_WIDGET.empty_layout() ViewOp.ui.COLLECTION_LIST_WIDGET.empty_layout() playlists = cls.controller.api.get_user_playlist() if not cls.controller.api.is_response_ok(playlists): return playlist_num = len(playlists) for playlist in playlists: pid = playlist['id'] w = PlaylistItem() w.set_playlist_item(playlist) w.signal_text_btn_clicked.connect(cls.on_playlist_btn_clicked) if cls.controller.api.is_playlist_mine(playlist): ViewOp.ui.MY_LIST_WIDGET.layout().addWidget(w) if pid == cls.controller.api.favorite_pid: favorite_playlist_detail = cls.controller.api.get_playlist_detail( pid) cls.controller.state["current_pid"] = pid ViewOp.ui.WEBVIEW.load_playlist(favorite_playlist_detail) else: if playlist_num <= 50: app_event_loop = asyncio.get_event_loop() app_event_loop.call_soon( cls.controller.api.get_playlist_detail, pid) else: ViewOp.ui.COLLECTION_LIST_WIDGET.layout().addWidget(w) LOG.info('load user infos finished')
def run(self): # Monitor keypress and button press LOG.info("Linux multimedia hotkey start") ctx = self.disp.record_create_context( 0, [record.AllClients], [{ 'core_requests': (0, 0), 'core_replies': (0, 0), 'ext_requests': (0, 0, 0, 0), 'ext_replies': (0, 0, 0, 0), 'delivered_events': (0, 0), 'device_events': (X.KeyReleaseMask, X.ButtonReleaseMask), 'errors': (0, 0), 'client_started': False, 'client_died': False, }]) self.disp.record_enable_context(ctx, self.handler) self.disp.record_free_context(ctx) while 1: # Infinite wait, doesn't do anything as no events are grabbed event = self.root.display.next_event()
def on_mode_changed(self, mode): LOG.info('current play mode is %d.' ' 1 for single in loop, 3 for loop, 4 for random' % mode) if mode != self._current_mode: self._current_mode = mode self._switch_mode()
def __login(self): """登录 在用户登录成功时,会发射("login_success")信号 """ data = {} if self.is_need_captcha is True: captcha_text = str(self.captcha_lineedit.text()) flag, self.captcha_id = self.ne.confirm_captcha( self.captcha_id, captcha_text) if flag is not True: self.hint_label.setText(u'验证码错误') url = self.ne.get_captcha_url(data['captchaId']) request = QNetworkRequest(QUrl(url)) self.nm.get(request) self.parent().network_queue.put(self.show_captcha) return phone_login = False # 0: 网易通行证, 1: 手机号登陆 username = str(self.username_widget.text()) # 包含中文会出错 password = str(self.password_widget.text()) # 2: checked, 1: partial checked is_remember = self.is_remember_chb.checkState() # judget if logining by using phone number if username.isdigit() and len(username) == 11: username = int(username) phone_login = True LOG.info(u"正在使用手机号进行登录") login_data = { 'username': username, 'password': password, 'is_remember': is_remember } if not self.is_autofill: data = self.ne.login(username, password, phone_login) else: data = self.ne.auto_login(username, password, phone_login) if data['code'] == 200: self.hint_label.setText(u'登录成功') self.signal_login_sucess.emit(data) self.close() self.save_login_info(login_data) elif data['code'] == 415: # 需要验证码 self.is_need_captcha = True self.hint_label.setText(data['message']) LOG.info(u'本次登陆需要验证码') self.captcha_id = data['captchaId'] self.captcha_label.show() self.captcha_lineedit.show() url = self.ne.get_captcha_url(data['captchaId']) request = QNetworkRequest(QUrl(url)) self.nm.get(request) self.parent().network_queue.put(self.show_captcha) elif data['code'] == 408: self.hint_label.setText(u'网络连接超时') elif data['code'] == 501: self.hint_label.setText(u'用户名错误') elif data['code'] == 502: self.hint_label.setText(u'密码错误') elif data['code'] == 509: self.hint_label.setText(u'你可能正在使用手机号登陆,密码错误几次之后,你可能需要等待几分钟再登录') else: self.hint_label.setText(u'未知错误')
def save_login_time(self): user = UserDb.get_user(self.uid) user.record_login_time() LOG.info('Save user login time')
def save_cookies(self): user = UserDb.get_user(self.uid) user.update(_cookies=pickle.dumps(self.ne.cookies)) LOG.info('Save user cookies')
def save_user_pw(self, username, password): user = UserDb.get_user(self.uid) if user is not None: user.update(username=username, password=password) LOG.info('Save user\'s username and password ')
def __login(self): """登录 在用户登录成功时,会发射("login_success")信号 """ data = {} if self.is_need_captcha is True: captcha_text = str(self.captcha_lineedit.text()) flag, self.captcha_id = self.ne.confirm_captcha(self.captcha_id, captcha_text) if flag is not True: self.hint_label.setText(u'验证码错误') url = self.ne.get_captcha_url(data['captchaId']) request = QNetworkRequest(QUrl(url)) self.nm.get(request) self.parent().network_queue.put(self.show_captcha) return phone_login = False # 0: 网易通行证, 1: 手机号登陆 username = str(self.username_widget.text()) # 包含中文会出错 password = str(self.password_widget.text()) # 2: checked, 1: partial checked is_remember = self.is_remember_chb.checkState() # judget if logining by using phone number if username.isdigit() and len(username) == 11: username = int(username) phone_login = True LOG.info(u"正在使用手机号进行登录") login_data = { 'username': username, 'password': password, 'is_remember': is_remember } if not self.is_autofill: data = self.ne.login(username, password, phone_login) else: data = self.ne.auto_login(username, password, phone_login) if data['code'] == 200: self.hint_label.setText(u'登录成功') self.signal_login_sucess.emit(data) self.close() self.save_login_info(login_data) elif data['code'] == 415: # 需要验证码 self.is_need_captcha = True self.hint_label.setText(data['message']) LOG.info(u'本次登陆需要验证码') self.captcha_id = data['captchaId'] self.captcha_label.show() self.captcha_lineedit.show() url = self.ne.get_captcha_url(data['captchaId']) request = QNetworkRequest(QUrl(url)) self.nm.get(request) self.parent().network_queue.put(self.show_captcha) elif data['code'] == 408: self.hint_label.setText(u'网络连接超时') elif data['code'] == 501: self.hint_label.setText(u'用户名错误') elif data['code'] == 502: self.hint_label.setText(u'密码错误') elif data['code'] == 509: self.hint_label.setText(u'你可能正在使用手机号登陆,密码错误几次之后,你可能需要等待几分钟再登录') else: self.hint_label.setText(u'未知错误')