作者 lemon

更新与新增接口

@@ -145,3 +145,15 @@ class Executor(): @@ -145,3 +145,15 @@ class Executor():
145 'next_url': 'https://www.facebook.com' + next_url if next_url else None 145 'next_url': 'https://www.facebook.com' + next_url if next_url else None
146 } 146 }
147 return data 147 return data
  148 +
  149 + def fetchUserInfo(self, fbid_list):
  150 + if not isinstance(fbid_list, (tuple, list)):
  151 + raise BaseException("fbid_list 参数要求是文本型列表")
  152 + users = self.client.fetchUserInfo(*fbid_list)
  153 + keys = ['type', 'gender', 'is_friend', 'name', 'photo', 'uid', 'url']
  154 + objects = []
  155 + for _, u in users.items():
  156 + info = common.todict(u, include=keys)
  157 + info['type'] = info.get('type').name
  158 + objects.append(info)
  159 + return objects
@@ -5,7 +5,6 @@ @@ -5,7 +5,6 @@
5 # @File : facebook.py 5 # @File : facebook.py
6 # @Software: PyCharm 6 # @Software: PyCharm
7 import base64 7 import base64
8 -import itertools  
9 import json 8 import json
10 import os 9 import os
11 import random 10 import random
@@ -335,7 +334,9 @@ class FacebookClient(Client): @@ -335,7 +334,9 @@ class FacebookClient(Client):
335 data = {'current_city_text': city_name, 'current_city': city_id, 334 data = {'current_city_text': city_name, 'current_city': city_id,
336 'privacy[8787650733]': PostParam.EVERYONE.value} 335 'privacy[8787650733]': PostParam.EVERYONE.value}
337 res = self._post('/profile/async/edit/infotab/save/current_city/', data) 336 res = self._post('/profile/async/edit/infotab/save/current_city/', data)
338 - return res 337 + if city_id in res['domops'][0][3]['__html']:
  338 + return {"success": True}
  339 + return {"success": False}
339 340
340 def setHometown(self, city_id, city_name): 341 def setHometown(self, city_id, city_name):
341 ''' 342 '''
@@ -345,7 +346,9 @@ class FacebookClient(Client): @@ -345,7 +346,9 @@ class FacebookClient(Client):
345 'nctr[_mod]': 'pagelet_hometown', 346 'nctr[_mod]': 'pagelet_hometown',
346 'privacy[8787655733]': PostParam.EVERYONE.value} 347 'privacy[8787655733]': PostParam.EVERYONE.value}
347 res = self._post("/profile/async/edit/infotab/save/hometown/", data) 348 res = self._post("/profile/async/edit/infotab/save/hometown/", data)
348 - return res 349 + if city_id in res['domops'][0][3]['__html']:
  350 + return {"success": True}
  351 + return {"success": False}
349 352
350 def setGender(self, gender: str): 353 def setGender(self, gender: str):
351 ''' 354 '''
@@ -357,7 +360,7 @@ class FacebookClient(Client): @@ -357,7 +360,7 @@ class FacebookClient(Client):
357 res = self._post('/profile/edit/infotab/save/gender/', data) 360 res = self._post('/profile/edit/infotab/save/gender/', data)
358 361
359 html = parse_html.get_domops_3(res) 362 html = parse_html.get_domops_3(res)
360 - if 'Gender' in html: 363 + if 'gender' in html:
361 return {"success": True} 364 return {"success": True}
362 else: 365 else:
363 raise BaseException("未知错误:", html) 366 raise BaseException("未知错误:", html)
@@ -734,10 +737,15 @@ class FacebookClient(Client): @@ -734,10 +737,15 @@ class FacebookClient(Client):
734 def get_user_agent(self): 737 def get_user_agent(self):
735 return self._state._session.headers.get('User-Agent', random.choice(_util.USER_AGENTS)) 738 return self._state._session.headers.get('User-Agent', random.choice(_util.USER_AGENTS))
736 739
737 - def searchForUserByFilter(self, ext_data=None): 740 + def searchForUserByFilter(self, name, city_id, ext_data=None):
738 if not ext_data: 741 if not ext_data:
  742 + from urllib import parse
  743 + tob64 = lambda x: str(base64.b64encode(x.encode('utf-8')), 'utf-8')
  744 + filter = json.dumps({'city': json.dumps({"name": "users_location", "args": str(city_id)})})
  745 + b64 = tob64(filter)
  746 +
