Update tweepy to 4.5.0 and...polls support!
This commit is contained in:
pare
d97153d245
commit
b3025f73ca
S'han modificat 2 arxius amb 150 adicions i 52 eliminacions
200
mastotuit.py
200
mastotuit.py
|
@ -12,7 +12,6 @@ from tweepy import TweepyException
|
||||||
import logging
|
import logging
|
||||||
import filetype
|
import filetype
|
||||||
import ffmpeg
|
import ffmpeg
|
||||||
import pdb
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
@ -29,6 +28,62 @@ def get_toot_text(title):
|
||||||
|
|
||||||
return tuit_text
|
return tuit_text
|
||||||
|
|
||||||
|
def get_poll(tuit_text):
|
||||||
|
|
||||||
|
poll_substring = '[ ]'
|
||||||
|
poll_options = tuit_text.count(poll_substring)
|
||||||
|
|
||||||
|
is_poll = False if poll_options == 0 else True
|
||||||
|
|
||||||
|
options_lst = []
|
||||||
|
|
||||||
|
remain_str = tuit_text.replace('\n', '')
|
||||||
|
|
||||||
|
i = poll_options
|
||||||
|
while (i > 0):
|
||||||
|
|
||||||
|
last_option_index = remain_str.rfind('[ ]')
|
||||||
|
option_str = remain_str[last_option_index+3:].strip()
|
||||||
|
options_lst.append(option_str)
|
||||||
|
remain_str = remain_str[:last_option_index]
|
||||||
|
i-=1
|
||||||
|
|
||||||
|
if is_poll:
|
||||||
|
|
||||||
|
options_lst_copy = options_lst.copy()
|
||||||
|
options_lst_copy.reverse()
|
||||||
|
options_lst = options_lst_copy.copy()
|
||||||
|
tuit_text = remain_str
|
||||||
|
|
||||||
|
return (tuit_text, poll_options, options_lst, is_poll)
|
||||||
|
|
||||||
|
def get_toot(title):
|
||||||
|
|
||||||
|
tuit_text = get_toot_text(title)
|
||||||
|
|
||||||
|
tuit_text, poll_options, options_lst, is_poll = get_poll(tuit_text)
|
||||||
|
|
||||||
|
return (tuit_text, poll_options, options_lst, is_poll)
|
||||||
|
|
||||||
|
def compose_poll(tuit_text, poll_options, options_lst, toot_id):
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
tweet = apiv2.create_tweet(
|
||||||
|
poll_duration_minutes=4320,
|
||||||
|
poll_options = options_lst,
|
||||||
|
text=tuit_text
|
||||||
|
)
|
||||||
|
|
||||||
|
write_db(toot_id, tweet.data['id'])
|
||||||
|
|
||||||
|
except TweepyException as err:
|
||||||
|
|
||||||
|
print('Error while trying to publish poll.\n')
|
||||||
|
sys.exit(err)
|
||||||
|
|
||||||
|
return tweet
|
||||||
|
|
||||||
def compose_tweet(tuit_text, with_images, is_reply):
|
def compose_tweet(tuit_text, with_images, is_reply):
|
||||||
|
|
||||||
images_id_lst = []
|
images_id_lst = []
|
||||||
|
@ -61,7 +116,7 @@ def compose_tweet(tuit_text, with_images, is_reply):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
media_upload = api.media_upload(
|
media_upload = apiv1.media_upload(
|
||||||
f'images/{image}',
|
f'images/{image}',
|
||||||
media_category='tweet_video' if is_video else 'tweet_image'
|
media_category='tweet_video' if is_video else 'tweet_image'
|
||||||
)
|
)
|
||||||
|
@ -84,30 +139,45 @@ def compose_tweet(tuit_text, with_images, is_reply):
|
||||||
# Compose tuit
|
# Compose tuit
|
||||||
tuit_text2 = ''
|
tuit_text2 = ''
|
||||||
|
|
||||||
|
three_parts = False
|
||||||
|
|
||||||
if len(tuit_text) > 280:
|
if len(tuit_text) > 280:
|
||||||
|
|
||||||
tuit_max_length = 250 if with_images else 275
|
tuit_max_length = 250 if with_images else 273
|
||||||
|
|
||||||
tuit_text1 = '{0} (1/2)'.format(
|
tuit_text1 = '{0}...'.format(tuit_text[:tuit_max_length].rsplit(' ', 1)[0])
|
||||||
tuit_text[:tuit_max_length].rsplit(' ', 1)[0]
|
|
||||||
)
|
tuit_text2 = '{0}'.format(tuit_text[len(tuit_text1) - 2:])
|
||||||
tuit_text2 = '{0} (2/2)'.format(
|
|
||||||
tuit_text[len(tuit_text1) - 6:]
|
if len(tuit_text2) > 250:
|
||||||
)
|
|
||||||
|
three_parts = True
|
||||||
|
|
||||||
|
tuit_text2 = '{0}'.format(tuit_text[len(tuit_text1) - 2:].rsplit('#', 1)[0])
|
||||||
|
|
||||||
|
tuit_text3 = '#{0}'.format(tuit_text[len(tuit_text1) - 2:].rsplit('#', 1)[1].rsplit(' ', 2)[0])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
first_tweet = api.update_status(
|
first_tweet = apiv1.update_status(
|
||||||
status=tuit_text1,
|
status=tuit_text1,
|
||||||
in_reply_to_status_id=tweet_id if is_reply else ''
|
in_reply_to_status_id=tweet_id if is_reply else '',
|
||||||
)
|
|
||||||
|
|
||||||
tweet = api.update_status(
|
|
||||||
status=tuit_text2,
|
|
||||||
in_reply_to_status_id=first_tweet.id,
|
|
||||||
media_ids=images_id_lst
|
media_ids=images_id_lst
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tweet = apiv1.update_status(
|
||||||
|
status=tuit_text2,
|
||||||
|
in_reply_to_status_id=first_tweet.id
|
||||||
|
#media_ids=images_id_lst
|
||||||
|
)
|
||||||
|
|
||||||
|
if three_parts:
|
||||||
|
|
||||||
|
tweet = apiv1.update_status(
|
||||||
|
status=tuit_text3,
|
||||||
|
in_reply_to_status_id=tweet.id
|
||||||
|
)
|
||||||
|
|
||||||
except TweepyException as err:
|
except TweepyException as err:
|
||||||
|
|
||||||
print('Error while trying to publish split tweet.\n')
|
print('Error while trying to publish split tweet.\n')
|
||||||
|
@ -117,7 +187,7 @@ def compose_tweet(tuit_text, with_images, is_reply):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
tweet = api.update_status(
|
tweet = apiv1.update_status(
|
||||||
status=tuit_text,
|
status=tuit_text,
|
||||||
in_reply_to_status_id=tweet_id if is_reply else '',
|
in_reply_to_status_id=tweet_id if is_reply else '',
|
||||||
media_ids=images_id_lst
|
media_ids=images_id_lst
|
||||||
|
@ -164,6 +234,34 @@ def get_tweet_id(toot_id):
|
||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def write_db(toot_id, tweet_id):
|
||||||
|
|
||||||
|
sql_insert_ids = 'INSERT INTO id(toot_id, tweet_id) VALUES (%s,%s)'
|
||||||
|
|
||||||
|
conn = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
conn = psycopg2.connect(database = feeds_db, user = feeds_db_user, password = "", host = "/var/run/postgresql", port = "5432")
|
||||||
|
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
cur.execute(sql_insert_ids, (toot_id, tweet_id))
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
cur.close()
|
||||||
|
|
||||||
|
except (Exception, psycopg2.DatabaseError) as error:
|
||||||
|
|
||||||
|
print(error)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
|
||||||
|
if conn is not None:
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
def write_image(image_url):
|
def write_image(image_url):
|
||||||
|
|
||||||
if not os.path.exists('images'):
|
if not os.path.exists('images'):
|
||||||
|
@ -176,19 +274,40 @@ def write_image(image_url):
|
||||||
|
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
def create_api():
|
def create_api_v1():
|
||||||
|
|
||||||
auth = tweepy.OAuthHandler(api_key, api_key_secret)
|
auth = tweepy.OAuthHandler(api_key, api_key_secret)
|
||||||
auth.set_access_token(access_token, access_token_secret)
|
auth.set_access_token(access_token, access_token_secret)
|
||||||
api = tweepy.API(auth)
|
apiv1 = tweepy.API(auth)
|
||||||
try:
|
try:
|
||||||
api.verify_credentials()
|
apiv1.verify_credentials()
|
||||||
logged_in = True
|
logged_in = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error creating API", exc_info=True)
|
logger.error("Error creating API", exc_info=True)
|
||||||
raise e
|
raise e
|
||||||
logger.info("API created")
|
logger.info("API created")
|
||||||
return (api, logged_in)
|
return (apiv1, logged_in)
|
||||||
|
|
||||||
|
def create_api_v2():
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
apiv2 = tweepy.Client(
|
||||||
|
consumer_key=api_key,
|
||||||
|
consumer_secret=api_key_secret,
|
||||||
|
access_token=access_token,
|
||||||
|
access_token_secret=access_token_secret
|
||||||
|
)
|
||||||
|
logged_in = True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
|
||||||
|
logger.error("Error creating API", exc_info=True)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
logger.info("API v2 created")
|
||||||
|
|
||||||
|
return (apiv2, logged_in)
|
||||||
|
|
||||||
def mastodon():
|
def mastodon():
|
||||||
|
|
||||||
|
@ -235,7 +354,6 @@ def twitter_config():
|
||||||
|
|
||||||
return(api_key, api_key_secret, access_token, access_token_secret)
|
return(api_key, api_key_secret, access_token, access_token_secret)
|
||||||
|
|
||||||
# Returns the parameter from the specified file
|
|
||||||
def get_parameter( parameter, file_path ):
|
def get_parameter( parameter, file_path ):
|
||||||
# Check if secrets file exists
|
# Check if secrets file exists
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
|
@ -252,7 +370,6 @@ def get_parameter( parameter, file_path ):
|
||||||
print(file_path + " Missing parameter %s "%parameter)
|
print(file_path + " Missing parameter %s "%parameter)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# main
|
# main
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -316,46 +433,26 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
if publish:
|
if publish:
|
||||||
|
|
||||||
tuit_text = get_toot_text(title)
|
tuit_text, poll_options, options_lst, is_poll = get_toot(title)
|
||||||
|
|
||||||
print("Tooting...")
|
print("Tooting...")
|
||||||
print(tuit_text)
|
print(tuit_text)
|
||||||
|
|
||||||
if not logged_in:
|
if not logged_in:
|
||||||
|
|
||||||
api, logged_in = create_api()
|
apiv1, logged_in = create_api_v1()
|
||||||
|
|
||||||
tweet = compose_tweet(tuit_text, with_images, is_reply)
|
apiv2, logged_in = create_api_v2()
|
||||||
|
|
||||||
#########################################################
|
if is_poll:
|
||||||
|
|
||||||
sql_insert_ids = 'INSERT INTO id(toot_id, tweet_id) VALUES (%s,%s)'
|
tweet = compose_poll(tuit_text, poll_options, options_lst, toot_id)
|
||||||
|
|
||||||
conn = None
|
else:
|
||||||
|
|
||||||
try:
|
tweet = compose_tweet(tuit_text, with_images, is_reply)
|
||||||
|
|
||||||
conn = psycopg2.connect(database = feeds_db, user = feeds_db_user, password = "", host = "/var/run/postgresql", port = "5432")
|
write_db(toot_id, tweet.id)
|
||||||
|
|
||||||
cur = conn.cursor()
|
|
||||||
|
|
||||||
cur.execute(sql_insert_ids, (toot_id, tweet.id))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
cur.close()
|
|
||||||
|
|
||||||
except (Exception, psycopg2.DatabaseError) as error:
|
|
||||||
|
|
||||||
print(error)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
|
|
||||||
if conn is not None:
|
|
||||||
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
|
@ -363,3 +460,4 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
print("Any new feeds")
|
print("Any new feeds")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,6 @@ psycopg2>=2.9.1
|
||||||
feedparser>=6.0.8
|
feedparser>=6.0.8
|
||||||
html2text>=2020.1.16
|
html2text>=2020.1.16
|
||||||
Mastodon.py>=1.5.1
|
Mastodon.py>=1.5.1
|
||||||
tweepy==4.1.0
|
tweepy>=4.5.0
|
||||||
filetype>=1.0.8
|
filetype>=1.0.8
|
||||||
ffmpeg-python>=0.2.0
|
ffmpeg-python>=0.2.0
|
||||||
|
|
Loading…
Referencia en una nova incidència