Giter VIP home page Giter VIP logo

sopel-twitter's Introduction

sopel-twitter

A Twitter plugin for Sopel.

Installation

Releases are hosted on PyPI, so after installing Sopel, all you need is pip:

$ pip install sopel-twitter

If you want to use the development version, simply clone the repository and use pip install path/to/sopel-twitter

Newer library versions

sopel-twitter relies on a third-party library to access data, which does not always publish its latest code to PyPI. If you run into problems with this plugin, install the latest library code and see if that solves your issue.

Please also feel free to submit pull requests updating this plugin's version constraints if you have tested a newer library release than what is currently allowed. Thanks for your help!

Configuring

Twitter account required to use this plugin as of 1 July 2023. You probably want to minimize the potential impact of adverse action by using a throwaway login instead of your real profile. New accounts can (as of 19 July 2023) be verified using only an email address.

The easiest way to configure sopel-twitter is via Sopel's configuration wizard – simply run sopel-plugins configure twitter and enter the values for which it prompts you.

Otherwise, you can edit your bot's configuration file:

[twitter]
username = mybotaccount
password = s3cretb0tp@ss
# Both Required

show_quoted_tweets = True
# Optional: For quote-tweets, send a second message showing the quoted tweet?
# Default: True

alternate_domains =
    fxtwitter.com
    vxtwitter.com
    nitter.net
# Optional: What other domains should we treat like twitter domains?
# Default: fxtwitter.com, vxtwitter.com, nitter.net

Important housekeeping notes

The library this plugin uses for Twitter data access previously stored its login session data in the current working directory. For Sopel, that was the directory from which the sopel command was run.

As of sopel-twitter 1.3.1, a newer library version became available with support for storing session data in Sopel's homedir instead. You can clean up the old session files left behind by sopel-twitter 1.3.0 by running e.g. find / -type f -name 'sopel-twitter*.json' 2>/dev/null. (Running find on / tends to output numerous "Permission denied" errors, so suppressing stderr is recommended.)

Prior to the release of sopel-twitter 1.3.2, the session data filename changed upstream from .json to .tw_session. This plugin will attempt to rename the old session file if it exists, but if that fails you might want to clean up the leftover config_name.sopel-twitter.json file.

Usage

Just send a link to a tweet or profile!

You can also retrieve a user's info with the .twitinfo command:

< Wiz> .twitinfo NASA
< Sopel> [Twitter] NASA (@NASA) ✔️ | Pale Blue Dot | http://www.nasa.gov/
         | 204 friends, 46,602,251 followers | 65,377 tweets, 13,040 ♥s
         | Joined: 2007-12-19 - 20:20:32UTC | There's space for everybody. ✨

sopel-twitter's People

Contributors

dgw avatar embolalia avatar half-duplex avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

sopel-twitter's Issues

Tweets from locked accounts cause uncaught exception

