Ejemplo n.º 1
0
def youtube_hunt(channel_url):
    banner()

    if not channel_url:
        exit(
            "Please give a valid channel URL.\nExample : https://www.youtube.com/user/PewDiePie"
        )

    if not isfile(config.data_path):
        exit(
            "Please generate cookies and tokens first, with the check_and_gen.py script."
        )

    internal_auth = ""
    internal_token = ""

    cookies = {}

    with open(config.data_path, 'r') as f:
        out = json.loads(f.read())
        internal_auth = out["internal_auth"]
        internal_token = out["keys"]["internal"]
        cookies = out["cookies"]

    if not "PREF" in cookies:
        pref_cookies = {
            "PREF": "tz=Europe.Paris&f6=40000000&hl=en"
        }  # To set the lang in english
        cookies = {**cookies, **pref_cookies}

    client = httpx.Client(cookies=cookies, headers=config.headers)

    is_within_docker = within_docker()
    if is_within_docker:
        print("[+] Docker detected, profile pictures will not be saved.")

    geolocator = Nominatim(user_agent="nominatim")

    print("\n📌 [Youtube channel]")

    channel_data = ytb.get_channel_data(client, channel_url)
    if channel_data:
        is_channel_existing = True
        print(f'[+] Channel name : {channel_data["name"]}\n')
    else:
        is_channel_existing = False
        print(
            "[-] Channel not found.\nSearching for a trace in the archives...\n"
        )

        channel_data = {
            "name": None,
            "description": None,
            "channel_urls": [channel_url],
            "email_contact": False,
            "views": None,
            "joined_date": None,
            "primary_links": [],
            "country": None
        }

    wb_client = wayback.WaybackClient()
    gaiaID = launch_checks(client, wb_client, channel_data)
    if gaiaID:
        print(f"[+] GaiaID => {gaiaID}\n")
    else:
        print("[-] No interesting snapshot found.\n")

    if is_channel_existing:
        if channel_data["email_contact"]:
            print(f'[+] Email on profile : available !')
        else:
            print(f'[-] Email on profile : not available.')
        if channel_data["country"]:
            print(f'[+] Country : {channel_data["country"]}')
        print()
        if channel_data["description"]:
            print(f'🧬 Description : {channel_data["description"]}')
        if channel_data["views"]:
            print(f'🧬 Total views : {channel_data["views"]}')
        if channel_data["joined_date"]:
            print(f'🧬 Joined date : {channel_data["joined_date"]}')

        if channel_data["primary_links"]:
            print(
                f'\n[+] Primary links ({len(channel_data["primary_links"])} found)'
            )
            for primary_link in channel_data["primary_links"]:
                print(f'- {primary_link["title"]} => {primary_link["url"]}')

    if not gaiaID:
        exit()

    print("\n📌 [Google account]")
    # get name & profile picture
    account = get_account_data(client, gaiaID, internal_auth, internal_token,
                               config)
    name = account["name"]

    if name:
        print(f"Name : {name}")

    # profile picture
    profile_pic_url = account.get(
        "profile_pics") and account["profile_pics"][0].url
    req = client.get(profile_pic_url)

    profile_pic_img = Image.open(BytesIO(req.content))
    profile_pic_hash = image_hash(profile_pic_img)
    is_default_profile_pic = detect_default_profile_pic(profile_pic_hash)

    if profile_pic_url:
        req = client.get(profile_pic_url)

        # TODO: make sure it's necessary now
        profile_pic_img = Image.open(BytesIO(req.content))
        profile_pic_flathash = image_hash(profile_pic_img)
        is_default_profile_pic = detect_default_profile_pic(
            profile_pic_flathash)

        if not is_default_profile_pic:
            print("\n[+] Custom profile picture !")
            print(f"=> {profile_pic_url}")
            if config.write_profile_pic and not is_within_docker:
                open(Path(config.profile_pics_dir) / f'{gaiaID}.jpg',
                     'wb').write(req.content)
                print("Profile picture saved !")
        else:
            print("\n[-] Default profile picture")

    # cover profile picture
    cover_pic = account.get("cover_pics") and account["cover_pics"][0]
    if cover_pic and not cover_pic.is_default:
        cover_pic_url = cover_pic.url
        req = client.get(cover_pic_url)

        print("\n[+] Custom profile cover picture !")
        print(f"=> {cover_pic_url}")
        if config.write_profile_pic and not is_within_docker:
            open(Path(config.profile_pics_dir) / f'cover_{gaiaID}.jpg',
                 'wb').write(req.content)
            print("Cover profile picture saved !")

    # reviews
    reviews = gmaps.scrape(gaiaID, client, cookies, config, config.headers,
                           config.regexs["review_loc_by_id"], config.headless)

    if reviews:
        confidence, locations = gmaps.get_confidence(geolocator, reviews,
                                                     config.gmaps_radius)
        print(f"\n[+] Probable location (confidence => {confidence}) :")

        loc_names = []
        for loc in locations:
            loc_names.append(
                f"- {loc['avg']['town']}, {loc['avg']['country']}")

        loc_names = set(loc_names)  # delete duplicates
        for loc in loc_names:
            print(loc)
