Example #1
0
def save_content(user: Member, post: instaloader.Post) -> Feed or None:
    ig = Feed.objects.instagram_v2().filter(status_id=post.shortcode).first()
    if ig:
        return ig

    profile = post.owner_profile
    created_at = post.date.replace(tzinfo=timezone.utc)

    # handle caption
    caption = ''
    if post.caption is not None:
        caption = post.caption
    ig = Feed.objects.create(author=profile.username, created_at=created_at, title=caption, user=user,
                             type='instagram_v2', status_id=post.shortcode,
                             link=f'https://www.instagram.com/p/{post.shortcode}')

    # Only an image
    if post.typename == 'GraphImage':
        m = Media.objects.create(feed=ig, original_url=post.url)
        async_task(m.download_to_local)

    # Multi images
    elif post.typename == 'GraphSidecar':
        for image in post.get_sidecar_nodes():
            m = Media.objects.create(feed=ig, original_url=image.display_url)
            async_task(m.download_to_local)

    elif post.typename == 'GraphVideo':
        ig.is_video = True
        ig.save(update_fields=['is_video'])
        m = Media.objects.create(feed=ig, original_url=post.url, )

    logger.info(f'Instagram: {ig} saved')
    return ig
Example #2
0
    async def create_from_instaloader(self, post: instaloader.Post) -> Post:
        """Create a post from a instaloader post object.

        :param post: a instaloader post object
        """

        # figure out post_type, items and download_tasks
        if post.typename == 'GraphImage':
            post_type = PostType.IMAGE
            items = [PostItem(index=0, type=PostItemType.IMAGE)]
            download_tasks = [DownloadTask(url=post.url)]
        elif post.typename == 'GraphVideo':
            post_type = PostType.VIDEO
            items = [
                PostItem(index=0,
                         type=PostItemType.VIDEO,
                         duration=post.video_duration)
            ]
            download_tasks = [
                DownloadTask(url=post.video_url, thumb_url=post.url)
            ]
        elif post.typename == 'GraphSidecar':
            post_type = PostType.SIDECAR
            items, download_tasks = [], []
            for index, node in enumerate(post.get_sidecar_nodes()):
                post_item = PostItem(index=index,
                                     type=PostItemType.VIDEO
                                     if node.is_video else PostItemType.IMAGE)
                download_task = DownloadTask(
                    url=node.video_url if node.is_video else node.display_url,
                    thumb_url=node.display_url if node.is_video else None,
                )
                items.append(post_item)
                download_tasks.append(download_task)
        else:
            post_type = None
            items, download_tasks = [], []

        # convert instaloader post to Post object
        post = Post(
            shortcode=post.shortcode,
            username=post.owner_username,
            timestamp=post.date_utc,
            type=post_type,
            caption=post.caption,
            caption_hashtags=post.caption_hashtags,
            caption_mentions=post.caption_mentions,
            items=[],
        )

        # create profile if not exist
        profile_service = ProfileService(self.database, self.http_session)
        if not await profile_service.exists(post.username):
            await profile_service.upsert(post.username)

        # download image and videos
        post_filename = f'{post.timestamp.strftime("%Y-%m-%dT%H-%M-%S")}_[{post.shortcode}]'
        for item, download_task in zip(items, download_tasks):
            filename = f'{post_filename}_{item.index}' if len(
                items) > 1 else post_filename
            file_path = await self._download(
                download_task.url, self.post_dir.joinpath(post.username),
                filename, post.timestamp)
            item.filename = file_path.name
            if download_task.thumb_url:
                file_path = await self._download(
                    download_task.thumb_url,
                    self.thumb_images_dir.joinpath(post.username),
                    filename,
                    post.timestamp,
                )
                item.thumb_image_filename = file_path.name

        # upsert the post entity
        post.items = items
        await self._upsert(post)

        logger.info(f'Saved post {post.shortcode} of user {post.username} '
                    f'which contains {len(post.items)} item(s).')
        return post
Example #3
0
def download_post_custom(self, post: Post, target: Union[str, Path]) -> bool:
    """
    Download everything associated with one instagram post node, i.e. picture, caption and video.
    :param post: Post to download.
    :param target: Target name, i.e. profile name, #hashtag, :feed; for filename.
    :return: True if something was downloaded, False otherwise, i.e. file was already there
    """

    # score = int(post.likes/post.video_view_count*20) + 1 if post.is_video else 0
    # score_str = str(score) + '_' + str(int(post.likes/post.video_view_count*100))
    score_str = 'score'
    dirname = instaloader._PostPathFormatter(post).format(self.dirname_pattern,
                                                          target=target,
                                                          score=score_str)
    filename = self.format_filename_custom(post,
                                           target=target,
                                           score=score_str)

    # insert post record
    db_manager.insert_post(post.mediaid, 'instagram', target, str(post.date),
                           time.strftime('%Y-%m-%d %X'), filename)

    filename = dirname + '/' + filename
    os.makedirs(os.path.dirname(filename), exist_ok=True)

    # Download the image(s) / video thumbnail and videos within sidecars if desired
    downloaded = True
    # self._committed = self.check_if_committed(filename)
    if self.download_pictures:
        if post.typename == 'GraphSidecar':
            edge_number = 1
            for sidecar_node in post.get_sidecar_nodes():
                # Download picture or video thumbnail
                if not sidecar_node.is_video or self.download_video_thumbnails is True:
                    downloaded &= self.download_pic(
                        filename=filename,
                        url=sidecar_node.display_url,
                        mtime=post.date_local,
                        filename_suffix=str(edge_number))
                # Additionally download video if available and desired
                if sidecar_node.is_video and self.download_videos is True:
                    downloaded &= self.download_pic(
                        filename=filename,
                        url=sidecar_node.video_url,
                        mtime=post.date_local,
                        filename_suffix=str(edge_number))
                edge_number += 1
        elif post.typename == 'GraphImage':
            downloaded = self.download_pic(filename=filename,
                                           url=post.url,
                                           mtime=post.date_local)
        elif post.typename == 'GraphVideo':
            if self.download_video_thumbnails is True:
                downloaded = self.download_pic(filename=filename,
                                               url=post.url,
                                               mtime=post.date_local)
        else:
            self.context.error("Warning: {0} has unknown typename: {1}".format(
                post, post.typename))

    # Download video if desired
    if post.is_video and self.download_videos is True:
        downloaded &= self.download_pic(filename=filename,
                                        url=post.video_url,
                                        mtime=post.date_local)

    if downloaded:
        # Save caption if desired
        metadata_string = instaloader._ArbitraryItemFormatter(post).format(
            self.post_metadata_txt_pattern).strip()
        if metadata_string:
            self.save_caption(filename=filename,
                              mtime=post.date_local,
                              caption=metadata_string)

        # Download geotags if desired
        if self.download_geotags and post.location:
            self.save_location(filename, post.location, post.date_local)

        # Update comments if desired
        # if self.download_comments is True:
        #     #self.update_comments(filename=filename, post=post)
        #     self.save_metadata_json(filename, post)
        #     with open(filename+'.json') as filename_json:
        #         with open(filename+'.txt', 'a', encoding='utf-8') as filename_txt:
        #             data = json.load(filename_json)
        #             for comment_data in data['node']['edge_media_to_parent_comment']['edges']:
        #                 comment_text = comment_data['node']['text']
        #                 filename_txt.write('\n'+comment_text+'\n')
        #     os.remove(filename+'.json')

        # Save metadata as JSON if desired.
        if self.save_metadata is not False:
            self.save_metadata_json(filename, post)

    self.context.log()
    return downloaded