Linking a tweet from a locked account (that the bot account doesn't have access to) causes an uncaught exception. This seems like an upstream tweety bug, but for now we could just catch and pass, or catch and "An error occurred... The account may be locked"?

Tested with tweety-ns 1.0.9.9 and 1.1.2, same behavior. Logs below are from 1.1.2.

22:21:49 <mal> https://twitter.com/[redacted]
22:21:50 <Sopel> Unexpected AttributeError ('NoneType' object has no attribute 'get') from mal. Message was: https://twitter.com/[redacted]

Logs:

sopel.bot            ERROR   : Unexpected AttributeError ('NoneType' object has no attribute 'get') from mal. Message was: https://twitter.com/[redacted]
Traceback (most recent call last):
  File "sopel/bot.py", line 695, in call_rule
    rule.execute(sopel, trigger)
  File "sopel/plugins/rules.py", line 1274, in execute
    exit_code = self._handler(bot, trigger)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "env/lib/python3.11/site-packages/sopel_twitter/__init__.py", line 197, in url_status
    output_status(bot, trigger, trigger.group("status"))
  File "env/lib/python3.11/site-packages/sopel_twitter/__init__.py", line 226, in output_status
    tweet = app.tweet_detail(id_)
            ^^^^^^^^^^^^^^^^^^^^^
  File "env/lib/python3.11/site-packages/tweety/bot.py", line 820, in tweet_detail
    tweet = Tweet(self, entry, response)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "env/lib/python3.11/site-packages/tweety/types/twDataTypes.py", line 42, in new_init
    init(self, *_args, **_kwargs) # noqa
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "env/lib/python3.11/site-packages/tweety/types/twDataTypes.py", line 166, in __init__
    self._format_tweet()
  File "env/lib/python3.11/site-packages/tweety/types/twDataTypes.py", line 261, in _format_tweet
    if self._tweet.get('tweet'):
       ^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'

Errors for `/i/` links are back

<xnaas> https://twitter.com/i/web/status/1521967479802798083
<+Sopel> Twitter returned an error: User not found.
<+Sopel> [Twitter] Taylor Ogan (@TaylorOgan): Another collision while on Tesla FSD Beta. https://video.twimg.com/ext_tw_video/1521910678096953344/pu/vid/1280x720/xruxYMpb1v-UOQVV.mp4?tag=12 | 20 RTs | 130 ♥s | Posted: 2022-05-04 16:38

ALL unauthenticated Twitter access has been suspended

https://techcrunch.com/2023/06/30/twitter-now-requires-an-account-to-view-tweets/

Nitter issue tracker has a tweet screenshot from Musk semi-officially classifying this as "temporary", but it's possible that—like all good hotfixes—this could actually be permanent.

What that means for this plugin depends on whether anyone (maintainers of Nitter, tweety-ns, etc.) finds a way around it. I do want to keep this plugin working for as long as possible, but it's not so much of a priority that I'd jump down the rabbit hole of building a scraper into the code here.

Response says 'op' not 'on'

12:50:20 <+ZppixBot> [ Nick🇬🇧🇪🇺 OP Twitter: "+UPDATE+ Boris Johnson requested the Queen that he use Buckingham Palace grounds “for his free time” to escape media attention and the general public." ] - twitter.com
should be
12:50:20 <+ZppixBot> [ Nick🇬🇧🇪🇺 ON Twitter: "+UPDATE+ Boris Johnson requested the Queen that he use Buckingham Palace grounds “for his free time” to escape media attention and the general public." ] - twitter.com

(In lowercase but made caps to add emphasis.)

For some reason, I can't see where the bug is so can someone look?

Cards are not handled

Tweets can have a "Card" attached. This appears to be a Twitter Ads API feature.

See e.g. https://twitter.com/TekSavvyBuzz/status/1616420405408849920

Screenshot for posterity

image

Data about these cards does not appear in the API response (tested with v1.1); even with include_entites and include_card_uri, I was unable to get any more than a card://<id> URI in the Tweet JSON, and was not able find documentation on how to get from that to anything useful for IRC display.

I'm opening this issue for the express purpose of immediately closing it as wontfix because 1) it looks very annoying to support, if it's even possible (would require at least a second API request), and 2) if it only really applies to Twitter Ads tweets, meh. The way things are going over there, building new features against Twitter's API seems like a questionable use of time anyway.


Credit as always to @xnaas for "not opening an issue" when something goes wrong. 😹

Free API deprecation

In one week, Twitter plans to shut off free API access:

01:11:36 <+xrl> Oh no. https://twitter.com/TwitterDev/status/1621026986784337922
01:11:36 <+Sopel> [Twitter] Twitter Dev (@TwitterDev): Starting February 9, we will no longer support free access to the Twitter API, both v2 and v1.1. A paid basic tier will be available instead 🧵 | 7775 RTs | 2880 ♥s | Posted: [05] Thursday, February 02, 07:05:25+0100 (CET)

Migrating to v2 no longer matters, I guess. #29 (scraping) all the way?