Ejemplo n.º 2
0
		req = client.get(profil_pic)
		img = Image.open(BytesIO(req.content))
		hash = image_hash(img)
		data = ytb.get_channels(client, name, cfg)
		if not data:
			print("\nYoutube channel not found.")
		else:
			confidence, channels = ytb.get_confidence(data, name, hash)
			if confidence:
				print(f"\nYoutube channel (confidence => {confidence}%) :")
				for channel in channels:
					print(f"- [{channel['name']}] {channel['profil_url']}")
				possible_usernames = ytb.extract_usernames(channels)
				if possible_usernames:
					print("\nPossible usernames found :")
					for username in possible_usernames:
						print(f"- {username}")
			else:
				print("\nYoutube channel not found.")

	gpics(gaiaID, client, cookies, cfg)
	reviews = gmaps.scrape(gaiaID, client, cookies, cfg)
	if reviews:
		confidence, locations = gmaps.get_confidence(reviews, cfg)
		print(f"\nProbable location (confidence => {confidence}) :")
		loc_names = []
		for loc in locations:
			loc_names.append(f"- {loc['avg']['town']}, {loc['avg']['country']}")
		loc_names = set(loc_names) # We delete duplicates
		for loc in loc_names:
			print(loc)
Ejemplo n.º 3
0
                for channel in channels:
                    print(f"- [{channel['name']}] {channel['profile_url']}")
                possible_usernames = ytb.extract_usernames(channels)
                if possible_usernames:
                    print("\nPossible usernames found :")
                    for username in possible_usernames:
                        print(f"- {username}")
            else:
                print("\nYouTube channel not found.")

        # TODO: return gpics function output here
        gpics(gaiaID, client, cookies, config.headers, config.regexs["albums"], config.regexs["photos"],
              config.headless)

        # reviews
        reviews = gmaps.scrape(gaiaID, client, cookies, config.headers, config.regexs["review_loc_by_id"], config.headless)

        if reviews:
            confidence, locations = gmaps.get_confidence(reviews, config.gmaps_radius)
            print(f"\nProbable location (confidence => {confidence}) :")

            loc_names = []
            for loc in locations:
                loc_names.append(
                    f"- {loc['avg']['town']}, {loc['avg']['country']}"
                )

            loc_names = set(loc_names)  # delete duplicates
            for loc in loc_names:
                print(loc)
