├── README.md ├── common_functions.py ├── config.py ├── tinderbase.py └── tindersearcher.py /README.md: -------------------------------------------------------------------------------- 1 | # Tinder-Searcher-and-DB-creation 2 | Tinder Searcher and DB creation - Proof of concept for Tinder security team 3 | 4 | 5 | ## Usage 6 | 7 | ### Database creation 8 | 9 | ``` 10 | python tinderbase.py -m {min age} -M {max age} -d {max distance} 11 | ``` 12 | 13 | ### Searching by name 14 | ``` 15 | python tindersearcher.py -n {name} -m {min age} -M {max age} -d {max distance} 16 | ``` 17 | 18 | 19 | ## Examples 20 | 21 | ### Database creation 22 | ``` 23 | python tinderbase.py -m 29 -M 29 -d 3 24 | ``` 25 | 26 | ### Searching by name 27 | ``` 28 | python tindersearcher.py -n "Ana" -m 25 -M 29 -d 3 29 | ``` 30 | 31 | 32 | ## Requirements 33 | 34 | ``` 35 | sudo pip install pynder robobrowser regex lxml 36 | 37 | sudo pip install --upgrade html5lib beautifulsoup4 38 | ``` 39 | 40 | Comment line 27 in /usr/local/lib/python2.7/dist-packages/pynder/models/user.py file (part of Pynder library): 41 | 42 | ``` 43 | #self.schools_id.extend([school["id"] for school in data['schools']]) 44 | ``` -------------------------------------------------------------------------------- /common_functions.py: -------------------------------------------------------------------------------- 1 | import re, time, os, csv, collections, argparse, pynder, robobrowser, itertools 2 | from optparse import OptionParser 3 | import config as config 4 | 5 | 6 | def get_args_db(): 7 | parser = argparse.ArgumentParser() 8 | parser.add_argument('-m', '--minAge', required=True, action='store', help='Min age') 9 | parser.add_argument('-M', '--maxAge', required=True, action='store', help='Max age') 10 | parser.add_argument('-d', '--maxDistance', required=True, action='store', help='Max distance') 11 | my_args = parser.parse_args() 12 | return my_args 13 | 14 | def get_args_searcher(): 15 | parser = argparse.ArgumentParser() 16 | parser.add_argument('-n', '--name', required=True, action='store', help='Max distance') 17 | parser.add_argument('-m', '--minAge', required=True, action='store', help='Min age') 18 | parser.add_argument('-M', '--maxAge', required=True, action='store', help='Max age') 19 | parser.add_argument('-d', '--maxDistance', required=True, action='store', help='Max distance') 20 | my_args = parser.parse_args() 21 | return my_args 22 | 23 | ### Credits for this function to the Github user Venomous 24 | def createFBToken(email,password): 25 | try: 26 | MOBILE_USER_AGENT = "Mozilla/5.0 (Linux; U; en-gb; KFTHWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.16 Safari/535.19" 27 | FB_AUTH = "https://www.facebook.com/v2.6/dialog/oauth?redirect_uri=fb464891386855067%3A%2F%2Fauthorize%2F&display=touch&state=%7B%22challenge%22%3A%22IUUkEUqIGud332lfu%252BMJhxL4Wlc%253D%22%2C%220_auth_logger_id%22%3A%2230F06532-A1B9-4B10-BB28-B29956C71AB1%22%2C%22com.facebook.sdk_client_state%22%3Atrue%2C%223_method%22%3A%22sfvc_auth%22%7D&scope=user_birthday%2Cuser_photos%2Cuser_education_history%2Cemail%2Cuser_relationship_details%2Cuser_friends%2Cuser_work_history%2Cuser_likes&response_type=token%2Csigned_request&default_audience=friends&return_scopes=true&auth_type=rerequest&client_id=464891386855067&ret=login&sdk=ios&logger_id=30F06532-A1B9-4B10-BB28-B29956C71AB1&ext=1470840777&hash=AeZqkIcf-NEW6vBd" 28 | s = robobrowser.RoboBrowser(user_agent=MOBILE_USER_AGENT, parser="lxml") 29 | s.open(FB_AUTH) 30 | f = s.get_form() 31 | f["pass"] = password 32 | f["email"] = email 33 | s.submit_form(f) 34 | f = s.get_form() 35 | s.submit_form(f, submit=f.submit_fields['__CONFIRM__']) 36 | access_token = re.search(r"access_token=([\w\d]+)", s.response.content.decode()).groups()[0] 37 | return access_token 38 | except: 39 | print("Auth token generation failed") 40 | 41 | 42 | def updateSearch(session,minAge,maxAge,distance): 43 | session.update_profile({ 44 | "gender_filter": 1, 45 | "age_filter_min": minAge, 46 | "age_filter_max": maxAge, 47 | "distance_filter": distance 48 | }) 49 | 50 | 51 | 52 | def changeLocation(session, coord): 53 | session.update_location(coord[0],coord[1]) 54 | time.sleep(20) 55 | 56 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | ### Time between row writing in seconds 2 | timesleeping=1 3 | 4 | ### Facebook account ID - You can check it at https://findmyfbid.com/ 5 | fb_id="" 6 | 7 | ### Facebook account credentials - Needed to generate the auth token. If you have a token you can substitute it in the line FBTOKEN = createFBToken(config.fb_email,config.fb_password) 8 | fb_email="" 9 | fb_password="" 10 | -------------------------------------------------------------------------------- /tinderbase.py: -------------------------------------------------------------------------------- 1 | import re, time, os, csv, collections, datetime, pynder 2 | import common_functions as cf 3 | import config as config 4 | 5 | 6 | 7 | def search(session,timesleeping,csvname): 8 | 9 | req=session.nearby_users() 10 | csvFile = open(csvname, 'a') 11 | csvWriter = csv.writer(csvFile) 12 | csvWriter.writerow(["name","age","id","photos_urls"]) 13 | for user in req: 14 | try: 15 | time.sleep(timesleeping) 16 | csvWriter.writerow([str(user.name.encode("utf-8")), user.age, user.id, user.photos]) 17 | except: 18 | pass 19 | 20 | 21 | def generateCSV(id_,token,timesleeping,csvname): 22 | if id is None or token is None: 23 | print("Facebook ID or Facebook Token not generated correctly") 24 | else: 25 | session = pynder.Session(facebook_id=id_, facebook_token=token) 26 | args = cf.get_args_db() 27 | cf.updateSearch(session,args.minAge,args.maxAge,args.maxDistance) 28 | search(session,timesleeping,csvname) 29 | 30 | 31 | def main(): 32 | CSV_NAME=(str(datetime.datetime.now().date())+".csv") 33 | SLEEP_TIME=config.timesleeping 34 | FBID = config.fb_id 35 | FBTOKEN = cf.createFBToken(config.fb_email,config.fb_password) 36 | generateCSV(FBID,FBTOKEN,SLEEP_TIME,CSV_NAME) 37 | 38 | 39 | if __name__ == "__main__": 40 | main() 41 | -------------------------------------------------------------------------------- /tindersearcher.py: -------------------------------------------------------------------------------- 1 | import re, time, os, csv, collections, pynder 2 | import common_functions as cf 3 | import config as config 4 | 5 | 6 | 7 | def search(session,name,timesleeping): 8 | req=session.nearby_users() 9 | for user in req: 10 | try: 11 | time.sleep(timesleeping) 12 | if (user.name == name): 13 | print("Name: "+str(user.name) ) 14 | # print("Bio: "+str(user.bio.encode("utf-8")) +"\n") 15 | print("Age: "+str(user.age) ) 16 | print("Photos: "+str(user.photos) ) 17 | print("Id: "+str(user.id) ) 18 | print("Distance: "+str(user.distance_km) ) 19 | except: 20 | pass 21 | 22 | 23 | def funct_(id_,token,timesleeping): 24 | if id is None or token is None: 25 | print("Facebook ID or Facebook Token not generated correctly") 26 | else: 27 | session = pynder.Session(facebook_id=id_, facebook_token=token) 28 | args = cf.get_args_searcher() 29 | cf.updateSearch(session,args.minAge,args.maxAge,args.maxDistance) 30 | search(session,args.name,timesleeping) 31 | 32 | 33 | def main(): 34 | SLEEP_TIME=config.timesleeping 35 | FBID = config.fb_id 36 | FBTOKEN = cf.createFBToken(config.fb_email,config.fb_password) 37 | funct_(FBID,FBTOKEN,SLEEP_TIME) 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | --------------------------------------------------------------------------------