mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2024-11-26 12:53:12 -06:00
Merge branch 'next-gen' into Win11Keymap
This commit is contained in:
commit
ed765117a5
@ -1,8 +1,12 @@
|
|||||||
TWBlue Changelog
|
TWBlue Changelog
|
||||||
|
|
||||||
## changes in this version
|
## changes in this version
|
||||||
|
|
||||||
* In the Windows 11 Keymap, the default shortcut to open the keystrokes editor is now CTRL plus Alt plus Windows plus K to avoid conflicts with the new global mute microphone shortcut.
|
* We have restored conversation and threads support powered by Twitter API V2 thanks to a set of improvements we have done in the application, as well as more generous limits to Tweet monthly cap by Twitter.
|
||||||
|
* In the Windows 11 Keymap, the default shortcut to open the keystrokes editor is now CTRL+Alt+Windows+K to avoid conflicts with the new global mute microphone shortcut.
|
||||||
|
* Fixed issue when uploading attachments (images, videos or gif files) while sending tweets or replies.
|
||||||
|
|
||||||
|
## Changes in version 2021.11.12
|
||||||
|
|
||||||
* Now it is possible to create a tweet from a trending topics buffer again.
|
* Now it is possible to create a tweet from a trending topics buffer again.
|
||||||
* TWBlue now includes a completely new set of dialogs to handle tweeting, replying and sending direct messages that takes advantage of more Twitter features.
|
* TWBlue now includes a completely new set of dialogs to handle tweeting, replying and sending direct messages that takes advantage of more Twitter features.
|
||||||
* It is possible to add videos in tweets and direct messages by using the new "add" button, located in every dialog where media can be added. Twitter suggests to add videos from 5 seconds up to 2 minutes lenght, in mp4 format (video Codec H.264 and audio codec AAC). Currently, TWBlue does not check if the uploaded video complies with Twitter media requirements. You can add only a video in a tweet or direct message. No other kind of media can be added after a video is in a tweet. If the video was unable to be uploaded successfully, the tweet or direct message won't be created.
|
* It is possible to add videos in tweets and direct messages by using the new "add" button, located in every dialog where media can be added. Twitter suggests to add videos from 5 seconds up to 2 minutes lenght, in mp4 format (video Codec H.264 and audio codec AAC). Currently, TWBlue does not check if the uploaded video complies with Twitter media requirements. You can add only a video in a tweet or direct message. No other kind of media can be added after a video is in a tweet. If the video was unable to be uploaded successfully, the tweet or direct message won't be created.
|
||||||
|
@ -64,12 +64,16 @@ class SearchPeopleBuffer(people.PeopleBuffer):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
class ConversationBuffer(SearchBuffer):
|
class ConversationBuffer(SearchBuffer):
|
||||||
|
last_thread_id = None
|
||||||
|
last_reply_id = None
|
||||||
|
|
||||||
def start_stream(self, start=False, mandatory=False, play_sound=True, avoid_autoreading=False):
|
def start_stream(self, start=False, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
||||||
self.execution_time = current_time
|
self.execution_time = current_time
|
||||||
results = self.get_replies_v1(self.tweet)
|
log.debug("Retrieving conversation. Last thread ID is {}, last reply ID is {}".format(self.last_thread_id, self.last_reply_id))
|
||||||
|
results = self.get_replies(self.tweet)
|
||||||
|
log.debug("Retrieved {} items before filters.".format(len(results)))
|
||||||
number_of_items = self.session.order_buffer(self.name, results)
|
number_of_items = self.session.order_buffer(self.name, results)
|
||||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
self.put_items_on_list(number_of_items)
|
self.put_items_on_list(number_of_items)
|
||||||
@ -117,12 +121,12 @@ class ConversationBuffer(SearchBuffer):
|
|||||||
# find all tweets replying to the original thread only. Those tweets are sent by the same author who originally posted the first tweet.
|
# find all tweets replying to the original thread only. Those tweets are sent by the same author who originally posted the first tweet.
|
||||||
try:
|
try:
|
||||||
term = "conversation_id:{} from:{} to:{}".format(conversation_id, original_tweet.data.author_id, original_tweet.data.author_id)
|
term = "conversation_id:{} from:{} to:{}".format(conversation_id, original_tweet.data.author_id, original_tweet.data.author_id)
|
||||||
thread_tweets = self.session.twitter_v2.search_recent_tweets(term, user_auth=True, max_results=98, tweet_fields=["in_reply_to_user_id", "author_id", "conversation_id"])
|
thread_tweets = self.session.twitter_v2.search_recent_tweets(term, user_auth=True, max_results=98, since_id=self.last_thread_id, tweet_fields=["in_reply_to_user_id", "author_id", "conversation_id"])
|
||||||
if thread_tweets.data != None:
|
if thread_tweets.data != None:
|
||||||
thread_results.extend(thread_tweets.data)
|
thread_results.extend(thread_tweets.data)
|
||||||
# Search only replies to conversation_id.
|
# Search only replies to conversation_id.
|
||||||
term = "conversation_id:{}".format(conversation_id, original_tweet.data.author_id)
|
term = "conversation_id:{}".format(conversation_id, original_tweet.data.author_id)
|
||||||
reply_tweets = self.session.twitter_v2.search_recent_tweets(term, user_auth=True, max_results=50, tweet_fields=["in_reply_to_user_id", "author_id", "conversation_id"])
|
reply_tweets = self.session.twitter_v2.search_recent_tweets(term, user_auth=True, max_results=50, since_id=self.last_reply_id, tweet_fields=["in_reply_to_user_id", "author_id", "conversation_id"])
|
||||||
if reply_tweets.data != None:
|
if reply_tweets.data != None:
|
||||||
reply_results.extend(reply_tweets.data)
|
reply_results.extend(reply_tweets.data)
|
||||||
except TweepyException as e:
|
except TweepyException as e:
|
||||||
@ -135,6 +139,7 @@ class ConversationBuffer(SearchBuffer):
|
|||||||
try:
|
try:
|
||||||
thread_results = self.session.twitter.lookup_statuses(ids, include_ext_alt_text=True, tweet_mode="extended")
|
thread_results = self.session.twitter.lookup_statuses(ids, include_ext_alt_text=True, tweet_mode="extended")
|
||||||
thread_results.sort(key=lambda x: x.id)
|
thread_results.sort(key=lambda x: x.id)
|
||||||
|
self.last_thread_id = thread_results[-1].id
|
||||||
results.extend(thread_results)
|
results.extend(thread_results)
|
||||||
except TweepyException as e:
|
except TweepyException as e:
|
||||||
log.exception("There was an error attempting to retrieve tweets for Twitter API V1.1, in conversation buffer {}".format(self.name))
|
log.exception("There was an error attempting to retrieve tweets for Twitter API V1.1, in conversation buffer {}".format(self.name))
|
||||||
@ -144,6 +149,7 @@ class ConversationBuffer(SearchBuffer):
|
|||||||
try:
|
try:
|
||||||
reply_results = self.session.twitter.lookup_statuses(ids, include_ext_alt_text=True, tweet_mode="extended")
|
reply_results = self.session.twitter.lookup_statuses(ids, include_ext_alt_text=True, tweet_mode="extended")
|
||||||
reply_results.sort(key=lambda x: x.id)
|
reply_results.sort(key=lambda x: x.id)
|
||||||
|
self.last_reply_id = reply_results[-1].id
|
||||||
results.extend(reply_results)
|
results.extend(reply_results)
|
||||||
except TweepyException as e:
|
except TweepyException as e:
|
||||||
log.exception("There was an error attempting to retrieve tweets for Twitter API V1.1, in conversation buffer {}".format(self.name))
|
log.exception("There was an error attempting to retrieve tweets for Twitter API V1.1, in conversation buffer {}".format(self.name))
|
||||||
|
@ -631,7 +631,7 @@ class Session(base.baseSession):
|
|||||||
if i["type"] == "photo":
|
if i["type"] == "photo":
|
||||||
self.api_call(call_name="create_media_metadata", media_id=img.media_id, alt_text=i["description"])
|
self.api_call(call_name="create_media_metadata", media_id=img.media_id, alt_text=i["description"])
|
||||||
media_ids.append(img.media_id)
|
media_ids.append(img.media_id)
|
||||||
item = self.api_call_v2(call_name="create_tweet", status=obj["text"], _sound="tweet_send.ogg", in_reply_to_tweet_id=in_reply_to_status_id, media_ids=media_ids, poll_duration_minutes=obj["poll_period"], poll_options=obj["poll_options"], quote_tweet_id=obj.get("quote_tweet_id"))
|
item = self.api_call_v2(call_name="create_tweet", text=obj["text"], _sound="tweet_send.ogg", in_reply_to_tweet_id=in_reply_to_status_id, media_ids=media_ids, poll_duration_minutes=obj["poll_period"], poll_options=obj["poll_options"], quote_tweet_id=obj.get("quote_tweet_id"))
|
||||||
in_reply_to_status_id = item.data["id"]
|
in_reply_to_status_id = item.data["id"]
|
||||||
|
|
||||||
def reply(self, text="", in_reply_to_status_id=None, attachments=[], *args, **kwargs):
|
def reply(self, text="", in_reply_to_status_id=None, attachments=[], *args, **kwargs):
|
||||||
@ -644,7 +644,7 @@ class Session(base.baseSession):
|
|||||||
if i["type"] == "photo":
|
if i["type"] == "photo":
|
||||||
self.api_call(call_name="create_media_metadata", media_id=img.media_id, alt_text=i["description"])
|
self.api_call(call_name="create_media_metadata", media_id=img.media_id, alt_text=i["description"])
|
||||||
media_ids.append(img.media_id)
|
media_ids.append(img.media_id)
|
||||||
item = self.api_call(call_name="update_status", status=text, _sound="reply_send.ogg", tweet_mode="extended", in_reply_to_status_id=in_reply_to_status_id, media_ids=media_ids, *args, **kwargs)
|
item = self.api_call_v2(call_name="create_tweet", text=text, _sound="reply_send.ogg", in_reply_to_tweet_id=in_reply_to_status_id, media_ids=media_ids, *args, **kwargs)
|
||||||
|
|
||||||
def direct_message(self, text, recipient, attachment=None, *args, **kwargs):
|
def direct_message(self, text, recipient, attachment=None, *args, **kwargs):
|
||||||
if attachment == None:
|
if attachment == None:
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import re
|
import re
|
||||||
import output
|
import output
|
||||||
import config
|
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
import sound
|
|
||||||
from tweepy.errors import TweepyException, NotFound, Forbidden
|
from tweepy.errors import TweepyException, NotFound, Forbidden
|
||||||
log = logging.getLogger("twitter.utils")
|
log = logging.getLogger("twitter.utils")
|
||||||
""" Some utilities for the twitter interface."""
|
""" Some utilities for the twitter interface."""
|
||||||
|
@ -28,11 +28,3 @@ file2 = open("..\\scripts\\twblue.nsi", "w", encoding="utf-8")
|
|||||||
file2.write(contents)
|
file2.write(contents)
|
||||||
file2.close()
|
file2.close()
|
||||||
print("done")
|
print("done")
|
||||||
print("Writing keys to module...")
|
|
||||||
file3 = open("appkeys.py", "w")
|
|
||||||
keys = """twitter_api_key = "{}"
|
|
||||||
twitter_api_secret = "{}"
|
|
||||||
""".format(os.environ.get("TWITTER_API_KEY"), os.environ.get("TWITTER_API_SECRET"))
|
|
||||||
file3.write(keys)
|
|
||||||
file3.close()
|
|
||||||
print("Wrote set of keys for consumer of {}".format(os.environ.get("TWITTER_API_KEY")))
|
|
Loading…
Reference in New Issue
Block a user