Ejemplo n.º 4
0
def gaia_hunt(gaiaID):
    banner()

    if not gaiaID:
        exit("Please give a valid GaiaID.\nExample : 113127526941309521065")

    if not isfile(config.data_path):
        exit(
            "Please generate cookies and tokens first, with the check_and_gen.py script."
        )

    internal_auth = ""
    internal_token = ""

    cookies = {}

    with open(config.data_path, 'r') as f:
        out = json.loads(f.read())
        internal_auth = out["internal_auth"]
        internal_token = out["keys"]["internal"]
        cookies = out["cookies"]

    client = httpx.Client(cookies=cookies, headers=config.headers)

    account = get_account_data(client, gaiaID, internal_auth, internal_token,
                               config)
    if not account:
        exit("[-] No account linked to this Gaia ID.")

    is_within_docker = within_docker()
    if is_within_docker:
        print("[+] Docker detected, profile pictures will not be saved.")

    geolocator = Nominatim(user_agent="nominatim")

    # get name & profile picture

    name = account["name"]

    if name:
        print(f"Name : {name}")

    # profile picture
    profile_pic_url = account["profile_pic_url"]
    req = client.get(profile_pic_url)

    profile_pic_img = Image.open(BytesIO(req.content))
    profile_pic_hash = image_hash(profile_pic_img)
    is_default_profile_pic = detect_default_profile_pic(profile_pic_hash)

    if not is_default_profile_pic and not is_within_docker:
        print("\n[+] Custom profile picture !")
        print(f"=> {profile_pic_url}")
        if config.write_profile_pic and not is_within_docker:
            open(Path(config.profile_pics_dir) / f'{gaiaID}.jpg',
                 'wb').write(req.content)
            print("Profile picture saved !")
    else:
        print("\n[-] Default profile picture")

    print(f"\nGaia ID : {gaiaID}")

    # check YouTube
    if name:
        confidence = None
        data = ytb.get_channels(client, name, config.data_path,
                                config.gdocs_public_doc)
        if not data:
            print("\n[-] YouTube channel not found.")
        else:
            confidence, channels = ytb.get_confidence(data, name,
                                                      profile_pic_hash)

            if confidence:
                print(f"\n[+] YouTube channel (confidence => {confidence}%) :")
                for channel in channels:
                    print(f"- [{channel['name']}] {channel['profile_url']}")
                possible_usernames = ytb.extract_usernames(channels)
                if possible_usernames:
                    print("\n[+] Possible usernames found :")
                    for username in possible_usernames:
                        print(f"- {username}")
            else:
                print("\n[-] YouTube channel not found.")

    # reviews
    reviews = gmaps.scrape(gaiaID, client, cookies, config, config.headers,
                           config.regexs["review_loc_by_id"], config.headless)

    if reviews:
        confidence, locations = gmaps.get_confidence(geolocator, reviews,
                                                     config.gmaps_radius)
        print(f"\n[+] Probable location (confidence => {confidence}) :")

        loc_names = []
        for loc in locations:
            loc_names.append(
                f"- {loc['avg']['town']}, {loc['avg']['country']}")

        loc_names = set(loc_names)  # delete duplicates
        for loc in loc_names:
            print(loc)
