diff --git a/conf/config.yaml b/conf/config.yaml index 3b94c2b..bab033a 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -4,5 +4,5 @@ SERVER: reconnect_interval: 3 VERSION: - code: 129 - name: 2.3.9 \ No newline at end of file + code: 130 + name: 2.4.0 \ No newline at end of file diff --git a/lib/facebook.py b/lib/facebook.py index 84762dc..303ddff 100644 --- a/lib/facebook.py +++ b/lib/facebook.py @@ -532,7 +532,7 @@ class FacebookClient(Client): variables = {"input": {"people_you_may_know_id": fbid, "people_you_may_know_location": "FRIENDS_CENTER", "actor_id": self.uid, - "client_mutation_id": "2"}} + "client_mutation_id": self.get_client_mutation_id()}} self.graphql_api('FriendingCometPYMKBlacklistSuggestionMutation', '2882558265094181', variables) return {"success": True} @@ -1541,7 +1541,8 @@ class FacebookClient(Client): params = {"notif_category": type, "notif_medium": channel, "toggle_value": toggle} # OFF/ON action = base64.b64encode(f'NotificationMediumToggleServerActionToken;{json.dumps(params)}'.encode()) action = action.decode() - mutation_id = "{}:{}".format(int(time.time() * 1000), random.randint(0, 4294967295) + 1) + # mutation_id = "{}:{}".format(int(time.time() * 1000), random.randint(0, 4294967295) + 1) + mutation_id = self.get_client_mutation_id() variables = {"input": { "client_mutation_id": mutation_id, "actor_id": self.uid, "action_type": action, @@ -1626,6 +1627,74 @@ class FacebookClient(Client): j = self._payload_post("/ajax/add_friend/action.php?dpr=1", data) return j + def FriendingCometFriendRequestConfirmMutation(self, friend_requester_id, source): + """同意好友请求""" + #TODO:source 多种未抓,文档 + var = {"input": {"cancelled_friend_requestee_id": friend_requester_id, "source": source, "actor_id": self.uid, + "client_mutation_id": self.get_client_mutation_id()}, "scale": 2} + res = self.graphql_api('FriendingCometFriendRequestCancelMutation', '3226051994092510', var) + try: + return {'success': True, 'data': res['data']} + except: + return {'success': False, "data": []} + + def FriendingCometFriendRequestDeleteMutation(self, friend_requester_id, source): + """移除好友请求""" + # FRIENDS_CENTER 朋友推荐列表处 + # pymk_timeline_chain 好友的好友位置取消 + # NETEGO 个人主页 + var = { + "input": {"people_you_may_know_id": friend_requester_id, "people_you_may_know_location": source, + "actor_id": self.uid, "client_mutation_id": self.get_client_mutation_id()}} + res = self.graphql_api('FriendingCometFriendRequestDeleteMutation', '2882558265094181', var) + try: + return {'success': True, 'data': res['data']} + except: + return {'success': False, "data": []} + + def FriendingCometFriendRequestCancelMutation(self, friend_requester_id, source): + """取消好友请求""" + # pymk 朋友推荐列表处 + # manage_outgoing_requests 查看已发出请求列表 + # profile 主页位置取消 + # pymk_timeline_chain 好友的好友位置取消 + # pymk_feed 自己主页推荐好友处取消 + # groups_member_list 公开小组成员 + # search 搜索好友取消 + var = {"input": {"cancelled_friend_requestee_id": friend_requester_id, "source": source, + "actor_id": self.uid, "client_mutation_id": self.get_client_mutation_id()}, + "scale": 2} + res = self.graphql_api('FriendingCometFriendRequestCancelMutation', '3226051994092510', var) + try: + return {'success': True, 'data': res['data']} + except: + return {'success': False, "data": []} + + def FriendingCometFriendRequestSendMutation(self, friend_requester_id, source): + """添加好友请求""" + # people_you_may_know 可能认识的人 + # profile_button 主页添加按钮 + # pymk_timeline_chain 好友的好友 + # groups_member_list 公开小组成员 + # search 搜索添加 + # netego_pymk 自己主页推荐好友添加 + source_list = { + 'people_you_may_know': 'friends_center', + 'netego_pymk': 'netego', + 'pymk_timeline_chain': 'pymk_timeline_chain' + } + var = { + "input": {"friend_requestee_ids": [friend_requester_id], + "refs": [None], "source": source, "actor_id": self.uid, + "client_mutation_id": self.get_client_mutation_id()}, "scale": 2} + if source in source_list.keys(): + var['input']['people_you_may_know_location'] = source_list[source] + res = self.graphql_api('FriendingCometFriendRequestSendMutation', '4391497287589685', var) + try: + return {'success': True, 'data': res['data']} + except: + return {'success': False, "data": []} + def primaryLocation(self): res = self._state._session.get('https://www.facebook.com/primary_location/info/') return parse_html.get_location_info(res.text) @@ -1697,7 +1766,7 @@ class FacebookClient(Client): def feedbackActions(self, photo_id, action='like', flag=True): feedback = 'feedback:%s' % photo_id try: - variables = {"input": {"client_mutation_id": '2', "actor_id": self.uid, + variables = {"input": {"client_mutation_id": self.get_client_mutation_id(), "actor_id": self.uid, "feedback_id": base64.b64encode(feedback.encode()).decode(), "feedback_reaction": 1, "feedback_source": "PHOTOS_SNOWLIFT", @@ -1762,7 +1831,7 @@ class FacebookClient(Client): def answersQuestions(self, group_id, answers: list, accept_rules=True): if isinstance(answers, str) and '[' in answers: answers = json.loads(answers) - var = {"input": {"client_mutation_id": "1", "actor_id": self.uid, + var = {"input": {"client_mutation_id": self.get_client_mutation_id(), "actor_id": self.uid, "group_id": group_id, "answers": answers, }} if accept_rules: @@ -2012,7 +2081,7 @@ class FacebookClient(Client): for x in story_actions: x['story_location'] = 'TIMELINE' data = {"input": { - "client_mutation_id": "1", + "client_mutation_id": self.get_client_mutation_id(), "actor_id": self.uid, "story_actions": story_actions }} @@ -2047,27 +2116,24 @@ class FacebookClient(Client): except Exception as e: return {'success': False, 'errors': str(e)} - def delete_dialog(self, pic_id, set_id): + def CometMediaViewerPhotoDeleteActionMutation(self, photo_id): """ 删除照片 """ - data = { - 'fbid': pic_id, - 'version': '9', - 'set': set_id, - 'next': '3143051995809753', - 'dpr': '2', - 'fb_dtsg': self._state.fb_dtsg_ag, - 'jazoest': self._state.jazoest, - 'confirmed': 1 - } - - url = '/ajax/photos/photo/delete/dialog.php' + variables = {"feedLocation": "COMET_MEDIA_VIEWER", + "input": {"photo_id": photo_id, "actor_id": self.uid, + "client_mutation_id": self.get_client_mutation_id()}, "isProfilePic": False, "scale": 2, + "renderLocation": None, + "privacySelectorRenderLocation": "COMET_MEDIA_VIEWER", "useDefaultActor": False} try: - res = self._post(url, data) - return {"success": True} - except: - return {"success": False} + res = self.graphql_api('CometMediaViewerPhotoDeleteActionMutation', '3292223457513194', + variables) + if 'errors' in res: + return {'success': False, 'errors': res['errors']} + else: + return {'success': True, 'data': res['data']} + except Exception as e: + return {'success': False, 'errors': str(e)} ###############graph接口 start ############## @@ -2409,6 +2475,13 @@ class FacebookClient(Client): def onWebNotice(self, kwargs): print(kwargs) + def get_client_mutation_id(self): + key = f'{self.uid}:client_mutation_id' + client_mutation_id = cache.get(key=key, default=0) + result = client_mutation_id + 1 + cache.set(key=key, value=client_mutation_id + 1, ttl=24 * 60 * 60) + return str(result) + def graphql_api(self, friendly_name, doc_id, variables: dict, is_mutli_json=False): data = { 'av': self.uid, @@ -2588,7 +2661,7 @@ class FacebookClient(Client): def playGame(self, game_id): payload = { - "input": {"client_mutation_id": f"{int(time.time() * 1000)}:{random.randint(1000000000, 9000000000)}", + "input": {"client_mutation_id": self.get_client_mutation_id(), "actor_id": self.uid, "app_id": game_id, "grant_permissions": ["PUBLIC_INFO", "CONNECTED_PLAYERS", "FRIENDS_CAN_SEE", @@ -2596,7 +2669,7 @@ class FacebookClient(Client): "enable_global_tos": False}} self.graphql_api('InstantGamesRelayPermissions_GrantPermissionsMutation', '1405747992825083', payload) payload = { - "input": {"client_mutation_id": f"{int(time.time() * 1000)}:{random.randint(1000000000, 9000000000)}", + "input": {"client_mutation_id": self.get_client_mutation_id(), "actor_id": self.uid, "game_id": game_id, "request": "QE_PARAM_NO_EXPOSURE_FETCH", "session_id": common.random_uuid(), "sdk_version": "6.3", "data": "{}"}}