From efd67c4a4b738c7e55dd4ecbfc8a2f0bc7743cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Wed, 5 Sep 2018 15:49:10 +0200 Subject: [PATCH] Use Instagram cache --- clients/discord.py | 6 +-- commands.py | 40 ++++++++++--------- services/instagram.py | 92 ------------------------------------------- settings.cfg.example | 8 ++-- 4 files changed, 28 insertions(+), 118 deletions(-) delete mode 100644 services/instagram.py diff --git a/clients/discord.py b/clients/discord.py index 4c2ea3b..0e770db 100644 --- a/clients/discord.py +++ b/clients/discord.py @@ -185,10 +185,10 @@ class DiscordClient(discord.Client): except CommandError as e: await self.send_message(message.channel, 'Sorry {0}, {1}'.format(message.author.mention, e)) else: - embed = discord.Embed(title=bellagram['title'], url=bellagram['url'], color=0xd2a517) + embed = discord.Embed(title=bellagram['caption'], url=bellagram['url'], color=0xd2a517) embed.set_image(url=bellagram['display_url']) - embed.set_author(name=bellagram['owner'], url=bellagram['owner_url'], - icon_url=bellagram['owner_pic_url']) + embed.set_author(name=bellagram['owner_username'], url=bellagram['owner_url'], + icon_url=bellagram['owner_profile_pic_url']) await self.send_message(message.channel, embed=embed) @cooldown(retries=3, timeout=5*60, failure=_cooldown_failure) diff --git a/commands.py b/commands.py index ab5c9e9..d10df5d 100644 --- a/commands.py +++ b/commands.py @@ -1,13 +1,12 @@ import datetime -import random import dateutil.parser import requests -from services.instagram import Instagram, InstagramError from services.youtube import Youtube, YoutubeError +INSTAGRAM_BASE_URL = 'https://www.instagram.com' CLIPS_BASE_URL = 'https://clips.twitch.tv' @@ -19,7 +18,6 @@ class Commands(object): def __init__(self, config, logger): self.config = config self.logger = logger - self._bellagrams = self._collect_bellagrams() def add_quote(self, id, text, game, date): try: @@ -128,9 +126,20 @@ class Commands(object): return quote def bellagram(self): - if not self._bellagrams: - raise CommandError('couldn\'t get any media from Instagram') - return random.choice(self._bellagrams) + keyword = self.config['Instagram'].get('keyword') + try: + media = self._get_instagram_media(dict( + filter=keyword, + type='GraphImage', + sort_order='random', + page_size=1)).json() + bellagram = media.pop(0) + bellagram['url'] = '{0}/p/{1}'.format(INSTAGRAM_BASE_URL, bellagram['shortcode']) + bellagram['owner_url'] = '{0}/{1}'.format(INSTAGRAM_BASE_URL, bellagram['owner_username']) + except (requests.exceptions.HTTPError, IndexError): + raise CommandError('no bellagrams found') + else: + return bellagram def query_youtube(self, query): api_key = self.config['Youtube'].get('api_key') @@ -158,6 +167,12 @@ class Commands(object): else: return clip + def _get_instagram_media(self, params): + api_url = self.config['Instagram'].get('api_url') + r = requests.get('{0}/media'.format(api_url), params=params) + r.raise_for_status() + return r + def _get_quotes(self, params): api_url = self.config['Quotes'].get('api_url') r = requests.get('{0}/quotes'.format(api_url), params=params) @@ -236,16 +251,3 @@ class Commands(object): r = requests.get('{0}/clips'.format(api_url), params=params) r.raise_for_status() return r - - def _collect_bellagrams(self): - username = self.config['Instagram'].get('username') - keywords = self.config['Instagram'].get('keywords').split(',') - instagram = Instagram(username) - try: - media = instagram.get_media() - media = [m for m in media if [k for k in keywords \ - if m['type'] == 'Image' and k.lower() in m['title'].lower()]] - except (InstagramError, TypeError, KeyError): - return None - else: - return media diff --git a/services/instagram.py b/services/instagram.py deleted file mode 100644 index 8d5c07f..0000000 --- a/services/instagram.py +++ /dev/null @@ -1,92 +0,0 @@ -import hashlib -import json -import re - -import requests - - -BASE_URL = 'https://www.instagram.com' - -QUERY_HASH = '42323d64886122307be10013ad2dcc44' - -SHARED_DATA = re.compile(r'window\._sharedData = (\{.*\});') - - -class InstagramError(Exception): - pass - - -class Instagram(object): - def __init__(self, username): - self.username = username - shared_data = self._get_shared_data() - try: - graphql = shared_data['entry_data']['ProfilePage'][0]['graphql'] - self.user_id = graphql['user']['id'] - self.rhx_gis = shared_data['rhx_gis'] - self.owner = dict( - name=graphql['user']['username'], - profile_pic_url=graphql['user']['profile_pic_url']) - except (IndexError, KeyError, TypeError): - self.user_id = None - self.rhx_gis = None - - def _get_shared_data(self): - r = requests.get('{0}/{1}'.format(BASE_URL, self.username)) - if not r.ok: - return None - m = SHARED_DATA.search(r.text) - if m: - return json.loads(m.group(1)) - return None - - def _get_media(self): - def request(count, cursor): - variables = json.dumps(dict( - id=self.user_id, - first=count, - after=cursor)) - gis = '{0}:{1}'.format(self.rhx_gis, variables) - gis = hashlib.md5(gis.encode('UTF-8')).hexdigest() - url = '{0}/graphql/query'.format(BASE_URL) - params = dict( - query_hash=QUERY_HASH, - variables=variables) - r = requests.get(url, params=params, headers={'X-Instagram-GIS': gis}) - r.raise_for_status() - return r.json() - result = [] - try: - count = 50 - cursor = '' - while True: - data = request(count, cursor) - data = data['data']['user']['edge_owner_to_timeline_media'] - for edge in data['edges']: - result.append(dict( - type=edge['node']['__typename'].split('Graph')[1], - title=edge['node']['edge_media_to_caption']['edges'][0]['node']['text'], - url='{0}/p/{1}'.format(BASE_URL, edge['node']['shortcode']), - display_url=edge['node']['display_url'], - owner=self.owner['name'], - owner_url='{0}/{1}'.format(BASE_URL, self.username), - owner_pic_url=self.owner['profile_pic_url'])) - cursor = data['page_info']['end_cursor'] - if not cursor: - break - except KeyError: - return None - else: - return result - - def get_media(self): - if not self.user_id: - return None - try: - result = self._get_media() - except requests.exceptions.HTTPError as e: - raise InstagramError('Failed to retrieve media: {0}'.format(e)) - except json.decoder.JSONDecodeError as e: - raise InstagramError('Failed to retrieve media: {0}'.format(e)) - else: - return result diff --git a/settings.cfg.example b/settings.cfg.example index 022871f..67443dc 100644 --- a/settings.cfg.example +++ b/settings.cfg.example @@ -32,15 +32,15 @@ announcement_pattern = Live now! Playing {game} - Bring Cheese! {url} cache_api_url = https://ladylilia.com/twitch-cache/api token = oauth:__TWITCH_OAUTH_TOKEN__ -[Instagram] -username = lilialovesgames -keywords = #bellameeze,bella,teeny,kitty,cat,😹,😻,🐱,🐈 - [Youtube] api_key = __GOOGLE_API_KEY__ # Lady Lilia, Lilia Live channel_ids = UC5970RJMoEcRNZl0MNp8tlQ,UCHNjavmkFUf2n0uzWSgj16w +[Instagram] +api_url = https://ladylilia.com/instagram/api +keyword = #bellameeze + [Quotes] api_url = https://ladylilia.com/quotes/api api_key = __QUOTES_API_KEY__