Ejemplo n.º 5
0
def email_hunt(email):
    banner()

    if not email:
        exit("Please give a valid email.\nExample : [email protected]")

    if not isfile(config.data_path):
        exit(
            "Please generate cookies and tokens first, with the check_and_gen.py script."
        )

    hangouts_auth = ""
    hangouts_token = ""
    internal_auth = ""
    internal_token = ""

    cookies = {}

    with open(config.data_path, 'r') as f:
        out = json.loads(f.read())
        hangouts_auth = out["hangouts_auth"]
        hangouts_token = out["keys"]["hangouts"]
        internal_auth = out["internal_auth"]
        internal_token = out["keys"]["internal"]
        cookies = out["cookies"]

    client = httpx.Client(cookies=cookies, headers=config.headers)

    data = is_email_google_account(client, hangouts_auth, cookies, email,
                                   hangouts_token)

    is_within_docker = within_docker()
    if is_within_docker:
        print("[+] Docker detected, profile pictures will not be saved.")

    geolocator = Nominatim(user_agent="nominatim")
    print(f"[+] {len(data['matches'])} account found !")

    for user in data["matches"]:
        print("\n------------------------------\n")

        gaiaID = user["personId"][0]
        email = user["lookupId"]
        infos = data["people"][gaiaID]

        # get name
        name = get_account_name(client, gaiaID, internal_auth, internal_token,
                                cookies, config)
        if name:
            print(f"Name : {name}")
        else:
            if "name" not in infos:
                print("[-] Couldn't find name")
            else:
                for i in range(len(infos["name"])):
                    if 'displayName' in infos['name'][i].keys():
                        name = infos["name"][i]["displayName"]
                        print(f"Name : {name}")

        # profile picture
        profile_pic_link = infos["photo"][0]["url"]
        req = client.get(profile_pic_link)

        profile_pic_img = Image.open(BytesIO(req.content))
        profile_pic_hash = image_hash(profile_pic_img)
        is_default_profile_pic = detect_default_profile_pic(profile_pic_hash)

        if not is_default_profile_pic and not is_within_docker:
            print("\n[+] Custom profile picture !")
            print(f"=> {profile_pic_link}")
            if config.write_profile_pic and not is_within_docker:
                open(Path(config.profile_pics_dir) / f'{email}.jpg',
                     'wb').write(req.content)
                print("Profile picture saved !")
        else:
            print("\n[-] Default profile picture")

        # last edit
        try:
            timestamp = int(infos["metadata"]["lastUpdateTimeMicros"][:-3])
            last_edit = datetime.utcfromtimestamp(timestamp).strftime(
                "%Y/%m/%d %H:%M:%S (UTC)")
            print(f"\nLast profile edit : {last_edit}")
        except KeyError:
            last_edit = None
            print(f"\nLast profile edit : Not found")
        print(f"\nEmail : {email}\nGoogle ID : {gaiaID}\n")

        # is bot?
        profile_pic = infos["photo"][0]["url"]
        if "extendedData" in infos:
            isBot = infos["extendedData"]["hangoutsExtendedData"]["isBot"]
            if isBot:
                print("Hangouts Bot : Yes !")
            else:
                print("Hangouts Bot : No")
        else:
            print("Hangouts Bot : Unknown")

        # decide to check YouTube
        ytb_hunt = False
        try:
            services = [
                x["appType"].lower()
                if x["appType"].lower() != "babel" else "hangouts"
                for x in infos["inAppReachability"]
            ]
            if name and (config.ytb_hunt_always or "youtube" in services):
                ytb_hunt = True
            print("\n[+] Activated Google services :")
            print('\n'.join(["- " + x.capitalize() for x in services]))

        except KeyError:
            ytb_hunt = True
            print("\n[-] Unable to fetch connected Google services.")

        # check YouTube
        if name and ytb_hunt:
            confidence = None
            data = ytb.get_channels(client, name, config.data_path,
                                    config.gdocs_public_doc)
            if not data:
                print("\n[-] YouTube channel not found.")
            else:
                confidence, channels = ytb.get_confidence(
                    data, name, profile_pic_hash)

                if confidence:
                    print(
                        f"\n[+] YouTube channel (confidence => {confidence}%) :"
                    )
                    for channel in channels:
                        print(
                            f"- [{channel['name']}] {channel['profile_url']}")
                    possible_usernames = ytb.extract_usernames(channels)
                    if possible_usernames:
                        print("\n[+] Possible usernames found :")
                        for username in possible_usernames:
                            print(f"- {username}")
                else:
                    print("\n[-] YouTube channel not found.")

        # TODO: return gpics function output here
        #gpics(gaiaID, client, cookies, config.headers, config.regexs["albums"], config.regexs["photos"],
        #      config.headless)

        # reviews
        reviews = gmaps.scrape(gaiaID, client, cookies, config, config.headers,
                               config.regexs["review_loc_by_id"],
                               config.headless)

        if reviews:
            confidence, locations = gmaps.get_confidence(
                reviews, config.gmaps_radius)
            print(f"\n[+] Probable location (confidence => {confidence}) :")

            loc_names = []
            for loc in locations:
                loc_names.append(
                    f"- {loc['avg']['town']}, {loc['avg']['country']}")

            loc_names = set(loc_names)  # delete duplicates
            for loc in loc_names:
                print(loc)

    # Google Calendar
        calendar_response = gcalendar.fetch(email, client, config)
        if calendar_response:
            print("[+] Public Google Calendar found !")
            events = calendar_response["events"]
            if events:
                gcalendar.out(events)
            else:
                print("=> No recent events found.")
        else:
            print("[-] No public Google Calendar.")
