mirror of
				https://github.com/MCV-Software/TWBlue.git
				synced 2025-10-31 04:12:00 +00:00 
			
		
		
		
	Merge branch 'next-gen' into Win11Keymap
This commit is contained in:
		| @@ -1,8 +1,12 @@ | ||||
| TWBlue Changelog | ||||
|  | ||||
| ## 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. | ||||
| * 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. | ||||
|   | ||||
| @@ -64,12 +64,16 @@ class SearchPeopleBuffer(people.PeopleBuffer): | ||||
|             return False | ||||
|  | ||||
| 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): | ||||
|         current_time = time.time() | ||||
|         if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True: | ||||
|             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) | ||||
|             log.debug("Number of items retrieved: %d" % (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. | ||||
|         try: | ||||
|             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: | ||||
|                 thread_results.extend(thread_tweets.data) | ||||
|             # Search only replies to conversation_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: | ||||
|                 reply_results.extend(reply_tweets.data) | ||||
|         except TweepyException as e: | ||||
| @@ -135,6 +139,7 @@ class ConversationBuffer(SearchBuffer): | ||||
|             try: | ||||
|                 thread_results = self.session.twitter.lookup_statuses(ids, include_ext_alt_text=True, tweet_mode="extended") | ||||
|                 thread_results.sort(key=lambda x: x.id) | ||||
|                 self.last_thread_id = thread_results[-1].id | ||||
|                 results.extend(thread_results) | ||||
|             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)) | ||||
| @@ -144,6 +149,7 @@ class ConversationBuffer(SearchBuffer): | ||||
|             try: | ||||
|                 reply_results = self.session.twitter.lookup_statuses(ids, include_ext_alt_text=True, tweet_mode="extended") | ||||
|                 reply_results.sort(key=lambda x: x.id) | ||||
|                 self.last_reply_id = reply_results[-1].id | ||||
|                 results.extend(reply_results) | ||||
|             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)) | ||||
|   | ||||
| @@ -631,7 +631,7 @@ class Session(base.baseSession): | ||||
|                     if i["type"] == "photo": | ||||
|                         self.api_call(call_name="create_media_metadata", media_id=img.media_id, alt_text=i["description"]) | ||||
|                     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"] | ||||
|  | ||||
|     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": | ||||
|                     self.api_call(call_name="create_media_metadata", media_id=img.media_id, alt_text=i["description"]) | ||||
|                 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): | ||||
|         if attachment == None: | ||||
|   | ||||
| @@ -1,11 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import re | ||||
| import output | ||||
| import config | ||||
| import logging | ||||
| import requests | ||||
| import time | ||||
| import sound | ||||
| from tweepy.errors import TweepyException, NotFound, Forbidden | ||||
| log = logging.getLogger("twitter.utils") | ||||
| """ Some utilities for the twitter interface.""" | ||||
|   | ||||
| @@ -28,11 +28,3 @@ file2 = open("..\\scripts\\twblue.nsi", "w", encoding="utf-8") | ||||
| file2.write(contents) | ||||
| file2.close() | ||||
| 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"))) | ||||
		Reference in New Issue
	
	Block a user
	 GitHub
						GitHub