How to disconnect the stream (Tweepy)? - twitter

I'm trying to update the stream every 15 minutes to change its rules.
As far as I understand it is impossible to update the filter rules in real time. So I try to stop the stream and then start it again.
class MyStream(tweepy.StreamingClient):
def disconnect(self):
self.running=False
print('stop stream)
stream = MyStream(bearer_token=bearer_token, wait_on_rate_limit=True)
stream.disconnect()
But it doesn't work. Streaming continues to work.
Can you please tell me how to reallocate what I have in mind?
update
I try to add a rule to the stream, then wait 10 seconds and add another one. But it doesn't work. Can you please tell me what the problem is and how to fix it?
import telebot
import tweepy
import time
bot = telebot.TeleBot()
api_key =
api_key_secret =
bearer_token =
access_token =
access_token_secret =
client = tweepy.Client(bearer_token, api_key, api_key_secret, access_token, access_token_secret)
auth = tweepy.OAuth1UserHandler(api_key, api_key_secret, access_token, access_token_secret)
api = tweepy.API(auth)
class MyStream(tweepy.StreamingClient):
def on_connect(self):
print('Connected')
def on_response(self, response):
print(response)
stream = MyStream(bearer_token=bearer_token, wait_on_rate_limit=True)
rules = ['book', 'tree', 'word']
#create the stream
for rule in rules:
stream.add_rules(tweepy.StreamRule(rule))
print('Showing the rule')
print(stream.get_rules().data)
stream.filter(tweet_fields=["referenced_tweets"])
# this part of the code no longer works.
print('sleep 10 sec')
time.sleep(10)
# this part not working too
print('Final Streaming Rules:')
print(stream.get_rules().data)

In Twitter API v2 (Tweepy using the tweepy.client interface and StreamingClient object) the stream does not need to disconnect in order to update the rules, you do that by adding rules via StreamingClient.add_rules(). Docs:
StreamingClient.add_rules() can be used to add rules before using StreamingClient.filter() to connect to and run a filtered stream:
streaming_client.add_rules(tweepy.StreamRule("Tweepy"))
streaming_client.filter()
StreamingClient.get_rules() can be used to retrieve existing rules
and
StreamingClient.delete_rules() can be used to delete rules.

Related

How to get a user's new Tweets with a Telegram Python bot while run_polling?

I'm currently developing a Telegram bot using telegram-python-bot and tweepy.
I want to create a feature that allows users of the bot to add their Twitter ID list via Telegram and have their new Tweets sent to them in real-time.
I want that the bot should be application.run_polling() to receive commands from the user, and at the same time, forwarding new tweets from Twitter users in users individual list.
When I read the tweepy documentation, I realized that I can get real-time tweets with fewer api requests if I fetch them through MyStream(auth=auth, listener=None).
But I don't know how to get both functions to work on the same file at the same time.
version
nest_asyncio-1.5.6 python_telegram_bot-20.0 tweepy-4.12.1
def main() -> None:
application = Application.builder().token("...").build()
add_list = ConversationHandler(
entry_points=[CallbackQueryHandler(input_id, pattern='input_id')],
states={ADD :[MessageHandler(filters.TEXT & ~filters.COMMAND, add)],},
fallbacks=[CallbackQueryHandler(button,pattern='back')])
application.add_handler(CommandHandler("on", on))
application.add_handler(add_list)
application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("list", list_setting))
application.add_handler(CommandHandler("admin", admin))
application.add_handler(CommandHandler("help", help_command))
application.add_handler(CallbackQueryHandler(button))
application.run_polling()
if __name__ == "__main__":
main()
This is my main statement and I made it work until the SIGINT(ctrl+c) came in via application.run_polling().
I want to combine the above code to run and do the following at the same time.
import tweepy
consumer_key = "..." # Twitter API Key
consumer_secret = "..." # Twitter API Secret Key
access_token = "..." # Twitter Access Key
access_token_secret = "..." # Twitter Access Secret Key
usernames = ['...']
auth = tweepy.OAuth1UserHandler(
consumer_key, consumer_secret, access_token, access_token_secret
)
# Convert screen names to user IDs
user_ids = []
for username in usernames:
user = tweepy.API(auth).get_user(screen_name=username)
user_ids.append(str(user.id))
# Create a custom stream class
class MyStream(tweepy.Stream):
def __init__(self, auth, listener=None):
super().__init__(consumer_key, consumer_secret, access_token, access_token_secret)
def on_status(self, status):
tweet_url = f"https://twitter.com/{status.user.screen_name}/status/{status.id_str}"
print(f"{status.user.screen_name} tweeted: {status.text}\n{tweet_url}")
# send message to telegram
# Create a stream object with the above class and authentication
myStream = MyStream(auth=auth, listener=None)
# Start streaming for the selected users
myStream.filter(follow=user_ids)
I also tried to use thread's interval function or python-telegram-bot's job_queue.run_repeating function,
but these seem problematic for forwarding messages in real time.
I'm desperately looking for someone to help me with this😢.