(Of course, Elno could change tacks on this ten times in the next week. We'll just have to see.)

No truncation indicator on super-long tweets

The code here:

bot.say(template.format(tweet=format_tweet(tweet),
RTs=tweet.retweet_counts,
hearts=tweet.likes,
posted=format_time(bot, trigger, tweet.created_on)))
if (
bot.config.twitter.show_quoted_tweets
and tweet.is_quoted
and tweet.quoted_tweet is not None
):
tweet = tweet.quoted_tweet
bot.say(template.format(tweet='Quoting: ' + format_tweet(tweet),
RTs=tweet.retweet_counts,
hearts=tweet.likes,
posted=format_time(bot, trigger, tweet.created_on)))

doesn't pass truncation to bot.say() like the similar method call in user-profile handling does:

bot.say(message, truncation=' […]')

This can even be a problem for tweets that are within the normal character limit, but contain super-long URLs.

One example is this tweet with a Bloomberg URL at the end: https://twitter.com/jasonschreier/status/1707412086651842669 (the expanded Bloomberg article link includes a very long access token, and is therefore silently dropped from the output by Sopel's default safe-length behavior)

Installation instructions?

Hi, I have just tried to install this with:

pip install sopel-modules.twitter

but despite operation seems to succeed, the module is not detected by sopel

Improve Errors

I haven't looked at the upstream tool used, but if there's a separate error message provided for 18+ (NSFW) tweets, it would be good for Sopel to reply with that, rather than saying (very incorrectly) that the tweet is not found/deleted.

[Discussion] Fallback for not using API?

We kinda chatted about this briefly once in IRC, but figured I'd open an issue for discussion, anyway.

<xnaas> ༼ つ ◕_◕ ༽つ twitter api key
<xnaas> I don't want to have a twitter account for a useful bot feature :P
<+dgw> no amount of Sponsors money could get you that lol
<xnaas> 😢
<+dgw> use a throwaway email
<xnaas> I just keep asking around randomly, hoping someone will love me someday 💔
<+dgw> love you enough to risk their own stuff getting blocked if/when Twitter finds out the keys have been shared? 🤔
<xnaas> that's true love, yes
<xnaas> I mean, personally, I only use nitter anyway, but lots of other people post normie twitter links :(
<+dgw> could make an alternate plugin that fetches from nitter? "Uses Twitter's unofficial API (no rate limits or developer account required)"
<xnaas> eh, url gets the gist of it
<xnaas> example: https://nitter.actionsack.com/NWSSanAntonio/status/1448738672040419331
<+Sopel> [url] NWS Austin/San Antonio (@NWSSanAntonio): "A much quieter evening is expected, however patchy dense fog is possible over the Coastal Plains and portions of the I-35 corridor by the early morning hours | nitter.actionsack.com
<xnaas> gud enough for someone to decide to click or not, I guess
<xnaas> :P
<+dgw> I meant an alternate plugin that sees twitter links, pretends they're links to the configured nitter instance, and fetches the full data that way
<xnaas> I know what ya meant, just saying url plugin is "good enough" :P
<xnaas> see: my laziness
<+dgw> though it �should� be possible to have sopel-twitter just use this "unofficial API" they say there is
<xnaas> that would be m.twitter.com I'm pretty sure lol
<+dgw> Is it? https://github.com/zedeus/nitter/blob/52a0b530cc35c4a8ab28b58994d8c07322a58a51/src/consts.nim#L6
<+Sopel> �[GitHub]� [zedeus/nitter] src/consts.nim @ 52a0b530cc35c4a8ab28b58994d8c07322a58a51 | L6: �  api = parseUri("https://api.twitter.com")�
<+dgw> Things that make you go hmm https://github.com/zedeus/nitter/blob/52a0b530cc35c4a8ab28b58994d8c07322a58a51/src/consts.nim#L20-L23
<+Sopel> �[GitHub]� [zedeus/nitter] src/consts.nim @ 52a0b530cc35c4a8ab28b58994d8c07322a58a51 | L20: �  graphql = api / "graphql"� […] (to L23)

Feel free to close if this is something that would never be considered or PRs accepted for. :P

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.