739 r = self._state._session.get( 747 r = self._state._session.get(
740 - 'https://www.facebook.com/search/people/?q=%E5%B1%B1%E4%B8%8B&epa=FILTERS&filters=eyJjaXR5Ijoie1wibmFtZVwiOlwidXNlcnNfbG9jYXRpb25cIixcImFyZ3NcIjpcIjEwNjUxNDAwNjA1MzI1MFwifSJ9') 748 + f'https://www.facebook.com/search/people/?q={parse.quote(name)}&epa=FILTERS&filters={b64}')
741 fbid = parse_html.get_all_raw_id(r.text) 749 fbid = parse_html.get_all_raw_id(r.text)
742 750
743 global_data = re.findall(r'globalData:(\{.*?display_params.*?\}),prefetchPixels', r.text)[0] 751 global_data = re.findall(r'globalData:(\{.*?display_params.*?\}),prefetchPixels', r.text)[0]
@@ -758,10 +766,60 @@ class FacebookClient(Client): @@ -758,10 +766,60 @@ class FacebookClient(Client):
758 pass 766 pass
759 767
760 fbid = parse_html.get_all_raw_id(res['payload']) 768 fbid = parse_html.get_all_raw_id(res['payload'])
761 - if fbid and 'page_number' not in ext_data:  
762 - ext_data = None  
763 - # 无更多了  
764 return { 769 return {
765 'fbid_list': fbid, 770 'fbid_list': fbid,
766 'ext_data': ext_data, 771 'ext_data': ext_data,
767 } 772 }
  773 +
  774 + def changePwd(self, old, new):
  775 + data = {
  776 + 'recommended': False,
  777 + 'fb_dtsg_ag': self._state.fb_dtsg_ag,
  778 + }
  779 + res = self._state._get('/settings/security/password/', data, 0)
  780 + data = parse_html.get_hidden_input(res)
  781 + assert 'password_change_session_identifier' in data, '参数不足:session_identifier未获取到'
  782 + data.update({
  783 + "password_strength": 2,
  784 + 'password_old': old,
  785 + 'password_new': new,
  786 + 'password_confirm': new,
  787 + })
  788 + res = self._post('/ajax/settings/security/password.php', data)
  789 + title = res['jsmods']['require'][0][0]
  790 + if title == 'SecuritySettingsPasswordErrorHandler':
  791 + html = res['jsmods']['require'][0][3][0]['__html']
  792 + error = parse_html.get_div_text(html)
  793 + return {'success': False, 'error': error}
  794 + elif title == 'JSPasswordChangeReason':
  795 + return {'success': True, 'error': None}
  796 + else:
  797 + raise BaseException('未知错误:' + json.dumps(res['jsmods']['require']))
  798 +
  799 + def setFriendListPrivate(self, value):
  800 + value = PostParam.__dict__.get(value).value
  801 + data = {'privacy_fbid': '8787365733', 'post_param': value, 'render_location_enum': 'settings',
  802 + 'is_saved_on_select': 'true', 'should_return_tooltip': 'false',
  803 + 'prefix_tooltip_with_app_privacy': 'false', 'ent_id': '0', 'user_id': self._uid}
  804 + self._post('https://www.facebook.com/privacy/selector/update?' + self._to_url_params(data), {})
  805 + data = {
  806 + 'post_param': value,
  807 + 'value': value,
  808 + 'saved_custom_opt_in': True,
  809 + }
  810 + res = self._post('/ajax/settings/granular_privacy/friendlist.php', data)
  811 + if 'fbSettingsListItem' in res['domops'][0][1]:
  812 + return {"success": True}
  813 + return {"success": False}
  814 +
  815 + def setCanFriendReq(self, value):
  816 + value = PostParam.__dict__.get(value).value
  817 + data = {'privacy_fbid': '8787540733', 'post_param': value, 'render_location_enum': 'settings',
  818 + 'is_saved_on_select': True, 'should_return_tooltip': 'false',
  819 + 'prefix_tooltip_with_app_privacy': False, 'ent_id': '0', 'user_id': self.uid}
  820 + self._post('/privacy/selector/update/?' + self._to_url_params(data), {})
  821 + data = {'post_param': value, 'saved_custom_opt_in': 'true', 'value': value}
  822 + res = self._post('/ajax/settings/granular_privacy/can_friend_req.php', data)
  823 + if 'fbSettingsListItem' in res['domops'][0][1]:
  824 + return {"success": True}
  825 + return {"success": False}
@@ -159,6 +159,22 @@ def get_all_raw_id(text): @@ -159,6 +159,22 @@ def get_all_raw_id(text):
159 fbids = list(set(fbids)) 159 fbids = list(set(fbids))
160 else: 160 else:
161 r = re.compile(r'\\"raw_id\\":(\d+),') 161 r = re.compile(r'\\"raw_id\\":(\d+),')
162 - key=r.findall(text) 162 + key = r.findall(text)
163 fbids.extend(key) 163 fbids.extend(key)
164 return fbids 164 return fbids
  165 +
  166 +
  167 +def get_hidden_input(res):
  168 + text = get_domops_3(res)
  169 + b = bs4.BeautifulSoup(text, 'html.parser')
  170 + ins = [x.attrs for x in b.find_all('input', type='hidden')]
  171 +
  172 + args = {}
  173 + for x in ins:
  174 + if 'name' in x and 'value' in x:
  175 + args.update({x['name']: x['value']})
  176 + return args
  177 +
  178 +def get_div_text(html):
  179 + b = bs4.BeautifulSoup(html, 'html.parser')
  180 + return b.text