From a93a8d736c0ea371e7c18f16d4121478743ff219 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Oct 2019 00:31:27 +0700 Subject: [PATCH] init --- .env.example | 14 ++ .gitignore | 18 +++ Dockerfile | 15 +++ README.md | 32 +++++ crontab.txt | 1 + requirements.txt | 10 ++ run.py | 268 +++++++++++++++++++++++++++++++++++++ screenshot-get-chat_id.png | Bin 0 -> 39279 bytes send_telegram.py | 77 +++++++++++ 9 files changed, 435 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 crontab.txt create mode 100644 requirements.txt create mode 100644 run.py create mode 100644 screenshot-get-chat_id.png create mode 100644 send_telegram.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..78e8c90 --- /dev/null +++ b/.env.example @@ -0,0 +1,14 @@ +OSHI_USERNAME= + +INSTAGRAM_USER= +INSTAGRAM_PASS= + +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 +REDIS_PASSWORD= +REDIS_DB=0 + +BOT_TOKEN= +CHAT_ID= + +TELEGRAM_URL=https://api.telegram.org/bot \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f908269 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ + +*.json + +__pycache__/ + +stories/ + +*.pyc + +users\.txt + +\.idea/ + +\.vscode/\.ropeproject/ + +.env +Env/ +venv/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3bbee3f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3-alpine + + +RUN apk update && apk upgrade && pip install -U pip + +COPY . /app +WORKDIR /app +RUN pip --no-cache-dir install -r requirements.txt + +RUN crontab /app/crontab.txt +RUN touch /var/log/cron.log + +RUN ln -snf /usr/share/zoneinfo/Asia/Jakarta /etc/localtime && echo "Asia/Jakarta" > /etc/timezone + +CMD crond && tail -f /var/log/cron.log \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec8218f --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# OshiStories +Telegram bot to download your idol's latest media stories and posts + +### Requirements +* [Python 3](https://www.python.org/) +* [Redis](https://redis.io) +* [Docker](https://docker.com) + +### Settings before run +1. rename .env.example to .env +2. Add instagram username to OSHI_USERNAME with comma separated + +### How To Create & Get BOT Token +[BotFather](https://www.siteguarding.com/en/how-to-get-telegram-bot-api-token) + +### How To Get CHAT ID +1. Add bot as your friend & start chat +2. Open +``` +https://api.telegram.org/bot/getUpdates +``` +![alt text](./screenshot-get-chat_id.png) + +### Build Docker Images +```bash +$ docker build -t oshi-stories . +``` + +### Run Docker Container +```bash +$ docker run -it --rm --name oshi-stories-container -d oshi-stories +``` \ No newline at end of file diff --git a/crontab.txt b/crontab.txt new file mode 100644 index 0000000..5f8ad09 --- /dev/null +++ b/crontab.txt @@ -0,0 +1 @@ +* * * * * python3 /app/run.py story feed > /dev/null diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..497ab87 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +certifi==2019.6.16 +chardet==3.0.4 +idna==2.8 +instagram-private-api==1.6.0 +python-dateutil==2.8.0 +python-dotenv==0.10.3 +redis==3.3.8 +requests==2.22.0 +six==1.12.0 +urllib3==1.25.3 diff --git a/run.py b/run.py new file mode 100644 index 0000000..efb27f5 --- /dev/null +++ b/run.py @@ -0,0 +1,268 @@ +import argparse +import codecs +import datetime +import json +import os +import sys +import time +import subprocess + +from dotenv import load_dotenv +from xml.dom.minidom import parseString +import urllib as urllib +import send_telegram +import time +# try: +# import urllib.request as urllib +# except ImportError: + +try: + from instagram_private_api import ( + Client, ClientError, ClientLoginError, + ClientCookieExpiredError, ClientLoginRequiredError, + __version__ as client_version) +except ImportError: + import sys + + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + from instagram_private_api import ( + Client, ClientError, ClientLoginError, + ClientCookieExpiredError, ClientLoginRequiredError, + __version__ as client_version) + +from instagram_private_api import ClientError +from instagram_private_api import Client +import redis + + +def to_json(python_object): + if isinstance(python_object, bytes): + return {'__class__': 'bytes', + '__value__': codecs.encode(python_object, 'base64').decode()} + raise TypeError(repr(python_object) + ' is not JSON serializable') + + +def from_json(json_object): + if '__class__' in json_object and json_object.get('__class__') == 'bytes': + return codecs.decode(json_object.get('__value__').encode(), 'base64') + return json_object + + +def onlogin_callback(api, setting_name): + cache_settings = api.settings + redis_client.setex(setting_name, 7776000000, json.dumps(cache_settings, default=to_json)) + print('[+] New auth cookie file was made: {0!s}'.format(setting_name)) + +def login(username, password): + device_id = None + try: + settings_file = "credentials.json" + credential = redis_client.get('credentials') + if credential is None: + api = Client( + username, password, + on_login=lambda x: onlogin_callback(x, 'credentials')) + else: + cached_settings = json.loads(credential, object_hook=from_json) + device_id = cached_settings.get('device_id') + # reuse auth settings + api = Client( + username, password, + settings=cached_settings) + print('[+] Using cached login cookie for "' + api.authenticated_user_name + '".') + except (ClientCookieExpiredError, ClientLoginRequiredError) as e: + print('ClientCookieExpiredError/ClientLoginRequiredError: {0!s}'.format(e)) + + # Login expired + # Do relogin but use default ua, keys and such + api = Client( + username, password, + device_id=device_id, + on_login=lambda x: onlogin_callback(x, settings_file)) + + except ClientLoginError as e: + print('[!] Could not login: {:s}.\n[!] {:s}\n\n{:s}'.format( + json.loads(e.error_response).get("error_title", "Error title not available."), + json.loads(e.error_response).get("message", "Not available"), e.error_response)) + print('-' * 70) + sys.exit(9) + except ClientError as e: + print('[!] Client Error: {:s}'.format(e.error_response)) + print('-' * 70) + sys.exit(9) + except Exception as e: + if str(e).startswith("unsupported pickle protocol"): + print("[W] This cookie file is not compatible with Python {}.".format(sys.version.split(' ')[0][0])) + print("[W] Please delete your cookie file 'credentials.json' and try again.") + else: + print('[!] Unexpected Exception: {0!s}'.format(e)) + print('-' * 70) + sys.exit(99) + + print('[+] Login to "' + api.authenticated_user_name + '" OK!') + cookie_expiry = api.cookie_jar.auth_expires + print('[+] Login cookie expiry date: {0!s}'.format( + datetime.datetime.fromtimestamp(cookie_expiry).strftime('%Y-%m-%d at %I:%M:%S %p'))) + + return api + +def like_post(post_id): + like = ig_client.post_like(post_id) + return like + +def latest_post(username, user_id): + today = datetime.date.today() + # today = "2019-09-13" + t = time.mktime(datetime.datetime.strptime(str(today), "%Y-%m-%d").timetuple()) + t = int(t) + feed = ig_client.user_feed(user_id, min_timestamp=str(t)) + f = open("feeds.json", "w") + f.write(json.dumps(feed)) + f.close() + + for post in feed['items']: + list_media = [] + # print() + post_id = post['id'] + pk = post['code'] + k = '{}:{}:{}'.format("post", username, pk) + exist = redis_client.exists(k) + if exist == 1: + print(pk + " Exist") + continue + media_type = "photo" if post['media_type'] == 1 else "video" + if "carousel_media" in post: + carousel = True + for i, cs in enumerate(post['carousel_media'], start=1): + carousel_media_type = "photo" if cs['media_type'] == 1 else "video" + if carousel_media_type == 'photo': + list_media.append({ + "caption":"Photo #{}".format(i), + "type":"photo", + "media":cs['image_versions2']['candidates'][0]['url'] + }) + else: + list_media.append({ + "caption":"Video #{}".format(i), + "type":"video", + "media":cs['video_versions'][0]['url'] + }) + else: + carousel = False + if media_type == 'photo': + url_media = post['image_versions2']['candidates'][0]['url'] + else: + url_media = post['video_versions'][0]['url'] + post_url = "https://instagram.com/p/{}".format(pk) + caption = "[POST] from {}\n\n{}\n\nLink: {}".format(username, post['caption']['text'], post_url) + if len(caption) > 1000: + caption = caption[:1000] + '...' + + like = like_post(post_id) + + print(pk + " Sending...") + if carousel is True: + send_telegram.send_media_group(caption=caption, media=list_media) + else: + send_telegram.telegram_bot_send_media(fileType=media_type, url=url_media, caption=caption) + print(pk + " OK") + redis_client.setex(k, 86400, "True") + return + +def latest_stories(username, user_id): + feed = ig_client.user_story_feed(user_id) + if feed['reel'] is None: + print('No Update') + # exit(9) + return False + taken_at = True + feed_json = feed['reel']['items'] + + list_video = [] + list_image = [] + + for media in feed_json: + if not taken_at: + taken_ts = None + else: + if media.get('imported_taken_at'): + taken_ts = datetime.datetime.utcfromtimestamp(media.get('imported_taken_at', "")).strftime( + '%Y-%m-%d %H:%M:%S') + else: + taken_ts = datetime.datetime.utcfromtimestamp(media.get('taken_at', "")).strftime( + '%Y-%m-%d %H:%M:%S') + + is_video = 'video_versions' in media and 'image_versions2' in media + pk = media['code'] + k = '{}:{}:{}:{}'.format("story", username, "video" if is_video else "photo", pk) + exist = redis_client.exists(k) + + if exist == 0: + print('{} Sending...'.format(pk)) + caption = "[STORY] from {}" + if is_video: + data_media = { + 'url': media['video_versions'][0]['url'], + 'taken': taken_ts + } + # caption = "[VIDEO] from {}" + list_video.append(data_media) + send_telegram.telegram_bot_send_media(fileType='video', url=data_media['url'], caption=caption.format(username)) + else: + data_media = { + 'url': media['image_versions2']['candidates'][0]['url'], + 'taken': taken_ts + } + # caption = "[PHOTO] from {}" + list_image.append(data_media) + send_telegram.telegram_bot_send_media(fileType='photo', url=data_media['url'], caption=caption.format(username)) + print('{} OK'.format(pk)) + redis_client.setex(k, 86400, json.dumps(data_media)) + else: + print(pk + ' Exists') + return feed + +def download_user(user, attempt=0): + try: + if not user.isdigit(): + user_res = ig_client.username_info(user) + user_id = user_res['user']['pk'] + else: + user_id = user + user_info = ig_client.user_info(user_id) + if not user_info.get("user", None): + raise Exception("No user is associated with the given user id.") + else: + user = user_info.get("user").get("username") + if "feed" in sys.argv: + print("[=] Fetch POST [=]") + latest_post(user, user_id) + if "story" in sys.argv: + print("[=] Fetch STORY [=]") + latest_stories(user, user_id) + + # print(user) + return user + except Exception as e: + print(e) + +def start(): + oshi = os.getenv('OSHI_USERNAME') + oshi = oshi.split(',') + print('------------------------------') + for o in oshi: + print("Oshi: "+ o) + download_user(o) + +if __name__ == '__main__': + load_dotenv() + try: + redis_client = redis.Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=os.getenv('REDIS_DB'), password=os.getenv('REDIS_PASSWORD')) + print("Connection to redis has been established...") + except Exception as e: + print("Cannot connect to redis...") + print(e) + username = os.getenv('INSTAGRAM_USER') + password = os.getenv('INSTAGRAM_PASS') + ig_client = login(username, password) + start() diff --git a/screenshot-get-chat_id.png b/screenshot-get-chat_id.png new file mode 100644 index 0000000000000000000000000000000000000000..d7bc21bb6602c35f3fc627081c5eed9bae30d619 GIT binary patch literal 39279 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 literal 0 HcmV?d00001 diff --git a/send_telegram.py b/send_telegram.py new file mode 100644 index 0000000..70e78a2 --- /dev/null +++ b/send_telegram.py @@ -0,0 +1,77 @@ +import os +import time +import requests +from dotenv import load_dotenv +import json + +def telegram_bot_sendtext(bot_message): + send_text = TELEGRAM_URL + BOT_TOKEN + '/sendMessage?chat_id={}&text={}'.format(CHAT_ID,bot_message) + response = requests.get(send_text) + response_json = response.json() + return response.json() + +def send_media_group(**kwargs): + caption = kwargs.get('caption') + media = kwargs.get('media') + carousel = kwargs.get('carousel', None) + + send_text = telegram_bot_sendtext(caption); + if send_text['ok'] is not True: + print('Stop') + return + else: + message_id = send_text.get('result')['message_id'] + + data = { + 'chat_id' : CHAT_ID, + "reply_to_message_id":message_id, + "media": json.dumps(media) + } + send_url = TELEGRAM_URL + '{}{}'.format(BOT_TOKEN, '/sendMediaGroup') + response = requests.post(send_url, data=data) + response_json = response.json() + if response_json.get('ok') is True: + print('DONE') + return response_json + +def telegram_bot_send_media(**kwargs): + fileType = kwargs.get('fileType') + url = kwargs.get('url', None) + caption = kwargs.get('caption') + reply_first = kwargs.get('reply_first', False) + reply_id = kwargs.get('reply_id', None) + data = { + 'chat_id' : CHAT_ID, + "caption": caption, + } + if reply_first is True: + send_text = telegram_bot_sendtext(caption); + if send_text['ok'] is not True: + print('Stop') + return + data.update({"reply_to_message_id": send_text.get('result')['message_id']}) + if reply_id is not None: data.update({"reply_to_message_id": reply_id}) + if fileType == 'video': + data.update({ + 'video': url + }) + endpoint = "/sendVideo" + elif fileType == 'photo': + data.update({ + 'photo': url + }) + endpoint = "/sendPhoto" + else: + print("Failed") + return False + + send_url = TELEGRAM_URL + '{}{}'.format(BOT_TOKEN, endpoint) + response = requests.post(send_url,data=data) + return response.json() + + +if __name__ == 'send_telegram': + load_dotenv() + BOT_TOKEN = os.getenv('BOT_TOKEN') + CHAT_ID = os.getenv('CHAT_ID') + TELEGRAM_URL = os.getenv('TELEGRAM_URL') \ No newline at end of file