wiki-postbot/wiki_postbot/thread.py

103 lines
3.0 KiB
Python

from wiki_postbot.creds import Creds
import tweepy
import typing
import re
from pathlib import Path
from dataclasses import dataclass
@dataclass
class Author:
username: str
name: str
class Thread:
def __init__(self,
tweets: typing.List[tweepy.tweet.Tweet],
responses: typing.List[tweepy.Response]
):
self.tweets = tweets
self.responses = responses
self.pdf = None
self.sort()
@property
def text(self) -> str:
"""
Text from all the tweets in a thread, double new lines between each
also replacing any @'s with markdown links to profiles i guess
"""
text = "\n\n".join([t.text for t in self.tweets])
# make @'s links
text = re.sub(r"@([\w\d_]{1,})", r"[@\1](https://twitter.com/\1)", text)
return text
@property
def author(self) -> Author:
return Author(
"@" + self.responses[0].includes['users'][0].username,
self.responses[0].includes['users'][0].name,
)
@property
def title(self) -> str:
return f"{self.author.name}'s thread - {self.tweets[0].created_at.strftime('%y-%m-%d %H:%M')}"
def sort(self):
"""
sort order of tweets
"""
self.tweets = sorted(self.tweets, key=lambda x: x.created_at)
self.responses = sorted(self.responses, key=lambda x: x.data.created_at)
def to_pdf(self, output_file:typing.Optional[Path]=None,
) -> Path:
if output_file is None:
output_file = Path('.') / f"{self.tweets[0].author_id}_{self.tweets[0].created_at.isoformat()}.pdf"
pypandoc.convert_text(
self.text, to="html", format="md",
outputfile=str(output_file),
extra_args = [
'--pdf-engine=weasyprint',
f'--data-dir={Path(__file__).parent}',
'--template=./template.html',
])
self.pdf = output_file
return output_file
@classmethod
def from_tweet(cls,
creds:Creds,
response:tweepy.Response,
limit:int=100) -> 'Thread':
"""
Starting with the mentioned tweet, get all of the tweets in a thread in order
"""
tweet = response.data
client = tweepy.Client(creds.bearer_token)
tweets = [tweet]
responses = [response]
while tweet.referenced_tweets is not None and len(tweet.referenced_tweets)>0 and len(tweets)<=limit:
replied = [t.id for t in tweet.referenced_tweets if t.type=="replied_to"]
if len(replied)==0:
# top tweet was qt
break
replied = replied[0]
response = client.get_tweet(id=replied, tweet_fields=[
"referenced_tweets",
"author_id",
"created_at"
], expansions=[
'author_id'
])
tweet = response.data
tweets.append(tweet)
responses.append(response)
return Thread(tweets, responses)