Skip to content

Commit

Permalink
update twitter api
Browse files Browse the repository at this point in the history
python-twitter appears to not handle the new twitter v2 changes,
example usage from twitter is to just call the api directly

bear/python-twitter#722
https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/Manage-Tweets/create_tweet.py#L51

which didn't work, so switched to Tweepy which is working.

Additionally the new rate limits don't like the bot bulk-posting a whole
update at once, so adjusted to just exit if we hit a rate limit. The
dynamo cache should make sure we don't miss a post or repost.

Last, the API apparently somehow now doesn't support tweets longer than
280 chars at all, so making sure we stay under budget
  • Loading branch information
adilosa committed Nov 22, 2023
1 parent 2ea5786 commit e1ee4c3
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 65 deletions.
3 changes: 2 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ verify_ssl = true
name = "pypi"

[packages]
python-twitter = "*"
requests = "*"
requests_oauthlib = "*"
"boto3" = "*"
feedparser = "*"
tweepy = "*"

[dev-packages]
"boto3" = "*"
Expand Down
58 changes: 26 additions & 32 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 26 additions & 32 deletions handler.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import json
import logging
import os
import time
from html.parser import HTMLParser

import boto3
import feedparser
import twitter
import requests
import tweepy
from botocore.client import Config
from requests_oauthlib import OAuth1Session

logger = logging.getLogger()
logger.setLevel(logging.INFO)
Expand All @@ -27,56 +28,49 @@ def get_data(self):
return "".join(self.fed)


s = MLStripper()


def strip_tags(html):
s = MLStripper()
s.feed(html)
return s.get_data()


api = twitter.Api(
**{
k: v
for k, v in json.loads(
boto3.client("s3", config=Config(signature_version="s3v4"))
.get_object(Bucket=os.environ["bucket"], Key="secrets.json")["Body"]
.read()
.decode("utf-8")
).items()
if k
in {
"consumer_key",
"consumer_secret",
"access_token_key",
"access_token_secret",
}
}
secret = json.loads(
boto3.client("s3", config=Config(signature_version="s3v4"))
.get_object(Bucket=os.environ["bucket"], Key="secrets.json")["Body"]
.read()
.decode("utf-8")
)

posts_table = boto3.resource("dynamodb", region_name="us-west-2").Table(os.environ["PostsTableName"])


def within(t: time.struct_time, minutes: int) -> bool:
return abs(time.mktime(time.gmtime()) - time.mktime(t)) <= (minutes * 60)
posts_table = boto3.resource("dynamodb", region_name="us-west-2").Table(
os.environ["PostsTableName"]
)


def already_posted(guid: str) -> bool:
return "Item" in posts_table.get_item(Key={"guid": guid})


client = tweepy.Client(**secret)

separator = "\n\n"
ellipsis = "... "

def lambda_handler(event, context):
for entry in feedparser.parse("http://aws.amazon.com/new/feed/").entries:
logger.info(f"Checking {entry.guid} - {entry.title}")
if not already_posted(entry.guid):
logger.info(f"Posting {entry.guid} - {entry.title}")
try:
api.PostUpdate(
(entry.title + "\n\n" + strip_tags(entry.description))[:249]
+ "... "
+ entry.link,
verify_status_length=False,
)
char_budget = 280 - len(entry.title) - len(entry.link) - len(separator) - len(ellipsis)
tweet_text = entry.title + separator + strip_tags(entry.description)[:char_budget] + ellipsis + entry.link
client.create_tweet(text=tweet_text)
posts_table.put_item(
Item={"guid": entry.guid, "title": entry.title, "link": entry.link}
)
except tweepy.TooManyRequests:
logger.exception("Too many requests, exiting lambda for now")
return
except Exception:
logger.exception(f"Failed to post tweet")
logger.exception("Failed to post tweet")

0 comments on commit e1ee4c3

Please sign in to comment.