Ejemplo n.º 6
0
def user_extract(user, data, client, internal_auth, internal_token, cookies,
                 items):
    res = {}
    gaiaID = user["personId"][0]
    email = user["lookupId"]
    infos = data["people"][gaiaID]

    user_base = {}

    # get name
    name = get_account_name(client, gaiaID, internal_auth, internal_token,
                            cookies, config)
    if name:
        user_base['user_name'] = name
    else:
        if "name" not in infos:
            print("[-] Couldn't find name")
        else:
            for i in range(len(infos["name"])):
                if 'displayName' in infos['name'][i].keys():
                    name = infos["name"][i]["displayName"]
                    user_base['user_name'] = name

    # profile picture

    # last edit
    try:
        timestamp = int(infos["metadata"]["lastUpdateTimeMicros"][:-3])
        # last_edit = datetime.utcfromtimestamp(timestamp).strftime("%Y/%m/%d %H:%M:%S (UTC)")
        user_base['last_profile_update_time'] = datetime.fromtimestamp(
            timestamp)
        # print(f"\nLast profile edit : {last_edit}")
    except KeyError:
        user_base['last_profile_update_time'] = None
    user_base['google_id'] = gaiaID

    maps_crawler = True
    youtube_crawler = True
    calendar_crawler = True
    if items:
        if 'maps' not in items:
            maps_crawler = False
        if 'youtube' not in items:
            youtube_crawler = False
        if 'calendar' not in items:
            calendar_crawler = False

    # if hangout_crawler:
    profile_pic_link = infos["photo"][0]["url"]
    req = client.get(profile_pic_link)

    profile_pic_img = Image.open(BytesIO(req.content))
    profile_pic_hash = image_hash(profile_pic_img)
    is_default_profile_pic = detect_default_profile_pic(profile_pic_hash)
    # 判断是否是默认头像
    user_base['is_default_profile_pic'] = is_default_profile_pic
    user_base['profile_imag_url'] = profile_pic_link

    # is bot?
    # profile_pic = infos["photo"][0]["url"]
    # res['hangout_profile_image_url'] = profile_pic
    if "extendedData" in infos:
        isBot = infos["extendedData"]["hangoutsExtendedData"]["isBot"]
        if isBot:
            user_base['is_hangout_bot'] = True
        else:
            user_base['is_hangout_bot'] = False
    else:
        user_base['is_hangout_bot'] = None

    # decide to check YouTube
    ytb_hunt = False
    try:
        services = [
            x["appType"].lower()
            if x["appType"].lower() != "babel" else "hangouts"
            for x in infos["inAppReachability"]
        ]
        if name and (config.ytb_hunt_always or "youtube" in services):
            ytb_hunt = True
        user_base['activated_google_services'] = [
            x.capitalize() for x in services
        ]

    except KeyError:
        ytb_hunt = True
        user_base['activated_google_services'] = []

    res['user_base'] = user_base

    # check YouTube
    if youtube_crawler:
        youtube = {
            'channel': [],
            'confidence': None,
            'possible_user_names': []
        }
        if name and ytb_hunt:
            data = ytb.get_channels(client, name, config.data_path,
                                    config.gdocs_public_doc)
            if not data:
                pass
            else:
                confidence, channels = ytb.get_confidence(
                    data, name, profile_pic_hash)
                youtube['confidence'] = confidence

                if confidence:
                    for channel in channels:
                        youtube['channel'].append({
                            'name':
                            channel['name'],
                            'profile_url':
                            channel['profile_url'],
                        })
                    possible_usernames = ytb.extract_usernames(channels)
                    if possible_usernames:
                        youtube['possible_user_names'] = possible_usernames

        res['youtube'] = youtube

    # TODO: return gpics function output here
    # gpics(gaiaID, client, cookies, config.headers, config.regexs["albums"], config.regexs["photos"],
    #      config.headless)

    # reviews
    if maps_crawler:
        reviews = gmaps.scrape(gaiaID, client, cookies, config, config.headers,
                               config.regexs["review_loc_by_id"],
                               config.headless)
        maps = {'confidence': None, 'location_names': []}
        if reviews:
            confidence, locations = gmaps.get_confidence(
                reviews, config.gmaps_radius)
            loc_names = []
            for loc in locations:
                loc_names.append(
                    f"{loc['avg']['town']},{loc['avg']['country']}")
            loc_names = set(loc_names)  # delete duplicates
            maps['loc_names'] = list(loc_names)

        res['maps'] = maps

    # Google Calendar
    if calendar_crawler:
        calendar_response = gcalendar.fetch(email, client, config)
        res['calendar'] = calendar_response if calendar_response else {
            "status": False,
            "events": []
        }
    return res