Twitter bot - Replying to specific users using Tweepy - python

I'm trying to write my first twitter bot, and what I specifically want it to do is to reply when a specific user tweets something. Instead of searching for every user that mentions the word 'taco' I want to only search for when a small list of people mention 'taco'. For example, my bot only looks for tweets from Bob and Sue that mention 'taco', but not tweets from Fred. I'm not finding what I need.

From the Tweepy documentation, you should probably use the method API.user_timeline to read a specific user tweets.
API.user_timeline([user_id/screen_name])
Returns the 20 most recent statuses posted from the
authenticating user or the user specified.
Parameters:
user_id – Specifies the ID of the user
screen_name – Specifies the screen name of the user

You could accomplish this through the user timeline API endpoint; however, depending on how many terms and users you want to track, you'd have to worry about rate limits (the user timeline endpoint rate limit is pretty high, 300/app auth/15 mins, 150/user auth/15 mins = 450/15 mins), and also the fact that you'd have to call the endpoint manually at some time interval.
Another way to do this is by using the streaming API endpoint, specifically the user stream. Follow everyone you want to reply to, and then create some rules for specific phrases. As followed users post tweets, they should stream to your user stream endpoint. You'd just have to have a listener running, with some logic for tracked users/phrases.
track = {
'taco': ['Bob', 'Sue'],
'salsa': ['John', 'Steve'],
'guacamole': ['Mary', 'Fred']
}
You'd subclass Tweepy's StreamListener:
class TacoListener(tweepy.StreamListener):
def on_status(self, status):
# Note, I rolled my own Twitter API wrapper, and just had a glance at the Tweepy docs, so some of this syntax might be incorrect, change it as required
# I think Tweepy has syntax like: status.text; I'll just refer to the fields as they appear in the Twitter JSON payload
for k, v in track.items():
if k in status.get('text') and status.get('screen_name') in v:
tweet = ""
for name in v:
tweet += "#" + name
tweet += " are talking about " + k + "! Yum."
api.update_status(status=tweet)

Related

Problem with getting tweet_fields from Twitter API 2.0 using Tweepy

