Use Post class attributes in filename-pattern
- Added owner_id and mediaid to Post class properties.
- In case of not downloading stories, the attributes of the Post class
  can now be used in filename-pattern, e.g. {post.owner_id} or {post.mediaid}.
Closes #53.
			
			
This commit is contained in:
		@@ -126,7 +126,7 @@ def mediaid_to_shortcode(mediaid: int) -> str:
 | 
			
		||||
def format_string_contains_key(format_string: str, key: str) -> bool:
 | 
			
		||||
    # pylint:disable=unused-variable
 | 
			
		||||
    for literal_text, field_name, format_spec, conversion in string.Formatter().parse(format_string):
 | 
			
		||||
        if field_name == key:
 | 
			
		||||
        if field_name == key or field_name.startswith(key + '.'):
 | 
			
		||||
            return True
 | 
			
		||||
    return False
 | 
			
		||||
 | 
			
		||||
@@ -176,7 +176,8 @@ class Post:
 | 
			
		||||
 | 
			
		||||
    LOGIN_REQUIRING_PROPERTIES = ["viewer_has_liked"]
 | 
			
		||||
 | 
			
		||||
    def __init__(self, instaloader: 'Instaloader', node: Dict[str, Any], profile: Optional[str] = None):
 | 
			
		||||
    def __init__(self, instaloader: 'Instaloader', node: Dict[str, Any],
 | 
			
		||||
                 profile: Optional[str] = None, profile_id: Optional[int] = None):
 | 
			
		||||
        """Create a Post instance from a node structure as returned by Instagram.
 | 
			
		||||
 | 
			
		||||
        :param instaloader: :class:`Instaloader` instance used for additional queries if neccessary.
 | 
			
		||||
@@ -186,6 +187,7 @@ class Post:
 | 
			
		||||
        self._instaloader = instaloader
 | 
			
		||||
        self._node = node
 | 
			
		||||
        self._profile = profile
 | 
			
		||||
        self._profile_id = profile_id
 | 
			
		||||
        self._full_metadata_dict = None
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
@@ -206,6 +208,11 @@ class Post:
 | 
			
		||||
        """Media shortcode. URL of the post is instagram.com/p/<shortcode>/."""
 | 
			
		||||
        return self._node['shortcode'] if 'shortcode' in self._node else self._node['code']
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def mediaid(self) -> int:
 | 
			
		||||
        """The mediaid is a decimal representation of the media shortcode."""
 | 
			
		||||
        return int(self._node['id'])
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return '<Post {}>'.format(self.shortcode)
 | 
			
		||||
 | 
			
		||||
@@ -252,6 +259,13 @@ class Post:
 | 
			
		||||
            self._instaloader.error("Get owner name of {}: {} -- using \'UNKNOWN\'.".format(self, err))
 | 
			
		||||
            return 'UNKNOWN'
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def owner_id(self) -> int:
 | 
			
		||||
        """The ID of the Post's owner."""
 | 
			
		||||
        if self._profile_id:
 | 
			
		||||
            return self._profile_id
 | 
			
		||||
        return int(self._field('owner', 'id'))
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def date(self) -> datetime:
 | 
			
		||||
        """Timestamp when the post was created."""
 | 
			
		||||
@@ -889,7 +903,8 @@ class Instaloader:
 | 
			
		||||
        profilename = post.owner_username if needs_profilename else None
 | 
			
		||||
        dirname = self.dirname_pattern.format(profile=profilename, target=target.lower())
 | 
			
		||||
        filename = dirname + '/' + self.filename_pattern.format(profile=profilename, target=target.lower(),
 | 
			
		||||
                                                                date=post.date, shortcode=post.shortcode)
 | 
			
		||||
                                                                date=post.date, shortcode=post.shortcode,
 | 
			
		||||
                                                                post=post)
 | 
			
		||||
        os.makedirs(os.path.dirname(filename), exist_ok=True)
 | 
			
		||||
 | 
			
		||||
        # Download the image(s) / video thumbnail and videos within sidecars if desired
 | 
			
		||||
