Skip to content

Instantly share code, notes, and snippets.

@skyme5
Last active August 3, 2021 11:59
Show Gist options
  • Save skyme5/b5b8aa357b683fcf9124cf9d0f199e4d to your computer and use it in GitHub Desktop.
Save skyme5/b5b8aa357b683fcf9124cf9d0f199e4d to your computer and use it in GitHub Desktop.

Revisions

  1. skyme5 revised this gist Aug 3, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion tw_thread.py
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@
    Usage:
    python tw_thread.py <TWEET_ID>
    python tw_thread.py <TWEET_URL>
    By default it tries to read tokens from Environment, you can supply them in
    script by assigning values to CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN,
  2. skyme5 revised this gist Aug 3, 2021. 1 changed file with 10 additions and 3 deletions.
    13 changes: 10 additions & 3 deletions tw_thread.py
    Original file line number Diff line number Diff line change
    @@ -82,20 +82,27 @@ def pretty_tweet(tweet):

    class Listener(StreamListener):
    def __init__(self, conversation_id):
    super(Listener, self).__init__()
    self.conversation_id = conversation_id
    super(Listener, self).__init__()

    def on_status(self, status):
    if status.in_reply_to_status_id_str == conversation_id:
    if status.in_reply_to_status_id_str == self.conversation_id:
    pretty_tweet(status)

    def on_error(self, status_code):
    print(status_code)
    return False


    conversation_id = sys.argv[1]
    conversation_id = sys.argv[1].split("/").pop().split("?")[0]
    source = api.get_status(id=conversation_id, tweet_mode="extended")

    if source.in_reply_to_status_id_str:
    print("Getting first tweet")
    conversation_id = source.in_reply_to_status_id_str
    source = api.get_status(id=conversation_id, tweet_mode="extended")


    source_name = source.author.screen_name
    source_id = source.author.id_str

  3. skyme5 created this gist Aug 3, 2021.
    21 changes: 21 additions & 0 deletions LICENSE
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    MIT License

    Copyright (c) 2021 Aakash Gajjar

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
    130 changes: 130 additions & 0 deletions tw_thread.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,130 @@
    #!/usr/bin/env python

    import re
    import sys
    import os

    from rich import print
    from rich.panel import Panel
    from rich.console import Console

    from tweepy import API
    from tweepy import Cursor
    from tweepy import OAuthHandler
    from tweepy import Stream
    from tweepy.streaming import StreamListener

    """ Stream Twitter threads using Tweepy in Console.
    Installation: It requires two python packages, install them using
    `pip install tweepy rich --user`
    Usage:
    python tw_thread.py <TWEET_ID>
    By default it tries to read tokens from Environment, you can supply them in
    script by assigning values to CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN,
    ACCESS_TOKEN_SECRET.
    Or set them in environment variable with the following names
    CONSUMER_KEY => TW_KEY
    CONSUMER_SECRET => TW_SKEY
    ACCESS_TOKEN => TW_TOK
    ACCESS_TOKEN_SECRET => TW_STOK
    Access Tokens can be generated from here,
    https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens.html
    """

    CONSUMER_KEY = os.environ.get("TW_KEY")
    CONSUMER_SECRET = os.environ.get("TW_SKEY")
    ACCESS_TOKEN = os.environ.get("TW_TOK")
    ACCESS_TOKEN_SECRET = os.environ.get("TW_STOK")

    auth = OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    api = API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)

    console = Console()

    history = []
    heading_template = """[bold bright_white]{}[/] ([grey50]@{}[/]) · [yellow]{}[/]"""
    tweet_template = (
    """{}\n\n[light_sky_blue3]https://twitter.com/{}/status/{}[/light_sky_blue3]"""
    )


    def print_heading(tweet):
    timestamp = tweet.created_at.strftime("%A, %d. %B %Y %I:%M%p")
    username = tweet.author.screen_name
    name = tweet.author.name
    console.rule(heading_template.format(name, username, timestamp), align="left")


    def pretty_tweet(tweet):
    if not tweet.id in history:
    history.append(tweet)
    username = tweet.author.screen_name
    tweet_id = tweet.id_str
    content = tweet.full_text

    hashtags = re.findall(r"(#\w*[0-9a-zA-Z]+\w*[0-9a-zA-Z])", content)

    for tag in hashtags:
    highlight = "[yellow]{}[/yellow]".format(tag)
    content = content.replace(tag, highlight)

    console.print(Panel(tweet_template.format(content, username, tweet_id)))


    class Listener(StreamListener):
    def __init__(self, conversation_id):
    super(Listener, self).__init__()
    self.conversation_id = conversation_id

    def on_status(self, status):
    if status.in_reply_to_status_id_str == conversation_id:
    pretty_tweet(status)

    def on_error(self, status_code):
    print(status_code)
    return False


    conversation_id = sys.argv[1]
    source = api.get_status(id=conversation_id, tweet_mode="extended")
    source_name = source.author.screen_name
    source_id = source.author.id_str

    print_heading(source)

    replies = Cursor(
    api.search,
    q="from:{} conversation_id:{}".format(source_name, conversation_id),
    tweet_mode="extended",
    timeout=999999,
    ).items(1000)

    conversations = []

    for reply in replies:
    conversations.append(reply)

    conversations.append(source)

    for tweet in reversed(conversations):
    pretty_tweet(tweet)

    listener = Listener(conversation_id=conversation_id)

    stream = Stream(auth=api.auth, listener=listener, tweet_mode="extended")

    try:
    stream.filter(follow=[source_id])
    except KeyboardInterrupt:
    print("Bye.")
    finally:
    stream.disconnect()