Skip to content

Commit

Permalink
Added refresh method to Hashtag & Comment
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwickerhf committed Jan 16, 2021
1 parent 9968978 commit 70065cf
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 5 deletions.
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ except SuspisciousLoginAttemptError as error:
code = input('Enter the security code that was sent to you via SMS: ')
client.input_security_code(code)
```
#### INSTAGRAM OBJECTS
Many client methods return objects defined in the [instagram](https://github.com/wickerdevs/instaclient/tree/main/instaclient/instagram) package of this library.
Such objects are reppresentations of the data returned by instagram, but they are not continuesly synced with Instagram, hence the data may not always be updated. To sync the local object to instagram, most objects have `.refresh()` method, as seen in the example below:
```python
profile = client.get_profile('<username>')
# Other code here
profile.refresh() # syncing with instagram
```

#### SEND A DIRECT MESSAGE
```python
result = client.send_dm('<username>', '<Message to send>') # send a DM to a user
Expand Down Expand Up @@ -119,14 +128,33 @@ profile = client.get_profile('<username>')
posts = client.get_user_posts('<username>', count=10)
# or:
profile = client.get_profile('<username>')
profile.get_posts(30)
posts = profile.get_posts(30)
```
> This returns a list of Post objects.
#### SCRAPE A HASHTAG
```python
hashtag = client.get_hashtag(tag='<tag>')
# This returns a Hashtag object, from which you can get the posts data.
posts = hashtag.get_posts(count=25)
```
#### SCRAPE A LOCATION
##### BY ID & SLUG
Every Instagram Location is defined by a slug and an ID.
You can find these two pieces of information in the URL of the location page on Instagram:
```https://www.instagram.com/explore/locations/270531492/italy/```
from this example, the ID would be `270531492` and the slug would be `italy`
```python
location = client.get_location(id='270531492', slug='italy')
posts = location.get_posts(count=25)
```
> This returns a Hashtag object, from which you can get the posts data. Using load_posts(), you get a list of BasePost objects, from which you can get the owner of the post

##### BY SEARCH RESULT
If you don't have access to either the ID or the slug of a location, you can still scrape such location by finding it on the search page.
```python
result = client.get_search_result('italy')
location = result.get('locations')[0]
```

#### ADD A COMMENT
```python
client.comment_post('<post_shortcode>', text='Nice post!')
Expand Down
2 changes: 1 addition & 1 deletion instaclient/client/scraper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Scraper(Component):

# SCRAPE USER DATA
@Component._login_required
def scrape_notifications(self:'InstaClient', types:Optional[list], count:int=None) -> Optional[List[Notification]]:
def get_notifications(self:'InstaClient', types:Optional[list], count:int=None) -> Optional[List[Notification]]:

if types is None or len(types) == 0:
types = [InstaBaseObject.GRAPH_FOLLOW, InstaBaseObject.GRAPH_LIKE, InstaBaseObject.GRAPTH_TAGGED, InstaBaseObject.GRAPH_COMMENT, InstaBaseObject.GRAPH_MENTION]
Expand Down
1 change: 1 addition & 0 deletions instaclient/instagram/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def get_owner(self, context:bool=True) -> Optional['Profile']:
"""
return self.client.get_profile(username=self.owner, context=context)


def get_post(self, context:bool=True):
"""Shortcut for::
Expand Down
10 changes: 10 additions & 0 deletions instaclient/instagram/hashtag.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ def __eq__(self, o: object) -> bool:
return False


def refresh(self):
"""Syncs this object instance with Instagram.
The object instance on which this method is called on will be
refreshed to match the data available on the instagram website.
"""
refreshed = self.client.get_hashtag(self.name)
return self._update(refreshed)


def get_posts(self, count:Optional[int]=None, deep_scrape:Optional[bool]=False, callback_frequency:int=100, callback=None, **callback_args) -> Optional[Union[List['Post'], List[str]]]:
"""Shortcut for::
client.get_hashtag_posts(username, count, deep_scrape, callback_frequency, callback, **callback_args)
Expand Down
20 changes: 18 additions & 2 deletions instaclient/instagram/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,36 @@ def __eq__(self, o: object) -> bool:
return True
return False


def __repr__(self) -> str:
return f'Notification<{self.type} | {self.from_user}>'


def __lt__(self, o) -> bool:
if self.timestamp < o.timestamp:
return True
else:
return False


def __gt__(self, o) -> bool:
if self.timestamp > o.timestamp:
return True
else:
return False

def get_timestamp(self):
return self.timestamp

def refresh(self):
"""Syncs this object instance with Instagram.
The object instance on which this method is called on will be
refreshed to match the data available on the instagram website.
"""
notifications = self.client.get_notifications(types=[self.type])
for noti in notifications:
if noti == self:
return self._update(noti)
return None



57 changes: 57 additions & 0 deletions instaclient/instagram/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,24 +154,81 @@ def __eq__(self, o: object) -> bool:
return True
return False


def refresh(self, context:bool=True):
"""Syncs this object instance with Instagram.
The object instance on which this method is called on will be
refreshed to match the data available on the instagram website.
Args:
context (bool): Set this to True if you wish for the client to
log in before scraping data.
"""
refreshed = self.client.get_post(self.shortcode, context)
return self._update(refreshed)


def get_owner(self) -> Optional[Profile]:
"""Shortcut for::
client.get_profile(owner, context=True)
for the full documentation of this method, please see
:meth:`instaclient.InstaClient.get_profile`.
Returns:
Optional[:class:`instagram.Profile`]: If the owner of this post
is valid, its Profile object will be returned.
"""
return self.client.get_profile(self.owner)


def add_comment(self, text) -> Optional[Comment]:
"""Shortcut for::
client.comment_post(shortcode, text)
for the full documentation of this method, please see
:meth:`instaclient.InstaClient.comment_post`.
Returns:
Optional[:class:`instagram.Comment`]: If the comment
is posted correctly, it will be returned.
"""
result = self.client.comment_post(self.shortcode, text)
if result:
self.comments_count += 1
return self.client._find_comment(self.shortcode, self.client.username, text)
return None


def like(self):
"""Shortcut for::
client.like_post(shortcode)
for the full documentation of this method, please see
:meth:`instaclient.InstaClient.like_post`.
Returns:
Optional[:class:`instagram.Post`]: If the post is
liked successfully, the instace this method is
called on will be refreshed.
"""
post = self.client.like_post(self.shortcode)
return self._update(post)


def unlike(self):
"""Shortcut for::
client.unlike_post(shortcode)
for the full documentation of this method, please see
:meth:`instaclient.InstaClient.inlike_post`.
Returns:
Optional[:class:`instagram.Post`]: If the post is
unliked successfully, the instace this method is
called on will be refreshed.
"""
post = self.client.unlike_post(self.shortcode)
return self._update(post)

Expand Down

0 comments on commit 70065cf

Please sign in to comment.