예제 #1
0
class ItsAGramLive:
    ig: InstagramAPI = None
    previewWidth: int = 1080
    previewHeight: int = 1920
    broadcastMessage: str = ""
    sendNotification: bool = True
    share_to_story: bool = False
    last_comment_ts: int = 1

    def __init__(self):
        parser = argparse.ArgumentParser(add_help=True)
        parser.add_argument("-u", "--username", type=str, help="username", required=True)
        parser.add_argument("-p", "--password", type=str, help="password", required=True)
        parser.add_argument("-share", type=bool, help="Share to Story after ended", default=self.share_to_story)
        parser.add_argument("-proxy", type=str, help="Proxy format - user:password@ip:port", default=None)
        args = parser.parse_args()

        self.share_to_story = args.share
        self.ig = InstagramAPI(username=args.username, password=args.password)

        self.ig.setProxy(proxy=args.proxy)

    def create_broadcast(self):
        if self.ig.login():
            data = json.dumps({'_uuid': self.ig.uuid,
                               '_uid': self.ig.username_id,
                               'preview_height': self.previewHeight,
                               'preview_width': self.previewWidth,
                               'broadcast_message': self.broadcastMessage,
                               'broadcast_type': 'RTMP',
                               'internal_only': 0,
                               '_csrftoken': self.ig.token})

            if self.ig.SendRequest(endpoint='live/create/', post=self.ig.generateSignature(data)):
                last_json = self.ig.LastJson
                broadcast_id = last_json['broadcast_id']
                upload_url = last_json['upload_url']

                splited = upload_url.split(str(broadcast_id))

                stream_key = "{}{}".format(str(broadcast_id), splited[1])

                server = splited[0]

                print("Server: {}".format(server))
                pyperclip.copy(stream_key)
                print("Stream Key (copied to clipboard): {}".format(stream_key))

            else:
                return False

        else:
            return False

        return broadcast_id

    def start_broadcast(self, broadcast_id):
        data = json.dumps({'_uuid': self.ig.uuid,
                           '_uid': self.ig.username_id,
                           'should_send_notifications': int(self.sendNotification),
                           '_csrftoken': self.ig.token})

        if self.ig.SendRequest(endpoint='live/' + str(broadcast_id) + '/start/', post=self.ig.generateSignature(data)):

            print('CTRL+C to quit.')
            spinner = Spinner(" - ")
            try:
                while True:
                    spinner.next()
            except KeyboardInterrupt:
                spinner.finish()
                pass
            except Exception as error:
                print(error)
                self.end_broadcast(broadcast_id)

    def end_broadcast(self, broadcast_id):
        data = json.dumps({'_uuid': self.ig.uuid, '_uid': self.ig.username_id, '_csrftoken': self.ig.token})
        if self.ig.SendRequest(endpoint='live/' + str(broadcast_id) + '/end_broadcast/',
                               post=self.ig.generateSignature(data)):
            if self.share_to_story:
                self.ig.SendRequest(endpoint='live/' + str(broadcast_id) + '/add_to_post_live/',
                                    post=self.ig.generateSignature(data))

        print('Ending Broadcasting')
