#!/usr/bin/env python3 from urllib.error import HTTPError from urllib.request import urlopen, Request import logging # from requests_oauthlib import OAuth1Session from datetime import datetime import sys import json bearer = None def _format_date(dt): """convert a datetime into an RFC 822 formatted date Input date must be in GMT. Stolen from PyRSS2Gen. """ # Looks like: # Sat, 07 Sep 2002 00:00:01 GMT # Can't use strftime because that's locale dependent # # Isn't there a standard way to do this for Python? The # rfc822 and email.Utils modules assume a timestamp. The # following is based on the rfc822 module. return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()], dt.day, [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ][dt.month - 1], dt.year, dt.hour, dt.minute, dt.second, ) def getBearer(): global bearer if bearer: return bearer headers = { "Authorization": "Basic Zzl1MXI2SFpYTXg0SXU5UGs5VlNvTzFUdzpmeTIyQjN2QVRRNUI2eGthb1BFdFFRUmtuUGQ1WGZBbnBKVG5hc0ZRa3NyUm5qaVNsaw==", "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", } data = b"grant_type=client_credentials" url = "https://api.twitter.com/oauth2/token" res = urlopen(Request(url, headers=headers, data=data, method="POST")) response = json.loads(res.read().decode("UTF-8")) bearer = response["access_token"] return bearer def unshorten_urls(title, description, urls): for url in urls: shorted_url = url["url"] long_url = url["expanded_url"] if "images" in url: img = url["images"][0]["url"] long_url_html = '' else: long_url_html = '' + long_url + "" description = description.replace(shorted_url, long_url_html) title = title.replace(shorted_url, long_url) return title, description def twitter(user): # 500.000 Tweets per month # API KEY = g9u1r6HZXMx4Iu9Pk9VSoO1Tw # API SECRET KEY = fy22B3vATQ5B6xkaoPEtQQRknPd5XfAnpJTnasFQksrRnjiSlk headers = {"authorization": "Bearer " + getBearer()} # Recent = last 7 days url = ( "https://api.twitter.com/2/tweets/search/recent?query=from:" + user + "&tweet.fields=created_at,author_id,lang,source,public_metrics,entities&expansions=referenced_tweets.id,attachments.media_keys&media.fields=url" ) try: res = urlopen(Request(url, headers=headers)) response = json.loads(res.read().decode("UTF-8")) except Exception as exc: logging.error('Request to twitter failed.', exc_info=exc) return None feed = { 'title': 'Twitter: ' + user, 'url': 'https://twitter.com/' + user, 'description': 'The latest entries of the twitter account of ' + user, 'content': [] } if not response["meta"]["result_count"]: return feed feed['content'] = [parse_tweet( user, tweet, response.get("includes", {}).get("tweets", []), response.get("includes", {}).get("media", []), ) for tweet in response["data"]] return feed def parse_tweet(user, tweet, included_tweets, included_media): title = description = tweet["text"] link = "https://twitter.com/" + user + "/status/" + str(tweet["id"]) # Check included re-tweets / replace by Retweet for rt in tweet.get("referenced_tweets", []): if rt["type"] == "retweeted": rt_info = title[: title.index(":") + 2] ref_tweet = next( t for t in included_tweets if t["id"] == rt["id"] ) title = rt_info + ref_tweet["text"] description = rt_info + ref_tweet["text"] title, description = unshorten_urls( title, description, ref_tweet.get("entities", {}).get("urls", []) ) elif rt["type"] == "replied_to": description += f"

This was a reply to {rt['id']}" else: description += f"

Unknown reference type: {rt['type']}" title, description = unshorten_urls( title, description, tweet.get("entities", {}).get("urls", []) ) # Attach media enclosures = [] included_media_keys = tweet.get('attachments', {}).get('media_keys', []) for included_media_key in included_media_keys: ref_media = next( t for t in included_media if t["media_key"] == included_media_key ) if 'url' not in ref_media: continue if ref_media.get('type', '') == 'photo': description += "
" else: enclosures.append(ref_media['url']) # Append Retweets etc description += "

" description += str(tweet["public_metrics"]["retweet_count"]) + " Retweets, " description += str(tweet["public_metrics"]["like_count"]) + " Likes, " description += str(tweet["public_metrics"]["reply_count"]) + " Replies, " description += str(tweet["public_metrics"]["quote_count"]) + " Quotes" description += "
" description += "Source: " + tweet["source"] date = datetime.strptime(tweet["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ") return { "title": title, "url": link, "content": description, "date": date, "enclosures": enclosures, } def main(channel): print(twitter(channel)) if __name__ == "__main__": if len(sys.argv) != 2: print("Usage:", sys.argv[0], "") sys.exit(1) main(sys.argv[1]) # twitter('rheinbahn_intim') # twitter('realDonaldTrump')