I have a similar problem as in this question (Problem with getting user.fields from Twitter API 2.0)
but I am using Tweepy. When making the request with tweet_fields, the response is only giving me the default values. In another fuction where I use user_fields it works perfectly.
I followed this guide, specifically number 17 (https://dev.to/twitterdev/a-comprehensive-guide-for-using-the-twitter-api-v2-using-tweepy-in-python-15d9)
My function looks like this:
def get_user_tweets():
client = get_client()
tweets = client.get_users_tweets(id=get_user_id(), max_results=5)
ids = []
for tweet in tweets.data:
ids.append(str(tweet.id))
tweets_info = client.get_tweets(ids=ids, tweet_fields=["public_metrics"])
print(tweets_info)
This is my response (with the last tweets from elonmusk) also there is no error code or anything else
Response(data=[<Tweet id=1471419792770973699 text=#WholeMarsBlog I came to the US with no money & graduated with over $100k in debt, despite scholarships & working 2 jobs while at school>, <Tweet id=1471399837753135108 text=#TeslaOwnersEBay #PPathole #ScottAdamsSays #johniadarola #SenWarren It’s complicated, but hopefully out next quarter, along with Witcher. Lot of internal debate as to whether we should be putting effort towards generalized gaming emulation vs making individual games work well.>, <Tweet id=1471393851843792896 text=#PPathole #ScottAdamsSays #johniadarola #SenWarren Yeah!>, <Tweet id=1471338213549744130 text=link>, <Tweet id=1471325148435394566 text=#24_7TeslaNews #Tesla ❤️>], includes={}, errors=[], meta={})
I found this link: https://giters.com/tweepy/tweepy/issues/1670. According to it,
Response is a namedtuple. Here, within its data field, is a single Tweet object.
The string representation of a Tweet object will only ever include its ID and text. This was an intentional design choice, to reduce the excess of information that could be displayed when printing all the data as the string representation, as with models.Status. The ID and text are the only default / guaranteed fields, so the string representation remains consistent and unique, while still being concise. This design is used throughout the API v2 models.
To access the data of the Tweet object, you can use attributes or keys (like a dictionary) to access each field.
If you want all the data as a dictionary, you can use the data attribute/key.
In that case, to access public metrics, you could maybe try doing this instead:
tweets_info = client.get_tweets(ids=ids, tweet_fields=["public_metrics"])
for tweet in tweets_info.data:
print(tweet["id"])
print(tweet["public_metrics"])

how to read twitter list of dm from a specific message id using tweepy 3.10.0

I am trying to fetch the twitter dms since a specific message id. But it returns all the dms. can anyone help to get this done. I was trying with the following code snippet
since_id = '134902xxxxxxxxx'
while True:
#last_dms = tweepy.Cursor(api.list_direct_messages, max_id=since_id).items()
last_dms = api.list_direct_messages(10, max_id = since_id)
for messages in last_dms:
print(messages._json)
#since_id = last_dms[0]["id"]
print('since_id %d:', since_id)
time.sleep(30)
with the above code i am able to get all dms from the userid. need hel to get the dms since a specific message id.
The list_direct_messages does not support the max_id, see Twitter API reference which is the REST endpoint invoked by Tweepy.
You have 2 options:
delete the DM after it is processed (ie already replied), hence at the next call it won't be returned by Twitter
you need to implement the max_id concept yourself: at every iteration keep the DM id (after you reply) and ignore DMs which have a smaller ID. The inconvenience here is that you need to persist the ID (in a database for example) to ensure it is still available after a restart/redeployment

Twython help: Is there a way to search for twitter users with a certain keyword in their bio?

I'm trying to identify interesting people to follow on Twitter. To do this,
I want to find users who post a tweet containing various keywords and then
filter out users whose bios don't contain certain keywords.
I'm using the following code to identify the tweets, and then automatically
follow the users who tweeted them:
naughty_words = ["example"]
good_words = ["example", "example"]
filter = " OR ".join(good_words)
blacklist = " -".join(naughty_words)
keywords = filter + blacklist
twitter = Twython(consumer_key, consumer_secret, access_token,
access_token_secret)
search_results = twitter.search(q=keywords, count=10)
try:
for tweet in search_results["statuses"]:
try:
st=tweet["entities"]["user_mentions"]
if st != []:
twitter.create_friendship(screen_name=st[0]["screen_name"])
except TwythonError as e:
print(e)
except TwythonError as e:
print(e)
This code is working great, but I want to filter my results more, as this
method returns a lot of users that I don't want to follow! Does anyone know
how I could amend this to include a second filter that looks at users'
bios?
According to the Twitter Doc, you can search for users based on a query string. However, if I check the Twython API documentation, it seems that this call is not directly supported. Tweepy, on the other hand, provides a corresponding method API.search_users, see here.
I don't think that you can search for users and tweets in one request. So might might have to stick to your current tweet search, and check each tweet if you have already seen this users. If not, you have to get the user's profile and check if they satisfy your conditions (probably batches of users to limit the number of API calls).
Edit: You probably can use Twython to search for users as well. While it does not provide a dedicated method, it provides a generic method get where you can make calls to any endpoint. So it might look something like :
get('users/search', params={'q': 'soccer music -sex -porn'})
I haven't tried it myself, but that's what I can get from the Twython Docs.

retrieve Soundcloud user resource from Soundcloud track resource

I am trying to 'trace back' from a given Soundcloud track resource object to the Soundcloud user resource object that created it. Given my understanding of the Soundcloud API this is what I have done.
1st: Retrieve a specific track
track = client.get('/tracks', title="White Lies (feat. Jenni Potts)",
limit=1)
This should return a collection of one track (by Odesza).
2nd: Gather info about tracks user from track resource
white_lies_perma = track[0].user["permalink"]
white_lies_uID = track[0].user["id"]
3rd: Get the user (hopefully) using the above filters
users = client.get('/users',
id=white_lies_uID,
permalink=white_lies_perma)
This should return 1 user, however the length of the resource collection is 50 (the API default). This is strange.
Printing the values:
for user in users:
print(user.id)
79582
2684450
3765692
9918957
12470953
etc...
This should just be a collection of length 1, containing a resource with id 18604897.
Furthermore, this code should reasonably return "Oklahoma City" twenty times over. However when run it gives me "Cape St Francis", "Augusta", "London U.K".
client = soundcloud.Client(client_id='xxxxx')
okcUsers = client.get('/users',city="Oklahoma City",limit=20)
for okcUser in okcUsers:
print okcUser.city
Is something wrong with Soundcloud's API?
Not sure how you implemented those filters in your 3rd call, but I think you should get the information you needed if you do
users = client.get('/users/%d' % white_lies_uID)
Since you do not need to do a search but just call the correct /users/ endpoint. To see which endpoints are available for a specific user go to https://developers.soundcloud.com/docs/api/reference#users and scroll down to below the list of fields a user contains. There you see a list of endpoints that can be called once you have a user id.

Twython getting tweets from user

I am using Twython to get a stream of tweets. I used this tutorial, expect that I am not using GPIO.
My code is the following:
import time
from twython import TwythonStreamer
TERMS='#stackoverflow'
APP_KEY='MY APP KEY'
APP_SECRET='MY APP SECRET'
OAUTH_TOKEN='MY OATH TOKEN'
OAUTH_TOKEN_SECRET='MY OATH TOKEN SECRET'
class BlinkyStreamer(TwythonStreamer):
def on_success(self, data):
if 'text' in data:
print data['text'].encode('utf-8')
try:
stream = BlinkyStreamer(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
stream.statuses.filter(track=TERMS)
except KeyboardInterrupt
That outputs a stream of all tweets containing #stackoverflow. But I want to output the tweet if it is from a certain user, e.g. #StackStatus.
I am running this on a Raspberry Pi.
How would I do that? Any help is appreciated!
Edit: if there is another, other or easier, way to execute some script when a new tweet is placed by some user, please let me know, this would solve my question as well!
The 'follow' parameter does not work as stated above by teknoboy. Correct usage is with the user's ID, not their screen name. You can get user IDs using http://gettwitterid.com/.
The third parameter available is Location - you can use 1, 2 or 3 of then as desired. They become linked with "OR", not 'AND'.
Example Usage:
SearchTerm = 'abracadabra' # If spaces are included, they are 'OR', ie finds tweets with any one of the words, not the whole string.
Tweeter = '25073877' # This is Donald Trump, finds tweets from him or mentioning him
Place = '"47.405,-177.296,1mi"' # Sent from within 1 mile of Lat, Long
stream.statuses.filter(track=SearchTerm, follow=Tweeter, location=Place)
you should supply the filter with the follow parameter to stream specific users' tweets.
if you wish to only follow one user, you can define
FOLLOW='StackStatus'
and change the appropriate line to
stream.statuses.filter(track=TERMS, follow=FOLLOW)
if you wish to see all the user's tweets, regardless of keyword, you can omit the track parameter:
stream.statuses.filter(follow=FOLLOW)

Categories