class Osintgram:
    api = None
    geolocator = Nominatim()
    user_id = None
    target_id = None
    is_private = True
    target = ""
    writeFile = False

    def __init__(self, target):
        u = self.__getUsername__()
        p = self.__getPassword__()
        self.api = InstagramAPI(u, p)
        print("\nAttempt to login...")
        self.api.login()
        self.setTarget(target)

    def setTarget(self, target):
        self.target = target
        user = self.getUser(target)
        self.target_id = user['id']
        self.is_private = user['is_private']
        self.__printTargetBanner__()

    def __getUsername__(self):
        u = open("config/username.conf", "r").read()
        u = u.replace("\n", "")
        return u

    def __getPassword__(self):
        p = open("config/pw.conf", "r").read()
        p = p.replace("\n", "")
        return p

    def __getAdressesTimes__(self, id):
        only_id = {}
        photos = []
        a = None
        while True:
            if (a == None):
                self.api.getUserFeed(id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson
            else:
                self.api.getUserFeed(id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']

            photos.append(a)

            if not 'next_max_id' in only_id:
                break

        locations = {}

        for i in photos:
            for j in i:
                if 'lat' in j.keys():
                    lat = j.get('lat')
                    lng = j.get('lng')

                    locations[str(lat) + ', ' + str(lng)] = j.get('taken_at')

        address = {}
        for k, v in locations.items():
            details = self.geolocator.reverse(k)
            unix_timestamp = datetime.datetime.fromtimestamp(v)
            address[details.address] = unix_timestamp.strftime(
                '%Y-%m-%d %H:%M:%S')

        sort_addresses = sorted(address.items(),
                                key=lambda p: p[1],
                                reverse=True)

        return sort_addresses

    def __printTargetBanner__(self):
        pc.printout("\nLogged as ", pc.GREEN)
        pc.printout(self.api.username, pc.CYAN)
        pc.printout(" (" + str(self.api.username_id) + ") ")
        pc.printout("target: ", pc.GREEN)
        pc.printout(str(self.target), pc.CYAN)
        pc.printout(" (private: " + str(self.is_private) + ")")
        print('\n')

    def setWriteFile(self, bool):
        if (bool):
            pc.printout("Write to file: ")
            pc.printout("enabled", pc.GREEN)
            pc.printout("\n")
        else:
            pc.printout("Write to file: ")
            pc.printout("disabled", pc.RED)
            pc.printout("\n")

        self.writeFile = bool

    def __getUserFollowigs__(self, id):
        following = []
        next_max_id = True
        while next_max_id:
            # first iteration hack
            if next_max_id is True:
                next_max_id = ''
            _ = self.api.getUserFollowings(id, maxid=next_max_id)
            following.extend(self.api.LastJson.get('users', []))
            next_max_id = self.api.LastJson.get('next_max_id', '')

        len(following)
        unique_following = {f['pk']: f for f in following}
        len(unique_following)
        return following

    def __getTotalFollowers__(self, user_id):
        followers = []
        next_max_id = True
        while next_max_id:
            # first iteration hack
            if next_max_id is True:
                next_max_id = ''

            _ = self.api.getUserFollowers(user_id, maxid=next_max_id)
            followers.extend(self.api.LastJson.get('users', []))
            next_max_id = self.api.LastJson.get('next_max_id', '')

        return followers

    def getHashtags(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target hashtags...\n")

        text = []
        only_id = {}
        a = None
        hashtags = []
        counter = 1
        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson
                with open('data.json', 'w') as outfile:
                    json.dump(only_id, outfile)

            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']

            try:
                for i in a:
                    c = i.get('caption', {}).get('text')
                    text.append(c)
                    counter = counter + 1
            except AttributeError:
                pass

            if not 'next_max_id' in only_id:
                break

        hashtag_counter = {}

        for i in text:
            for j in i.split():
                if j.startswith('#'):
                    hashtags.append(j.encode('UTF-8'))

        for i in hashtags:
            if i in hashtag_counter:
                hashtag_counter[i] += 1
            else:
                hashtag_counter[i] = 1

        sortE = sorted(hashtag_counter.items(),
                       key=lambda value: value[1],
                       reverse=True)

        if (self.writeFile):
            file_name = "output/" + self.target + "_hashtags.txt"
            file = open(file_name, "w")
            for k, v in sortE:
                file.write(str(v) + ". " + str(k.decode('utf-8')) + "\n")
            file.close()

        for k, v in sortE:
            print(str(v) + ". " + str(k.decode('utf-8')))

    def getTotalLikes(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target total likes...\n")

        like_counter = 0
        only_id = {}
        a = None
        counter = 0
        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson
            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']
            try:
                for i in a:
                    c = int(i.get('like_count'))
                    like_counter += c
                    counter = counter + 1
            except AttributeError:
                pass

            if not 'next_max_id' in only_id:
                break

        if (self.writeFile):
            file_name = "output/" + self.target + "_likes.txt"
            file = open(file_name, "w")
            file.write(
                str(like_counter) + " likes in " + str(counter) + " posts\n")
            file.close()

        pc.printout(str(like_counter), pc.MAGENTA)
        pc.printout(" likes in " + str(counter) + " posts\n")

    def getTotalComments(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target total comments...\n")

        comment_counter = 0
        only_id = {}
        a = None
        counter = 0
        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson
            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']
            try:
                for i in a:
                    c = int(i.get('comment_count'))
                    comment_counter += c
                    counter = counter + 1
            except AttributeError:
                pass

            if not 'next_max_id' in only_id:
                break

        if (self.writeFile):
            file_name = "output/" + self.target + "_comments.txt"
            file = open(file_name, "w")
            file.write(
                str(comment_counter) + " comments in " + str(counter) +
                " posts\n")
            file.close()

        pc.printout(str(comment_counter), pc.MAGENTA)
        pc.printout(" comments in " + str(counter) + " posts\n")

    def getPeopleTaggedByUser(self):
        pc.printout("Searching for users tagged by target...\n")

        ids = []
        username = []
        full_name = []
        post = []
        only_id = {}
        a = None
        counter = 1
        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson

            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']

            try:
                for i in a:
                    if "usertags" in i:
                        c = i.get('usertags').get('in')
                        for cc in c:
                            if cc.get('user').get('pk') not in ids:
                                ids.append(cc.get('user').get('pk'))
                                username.append(cc.get('user').get('username'))
                                full_name.append(
                                    cc.get('user').get('full_name'))
                                post.append(1)
                            else:
                                index = ids.index(cc.get('user').get('pk'))
                                post[index] += 1
                            counter = counter + 1
            except AttributeError as ae:
                pc.printout("\nERROR: an error occurred: ", pc.RED)
                print(ae)
                print("")
                pass

            if not 'next_max_id' in only_id:
                break

        if len(ids) > 0:
            t = PrettyTable()

            t.field_names = ['Posts', 'Full Name', 'Username', 'ID']
            t.align["Posts"] = "l"
            t.align["Full Name"] = "l"
            t.align["Username"] = "******"
            t.align["ID"] = "l"

            pc.printout(
                "\nWoohoo! We found " + str(len(ids)) + " (" + str(counter) +
                ") users\n", pc.GREEN)

            for i in range(len(ids)):
                t.add_row([post[i], full_name[i], username[i], str(ids[i])])

            if (self.writeFile):
                file_name = "output/" + self.target + "_tagged.txt"
                file = open(file_name, "w")
                file.write(str(t))
                file.close()

            print(t)
        else:
            pc.printout("Sorry! No results found :-(\n", pc.RED)

    def getAddrs(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout(
            "Searching for target address... this may take a few minutes...\n")
        addrs = self.__getAdressesTimes__(self.target_id)
        t = PrettyTable()

        t.field_names = ['Post', 'Address', 'time']
        t.align["Post"] = "l"
        t.align["Address"] = "l"
        t.align["Time"] = "l"
        pc.printout("\nWoohoo! We found " + str(len(addrs)) + " addresses\n",
                    pc.GREEN)

        i = 1
        for address, time in addrs:
            t.add_row([str(i), address, time])
            i = i + 1

        if (self.writeFile):
            file_name = "output/" + self.target + "_addrs.txt"
            file = open(file_name, "w")
            file.write(str(t))
            file.close()

        print(t)

    def getFollowers(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target followers...\n")

        followers = self.__getTotalFollowers__(self.target_id)
        t = PrettyTable(['ID', 'Username', 'Full Name'])
        t.align["ID"] = "l"
        t.align["Username"] = "******"
        t.align["Full Name"] = "l"

        for i in followers:
            t.add_row([str(i['pk']), i['username'], i['full_name']])

        if (self.writeFile):
            file_name = "output/" + self.target + "_followers.txt"
            file = open(file_name, "w")
            file.write(str(t))
            file.close()

        print(t)

    def getFollowings(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target followings...\n")

        followings = self.__getUserFollowigs__(self.target_id)
        t = PrettyTable(['ID', 'Username', 'Full Name'])
        t.align["ID"] = "l"
        t.align["Username"] = "******"
        t.align["Full Name"] = "l"

        for i in followings:
            t.add_row([str(i['pk']), i['username'], i['full_name']])

        if (self.writeFile):
            file_name = "output/" + self.target + "_followings.txt"
            file = open(file_name, "w")
            file.write(str(t))
            file.close()

        print(t)

    def getUser(self, username):
        try:
            content = urllib.request.urlopen("https://www.instagram.com/" +
                                             username + "/?__a=1")
        except urllib.error.HTTPError as err:
            if (err.code == 404):
                print("Oops... " + username +
                      " non exist, please enter a valid username.")
                sys.exit(2)

        data = json.load(content)

        if (self.writeFile):
            file_name = "output/" + self.target + "_user_id.txt"
            file = open(file_name, "w")
            file.write(str(data['graphql']['user']['id']))
            file.close()

        user = dict()
        user['id'] = data['graphql']['user']['id']
        user['is_private'] = data['graphql']['user']['is_private']

        return user

    def getUserInfo(self):
        try:
            content = urllib.request.urlopen("https://www.instagram.com/" +
                                             str(self.target) + "/?__a=1")
        except urllib.error.HTTPError as err:
            if (err.code == 404):
                print("Oops... " + str(self.target) +
                      " non exist, please enter a valid username.")
                sys.exit(2)

        data = json.load(content)
        data = data['graphql']['user']

        pc.printout("[ID] ", pc.GREEN)
        pc.printout(str(data['id']) + '\n')
        pc.printout("[FULL NAME] ", pc.RED)
        pc.printout(str(data['full_name']) + '\n')
        pc.printout("[BIOGRAPHY] ", pc.CYAN)
        pc.printout(str(data['biography']) + '\n')
        pc.printout("[FOLLOWED] ", pc.GREEN)
        pc.printout(str(data['edge_followed_by']['count']) + '\n')
        pc.printout("[FOLLOW] ", pc.BLUE)
        pc.printout(str(data['edge_follow']['count']) + '\n')
        pc.printout("[BUSINESS ACCOUNT] ", pc.RED)
        pc.printout(str(data['is_business_account']) + '\n')
        if data['is_business_account'] == True:
            pc.printout("[BUSINESS CATEGORY] ")
            pc.printout(str(data['business_category_name']) + '\n')
        pc.printout("[VERIFIED ACCOUNT] ", pc.CYAN)
        pc.printout(str(data['is_verified']) + '\n')

    def getPhotoDescription(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        content = self.api.SendRequest2(self.target + '/?__a=1')
        data = self.api.LastJson
        dd = data['graphql']['user']['edge_owner_to_timeline_media']['edges']

        if len(dd) > 0:
            pc.printout(
                "\nWoohoo! We found " + str(len(dd)) + " descriptions\n",
                pc.GREEN)

            count = 1

            t = PrettyTable(['Photo', 'Description'])
            t.align["Photo"] = "l"
            t.align["Description"] = "l"

            for i in dd:
                node = i.get('node')
                t.add_row([str(count), node.get('accessibility_caption')])
                count += 1

            if (self.writeFile):
                file_name = "output/" + self.target + "_photodes.txt"
                file = open(file_name, "w")
                file.write(str(t))
                file.close()

            print(t)
        else:
            pc.printout("Sorry! No results found :-(\n", pc.RED)

    def getUserPhoto(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        limit = -1
        pc.printout("How many photos you want to download (default all): ",
                    pc.YELLOW)
        l = input()
        try:
            if l == "":
                pc.printout("Downloading all photos avaible...\n")
            else:
                limit = int(l)
                pc.printout("Downloading " + l + " photos...\n")

        except ValueError:
            pc.printout("Wrong value entered\n", pc.RED)
            return

        a = None
        counter = 0
        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson

            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']

            try:
                for item in a:
                    if counter == limit:
                        break
                    if "image_versions2" in item:
                        counter = counter + 1
                        url = item["image_versions2"]["candidates"][0]["url"]
                        photo_id = item["id"]
                        end = "output/" + self.target + "_" + photo_id + ".jpg"
                        urllib.request.urlretrieve(url, end)
                        sys.stdout.write("\rDownloaded %i" % counter)
                        sys.stdout.flush()
                    else:
                        carousel = item["carousel_media"]
                        for i in carousel:
                            if counter == limit:
                                break
                            counter = counter + 1
                            url = i["image_versions2"]["candidates"][0]["url"]
                            photo_id = i["id"]
                            end = "output/" + self.target + "_" + photo_id + ".jpg"
                            urllib.request.urlretrieve(url, end)
                            sys.stdout.write("\rDownloaded %i" % counter)
                            sys.stdout.flush()

            except AttributeError:
                pass

            except KeyError:
                pass

            if not 'next_max_id' in only_id:
                break

        sys.stdout.write(" photos")
        sys.stdout.flush()

        pc.printout(
            "\nWoohoo! We downloaded " + str(counter) +
            " photos (saved in output/ folder) \n", pc.GREEN)

    def getCaptions(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target captions...\n")

        a = None
        counter = 0
        captions = []
        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson

            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']

            try:
                for item in a:
                    if "caption" in item:
                        if item["caption"] != None:
                            text = item["caption"]["text"]
                            captions.append(text)
                            counter = counter + 1
                            sys.stdout.write("\rFound %i" % counter)
                            sys.stdout.flush()

            except AttributeError:
                pass

            except KeyError:
                pass

            if not 'next_max_id' in only_id:
                break

        sys.stdout.write(" captions")
        sys.stdout.flush()

        if counter > 0:
            pc.printout("\nWoohoo! We found " + str(counter) + " captions\n",
                        pc.GREEN)

            if (self.writeFile):
                file_name = "output/" + self.target + "_captions.txt"
                file = open(file_name, "w")
                for s in captions:
                    file.write(s + "\n")
                file.close()

            for s in captions:
                print(s + "\n")

        else:
            pc.printout("Sorry! No results found :-(\n", pc.RED)

        return

    def getMediaType(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target captions...\n")

        a = None
        counter = 0
        photo_counter = 0
        video_counter = 0

        while True:
            if (a == None):
                self.api.getUserFeed(self.target_id)
                a = self.api.LastJson['items']
                only_id = self.api.LastJson

            else:
                self.api.getUserFeed(self.target_id, only_id['next_max_id'])
                only_id = self.api.LastJson
                a = self.api.LastJson['items']

            try:
                for item in a:
                    if "media_type" in item:
                        if item["media_type"] == 1:
                            photo_counter = photo_counter + 1
                        elif item["media_type"] == 2:
                            video_counter = video_counter + 1

                        counter = counter + 1
                        sys.stdout.write("\rChecked %i" % counter)
                        sys.stdout.flush()

            except AttributeError:
                pass

            except KeyError:
                pass

            if not 'next_max_id' in only_id:
                break

        sys.stdout.write(" posts")
        sys.stdout.flush()

        if counter > 0:

            if (self.writeFile):
                file_name = "output/" + self.target + "_mediatype.txt"
                file = open(file_name, "w")
                file.write(str(photo_counter) + " photos and " + str(video_counter) \
                        + " video posted by target\n")
                file.close()


            pc.printout("\nWoohoo! We found " + str(photo_counter) + " photos and " + str(video_counter) \
                        + " video posted by target\n", pc.GREEN)

        else:
            pc.printout("Sorry! No results found :-(\n", pc.RED)

        return

    def getUserPropic(self):
        try:
            content = urllib.request.urlopen("https://www.instagram.com/" +
                                             str(self.target) + "/?__a=1")
        except urllib.error.HTTPError as err:
            if (err.code == 404):
                print("Oops... " + str(self.target) +
                      " non exist, please enter a valid username.")
                sys.exit(2)

        data = json.load(content)

        URL = ""

        uurl = data["graphql"]["user"]
        if "profile_pic_url_hd" in uurl:
            URL = data["graphql"]["user"]["profile_pic_url_hd"]
        else:
            URL = data["graphql"]["user"]["profile_pic_url"]

        if URL != "":
            end = "output/" + self.target + "_propic.jpg"
            urllib.request.urlretrieve(URL, end)
            pc.printout("Target propic saved in output folder\n", pc.GREEN)

        else:
            pc.printout("Sorry! No results found :-(\n", pc.RED)

    def getUserStories(self):
        if (self.is_private):
            pc.printout(
                "Impossible to execute command: user has private profile\n",
                pc.RED)
            return

        pc.printout("Searching for target stories...\n")

        endpoint = 'feed/user/{id!s}/story/'.format(**{'id': self.target_id})
        content = self.api.SendRequest(endpoint)
        data = self.api.LastJson
        counter = 0

        if data['reel'] != None:  # no stories avaibile
            for i in data['reel']['items']:
                story_id = i["id"]
                if i["media_type"] == 1:  # it's a photo
                    url = i['image_versions2']['candidates'][0]['url']
                    end = "output/" + self.target + "_" + story_id + ".jpg"
                    urllib.request.urlretrieve(url, end)
                    counter += 1

                elif i["media_type"] == 2:  # it's a gif or video
                    url = i['video_versions'][0]['url']
                    end = "output/" + self.target + "_" + story_id + ".mp4"
                    urllib.request.urlretrieve(url, end)
                    counter += 1

        if counter > 0:
            pc.printout(
                str(counter) + " target stories saved in output folder\n",
                pc.GREEN)
        else:
            pc.printout("Sorry! No results found :-(\n", pc.RED)

    def changeTarget(self):
        pc.printout("Insert new target username: ", pc.YELLOW)
        l = input()
        self.setTarget(l)

        return
예제 #3
0
class User: #Setup custom user class
    def __init__(self, usr_name, password):
        self.name = usr_name
        self.api = InstagramAPI(usr_name, password)

        InstagramAPI.USER_AGENT = "Instagram 99.0.0.19.93 Android (5000/5000.0; 1dpi; 1x1; noname; noname; noname; noname)"
        #Setup custom UA to ensure reading dms allowed

    def sendMessage(self, target, msgText):
        targets = []
        if type(target) != type([]):
            target = [target]

        for user in target:
            try:
                int(user)
                targets.append(str(user))
            except ValueError:
                target = self.api.searchUsername(user)
                try:
                    targets.append(str(self.api.LastJson["user"]["pk"]))
                except:
                    return ValueError("Invalid User")

        url = "direct_v2/threads/broadcast/text/"

        target = "[[{}]]".format(",".join([str(user) for user in targets]))
        data = {
            "text": msgText,
            "_uuid": self.api.uuid,
            "_csrftoken": self.api.token,
            "recipient_users": target,
            "_uid": self.api.username_id,
            "action": "send_item",
            "client_context": self.api.generateUUID(True)}

        return self.api.SendRequest(url, data)

    def getChats(self):
        #TODO: Find some way of checking if thread is unread
        self.api.getv2Inbox()
        content = json.loads(self.api.LastResponse.content)["inbox"]["threads"]
        chats = []
        for chat in content:
            users = []
            if len(chat["users"]) == 0:
                self.api.searchUsername(self.name)
                response = json.loads(json.dumps(self.api.LastJson))
                chats.append({
                    "thread_name": self.name,
                    "thread_id"  : chat["thread_id"],
                    "users"      : [self.name],
                    "thread_icon": response["user"]["profile_pic_url"]
                })
                continue

            for user in chat["users"]:
                users.append(user["username"])

            chats.append({
                "thread_name": chat["thread_title"],
                "thread_id"  : chat["thread_id"],
                "users"      : [user["username"] for user in chat["users"]],
                "thread_icon": chat["users"][0]["profile_pic_url"]
            })

        return chats

    def getMessages(self, chat_id):
        self.api.getv2Threads(str(chat_id))
        thread = json.loads(json.dumps(self.api.LastJson))["thread"]

        users = {} #Get list of people
        for user in thread["users"]:
            users[user["pk"]] = user["username"]

        items = [] #List of dict(UID: Item data)

        for item in thread["items"]:
            type = item["item_type"]
            # TODO: Add new messages in this order: image, link, profile
            if type == "text":
                items.append({"user"    : item["user_id"],
                              "text"    : " " * 4 + item["text"],
                              "time"    : item["timestamp"],
                              "item_id" : item["item_id"],
                              "show_pfp": True})

            elif type == "video_call_event":
                items.append({"user"    : item["user_id"],
                              "text"    : " " * 4 + item["video_call_event"]["description"],
                              "time"    : item["timestamp"],
                              "item_id" : item["item_id"],
                              "show_pfp": False})

            elif type == "like":
                items.append({"user"    : item["user_id"],
                              "text"    : u" \u2764\uFE0F",
                              "time"    : item["timestamp"],
                              "item_id" : item["item_id"],
                              "show_pfp": True})

            else:
                items.append({"user"    : item["user_id"],
                              "text"    : "    Unsupported message type: " + item["item_type"],
                              "time"    : item["timestamp"],
                              "item_id" : item["item_id"],
                              "show_pfp": True})

        return items

    def unsend(self, thread_id, item_id):
        thread_id = str(thread_id)
        item_id = str(item_id)
        endpoint = "direct_v2/threads/"+thread_id+"/items/"+item_id+"/delete/"
        data = {
            "_uuid": self.api.uuid,
            "_csrftoken": self.api.token}

        response = self.api.s.post(self.api.API_URL + endpoint, data=data)

        if response.status_code == 200:
            self.api.LastResponse = response
            self.api.LastJson = json.loads(response.text)
            return True

        else:
            try:
                self.api.LastResponse = response
                self.api.LastJson = json.loads(response.text)
            except:
                pass

            return False
class Main:

    def __init__(self):
        IG_NAME = input('Username: '******'Password: '******'10.26.0', '10.34.0')
        self.broadcast_id = 0
        self.chat_thread = threading.Thread(target=self.chat_job, daemon=True)
        self.isRunning = True

    def chat_job(self):
        server = HTTPServer(('', 4132), chat_server.ChatServer)

        while self.isRunning:
            server.handle_request()
            time.sleep(1)
            a = self.SendRequest(f'live/{self.broadcast_id}/get_comment/', last=False)
            try:
                if a['comments']:
                    for comment in a['comments']:
                        try:
                            if comment['user']['username'] == self.api.username:
                                chatter = 'Me'
                            else:
                                chatter = comment['user']['username']
                            comment_user = {'username': chatter, 'user_id': comment['user_id']}
                            timestamp = time.gmtime(comment['created_at_utc'])
                            comment_time = time.strftime('%H:%M:%S', timestamp)
                            comment_text = comment['text']
                            comment_id = comment['pk']
                            chat = {
                                'id': comment_id,
                                'user': comment_user,
                                'text': comment_text,
                                'time': comment_time
                            }
                        except Exception as e:
                            print(e)

                        if chat in chat_server.GARBAGE:
                            pass
                        else:
                            chat_server.GARBAGE.append(chat)

            except Exception as e:
                pass
        print('Comment Thread Stopped')

    def create_live(self, msg=''):
        data = json.dumps({
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token,
            'preview_height': 1280,
            'preview_width': 720,
            'broadcast_message': msg
        })
        self.api.SendRequest('live/create/', self.api.generateSignature(data))
        broadcast_id, live_url, stream_key = (self.api.LastJson['broadcast_id'], self.api.LastJson['upload_url'][:43], self.api.LastJson['upload_url'][43:])

        print(f'[*]Broadcast ID: {broadcast_id}\n')
        print(f'[*]Live Upload URL: {live_url}\n')
        print(f'[*]Stream Key:\n{stream_key}\n\n')

        self.broadcast_id = broadcast_id

        return True

    def start_live(self):
        notify = True

        data = json.dumps({
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token,
            'should_send_notifications': notify
        })
        self.api.SendRequest(f'live/{self.broadcast_id}/start/', self.api.generateSignature(data))
        return True

    def end_live(self):
        data = json.dumps({
            '_uid': self.api.username_id,
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token,
            'end_after_copyright_warning': False
        })

        return self.api.SendRequest(f'live/{self.broadcast_id}/end_broadcast/', self.api.generateSignature(data))

    def save_post_live(self):
        trial = 3
        posted = bool
        while trial:
            trial -= 1
            data = json.dumps({
                '_uid': self.api.username_id,
                '_uuid': self.api.uuid,
                '_csrftoken': self.api.token
            })
            self.api.SendRequest(f'live/{self.broadcast_id}/add_to_post_live', self.api.generateSignature(data))

            if self.api.LastResponse.status_code == 200:
                print('Live Posted to Story!')
                posted = True
                break
        if not posted:
            print('Vailed to post live to story!')

    def delete_post_live(self):
        data = json.dumps({
            '_uid': self.api.username_id,
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token
        })
        return self.api.SendRequest(f'live/{self.broadcast_id}/delete_post_live', self.api.generateSignature(data))

    def pin_comment(self, comment_id):
        data = json.dumps({
            'offset_to_video_start': 0,
            'comment_id': comment_id,
            '_uid': self.api.username_id,
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token
        })
        return self.api.SendRequest(f'live/{self.broadcast_id}/pin_comment', self.api.generateSignature(data))

    def unpin_comment(self, comment_id):
        data = json.dumps({
            'offset_to_video_start': 0,
            'comment_id': comment_id,
            '_uid': self.api.username_id,
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token
        })
        return self.api.SendRequest(f'live/{self.broadcast_id}/unpin_comment', self.api.generateSignature(data))

    def SendRequest(self, endpoint, post=None, login=False, last=True):
        verify = False  # don't show request warning
        if not last:
            if (not self.api.isLoggedIn and not login):
                raise Exception("Not logged in!\n")

            self.api.s.headers.update({'Connection': 'close',
                                       'Accept': '*/*',
                                       'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                                       'Cookie2': '$Version=1',
                                       'Accept-Language': 'en-US',
                                       'User-Agent': self.api.USER_AGENT})

            while True:
                try:
                    if (post is not None):
                        response = self.api.s.post(self.api.API_URL + endpoint, data=post, verify=verify)
                    else:
                        response = self.api.s.get(self.api.API_URL + endpoint, verify=verify)
                    break
                except Exception as e:
                    print('Except on SendRequest (wait 60 sec and resend): ' + str(e))
                    time.sleep(60)

            if response.status_code == 200:
                self.api.LastResponse = response
                self.api.LastJson = json.loads(response.text)
            else:
                print("Request return " + str(response.status_code) + " error!")
                # for debugging
                try:
                    self.api.LastResponse = response
                    self.api.LastJson = json.loads(response.text)
                    print(self.api.LastJson)
                    if 'error_type' in self.api.LastJson and self.api.LastJson['error_type'] == 'sentry_block':
                        raise SentryBlockException(self.api.LastJson['message'])
                except SentryBlockException:
                    raise
                except:
                    pass
            return self.api.LastJson
        else:
            return self.api.SendRequest(endpoint, post=None, login=False)

    def live_info(self):
        _json = self.SendRequest(f'live/{self.broadcast_id}/info/', last=False)
        dash_url = _json['dash_playback_url']
        viewer_count = _json['viewer_count']
        _id = _json['id']
        owner = _json['broadcast_owner']['username']
        status = _json['broadcast_status']

        print(f'[*]ID: {_id}')
        print(f'[*]Broadcast Owner: {owner}')
        print(f'[*]Dash URL: {dash_url}')
        print(f'[*]Viewer Count: {viewer_count}')
        print(f'[*]Status: {status}')

    def send_comment(self, msg):
        data = json.dumps({
            'idempotence_token': self.api.generateUUID(True),
            'comment_text': msg,
            'live_or_vod': 1,
            'offset_to_video_start': 0
        })

        _json = self.SendRequest(f'live/{self.broadcast_id}/comment/', self.api.generateSignature(data), last=False)
        if _json['status'] == 'ok':
            return True

    def exit(self):
        self.end_live()
        print('Save Live replay to story ? <y/n>')
        save = input('command> ')
        if save == 'y':
            self.save_post_live()
        else:
            self.delete_post_live()
        print('Exiting...')
        self.isRunning = False
        self.chat_thread.join()
        print('All process Stopped')
        time.sleep(1)
        print('Cleaning cache...')

    def wave(self, userid):

        data = json.dumps({
            '_uid': self.api.username_id,
            '_uuid': self.api.uuid,
            '_csrftoken': self.api.token,
            'viewer_id': userid
        })

        _json = self.SendRequest(f'live/{self.broadcast_id}/wave/', self.api.generateSignature(data), last=False)
        if _json:
            return True

    def get_viewer_list(self):
        _json = self.SendRequest(f'live/{self.broadcast_id}/get_viewer_list/', last=False)
        users = []
        ids = []
        for user in _json['users']:
            users.append(f"{user['username']}")
            ids.append(f"{user['pk']}")

        return users, ids

    def run(self):
        print('[!]logging in...')
        if self.api.login():
            print('[*]logged in!!')
            print('[!]Generating stream upload_url and keys...\n')
            self.create_live()
            print('Now Open Broadcast Software and start streaming on given url and key')
            input('Press Enter after your Broadcast Software started streaming\n')
            self.start_live()
            self.chat_thread.start()
            print("Chat Server Started")

            while self.isRunning:
                cmd = input('command> ')

                if cmd == 'stop':
                    self.exit()

                elif cmd == 'wave':
                    users, ids = self.get_viewer_list()
                    for i in range(len(users)):
                        print(f'{i+1}. {users[i]}')
                    print('Type number according to user e.g 1.')
                    while True:
                        cmd = input('number> ')

                        if cmd == 'back':
                            break
                        try:
                            userid = int(cmd) - 1
                            self.wave(ids[userid])
                            break
                        except:
                            print('Please type number e.g 1')

                elif cmd == 'info':
                    self.live_info()

                elif cmd == 'viewers':
                    users, ids = self.get_viewer_list()
                    print(users)

                elif cmd[:4] == 'chat':
                    to_send = cmd[5:]
                    if to_send:
                        self.send_comment(to_send)
                    else:
                        print('usage: chat <text to chat>')

                else:
                    print('Available commands:\n\t"stop"\n\t"info"\n\t"viewers"\n\t"chat"\n\t"wave"')
예제 #5
0
from InstagramAPI import InstagramAPI

api = InstagramAPI("aringhosh", "Asansol@123")
if (api.login()):
    result = api.SendRequest('users/madhubanimotifs/media/recent/')
    # api.getSelfUserFeed()  # get self user feed
    # print(api.LastJson)  # print last response JSON
    print(result)
else:
    print("Can't login!")