@@ -993,6 +1008,10 @@ class Instaloader:
 | 
			
		||||
        :param filename_target: Replacement for {target} in dirname_pattern and filename_pattern
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if format_string_contains_key(self.filename_pattern, 'post'):
 | 
			
		||||
            raise InvalidArgumentException("The \"post\" keyword is not supported in the filename pattern when "
 | 
			
		||||
                                           "downloading stories.")
 | 
			
		||||
 | 
			
		||||
        if not self.is_logged_in:
 | 
			
		||||
            raise LoginRequiredException('Login required to download stories')
 | 
			
		||||
 | 
			
		||||
@@ -1202,7 +1221,9 @@ class Instaloader:
 | 
			
		||||
    def get_profile_posts(self, profile_metadata: Dict[str, Any]) -> Iterator[Post]:
 | 
			
		||||
        """Retrieve all posts from a profile."""
 | 
			
		||||
        profile_name = profile_metadata['user']['username']
 | 
			
		||||
        yield from (Post(self, node, profile=profile_name) for node in profile_metadata['user']['media']['nodes'])
 | 
			
		||||
        profile_id = int(profile_metadata['user']['id'])
 | 
			
		||||
        yield from (Post(self, node, profile=profile_name, profile_id=profile_id)
 | 
			
		||||
                    for node in profile_metadata['user']['media']['nodes'])
 | 
			
		||||
        has_next_page = profile_metadata['user']['media']['page_info']['has_next_page']
 | 
			
		||||
        end_cursor = profile_metadata['user']['media']['page_info']['end_cursor']
 | 
			
		||||
        while has_next_page:
 | 
			
		||||
@@ -1213,7 +1234,8 @@ class Instaloader:
 | 
			
		||||
                                                          'after': end_cursor},
 | 
			
		||||
                                      'https://www.instagram.com/{0}/'.format(profile_name))
 | 
			
		||||
            media = data['data']['user']['edge_owner_to_timeline_media']
 | 
			
		||||
            yield from (Post(self, edge['node'], profile=profile_name) for edge in media['edges'])
 | 
			
		||||
            yield from (Post(self, edge['node'], profile=profile_name, profile_id=profile_id)
 | 
			
		||||
                        for edge in media['edges'])
 | 
			
		||||
            has_next_page = media['page_info']['has_next_page']
 | 
			
		||||
            end_cursor = media['page_info']['end_cursor']
 | 
			
		||||
 | 
			
		||||
@@ -1468,8 +1490,9 @@ def main():
 | 
			
		||||
                       help='Prefix of filenames. Posts are stored in the directory whose pattern is given with '
 | 
			
		||||
                            '--dirname-pattern. {profile} is replaced by the profile name, '
 | 
			
		||||
                            '{target} is replaced by the target you specified, i.e. either :feed, #hashtag or the '
 | 
			
		||||
                            'profile name. Also, the fields date and shortcode can be specified. Defaults to '
 | 
			
		||||
                            '\'{date:%%Y-%%m-%%d_%%H-%%M-%%S}\'.')
 | 
			
		||||
                            'profile name. Also, the fields {date} and {shortcode} can be specified. In case of not '
 | 
			
		||||
                            'downloading stories, the attributes of the Post class can be used in addition, e.g. '
 | 
			
		||||
                            '{post.owner_id} or {post.mediaid}. Defaults to \'{date:%%Y-%%m-%%d_%%H-%%M-%%S}\'.')
 | 
			
		||||
    g_how.add_argument('--user-agent',
 | 
			
		||||
                       help='User Agent to use for HTTP requests. Defaults to \'{}\'.'.format(default_user_agent()))
 | 
			
		||||
    g_how.add_argument('-S', '--no-sleep', action='store_true', help=SUPPRESS)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user