Twilio - Quick question (Unable to update record)

hope you are doing it right these days.
To summarize my problem, I think this is not working becuase I am using a free Twilio account instead of a paid one. But that's just my beginner theory. Now, the issue:
I have tried an official Twilio tutorial (https://www.twilio.com/blog/automating-ngrok-python-twilio-applications-pyngrok, I shared the link in case someone finds it interesting or needs it), which allows us to automate SMS webhook (sms_url) configuration by using Client (twilio) and pyngrok (ngrok).
def start_ngrok():
from twilio.rest import Client
from pyngrok import ngrok
url = ngrok.connect(5000)
print(' * Tunnel URL:', url)
client = Client()
client.incoming_phone_numbers.list(
phone_number=os.environ.get('TWILIO_PHONE_NUMBER'))[0].update(
sms_url=url + '/bot')
I can't explain all the things that I tried in the last 4 days, with no success. I keep getting the same error:
client.incoming_phone_numbers.list(phone_number=os.environ.get('TWILIO_PHONE_NUMBER'))[0].update(sms_url=url + '/bot')
IndexError: list index out of range
Something is not working with the list, it comes empty, although environment variables are working properly. I will work with just one phone_number, so there no need for list, indeed, so I started to change that line to avoid different errors and ended up with this:
def start_ngrok():
from twilio.rest import Client
from pyngrok import ngrok
url = ngrok.connect(5000)
print(' * Tunnel URL:', url)
client = Client()
client.incoming_phone_numbers("my_number").update(sms_url=str(url) + '/bot')
Then I got the final error that I can't solve by my self:
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/twilio/rest/api/v2010/account/incoming_phone_number/__init__.py", line 442, in update
payload = self._version.update(method='POST', uri=self._uri, data=data, )
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/twilio/base/version.py", line 106, in update
raise self.exception(method, uri, response, 'Unable to update record')
twilio.base.exceptions.TwilioRestException:
HTTP Error Your request was:
POST /Accounts/my_account_SID/IncomingPhoneNumbers/+my_number.json
Twilio returned the following information:
Unable to update record: The requested resource /2010-04-01/Accounts/my_account_SID/IncomingPhoneNumbers/+my_number.json was not found
More information may be available here:
https://www.twilio.com/docs/errors/20404
I tried all different phone numbers combinations/formats: nothing works.
Thanks for your time reading all this!
Looks like something changed since the blog was written or there was a mistake.
Try the below:
The only difference is adding .public_url to the url object. Also allowed a GET to /bot for testing.
from dotenv import load_dotenv
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
load_dotenv()
app = Flask(__name__)
#app.route('/bot', methods=['POST','GET'])
def bot():
user = request.values.get('From', '')
resp = MessagingResponse()
resp.message(f'Hello, {user}, thank you for your message!')
return str(resp)
def start_ngrok():
from twilio.rest import Client
from pyngrok import ngrok
url = ngrok.connect(5000)
print('This is',url)
print(' * Tunnel URL:', url)
client = Client()
client.incoming_phone_numbers.list(
phone_number=os.environ.get('TWILIO_PHONE_NUMBER'))[0].update(
sms_url=url.public_url + '/bot')
if __name__ == '__main__':
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
start_ngrok()
app.run(debug=True)

how to listen for new tweets for an #mention using tweepy?

I am new to tweepy. And tried to implement an api which can listen the new tweets for a #mention or screen name.
tweets = api.user_timeline(screen_name=username)
But it is not listening the new tweets. Could you please help me to understand how it can be implemented so that whenever a tweet comes with '#mention'. the api should listen immediately
Creating a StreamListener
The on_data method of Tweepy’s StreamListener conveniently passes data from statuses to the on_status method.
Create class MyStreamListener inheriting from StreamListener and overriding on_status.
import tweepy
override tweepy.StreamListener to add logic to on_status
class MyStreamListener(tweepy.StreamListener):
def on_status(self, status):
print(status.text)
Creating a Stream
Need an API to stream with the right credentials for authentications. Once we have an API and a status listener we can create our stream object.
myStreamListener = MyStreamListener()
myStream = tweepy.Stream(auth = api.auth, listener=myStreamListener)
start stream
myStream.filter(track=['python'])
myStream.filter(follow=["2211149702"])
Async stream
myStream.filter(track=['python'], is_async=True)
handling errors
class MyStreamListener(tweepy.StreamListener):
def on_error(self, status_code):
if status_code == 420:
#returning False in on_error disconnects the stream
return False
# returning non-False reconnects the stream, with backoff.
Firstly, get their twitter user id using this.
Then, use this:
from tweepy import OAuthHandler
from tweepy import Stream
from tweepy import StreamListener
listener = StreamListener()
auth = OAuthHandler(config.API_KEY, config.API_SECRET)
auth.set_access_token(config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
stream = Stream(auth, listener)
stream.filter(follow=['1102105048253849600']) # user ID for random account
def on_data( self, status ):
print("Entered on_data()")
print(status.text, flush = True)
return True
...
user = api.verify_credentials()
# this is just for getting user. without this also connection can be established
if user:
print(user.id)
print('started')
twitter_stream=Stream(auth,StdOutListener())
print('Stream created...')
twitter_stream.filter(follow=[user.id_str], is_async=True)

Call more than 10 numbers at once

We need to implement simultaneous GSM calls, but as stated in documentation (https://www.twilio.com/docs/api/twiml/number), "You can specify up to ten numbers within a verb to dial simultaneously" which looks like a very tough limit.
Could anyone please suggest a workaround for this?
You can do this via the REST API: https://www.twilio.com/docs/api/rest/making-calls.
A quick example would look something like this:
# Download the Python helper library from twilio.com/docs/python/install
from twilio.rest import TwilioRestClient
# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token = "your_auth_token"
client = TwilioRestClient(account_sid, auth_token)
# The following grabs a list of numbers that have sent a message to my Twilio number.
call_list = client.messages.list(to='+1415XXXXXXX')
# Then loop through all the numbers in the list and send a call from Twilio number via REST API.
for c in call_list:
client.calls.create(to=c.from_, from_="+1415XXXXXXX", url='YOUR_VOICE_URL')

Using Doubleclick Bid Manager API

I am writing a Python program to read line items from Doubleclick Bid Manager using its API, but facing issue while making a query to getlineitems.
To Authenticate, here is my code:
authorize_url = flow.step1_get_authorize_url()
# After entering the verification for code,
code = raw_input('Code: ').strip()
credential = flow.step2_exchange(code)
I successfully get my credential as a oauth2client.client.OAuth2Credentials object.
Then using following parameters, I make a http request.
params = dict(
api_key='xxxxxxxxxxxxxxxxxx' # client secret from the API JSON file
)
url = 'https://developers.google.com/bid-manager/v1/lineitems/downloadlineitems'
r = requests.get(url = url, params=params)
But my request returns 404; not found code. Per the API guidelines (https://developers.google.com/bid-manager/v1/lineitems/downloadlineitems), you need to make following HTTP request.
POST https://www.googleapis.com/doubleclickbidmanager/v1/lineitems/downloadlineitems?key={YOUR_API_KEY}
Any help will be appreciated.
I don't know much about python, but since the call is a POST request, should you be using requests.get()? Is there a request.post() method?

Resources