Skip to content

Instantly share code, notes, and snippets.

@szero
Last active May 11, 2019 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szero/5801ed66e9e31aa7eda181a866b0177d to your computer and use it in GitHub Desktop.
Save szero/5801ed66e9e31aa7eda181a866b0177d to your computer and use it in GitHub Desktop.
Send tweets of given person to given volafile room
#!/usr/bin/env python3
import sys
import re
import argparse
from io import BytesIO
from random import random
from time import sleep
from functools import lru_cache
from contextlib import ExitStack
from requests import Session
from bs4 import BeautifulSoup as bs
from volapi import Room
from tweetmagick import TweetGenerator
UA = (
"Mozilla/5.0 (Linux; cli) pyrequests/0.1 "
"(python, like Gecko, like KHTML, like wget, like CURL) redtweet"
)
requests = Session()
requests.headers.update({"User-Agent": UA})
def get_text(url):
return requests.get(url).text
@lru_cache(maxsize=512)
def get_img(url):
return BytesIO(requests.get(url).content)
def parse_args():
desc = """Upload tweets of given person to a given vola room
"""
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"-t",
"--twitter",
required=True,
help="Specify twitter account to fetch stuff from",
)
parser.add_argument(
"-r",
"--room",
required=True,
help="Set vola room you want the stuff be uploaded to",
)
parser.add_argument(
"-i",
"--initial-upload",
dest="initial",
action="store_false",
default=True,
help="By default script will only upload new tweets. "
"If this option is set, program will also upload latest 5 tweets",
)
parser.add_argument(
"-v",
"--verified",
action="store_true",
default=False,
help="Set this to true if you want verified symbol in tweets",
)
parser.add_argument(
"-e",
"--retries",
default=5,
help="How many time program will retry on connection and other errors",
)
return parser.parse_args()
def main():
args = parse_args()
latest_tweet = ""
url = ""
patterns = [re.compile(r".+/(.+?)$"), re.compile(r"^([a-zA-Z0-9]+)$")]
for pattern in patterns:
match = pattern.search(args.twitter)
if match:
url = f"https://twitter.com/{match.group(1)}"
break
if not url:
raise ValueError(f"{args.twitter} isn't valid twitter username")
while args.retries:
try:
html = get_text(url)
soup = bs(html, "html.parser")
first_tweet = soup.select(".js-tweet-text")[0].text.replace("…", "").strip()
if first_tweet == latest_tweet:
sleep((random() * 30) + 60)
continue
name = soup.select(".ProfileNameTruncated-link")[0].text.strip()
longname = soup.select(".u-linkComplex-target")[0].text.strip()
avatar = get_img(soup.select(".ProfileAvatar-container")[0]["href"])
except Exception as ex:
print(f"Error: {ex}", file=sys.stderr)
args.retries -= 1
sleep((random() * 30) + 30)
continue
gathered_tweets = []
posts = (
tweet.text.replace("…", "").strip()
for tweet in soup.select(".js-tweet-text")[:5]
)
for post in posts:
if post != latest_tweet:
gathered_tweets.append(post)
else:
break
latest_tweet = first_tweet
if args.initial:
args.initial = False
sleep((random() * 30) + 30)
continue
gathered_tweets = gathered_tweets[::-1]
with ExitStack() as st:
tweets = [
st.enter_context(TweetGenerator(name, longname, avatar, txt))
for txt in gathered_tweets
]
with Room(args.room, "redtweet") as r:
for tw in tweets:
r.upload_file(
tw.tweetgen(verified=args.verified), upload_as=tw.filename
)
raise ConnectionError(f"Retries count of {args.retries} got exceeded")
if __name__ == "__main__":
try:
sys.exit(main())
except KeyboardInterrupt:
sys.exit(1)
@szero
Copy link
Author

szero commented May 10, 2019

To install requirements do pip3 install requests bs4 volapi tweetmagick
Type redtweet.py -h to learn how to use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment