Source code for instatools.models

from cached_property import threaded_cached_property_ttl as cached_property
from time import time as timestamp


class _Downloader:
    pass


downloader = _Downloader()


[docs]class Model(object): def __init__(self, api, json): self._api = api self._json = json def __hash__(self): return getattr(self, 'id', -1) def __getstate__(self): # pickle pickle = dict(self.__dict__) try: del pickle['_api'] # do not pickle the API reference except KeyError: pass return pickle def __repr__(self): return '{:s}(id={:s})'.format(self.__class__.__name__, str(getattr(self, 'id', -1)))
[docs] @classmethod def parse(cls, api, json, extra=None): model = cls(api, json) for k, v in json.items(): setattr(model, k, v) if extra: for k, v in extra.items(): setattr(model, k, v) return model
[docs] @classmethod def parse_list(cls, api, json_list, extra=None): items = [] for item in json_list: items.append(cls.parse(api, item, extra=extra)) return items
[docs]class Comment(Model):
[docs] @classmethod def parse(cls, api, json, extra=None): model = cls(api, json) for k, v in json.items(): if k == 'pk': setattr(model, 'id', v) elif k == 'media_id': setattr(model, 'post_id', v) else: setattr(model, k, v) return model
[docs] def reply(self, msg): pass
[docs] def remove(self): return self._api.remove_comment(self.post_id, self.id)
# todo location model
[docs]class Location(Model):
[docs] @classmethod def parse(cls, api, json, extra=None): model = cls(api, json) for k, v in json.items(): if k == '': setattr(model, '', v) else: setattr(model, k, v) return model
[docs]class Post(Model):
[docs] @classmethod def parse(cls, api, json, extra=None): model = cls(api, json) for k, v in json.items(): # Media data if k == 'pk': setattr(model, 'id', v) elif k == 'id': setattr(model, 'media_id', v) elif k == 'like_count': setattr(model, 'likes', v) elif k == 'has_likes': setattr(model, 'liked_by_me', v) elif k == 'user': setattr(model, 'user', ModelFactory.user.parse(api, v)) # Image / Thumbnails elif k == 'image_versions2': setattr(model, 'image_versions', sorted( v.get('candidates', []), key=lambda t: t['width'] * t['height'] )) # GIFs elif k == 'carousel_media' and len(v) > 0: setattr(model, 'image_versions', sorted( v[0].get('image_versions2', {}).get('candidates', []), key=lambda t: t['width'] * t['height'] )) elif k == 'media_type': media_types = {1: 'image', 2: 'video', 8: 'gif'} setattr(model, 'media_type', media_types[v]) # Video elif k == 'original_width': setattr(model, 'width', v) elif k == 'original_height': setattr(model, 'height', v) elif k == 'video_duration': setattr(model, 'duration', v) else: setattr(model, k, v) return model
[docs] @cached_property(60) def comments(self): return self._api.get_comments(self.id)
[docs] @cached_property(60) def likers(self): return self._api.get_likers(self.id)
[docs] def download(self): pass
[docs] def upload(self): pass
[docs] def save(self): return self._api.save(self.id)
[docs] def unsave(self): return self._api.unsave(self.id)
[docs] def share(self, user_ids, msg=None): return self._api.direct_share(self.id, user_ids, msg=msg)
[docs]class Relationship(Model):
[docs] @classmethod def parse(cls, api, json, extra=None): model = cls(api, json) for k, v in json.items(): setattr(model, k, v) if extra and extra.get('to', False): setattr(model, 'to', extra.get('to')) return model
def __repr__(self): return 'Relationship(to=%s, from=%s)' % ( self._api.username_id, self.to)
[docs]class User(Model):
[docs] @classmethod def parse(cls, api, json, extra=None): model = cls(api, json) for k, v in json.items(): if k == 'pk': setattr(model, 'id', v) elif k == 'biography': setattr(model, 'bio', v) elif k == 'is_private': setattr(model, 'private', v) elif k == 'follower_count': setattr(model, 'n_followers', v) elif k == 'following_count': setattr(model, 'n_following', v) elif k == 'media_count': setattr(model, 'n_posts', v) else: setattr(model, k, v) # This is so Users object can track other people's follow durations if getattr(model, 'id', -1) != api.username_id: model.followed_me_at = timestamp() return model
@property def feed(self): return self._api.feeds.user(self.id)
[docs] @cached_property(3600) def followers(self): return self._api.get_followers(self.id)
[docs] @cached_property(3600) def following(self): return self._api.get_following(self.id)
[docs] def follow(self): return self._api.follow(self.id)
[docs] def unfollow(self): return self._api.unfollow(self.id)
[docs] def approve(self): return self._api.approve(self.id)
[docs] def ignore(self): return self._api.ignore(self.id)
[docs] def block(self): return self._api.block(self.id)
[docs] def unblock(self): return self._api.unblock(self.id)
[docs] def direct_message(self, msg): return self._api.direct_message([self.id], msg)
[docs] def direct_share(self, post_id, msg=None): return self._api.direct_share([self.id], post_id, msg=msg)
def __repr__(self): return 'User(%s)' % (self.username,)
[docs]class ModelFactory: default = Model comment = Comment location = Location post = item = ranked_item = Post relationship = friendship_status = Relationship user = User