From a89cc35d40409550b07204a9bda42152d3c8fc3b Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 20 Jul 2020 12:56:29 -0500 Subject: [PATCH 01/34] Started work: Added Tweepy as a dependency --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4d0eb504..bcc4a3bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,7 +25,7 @@ pypiwin32 certifi backports.functools_lru_cache cx_freeze -git+https://github.com/manuelcortez/twython +tweepy git+https://github.com/manuelcortez/libloader git+https://github.com/manuelcortez/platform_utils git+https://github.com/manuelcortez/accessible_output2 From 13f5df3a484612fdc67eb13a934b521990e0d711 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 20 Jul 2020 13:11:37 -0500 Subject: [PATCH 02/34] Use Tweepy functions for authentication and login --- src/sessions/twitter/session.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index ee2254c8..0309fd70 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -12,7 +12,8 @@ import config import output import application from pubsub import pub -from twython import Twython, TwythonError, TwythonRateLimitError, TwythonAuthError +from twython import Twython +import tweepy from mysc.thread_utils import call_threaded from keys import keyring from sessions import base @@ -115,7 +116,9 @@ class Session(base.baseSession): if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None: try: log.debug("Logging in to twitter...") - self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"]) + self.auth = tweepy.OAuthHandler(keyring.get("api_key"), keyring.get("api_secret")) + self.auth.set_access_token(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"]) + self.twitter = tweepy.API(self.auth) if verify_credentials == True: self.credentials = self.twitter.verify_credentials() self.logged = True @@ -134,19 +137,18 @@ class Session(base.baseSession): if self.logged == True: raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.") else: - twitter = Twython(keyring.get("api_key"), keyring.get("api_secret")) - self.auth = twitter.get_authentication_tokens(callback_url="oob") - webbrowser.open_new_tab(self.auth['auth_url']) + self.auth = tweepy.OAuthHandler(keyring.get("api_key"), keyring.get("api_secret")) + redirect_url = self.auth.get_authorization_url() + webbrowser.open_new_tab(redirect_url) self.authorisation_dialog = authorisationDialog() self.authorisation_dialog.cancel.Bind(wx.EVT_BUTTON, self.authorisation_cancelled) self.authorisation_dialog.ok.Bind(wx.EVT_BUTTON, self.authorisation_accepted) self.authorisation_dialog.ShowModal() def verify_authorisation(self, pincode): - twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), self.auth['oauth_token'], self.auth['oauth_token_secret']) - final = twitter.get_authorized_tokens(pincode) - self.settings["twitter"]["user_key"] = final["oauth_token"] - self.settings["twitter"]["user_secret"] = final["oauth_token_secret"] + self.auth.get_access_token(pincode) + self.settings["twitter"]["user_key"] = self.auth.access_token + self.settings["twitter"]["user_secret"] = self.auth.access_token_secret self.settings.write() del self.auth From 56103466fa24757bdc35bff141d5edd330be9853 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 20 Jul 2020 13:26:22 -0500 Subject: [PATCH 03/34] Replaced get_account_settings, get_supported_languages, show_user, get_mute_ids --- src/sessions/twitter/session.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 0309fd70..8fffc5fe 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -261,11 +261,11 @@ class Session(base.baseSession): # @_require_login def get_user_info(self): """ Retrieves some information required by TWBlue for setup.""" - f = self.twitter.get_account_settings() + f = self.twitter.get_settings() sn = f["screen_name"] self.settings["twitter"]["user_name"] = sn self.db["user_name"] = sn - self.db["user_id"] = self.twitter.show_user(screen_name=sn)["id_str"] + self.db["user_id"] = self.twitter.get_user(screen_name=sn).id try: self.db["utc_offset"] = f["time_zone"]["utc_offset"] except KeyError: @@ -273,7 +273,7 @@ class Session(base.baseSession): # Get twitter's supported languages and save them in a global variable #so we won't call to this method once per session. if len(application.supported_languages) == 0: - application.supported_languages = self.twitter.get_supported_languages() + application.supported_languages = self.twitter.supported_languages self.get_lists() self.get_muted_users() self.settings.write() @@ -281,12 +281,12 @@ class Session(base.baseSession): # @_require_login def get_lists(self): """ Gets the lists that the user is subscribed to and stores them in the database. Returns None.""" - self.db["lists"] = self.twitter.show_lists(reverse=True) + self.db["lists"] = self.twitter.lists_all(reverse=True) # @_require_login def get_muted_users(self): """ Gets muted users (oh really?).""" - self.db["muted_users"] = self.twitter.list_mute_ids()["ids"] + self.db["muted_users"] = self.twitter.mutes_ids # @_require_login def get_stream(self, name, function, *args, **kwargs): From 7ceb806af2b22461176f8bfa252ca9486711b55a Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Tue, 22 Dec 2020 17:29:33 -0600 Subject: [PATCH 04/34] Added more changes in order to deal with tweet objects --- src/controller/mainController.py | 28 +++---- src/sessions/twitter/compose.py | 118 +++++++++++++------------- src/sessions/twitter/session.py | 80 +++++++++--------- src/sessions/twitter/utils.py | 139 ++++++++++++++++--------------- 4 files changed, 183 insertions(+), 182 deletions(-) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 4ed92cd0..f6f75c54 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -304,15 +304,15 @@ class Controller(object): self.view.add_buffer(account.buffer , name=session.db["user_name"]) for i in session.settings['general']['buffer_order']: if i == 'home': - home = twitterBuffers.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended") + home = twitterBuffers.baseBufferController(self.view.nb, "home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended") self.buffers.append(home) self.view.insert_buffer(home.buffer, name=_(u"Home"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'mentions': - mentions = twitterBuffers.baseBufferController(self.view.nb, "get_mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended") + mentions = twitterBuffers.baseBufferController(self.view.nb, "mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended") self.buffers.append(mentions) self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'dm': - dm = twitterBuffers.directMessagesController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg", full_text=True, items="events") + dm = twitterBuffers.directMessagesController(self.view.nb, "list_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg", full_text=True, items="events") self.buffers.append(dm) self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'sent_dm': @@ -320,62 +320,62 @@ class Controller(object): self.buffers.append(sent_dm) self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'sent_tweets': - sent_tweets = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended") + sent_tweets = twitterBuffers.baseBufferController(self.view.nb, "user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended") self.buffers.append(sent_tweets) self.view.insert_buffer(sent_tweets.buffer, name=_(u"Sent tweets"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'favorites': - favourites = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended") + favourites = twitterBuffers.baseBufferController(self.view.nb, "favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended") self.buffers.append(favourites) self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'followers': - followers = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"]) + followers = twitterBuffers.peopleBufferController(self.view.nb, "followers", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"]) self.buffers.append(followers) self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'friends': - friends = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "friends", session, session.db["user_name"], screen_name=session.db["user_name"]) + friends = twitterBuffers.peopleBufferController(self.view.nb, "friends", "friends", session, session.db["user_name"], screen_name=session.db["user_name"]) self.buffers.append(friends) self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'blocks': - blocks = twitterBuffers.peopleBufferController(self.view.nb, "list_blocks", "blocked", session, session.db["user_name"]) + blocks = twitterBuffers.peopleBufferController(self.view.nb, "blocks", "blocked", session, session.db["user_name"]) self.buffers.append(blocks) self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) elif i == 'muted': - muted = twitterBuffers.peopleBufferController(self.view.nb, "list_mutes", "muted", session, session.db["user_name"]) + muted = twitterBuffers.peopleBufferController(self.view.nb, "mutes", "muted", session, session.db["user_name"]) self.buffers.append(muted) self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) timelines = baseBuffers.emptyPanel(self.view.nb, "timelines", session.db["user_name"]) self.buffers.append(timelines) self.view.insert_buffer(timelines.buffer , name=_(u"Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) for i in session.settings["other_buffers"]["timelines"]: - tl = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended") + tl = twitterBuffers.baseBufferController(self.view.nb, "user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended") self.buffers.append(tl) self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(i,), pos=self.view.search("timelines", session.db["user_name"])) favs_timelines = baseBuffers.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"]) self.buffers.append(favs_timelines) self.view.insert_buffer(favs_timelines.buffer , name=_(u"Likes timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) for i in session.settings["other_buffers"]["favourites_timelines"]: - tl = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended") + tl = twitterBuffers.baseBufferController(self.view.nb, "favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended") self.buffers.append(tl) self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"])) followers_timelines = baseBuffers.emptyPanel(self.view.nb, "followers_timelines", session.db["user_name"]) self.buffers.append(followers_timelines) self.view.insert_buffer(followers_timelines.buffer , name=_(u"Followers' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) for i in session.settings["other_buffers"]["followers_timelines"]: - tl = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i) + tl = twitterBuffers.peopleBufferController(self.view.nb, "followers", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i) self.buffers.append(tl) self.view.insert_buffer(tl.buffer, name=_(u"Followers for {}").format(i,), pos=self.view.search("followers_timelines", session.db["user_name"])) friends_timelines = baseBuffers.emptyPanel(self.view.nb, "friends_timelines", session.db["user_name"]) self.buffers.append(friends_timelines) self.view.insert_buffer(friends_timelines.buffer , name=_(u"Friends' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) for i in session.settings["other_buffers"]["friends_timelines"]: - tl = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i) + tl = twitterBuffers.peopleBufferController(self.view.nb, "friends", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i) self.buffers.append(tl) self.view.insert_buffer(tl.buffer, name=_(u"Friends for {}").format(i,), pos=self.view.search("friends_timelines", session.db["user_name"])) lists = baseBuffers.emptyPanel(self.view.nb, "lists", session.db["user_name"]) self.buffers.append(lists) self.view.insert_buffer(lists.buffer , name=_(u"Lists"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) for i in session.settings["other_buffers"]["lists"]: - tl = twitterBuffers.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended") + tl = twitterBuffers.listBufferController(self.view.nb, "list_timeline", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended") session.lists.append(tl) self.buffers.append(tl) self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(i), pos=self.view.search("lists", session.db["user_name"])) diff --git a/src/sessions/twitter/compose.py b/src/sessions/twitter/compose.py index 3b7abdaf..21496d2f 100644 --- a/src/sessions/twitter/compose.py +++ b/src/sessions/twitter/compose.py @@ -39,41 +39,41 @@ chars = "abcdefghijklmnopqrstuvwxyz" def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=None): """ It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is.""" if system == "Windows": - original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en") + original_date = arrow.get(tweet.created_at, "ddd MMM DD H:m:s Z YYYY", locale="en") if relative_times == True: ts = original_date.humanize(locale=languageHandler.curLang[:2]) else: ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2]) else: - ts = tweet["created_at"] - if "message" in tweet: + ts = tweet.created_at + if hasattr(tweet, "message"): value = "message" - elif "full_text" in tweet: + elif hasattr(tweet, "full_text"): value = "full_text" else: value = "text" - if "retweeted_status" in tweet and value != "message": - text = StripChars(tweet["retweeted_status"][value]) + if hasattr(tweet, "retweeted_status") and value != "message": + text = StripChars(getattr(tweet.retweeted_status, value)) else: - text = StripChars(tweet[value]) + text = StripChars(getattr(tweet, value)) if show_screen_names: - user = tweet["user"]["screen_name"] + user = tweet.user.screen_name else: - user = tweet["user"]["name"] - source = re.sub(r"(?s)<.*?>", "", tweet["source"]) - if "retweeted_status" in tweet: - if ("message" in tweet) == False and tweet["retweeted_status"]["is_quote_status"] == False: - text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text) - elif tweet["retweeted_status"]["is_quote_status"]: + user = tweet.user.name + source = re.sub(r"(?s)<.*?>", "", tweet.source) + if hasattr(tweet, "retweeted_status"): + if (hasattr(tweet, "message")) == False and tweet.retweeted_status.is_quote_status == False: + text = "RT @%s: %s" % (tweet.retweeted_status.user.screen_name, text) + elif tweet.retweeted_status.is_quote_status: text = "%s" % (text) else: - text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text) - if ("message" in tweet) == False: + text = "RT @%s: %s" % (tweet.retweeted_status.user.screen_name, text) + if not hasattr(tweet, "message"): - if "retweeted_status" in tweet: - text = utils.expand_urls(text, tweet["retweeted_status"]["entities"]) + if hasattr(tweet, "retweeted_status"): + text = utils.expand_urls(text, tweet.retweeted_status.entities) else: - text = utils.expand_urls(text, tweet["entities"]) + text = utils.expand_urls(text, tweet.entities) if config.app['app-settings']['handle_longtweets']: pass return [user+", ", text, ts+", ", source] @@ -83,76 +83,76 @@ def compose_direct_message(item, db, relative_times, show_screen_names=False, se if system == "Windows": # Let's remove the last 3 digits in the timestamp string. # Twitter sends their "epoch" timestamp with 3 digits for milliseconds and arrow doesn't like it. - original_date = arrow.get(int(item["created_timestamp"][:-3])) + original_date = arrow.get(int(item.created_timestamp[:-3])) if relative_times == True: ts = original_date.humanize(locale=languageHandler.curLang[:2]) else: ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2]) else: - ts = item["created_timestamp"] - text = StripChars(item["message_create"]["message_data"]["text"]) + ts = item.created_timestamp + text = StripChars(item.message_create.message_data.text) source = "DM" - sender = session.get_user(item["message_create"]["sender_id"]) - if db["user_name"] == sender["screen_name"]: + sender = session.get_user(item.message_create.sender_id) + if db["user_name"] == sender.screen_name: if show_screen_names: - user = _(u"Dm to %s ") % (session.get_user(item["message_create"]["target"]["recipient_id"])["screen_name"]) + user = _(u"Dm to %s ") % (session.get_user(item.message_create.target.recipient_id).screen_name) else: - user = _(u"Dm to %s ") % (session.get_user(item["message_create"]["target"]["recipient_id"])["name"]) + user = _(u"Dm to %s ") % (session.get_user(item.message_create.target.recipient_id).name) else: if show_screen_names: - user = sender["screen_name"] + user = sender.screen_name else: - user = sender["name"] + user = sender.name if text[-1] in chars: text=text+"." - text = utils.expand_urls(text, item["message_create"]["message_data"]["entities"]) + text = utils.expand_urls(text, item.message_create.message_data.entities) return [user+", ", text, ts+", ", source] def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, session=None): """ It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is.""" - if "retweeted_status" in quoted_tweet: - if "full_text" in quoted_tweet["retweeted_status"]: + if hasattr(quoted_tweet, "retweeted_status"): + if hasattr(quoted_tweet.retweeted_status, "full_text"): value = "full_text" else: value = "text" - text = StripChars(quoted_tweet["retweeted_status"][value]) + text = StripChars(getattr(quoted_tweet.retweeted_status, value)) else: - if "full_text" in quoted_tweet: + if hasattr(quoted_tweet, "full_text"): value = "full_text" else: value = "text" - text = StripChars(quoted_tweet[value]) + text = StripChars(getattr(quoted_tweet, value)) if show_screen_names: - quoting_user = quoted_tweet["user"]["screen_name"] + quoting_user = quoted_tweet.user.screen_name else: - quoting_user = quoted_tweet["user"]["name"] - source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"]) - if "retweeted_status" in quoted_tweet: - text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], text) + quoting_user = quoted_tweet.user.name + source = re.sub(r"(?s)<.*?>", "", quoted_tweet.source) + if hasattr(quoted_tweet, "retweeted_status"): + text = "rt @%s: %s" % (quoted_tweet.retweeted_status.user.screen_name, text) if text[-1] in chars: text=text+"." - original_user = original_tweet["user"]["screen_name"] - if "message" in original_tweet: - original_text = original_tweet["message"] - elif "full_text" in original_tweet: - original_text = StripChars(original_tweet["full_text"]) + original_user = original_tweet.user.screen_name + if hasattr(original_tweet, "message"): + original_text = original_tweet.message + elif hasattr(original_tweet, "full_text"): + original_text = StripChars(original_tweet.full_text) else: - original_text = StripChars(original_tweet["text"]) - quoted_tweet["message"] = _(u"{0}. Quoted tweet from @{1}: {2}").format( text, original_user, original_text) + original_text = StripChars(original_tweet.text) + quoted_tweet.message = _(u"{0}. Quoted tweet from @{1}: {2}").format( text, original_user, original_text) quoted_tweet = tweets.clear_url(quoted_tweet) - quoted_tweet["entities"]["urls"].extend(original_tweet["entities"]["urls"]) + quoted_tweet.entities.urls.extend(original_tweet.entities.urls) return quoted_tweet def compose_followers_list(tweet, db, relative_times=True, show_screen_names=False, session=None): if system == "Windows": - original_date = arrow.get(tweet["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en") + original_date = arrow.get(tweet.created_at, "ddd MMM D H:m:s Z YYYY", locale="en") if relative_times == True: ts = original_date.humanize(locale=languageHandler.curLang[:2]) else: ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2]) else: - ts = tweet["created_at"] - if "status" in tweet: - if len(tweet["status"]) > 4 and system == "Windows": - original_date2 = arrow.get(tweet["status"]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en") + ts = tweet.created_at + if hasattr(tweet, "status"): + if len(tweet.status) > 4 and system == "Windows": + original_date2 = arrow.get(tweet.status.created_at, "ddd MMM D H:m:s Z YYYY", locale="en") if relative_times: ts2 = original_date2.humanize(locale=languageHandler.curLang[:2]) else: @@ -161,14 +161,14 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal ts2 = _("Unavailable") else: ts2 = _("Unavailable") - return [_(u"%s (@%s). %s followers, %s friends, %s tweets. Last tweeted %s. Joined Twitter %s") % (tweet["name"], tweet["screen_name"], tweet["followers_count"], tweet["friends_count"], tweet["statuses_count"], ts2, ts)] + return [_(u"%s (@%s). %s followers, %s friends, %s tweets. Last tweeted %s. Joined Twitter %s") % (tweet.name, tweet.screen_name, tweet.followers_count, tweet.friends_count, tweet.statuses_count, ts2, ts)] def compose_list(list): - name = list["name"] - if list["description"] == None: description = _(u"No description available") - else: description = list["description"] - user = list["user"]["name"] - members = str(list["member_count"]) - if list["mode"] == "private": status = _(u"private") + name = list.name + if list.description == None: description = _(u"No description available") + else: description = list.description + user = list.user.name + members = str(list.member_count) + if list.mode == "private": status = _(u"private") else: status = _(u"public") return [name, description, user, members, status] diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 8fffc5fe..3b584d40 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -40,24 +40,24 @@ class Session(base.baseSession): self.db["users"] = {} if ignore_older and len(self.db[name]) > 0: if self.settings["general"]["reverse_timelines"] == False: - last_id = self.db[name][0]["id"] + last_id = self.db[name][0].id else: - last_id = self.db[name][-1]["id"] + last_id = self.db[name][-1].id for i in data: if ignore_older and last_id != None: - if i["id"] < last_id: - log.error("Ignoring an older tweet... Last id: {0}, tweet id: {1}".format(last_id, i["id"])) + if i.id < last_id: + log.error("Ignoring an older tweet... Last id: {0}, tweet id: {1}".format(last_id, i.id)) continue - if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings, name) == True: + if utils.find_item(i.id, self.db[name]) == None and utils.is_allowed(i, self.settings, name) == True: i = self.check_quoted_status(i) i = self.check_long_tweet(i) if i == False: continue if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i) else: self.db[name].insert(0, i) num = num+1 - if ("user" in i) == True: - if (i["user"]["id"] in self.db["users"]) == False: - self.db["users"][i["user"]["id"]] = i["user"] + if hasattr(i, "user"): + if (i.user.id in self.db["users"]) == False: + self.db["users"][i.user.id] = i.user return num def order_cursored_buffer(self, name, data): @@ -74,7 +74,7 @@ class Session(base.baseSession): self.db[name] = {} self.db[name]["items"] = [] for i in data: - if utils.find_item(i["id"], self.db[name]["items"]) == None: + if utils.find_item(i.id, self.db[name]["items"]) == None: if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].append(i) else: self.db[name]["items"].insert(0, i) num = num+1 @@ -90,13 +90,13 @@ class Session(base.baseSession): self.db["direct_messages"] = {} self.db["direct_messages"]["items"] = [] for i in data: - if i["message_create"]["sender_id"] == self.db["user_id"]: - if "sent_direct_messages" in self.db and utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None: + if i.message_create.sender_id == self.db["user_id"]: + if "sent_direct_messages" in self.db and utils.find_item(i.id, self.db["sent_direct_messages"]["items"]) == None: if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"]["items"].append(i) else: self.db["sent_direct_messages"]["items"].insert(0, i) sent = sent+1 else: - if utils.find_item(i["id"], self.db["direct_messages"]["items"]) == None: + if utils.find_item(i.id, self.db["direct_messages"]["items"]) == None: if self.settings["general"]["reverse_timelines"] == False: self.db["direct_messages"]["items"].append(i) else: self.db["direct_messages"]["items"].insert(0, i) incoming = incoming+1 @@ -229,15 +229,15 @@ class Session(base.baseSession): def search(self, name, *args, **kwargs): """ Search in twitter, passing args and kwargs as arguments to the Twython function.""" tl = self.twitter.search(*args, **kwargs) - tl["statuses"].reverse() - return tl["statuses"] + tl.reverse() + return tl # @_require_login def get_favourites_timeline(self, name, *args, **kwargs): """ Gets favourites for the authenticated user or a friend or follower. name str: Name for storage in the database. args and kwargs are passed directly to the Twython function.""" - tl = self.call_paged("get_favorites", *args, **kwargs) + tl = self.call_paged("favorites", *args, **kwargs) return self.order_buffer(name, tl) def call_paged(self, update_function, *args, **kwargs): @@ -251,8 +251,8 @@ class Session(base.baseSession): data = getattr(self.twitter, update_function)(count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) results.extend(data) for i in range(0, max): - if i == 0: max_id = results[-1]["id"] - else: max_id = results[0]["id"] + if i == 0: max_id = results[-1].id + else: max_id = results[0].id data = getattr(self.twitter, update_function)(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) results.extend(data) results.reverse() @@ -357,25 +357,25 @@ class Session(base.baseSession): def get_quoted_tweet(self, tweet): """ Process a tweet and extract all information related to the quote.""" quoted_tweet = tweet - if "full_text" in tweet: + if hasattr(tweet, "full_text"): value = "full_text" else: value = "text" - quoted_tweet[value] = utils.expand_urls(quoted_tweet[value], quoted_tweet["entities"]) - if "quoted_status" in quoted_tweet: - original_tweet = quoted_tweet["quoted_status"] - elif "retweeted_status" in quoted_tweet and "quoted_status" in quoted_tweet["retweeted_status"]: - original_tweet = quoted_tweet["retweeted_status"]["quoted_status"] + setattr(quoted_tweet, value)(utils.expand_urls(getattr(quoted_tweet, value), quoted_tweet.entities)) + if hasattr(quoted_tweet, "quoted_status"): + original_tweet = quoted_tweet.quoted_status + elif hasattr(quoted_tweet, "retweeted_status") and hasattr(quoted_tweet.retweeted_status, "quoted_status"): + original_tweet = quoted_tweet.retweeted_status.quoted_status else: return quoted_tweet original_tweet = self.check_long_tweet(original_tweet) - if "full_text" in original_tweet: + if hasattr(original_tweet, "full_text"): value = "full_text" - elif "message" in original_tweet: + elif hasattr(original_tweet, "message"): value = "message" else: value = "text" - original_tweet[value] = utils.expand_urls(original_tweet[value], original_tweet["entities"]) + setattr(original_tweet, value)(utils.expand_urls(getattr(original_tweet, value), original_tweet.entities)) return compose.compose_quoted_tweet(quoted_tweet, original_tweet) def check_long_tweet(self, tweet): @@ -385,22 +385,22 @@ class Session(base.baseSession): long = twishort.is_long(tweet) if long != False and config.app["app-settings"]["handle_longtweets"]: message = twishort.get_full_text(long) - if "quoted_status" in tweet: - tweet["quoted_status"]["message"] = message - if tweet["quoted_status"]["message"] == False: return False - tweet["quoted_status"]["twishort"] = True - for i in tweet["quoted_status"]["entities"]["user_mentions"]: - if "@%s" % (i["screen_name"]) not in tweet["quoted_status"]["message"] and i["screen_name"] != tweet["user"]["screen_name"]: - if "retweeted_status" in tweet["quoted_status"] and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]: + if hasattr(tweet, "quoted_status"): + tweet.quoted_status.message = message + if tweet.quoted_status.message == False: return False + tweet.quoted_status.twishort = True + for i in tweet.quoted_status.entities.user_mentions: + if "@%s" % (i.screen_name) not in tweet.quoted_status.message and i.screen_name != tweet.user.screen_name: + if hasattr(tweet["quoted_status"], "retweeted_status") and tweet.retweeted_status.user.screen_name == i.screen_name: continue - tweet["quoted_status"]["message"] = u"@%s %s" % (i["screen_name"], tweet["message"]) + tweet.quoted_status.message = u"@%s %s" % (i.screen_name, tweet.message) else: - tweet["message"] = message - if tweet["message"] == False: return False - tweet["twishort"] = True - for i in tweet["entities"]["user_mentions"]: - if "@%s" % (i["screen_name"]) not in tweet["message"] and i["screen_name"] != tweet["user"]["screen_name"]: - if "retweeted_status" in tweet and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]: + tweet.message = message + if tweet.message == False: return False + tweet.twishort = True + for i in tweet.entities.user_mentions: + if "@%s" % (i.screen_name) not in tweet.message and i.screen_name != tweet.user.screen_name: + if hasattr(tweet, "retweeted_status") and tweet.retweeted_status.user.screen_name == i.screen_name: continue return tweet diff --git a/src/sessions/twitter/utils.py b/src/sessions/twitter/utils.py index ff4db939..dfdabfa5 100644 --- a/src/sessions/twitter/utils.py +++ b/src/sessions/twitter/utils.py @@ -28,35 +28,35 @@ def find_urls_in_text(text): def find_urls (tweet): urls = [] # Let's add URLS from tweet entities. - if "message_create" in tweet: - entities = tweet["message_create"]["message_data"]["entities"] + if hasattr(tweet, "message_create"): + entities = tweet.message_create.message_data.entities else: - entities = tweet["entities"] - for i in entities["urls"]: - if i["expanded_url"] not in urls: - urls.append(i["expanded_url"]) - if "quoted_status" in tweet: - for i in tweet["quoted_status"]["entities"]["urls"]: - if i["expanded_url"] not in urls: - urls.append(i["expanded_url"]) - if "retweeted_status" in tweet: - for i in tweet["retweeted_status"]["entities"]["urls"]: - if i["expanded_url"] not in urls: - urls.append(i["expanded_url"]) - if "quoted_status" in tweet["retweeted_status"]: - for i in tweet["retweeted_status"]["quoted_status"]["entities"]["urls"]: - if i["expanded_url"] not in urls: - urls.append(i["expanded_url"]) - if "message" in tweet: + entities = tweet.entities + for i in entities.urls: + if i.expanded_url not in urls: + urls.append(i.expanded_url) + if hasattr(tweet, "quoted_status"): + for i in tweet.quoted_status.entities.urls: + if i.expanded_url not in urls: + urls.append(i.expanded_url) + if hasattr(tweet, "retweeted_status"): + for i in tweet.retweeted_status.entities.urls: + if i.expanded_url not in urls: + urls.append(i.expanded_url) + if hasattr(tweet["retweeted_status"], "quoted_status"): + for i in tweet.retweeted_status.quoted_status.entities.urls: + if i.expanded_url not in urls: + urls.append(i.expanded_url) + if hasattr(tweet, "message"): i = "message" - elif "full_text" in tweet: + elif hasattr(tweet, "full_text"): i = "full_text" else: i = "text" - if "message_create" in tweet: - extracted_urls = find_urls_in_text(tweet["message_create"]["message_data"]["text"]) + if hasattr(tweet, "message_create"): + extracted_urls = find_urls_in_text(tweet.message_create.message_data.text) else: - extracted_urls = find_urls_in_text(tweet[i]) + extracted_urls = find_urls_in_text(getattr(tweet, i)) # Don't include t.co links (mostly they are photos or shortened versions of already added URLS). for i in extracted_urls: if i not in urls and "https://t.co" not in i: @@ -65,70 +65,70 @@ def find_urls (tweet): def find_item(id, listItem): for i in range(0, len(listItem)): - if listItem[i]["id"] == id: return i + if listItem[i].id == id: return i return None def find_list(name, lists): for i in range(0, len(lists)): - if lists[i]["name"] == name: return lists[i]["id"] + if lists[i].name == name: return lists[i].id def is_audio(tweet): try: if len(find_urls(tweet)) < 1: return False - if "message_create" in tweet: - entities = tweet["message_create"]["message_data"]["entities"] + if hasattr(tweet, "message_create"): + entities = tweet.message_create.message_data.entities else: - entities = tweet["entities"] - if len(entities["hashtags"]) > 0: - for i in entities["hashtags"]: - if i["text"] == "audio": + entities = tweet.entities + if len(entities.hashtags) > 0: + for i in entities.hashtags: + if i.text == "audio": return True except IndexError: - print(tweet["entities"]["hashtags"]) + print(tweet.entities.hashtags) log.exception("Exception while executing is_audio hashtag algorithm") def is_geocoded(tweet): - if "coordinates" in tweet and tweet["coordinates"] != None: + if hasattr(tweet, "coordinates") and tweet.coordinates != None: return True def is_media(tweet): - if "message_create" in tweet: - entities = tweet["message_create"]["message_data"]["entities"] + if hasattr(tweet, "message_create"): + entities = tweet.message_create.message_data.entities else: - entities = tweet["entities"] - if ("media" in entities) == False: + entities = tweet.entities + if not hasattr(entities, media): return False - for i in entities["media"]: - if "type" in i and i["type"] == "photo": + for i in entities.media: + if hasattr(i, "type") and i.type == "photo": return True return False def get_all_mentioned(tweet, conf, field="screen_name"): """ Gets all users that have been mentioned.""" results = [] - for i in tweet["entities"]["user_mentions"]: - if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]: - if i[field] not in results: - results.append(i[field]) + for i in tweet.entities.user_mentions: + if i.screen_name != conf["user_name"] and i.screen_name != tweet.user.screen_name: + if getattr(i, field) not in results: + results.append(getattr(i, field)) return results def get_all_users(tweet, conf): string = [] - if "retweeted_status" in tweet: - string.append(tweet["user"]["screen_name"]) - tweet = tweet["retweeted_status"] - if "sender" in tweet: - string.append(tweet["sender"]["screen_name"]) + if hasattr(tweet, "retweeted_status"): + string.append(tweet.user.screen_name) + tweet = tweet.retweeted_status + if hasattr(tweet, "sender"): + string.append(tweet.sender.screen_name) else: - if tweet["user"]["screen_name"] != conf["user_name"]: - string.append(tweet["user"]["screen_name"]) - for i in tweet["entities"]["user_mentions"]: - if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]: - if i["screen_name"] not in string: - string.append(i["screen_name"]) + if tweet.user.screen_name != conf["user_name"]: + string.append(tweet.user.screen_name) + for i in tweet.entities.user_mentions: + if i.screen_name != conf["user_name"] and i.screen_name != tweet.user.screen_name: + if i.screen_name not in string: + string.append(i.screen_name) if len(string) == 0: - string.append(tweet["user"]["screen_name"]) + string.append(tweet.user.screen_name) return string def if_user_exists(twitter, user): @@ -143,24 +143,25 @@ def if_user_exists(twitter, user): def is_allowed(tweet, settings, buffer_name): clients = settings["twitter"]["ignored_clients"] - if "sender" in tweet: return True + if hasattr(tweet, "sender"): return True allowed = True tweet_data = {} - if "retweeted_status" in tweet: + if hasattr(tweet, "retweeted_status"): tweet_data["retweet"] = True - if tweet["in_reply_to_status_id_str"] != None: + if tweet.in_reply_to_status_id_str != None: tweet_data["reply"] = True - if "quoted_status" in tweet: + if hasattr(tweet, "quoted_status"): tweet_data["quote"] = True - if "retweeted_status" in tweet: tweet = tweet["retweeted_status"] - source = re.sub(r"(?s)<.*?>", "", tweet["source"]) + if hasattr(tweet, "retweeted_status"): + tweet = tweet.retweeted_status + source = re.sub(r"(?s)<.*?>", "", tweet.source) for i in clients: if i.lower() == source.lower(): return False return filter_tweet(tweet, tweet_data, settings, buffer_name) def filter_tweet(tweet, tweet_data, settings, buffer_name): - if "full_text" in tweet: + if hasattr(tweet, "full_text"): value = "full_text" else: value = "text" @@ -188,16 +189,16 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name): if allow_replies == "False" and "reply" in tweet_data: return False if word != "" and settings["filters"][i]["if_word_exists"]: - if word in tweet[value]: + if word in getattr(tweet, value): return False elif word != "" and settings["filters"][i]["if_word_exists"] == False: - if word not in tweet[value]: + if word not in getattr(tweet, value): return False if settings["filters"][i]["in_lang"] == "True": - if tweet["lang"] not in settings["filters"][i]["languages"]: + if getattr(tweet, lang) not in settings["filters"][i]["languages"]: return False elif settings["filters"][i]["in_lang"] == "False": - if tweet["lang"] in settings["filters"][i]["languages"]: + if tweet.lang in settings["filters"][i]["languages"]: return False return True @@ -213,7 +214,7 @@ def twitter_error(error): def expand_urls(text, entities): """ Expand all URLS present in text with information found in entities""" urls = find_urls_in_text(text) - for url in entities["urls"]: - if url["url"] in text: - text = text.replace(url["url"], url["expanded_url"]) + for url in entities.urls: + if url.url in text: + text = text.replace(url.url, url.expanded_url) return text From bcd51d6259963454ae7003b84b81ae03822ef14f Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 11:13:20 -0600 Subject: [PATCH 05/34] Migrated most of twitter util functions from sessions/twitter/utils.py --- src/sessions/twitter/utils.py | 71 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/sessions/twitter/utils.py b/src/sessions/twitter/utils.py index dfdabfa5..097586c1 100644 --- a/src/sessions/twitter/utils.py +++ b/src/sessions/twitter/utils.py @@ -29,24 +29,24 @@ def find_urls (tweet): urls = [] # Let's add URLS from tweet entities. if hasattr(tweet, "message_create"): - entities = tweet.message_create.message_data.entities + entities = tweet.message_create["message_data"]["entities"] else: entities = tweet.entities - for i in entities.urls: - if i.expanded_url not in urls: - urls.append(i.expanded_url) + for i in entities["urls"]: + if i["expanded_url"] not in urls: + urls.append(i["expanded_url"]) if hasattr(tweet, "quoted_status"): - for i in tweet.quoted_status.entities.urls: - if i.expanded_url not in urls: - urls.append(i.expanded_url) + for i in tweet.quoted_status.entities["urls"]: + if i["expanded_url"] not in urls: + urls.append(i["expanded_url"]) if hasattr(tweet, "retweeted_status"): - for i in tweet.retweeted_status.entities.urls: - if i.expanded_url not in urls: - urls.append(i.expanded_url) + for i in tweet.retweeted_status.entities["urls"]: + if i["expanded_url"] not in urls: + urls.append(i["expanded_url"]) if hasattr(tweet["retweeted_status"], "quoted_status"): - for i in tweet.retweeted_status.quoted_status.entities.urls: - if i.expanded_url not in urls: - urls.append(i.expanded_url) + for i in tweet.retweeted_status.quoted_status.entities["urls"]: + if i["expanded_url"] not in urls: + urls.append(i["expanded_url"]) if hasattr(tweet, "message"): i = "message" elif hasattr(tweet, "full_text"): @@ -54,7 +54,7 @@ def find_urls (tweet): else: i = "text" if hasattr(tweet, "message_create"): - extracted_urls = find_urls_in_text(tweet.message_create.message_data.text) + extracted_urls = find_urls_in_text(tweet.message_create["message_data"]["text"]) else: extracted_urls = find_urls_in_text(getattr(tweet, i)) # Don't include t.co links (mostly they are photos or shortened versions of already added URLS). @@ -77,15 +77,15 @@ def is_audio(tweet): if len(find_urls(tweet)) < 1: return False if hasattr(tweet, "message_create"): - entities = tweet.message_create.message_data.entities + entities = tweet.message_create["message_data"]["entities"] else: entities = tweet.entities - if len(entities.hashtags) > 0: - for i in entities.hashtags: - if i.text == "audio": + if len(entities["hashtags"]) > 0: + for i in entities["hashtags"]: + if i["text"] == "audio": return True except IndexError: - print(tweet.entities.hashtags) + print(tweet.entities["hashtags"]) log.exception("Exception while executing is_audio hashtag algorithm") def is_geocoded(tweet): @@ -94,23 +94,23 @@ def is_geocoded(tweet): def is_media(tweet): if hasattr(tweet, "message_create"): - entities = tweet.message_create.message_data.entities + entities = tweet.message_create["message_data"]["entities"] else: entities = tweet.entities - if not hasattr(entities, media): + if entities.get("media") == None: return False - for i in entities.media: - if hasattr(i, "type") and i.type == "photo": + for i in entities["media"]: + if i.get("type") != None and i.get("type") == "photo": return True return False def get_all_mentioned(tweet, conf, field="screen_name"): """ Gets all users that have been mentioned.""" results = [] - for i in tweet.entities.user_mentions: - if i.screen_name != conf["user_name"] and i.screen_name != tweet.user.screen_name: - if getattr(i, field) not in results: - results.append(getattr(i, field)) + for i in tweet.entities["user_mentions"]: + if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet.user.screen_name: + if i.get(field) not in results: + results.append(i.get(field)) return results def get_all_users(tweet, conf): @@ -123,14 +123,15 @@ def get_all_users(tweet, conf): else: if tweet.user.screen_name != conf["user_name"]: string.append(tweet.user.screen_name) - for i in tweet.entities.user_mentions: - if i.screen_name != conf["user_name"] and i.screen_name != tweet.user.screen_name: - if i.screen_name not in string: - string.append(i.screen_name) + for i in tweet.entities["user_mentions"]: + if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet.user.screen_name: + if i["screen_name"] not in string: + string.append(i["screen_name"]) if len(string) == 0: string.append(tweet.user.screen_name) return string +# ToDo: implement this using tweepy def if_user_exists(twitter, user): try: data = twitter.show_user(screen_name=user) @@ -154,7 +155,7 @@ def is_allowed(tweet, settings, buffer_name): tweet_data["quote"] = True if hasattr(tweet, "retweeted_status"): tweet = tweet.retweeted_status - source = re.sub(r"(?s)<.*?>", "", tweet.source) + source = tweet.source for i in clients: if i.lower() == source.lower(): return False @@ -214,7 +215,7 @@ def twitter_error(error): def expand_urls(text, entities): """ Expand all URLS present in text with information found in entities""" urls = find_urls_in_text(text) - for url in entities.urls: - if url.url in text: - text = text.replace(url.url, url.expanded_url) + for url in entities["urls"]: + if url["url"] in text: + text = text.replace(url["url"], url["expanded_url"]) return text From d0cc12ef5c223c91fc5eba3b3517b406a5b45926 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 11:14:55 -0600 Subject: [PATCH 06/34] Added basic tweet rendering --- src/sessions/twitter/compose.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sessions/twitter/compose.py b/src/sessions/twitter/compose.py index 21496d2f..a1019bc6 100644 --- a/src/sessions/twitter/compose.py +++ b/src/sessions/twitter/compose.py @@ -39,7 +39,7 @@ chars = "abcdefghijklmnopqrstuvwxyz" def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=None): """ It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is.""" if system == "Windows": - original_date = arrow.get(tweet.created_at, "ddd MMM DD H:m:s Z YYYY", locale="en") + original_date = arrow.get(tweet.created_at, locale="en") if relative_times == True: ts = original_date.humanize(locale=languageHandler.curLang[:2]) else: @@ -138,7 +138,7 @@ def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, original_text = StripChars(original_tweet.text) quoted_tweet.message = _(u"{0}. Quoted tweet from @{1}: {2}").format( text, original_user, original_text) quoted_tweet = tweets.clear_url(quoted_tweet) - quoted_tweet.entities.urls.extend(original_tweet.entities.urls) + quoted_tweet.entities["urls"].extend(original_tweet.entities["urls"]) return quoted_tweet def compose_followers_list(tweet, db, relative_times=True, show_screen_names=False, session=None): From a37f339fea1aa47806b37f48def8d63bb5a92d25 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 11:15:27 -0600 Subject: [PATCH 07/34] Fixed some issues when determining the presence of long tweets based on entities present in objects --- src/sessions/twitter/long_tweets/tweets.py | 22 ++++++++++---------- src/sessions/twitter/long_tweets/twishort.py | 14 ++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/sessions/twitter/long_tweets/tweets.py b/src/sessions/twitter/long_tweets/tweets.py index 44b898a9..2ba1b48f 100644 --- a/src/sessions/twitter/long_tweets/tweets.py +++ b/src/sessions/twitter/long_tweets/tweets.py @@ -23,30 +23,30 @@ def is_long(tweet): """ Check if the passed tweet contains a quote in its metadata. tweet dict: a tweet dictionary. returns True if a quote is detected, False otherwise.""" - if "quoted_status_id" in tweet and "quoted_status" in tweet: - return tweet["quoted_status_id"] - elif "retweeted_status" in tweet and "quoted_status_id" in tweet["retweeted_status"] and "quoted_status" in tweet["retweeted_status"]: - return tweet["retweeted_status"]["quoted_status_id"] + if hasattr(tweet, "quoted_status_id") and hasattr(tweet, "quoted_status"): + return tweet.quoted_status_id + elif hasattr(tweet, "retweeted_status") and hasattr(tweet, "quoted_status_id") and hasattr(tweet, "quoted_status"): + return tweet.retweeted_status.quoted_status_id return False def clear_url(tweet): """ Reads data from a quoted tweet and removes the link to the Status from the tweet's text. tweet dict: a tweet dictionary. returns a tweet dictionary without the URL to the status ID in its text to display.""" - if "retweeted_status" in tweet: - if "full_text" in tweet["retweeted_status"]: + if hasattr(tweet, "retweeted_status"): + if hasattr(tweet.retweeted_status, "full_text"): value = "full_text" else: value = "text" - urls = utils.find_urls_in_text(tweet["retweeted_status"][value]) - try: tweet["message"] = tweet["message"].replace(urls[-1], "") + urls = utils.find_urls_in_text(getattr(tweet.retweeted_status, value)) + try: tweet.message = tweet.message.replace(urls[-1], "") except IndexError: pass else: - if "full_text" in tweet: + if hasattr(tweet, "full_text"): value = "full_text" else: value = "text" - urls = utils.find_urls_in_text(tweet[value]) - try: tweet["message"] = tweet["message"].replace(urls[-1], "") + urls = utils.find_urls_in_text(getattr(tweet, value)) + try: tweet.message = tweet.message.replace(urls[-1], "") except IndexError: pass return tweet \ No newline at end of file diff --git a/src/sessions/twitter/long_tweets/twishort.py b/src/sessions/twitter/long_tweets/twishort.py index 076b3871..25878cf0 100644 --- a/src/sessions/twitter/long_tweets/twishort.py +++ b/src/sessions/twitter/long_tweets/twishort.py @@ -40,21 +40,21 @@ def is_long(tweet): """ Check if the passed tweet is made with Twishort. returns True if is a long tweet, False otherwise.""" long = False - for url in range(0, len(tweet["entities"]["urls"])): + for url in range(0, len(tweet.entities["urls"])): try: - if tweet["entities"]["urls"][url] != None and "twishort.com" in tweet["entities"]["urls"][url]["expanded_url"]: - long = get_twishort_uri(tweet["entities"]["urls"][url]["expanded_url"]) + if tweet.entities["urls"][url] != None and "twishort.com" in tweet.entities["urls"][url]["expanded_url"]: + long = get_twishort_uri(tweet.entities["urls"][url]["expanded_url"]) except IndexError: pass # sometimes Twitter returns URL's with None objects, so let's take it. # see https://github.com/manuelcortez/TWBlue/issues/103 except TypeError: pass - if long == False and "retweeted_status" in tweet: - for url in range(0, len(tweet["retweeted_status"]["entities"]["urls"])): + if long == False and hasattr(tweet, "retweeted_status"): + for url in range(0, len(tweet.retweeted_status.entities["urls"])): try: - if tweet["retweeted_status"]["entities"]["urls"][url] != None and "twishort.com" in tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"]: - long = get_twishort_uri(tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"]) + if tweet.retweeted_status.entities["urls"][url] != None and "twishort.com" in tweet.retweeted_status.entities["urls"][url]["expanded_url"]: + long = get_twishort_uri(tweet.retweeted_status.entities["urls"][url]["expanded_url"]) except IndexError: pass except TypeError: From 78cc6e67847839ef3508c8086b5034475611d7e9 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 11:16:56 -0600 Subject: [PATCH 08/34] Changed library calls on some basic buffer creation and manipulation --- src/controller/buffers/twitterBuffers.py | 93 +++++++++++------------- src/sessions/twitter/session.py | 4 +- 2 files changed, 43 insertions(+), 54 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index b977d456..c9bb33ff 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -108,6 +108,7 @@ class baseBufferController(baseBuffers.buffer): if hasattr(tweet.message, "destroy"): tweet.message.destroy() self.session.settings.write() + # ToDo: Update to tweepy. def post_with_media(self, text, attachments): media_ids = [] for i in attachments: @@ -129,24 +130,24 @@ class baseBufferController(baseBuffers.buffer): def get_full_tweet(self): tweet = self.get_right_tweet() tweetsList = [] - tweet_id = tweet["id"] + tweet_id = tweet.id message = None - if "message" in tweet: - message = tweet["message"] + if hasattr(tweet, "message"): + message = tweet.message try: - tweet = self.session.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended") - tweet["full_text"] = utils.expand_urls(tweet["full_text"], tweet["entities"]) + tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended") + tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities) except TwythonError as e: utils.twitter_error(e) return if message != None: - tweet["message"] = message + tweet.message = message l = tweets.is_long(tweet) while l != False: tweetsList.append(tweet) try: - tweet = self.session.twitter.show_status(id=l, include_ext_alt_text=True, tweet_mode="extended") - tweet["full_text"] = utils.expand_urls(tweet["full_text"], tweet["entities"]) + tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True) + tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities) except TwythonError as e: utils.twitter_error(e) return @@ -376,8 +377,8 @@ class baseBufferController(baseBuffers.buffer): self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition()) def get_tweet(self): - if "retweeted_status" in self.session.db[self.name][self.buffer.list.get_selected()]: - tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"] + if hasattr(self.session.db[self.name][self.buffer.list.get_selected()], "retweeted_status"): + tweet = self.session.db[self.name][self.buffer.list.get_selected()].retweeted_status else: tweet = self.session.db[self.name][self.buffer.list.get_selected()] return tweet @@ -389,9 +390,9 @@ class baseBufferController(baseBuffers.buffer): @_tweets_exist def reply(self, *args, **kwargs): tweet = self.get_right_tweet() - screen_name = tweet["user"]["screen_name"] - id = tweet["id"] - twishort_enabled = "twishort" in tweet + screen_name = tweet.user["screen_name"] + id = tweet.id + twishort_enabled = getattr(tweet, "twishort") users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name") ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str") # Build the window title @@ -426,7 +427,6 @@ class baseBufferController(baseBuffers.buffer): else: params["call_name"] = "update_status_with_media" params["media"] = message.file - item = self.session.api_call(**params) if item != None: pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"]) @@ -437,32 +437,21 @@ class baseBufferController(baseBuffers.buffer): def send_message(self, *args, **kwargs): tweet = self.get_right_tweet() if self.type == "dm": - screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"] + screen_name = self.session.get_user(tweet.message_create["sender_id"])["screen_name"] users = [screen_name] elif self.type == "people": - screen_name = tweet["screen_name"] + screen_name = tweet.screen_name users = [screen_name] else: - screen_name = tweet["user"]["screen_name"] + screen_name = tweet.user["screen_name"] users = utils.get_all_users(tweet, self.session.db) dm = messages.dm(self.session, _(u"Direct message to %s") % (screen_name,), _(u"New direct message"), users) if dm.message.get_response() == widgetUtils.OK: screen_name = dm.message.get("cb") user = self.session.get_user_by_screen_name(screen_name) - event_data = { - 'event': { - 'type': 'message_create', - 'message_create': { - 'target': { - 'recipient_id': user, - }, - 'message_data': { - 'text': dm.message.get_text(), - } - } - } -} - val = self.session.api_call(call_name="send_direct_message", **event_data) + recipient_id = user + text = dm.message.get_text() + val = self.session.api_call(call_name="send_direct_message", recipient_id=recipient_id, text=text) if val != None: if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["sent_direct_messages"]["items"].append(val["event"]) @@ -474,7 +463,7 @@ class baseBufferController(baseBuffers.buffer): @_tweets_exist def share_item(self, *args, **kwargs): tweet = self.get_right_tweet() - id = tweet["id"] + id = tweet.id if self.session.settings["general"]["retweet_mode"] == "ask": answer = commonMessageDialogs.retweet_question(self.buffer) if answer == widgetUtils.YES: @@ -488,22 +477,22 @@ class baseBufferController(baseBuffers.buffer): def _retweet_with_comment(self, tweet, id, comment=''): # If quoting a retweet, let's quote the original tweet instead the retweet. - if "retweeted_status" in tweet: - tweet = tweet["retweeted_status"] - if "full_text" in tweet: - comments = tweet["full_text"] + if hasattr(tweet, "retweeted_status"): + tweet = tweet.retweeted_status + if hasattr(tweet, "full_text"): + comments = tweet.full_text else: - comments = tweet["text"] - retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet["user"]["screen_name"], comments), max=256, messageType="retweet") + comments = tweet.text + retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet.user["screen_name"], comments), max=256, messageType="retweet") if comment != '': retweet.message.set_text(comment) if retweet.message.get_response() == widgetUtils.OK: text = retweet.message.get_text() - text = text+" https://twitter.com/{0}/status/{1}".format(tweet["user"]["screen_name"], id) + text = text+" https://twitter.com/{0}/status/{1}".format(tweet.user["screen_name"], id) if retweet.image == None: item = self.session.api_call(call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id, tweet_mode="extended") if item != None: - new_item = self.session.twitter.show_status(id=item["id"], include_ext_alt_text=True, tweet_mode="extended") + new_item = self.session.twitter.get_status(id=item.id, include_ext_alt_text=True, tweet_mode="extended") pub.sendMessage("sent-tweet", data=new_item, user=self.session.db["user_name"]) else: call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image) @@ -514,14 +503,14 @@ class baseBufferController(baseBuffers.buffer): if item != None: # Retweets are returned as non-extended tweets, so let's get the object as extended # just before sending the event message. See https://github.com/manuelcortez/TWBlue/issues/253 - item = self.session.twitter.show_status(id=item["id"], include_ext_alt_text=True, tweet_mode="extended") + item = self.session.twitter.get_status(id=item.id, include_ext_alt_text=True, tweet_mode="extended") pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"]) def onFocus(self, *args, **kwargs): tweet = self.get_tweet() if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True: # fix this: - original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en") + original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()].created_at, locale="en") ts = original_date.humanize(locale=languageHandler.getLanguage()) self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts) if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet): @@ -583,10 +572,10 @@ class baseBufferController(baseBuffers.buffer): if answer == widgetUtils.YES: try: if self.name == "direct_messages" or self.name == "sent_direct_messages": - self.session.twitter.destroy_direct_message(id=self.get_right_tweet()["id"]) + self.session.twitter.destroy_direct_message(id=self.get_right_tweet().id) self.session.db[self.name]["items"].pop(index) else: - self.session.twitter.destroy_status(id=self.get_right_tweet()["id"]) + self.session.twitter.destroy_status(id=self.get_right_tweet().id) self.session.db[self.name].pop(index) self.buffer.list.remove_item(index) except TwythonError: @@ -596,9 +585,9 @@ class baseBufferController(baseBuffers.buffer): def user_details(self): tweet = self.get_right_tweet() if self.type == "dm": - users = [self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [self.session.get_user(tweet.message_create["sender_id"])["screen_name"]] elif self.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] else: users = utils.get_all_users(tweet, self.session.db) dlg = dialogs.utils.selectUserDialog(title=_(u"User details"), users=users) @@ -607,18 +596,18 @@ class baseBufferController(baseBuffers.buffer): if hasattr(dlg, "destroy"): dlg.destroy() def get_quoted_tweet(self, tweet): - quoted_tweet = self.session.twitter.show_status(id=tweet["id"]) - quoted_tweet["text"] = utils.find_urls_in_text(quoted_tweet["text"], quoted_tweet["entities"]) + quoted_tweet = self.session.twitter.get_status(id=tweet.id) + quoted_tweet.text = utils.find_urls_in_text(quoted_tweet.text, quoted_tweet.entities) l = tweets.is_long(quoted_tweet) id = tweets.get_id(l) - original_tweet = self.session.twitter.show_status(id=id) - original_tweet["text"] = utils.find_urls_in_text(original_tweet["text"], original_tweet["entities"]) + original_tweet = self.session.twitter.get_status(id=id) + original_tweet.text = utils.find_urls_in_text(original_tweet.text, original_tweet.entities) return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"]) def open_in_browser(self, *args, **kwargs): tweet = self.get_tweet() output.speak(_(u"Opening item in web browser...")) - url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet["user"]["screen_name"], tweet_id=tweet["id"]) + url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet.user["screen_name"], tweet_id=tweet.id) webbrowser.open(url) class directMessagesController(baseBufferController): @@ -670,7 +659,7 @@ class directMessagesController(baseBufferController): @_tweets_exist def reply(self, *args, **kwargs): tweet = self.get_right_tweet() - screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"] + screen_name = self.session.get_user(tweet.message_create["sender_id"])["screen_name"] message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,]) if message.message.get_response() == widgetUtils.OK: if config.app["app-settings"]["remember_mention_and_longtweet"]: diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 3b584d40..78f79736 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -361,7 +361,7 @@ class Session(base.baseSession): value = "full_text" else: value = "text" - setattr(quoted_tweet, value)(utils.expand_urls(getattr(quoted_tweet, value), quoted_tweet.entities)) + setattr(quoted_tweet, value, utils.expand_urls(getattr(quoted_tweet, value), quoted_tweet.entities)) if hasattr(quoted_tweet, "quoted_status"): original_tweet = quoted_tweet.quoted_status elif hasattr(quoted_tweet, "retweeted_status") and hasattr(quoted_tweet.retweeted_status, "quoted_status"): @@ -375,7 +375,7 @@ class Session(base.baseSession): value = "message" else: value = "text" - setattr(original_tweet, value)(utils.expand_urls(getattr(original_tweet, value), original_tweet.entities)) + setattr(original_tweet, value, utils.expand_urls(getattr(original_tweet, value), original_tweet.entities)) return compose.compose_quoted_tweet(quoted_tweet, original_tweet) def check_long_tweet(self, tweet): From 1e1f2b089f6b05a571b11ff2b2e79346c95975c6 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 12:23:04 -0600 Subject: [PATCH 09/34] Fix call to api.supported_languages() --- src/sessions/twitter/session.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 78f79736..9e106405 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -273,7 +273,7 @@ class Session(base.baseSession): # Get twitter's supported languages and save them in a global variable #so we won't call to this method once per session. if len(application.supported_languages) == 0: - application.supported_languages = self.twitter.supported_languages + application.supported_languages = self.twitter.supported_languages() self.get_lists() self.get_muted_users() self.settings.write() @@ -389,18 +389,18 @@ class Session(base.baseSession): tweet.quoted_status.message = message if tweet.quoted_status.message == False: return False tweet.quoted_status.twishort = True - for i in tweet.quoted_status.entities.user_mentions: - if "@%s" % (i.screen_name) not in tweet.quoted_status.message and i.screen_name != tweet.user.screen_name: - if hasattr(tweet["quoted_status"], "retweeted_status") and tweet.retweeted_status.user.screen_name == i.screen_name: + for i in tweet.quoted_status.entities["user_mentions"]: + if "@%s" % (i["screen_name"]) not in tweet.quoted_status.message and i["screen_name"] != tweet.user.screen_name: + if hasattr(tweet["quoted_status"], "retweeted_status") and tweet.retweeted_status.user.screen_name == i["screen_name"]: continue - tweet.quoted_status.message = u"@%s %s" % (i.screen_name, tweet.message) + tweet.quoted_status.message = u"@%s %s" % (i["screen_name"], tweet.message) else: tweet.message = message if tweet.message == False: return False tweet.twishort = True - for i in tweet.entities.user_mentions: - if "@%s" % (i.screen_name) not in tweet.message and i.screen_name != tweet.user.screen_name: - if hasattr(tweet, "retweeted_status") and tweet.retweeted_status.user.screen_name == i.screen_name: + for i in tweet.entities["user_mentions"]: + if "@%s" % (i["screen_name"]) not in tweet.message and i["screen_name"] != tweet.user.screen_name: + if hasattr(tweet, "retweeted_status") and tweet.retweeted_status.user.screen_name == i["screen_name"]: continue return tweet From 8569d9b0a0aef9cad1d51e99c1c158428698c5b1 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 12:30:38 -0600 Subject: [PATCH 10/34] Readded code to load timelines with tweepy --- src/controller/buffers/twitterBuffers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index c9bb33ff..46ca1023 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -172,7 +172,7 @@ class baseBufferController(baseBuffers.buffer): self.put_items_on_list(number_of_items) if hasattr(self, "finished_timeline") and self.finished_timeline == False: if "-timeline" in self.name: - self.username = val[0]["user"]["screen_name"] + self.username = val[0].user.screen_name elif "-favorite" in self.name: self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"] self.finished_timeline = True From 29a905199de63c88d862818c4ee93ac0ff5cd264 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 12:55:29 -0600 Subject: [PATCH 11/34] Basic implementation of tweetDisplayerDialog. Needs testing with lists of tweets and image description entities --- src/controller/messages.py | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/controller/messages.py b/src/controller/messages.py index 295cd939..e529a752 100644 --- a/src/controller/messages.py +++ b/src/controller/messages.py @@ -216,52 +216,52 @@ class viewTweet(basicTweet): text = "" for i in range(0, len(tweetList)): # tweets with message keys are longer tweets, the message value is the full messaje taken from twishort. - if "message" in tweetList[i] and tweetList[i]["is_quote_status"] == False: + if hasattr(tweetList[i], "message") and tweetList[i].is_quote_status == False: value = "message" else: value = "full_text" - if "retweeted_status" in tweetList[i] and tweetList[i]["is_quote_status"] == False: - if ("message" in tweetList[i]) == False: - text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"]) + if hasattr(tweetList[i], "retweeted_status") and tweetList[i].is_quote_status == False: + if not hasattr(tweetList[i], "message"): + text = text + "rt @%s: %s\n" % (tweetList[i].retweeted_status.user.screen_name, tweetList[i].retweeted_status.full_text) else: - text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value]) + text = text + "rt @%s: %s\n" % (tweetList[i].retweeted_status.user.screen_name, getattr(tweetList[i], value)) else: - text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value]) + text = text + " @%s: %s\n" % (tweetList[i].user.screen_name, getattr(tweetList[i], value)) # tweets with extended_entities could include image descriptions. - if "extended_entities" in tweetList[i] and "media" in tweetList[i]["extended_entities"]: - for z in tweetList[i]["extended_entities"]["media"]: + if getattr(tweetList[i], "extended_entities") and "media" in tweetList[i].extended_entities: + for z in tweetList[i].extended_entities["media"]: if "ext_alt_text" in z and z["ext_alt_text"] != None: image_description.append(z["ext_alt_text"]) - if "retweeted_status" in tweetList[i] and "extended_entities" in tweetList[i]["retweeted_status"] and "media" in tweetList[i]["retweeted_status"]["extended_entities"]: - for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]: + if hasattr(tweetList[i], "retweeted_status") and hasattr(tweetList[i].retweeted_status, "extended_entities") and "media" in tweetList[i].retweeted_status["extended_entities"]: + for z in tweetList[i].retweeted_status.extended_entities["media"]: if "ext_alt_text" in z and z["ext_alt_text"] != None: image_description.append(z["ext_alt_text"]) # set rt and likes counters. - rt_count = str(tweet["retweet_count"]) - favs_count = str(tweet["favorite_count"]) + rt_count = str(tweet.retweet_count) + favs_count = str(tweet.favorite_count) # Gets the client from where this tweet was made. - source = re.sub(r"(?s)<.*?>", "", tweet["source"]) - original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en") + source = tweet.source + original_date = arrow.get(tweet.created_at, locale="en") date = original_date.shift(seconds=utc_offset).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage()) if text == "": - if "message" in tweet: + if hasattr(tweet, "message"): value = "message" else: value = "full_text" - if "retweeted_status" in tweet: - if ("message" in tweet) == False: - text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"]) + if hasattr(tweet, "retweeted_status"): + if not hasattr(tweet, "message"): + text = "rt @%s: %s" % (tweet.retweeted_status.user.screen_name, tweet.retweeted_status.full_text) else: - text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value]) + text = "rt @%s: %s" % (tweet.retweeted_status.user.screen_name, getattr(tweet, value)) else: - text = tweet[value] + text = getattr(tweet, value) text = self.clear_text(text) - if "extended_entities" in tweet and "media" in tweet["extended_entities"]: - for z in tweet["extended_entities"]["media"]: + if hasattr(tweet, "extended_entities") and "media" in tweet.extended_entities: + for z in tweet.extended_entities["media"]: if "ext_alt_text" in z and z["ext_alt_text"] != None: image_description.append(z["ext_alt_text"]) - if "retweeted_status" in tweet and "extended_entities" in tweet["retweeted_status"] and "media" in tweet["retweeted_status"]["extended_entities"]: - for z in tweet["retweeted_status"]["extended_entities"]["media"]: + if hasattr(tweet, "retweeted_status") and hasattr(tweet.retweeted_status, "extended_entities") and "media" in tweet.retweeted_status.extended_entities: + for z in tweet.retweeted_status.extended_entities["media"]: if "ext_alt_text" in z and z["ext_alt_text"] != None: image_description.append(z["ext_alt_text"]) self.message = message.viewTweet(text, rt_count, favs_count, source, date) From 93705bf534bc17bd0ef9f9c8bc3989bea05980c8 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Mon, 4 Jan 2021 15:52:25 -0600 Subject: [PATCH 12/34] Fixed user timeline creation --- src/controller/mainController.py | 52 +++++++++++++++----------------- src/sessions/twitter/utils.py | 21 +++++-------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index f6f75c54..8c8db69b 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -1,8 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals -from builtins import str -from builtins import range -from builtins import object import platform system = platform.system() import application @@ -828,9 +824,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.userSelection.selectUserDialog(users=users, default=default) @@ -840,85 +836,85 @@ class Controller(object): if usr == dlg.get_user(): commonMessageDialogs.suspended_user() return - if usr["protected"] == True: - if usr["following"] == False: + if usr.protected == True: + if usr.following == False: commonMessageDialogs.no_following() return tl_type = dlg.get_action() if tl_type == "tweets": - if usr["statuses_count"] == 0: + if usr.statuses_count == 0: commonMessageDialogs.no_tweets() return - if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]: + if usr.id_str in buff.session.settings["other_buffers"]["timelines"]: commonMessageDialogs.timeline_exist() return - tl = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr["id_str"], tweet_mode="extended") + tl = twitterBuffers.baseBufferController(self.view.nb, "user_timeline", "%s-timeline" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr.id_str, tweet_mode="extended") try: tl.start_stream(play_sound=False) - except TwythonAuthError: + except ValueError: commonMessageDialogs.unauthorized() return pos=self.view.search("timelines", buff.session.db["user_name"]) self.insert_buffer(tl, pos+1) self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(dlg.get_user()), pos=pos) - buff.session.settings["other_buffers"]["timelines"].append(usr["id_str"]) + buff.session.settings["other_buffers"]["timelines"].append(usr.id_str) pub.sendMessage("buffer-title-changed", buffer=tl) buff.session.sound.play("create_timeline.ogg") elif tl_type == "favourites": - if usr["favourites_count"] == 0: + if usr.favourites_count == 0: commonMessageDialogs.no_favs() return - if usr["id_str"] in buff.session.settings["other_buffers"]["favourites_timelines"]: + if usr.id_str in buff.session.settings["other_buffers"]["favourites_timelines"]: commonMessageDialogs.timeline_exist() return - tl = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr["id_str"], tweet_mode="extended") + tl = twitterBuffers.baseBufferController(self.view.nb, "favorites", "%s-favorite" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr.id_str, tweet_mode="extended") try: tl.start_stream(play_sound=False) - except TwythonAuthError: + except ValueError: commonMessageDialogs.unauthorized() return pos=self.view.search("favs_timelines", buff.session.db["user_name"]) self.insert_buffer(tl, pos+1) self.view.insert_buffer(buffer=tl.buffer, name=_(u"Likes for {}").format(dlg.get_user()), pos=pos) - buff.session.settings["other_buffers"]["favourites_timelines"].append(usr["id_str"]) + buff.session.settings["other_buffers"]["favourites_timelines"].append(usr.id_str) pub.sendMessage("buffer-title-changed", buffer=buff) buff.session.sound.play("create_timeline.ogg") elif tl_type == "followers": - if usr["followers_count"] == 0: + if usr.followers_count == 0: commonMessageDialogs.no_followers() return - if usr["id_str"] in buff.session.settings["other_buffers"]["followers_timelines"]: + if usr.id_str in buff.session.settings["other_buffers"]["followers_timelines"]: commonMessageDialogs.timeline_exist() return - tl = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"]) + tl = twitterBuffers.peopleBufferController(self.view.nb, "followers", "%s-followers" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str) try: tl.start_stream(play_sound=False) - except TwythonAuthError: + except ValueError: commonMessageDialogs.unauthorized() return pos=self.view.search("followers_timelines", buff.session.db["user_name"]) self.insert_buffer(tl, pos+1) self.view.insert_buffer(buffer=tl.buffer, name=_(u"Followers for {}").format(dlg.get_user()), pos=pos) - buff.session.settings["other_buffers"]["followers_timelines"].append(usr["id_str"]) + buff.session.settings["other_buffers"]["followers_timelines"].append(usr.id_str) buff.session.sound.play("create_timeline.ogg") pub.sendMessage("buffer-title-changed", buffer=i) elif tl_type == "friends": - if usr["friends_count"] == 0: + if usr.friends_count == 0: commonMessageDialogs.no_friends() return - if usr["id_str"] in buff.session.settings["other_buffers"]["friends_timelines"]: + if usr.id_str in buff.session.settings["other_buffers"]["friends_timelines"]: commonMessageDialogs.timeline_exist() return - tl = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"]) + tl = twitterBuffers.peopleBufferController(self.view.nb, "friends", "%s-friends" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str) try: tl.start_stream(play_sound=False) - except TwythonAuthError: + except ValueError: commonMessageDialogs.unauthorized() return pos=self.view.search("friends_timelines", buff.session.db["user_name"]) self.insert_buffer(tl, pos+1) self.view.insert_buffer(buffer=tl.buffer, name=_(u"Friends for {}").format(dlg.get_user()), pos=pos) - buff.session.settings["other_buffers"]["friends_timelines"].append(usr["id_str"]) + buff.session.settings["other_buffers"]["friends_timelines"].append(usr.id_str) buff.session.sound.play("create_timeline.ogg") pub.sendMessage("buffer-title-changed", buffer=i) else: diff --git a/src/sessions/twitter/utils.py b/src/sessions/twitter/utils.py index 097586c1..0d5d5f89 100644 --- a/src/sessions/twitter/utils.py +++ b/src/sessions/twitter/utils.py @@ -1,16 +1,12 @@ # -*- coding: utf-8 -*- -from __future__ import print_function -from __future__ import unicode_literals -from builtins import str -from builtins import range import url_shortener, re import output -from twython import TwythonError import config import logging import requests import time import sound +from tweepy.error import TweepError log = logging.getLogger("twitter.utils") """ Some utilities for the twitter interface.""" @@ -131,14 +127,13 @@ def get_all_users(tweet, conf): string.append(tweet.user.screen_name) return string -# ToDo: implement this using tweepy def if_user_exists(twitter, user): try: - data = twitter.show_user(screen_name=user) + data = twitter.get_user(screen_name=user) return data - except TwythonError as err: - if err.error_code == 404: - return None + except TweepError as err: + if err.error_code == 50: + return None else: return user @@ -204,12 +199,12 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name): return True def twitter_error(error): - if error.error_code == 403: + if error.api_code == 179: msg = _(u"Sorry, you are not authorised to see this status.") - elif error.error_code == 404: + elif error.error_code == 144: msg = _(u"No status found with that ID") else: - msg = _(u"Error code {0}").format(error.error_code,) + msg = _(u"Error code {0}").format(error.api_code,) output.speak(msg) def expand_urls(text, entities): From 65ec231349e2645aa1904ec34e73f2e6ff7fa91b Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Tue, 5 Jan 2021 09:20:36 -0600 Subject: [PATCH 13/34] Fixed an indentation issue --- src/sessions/twitter/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sessions/twitter/utils.py b/src/sessions/twitter/utils.py index 0d5d5f89..e2e12950 100644 --- a/src/sessions/twitter/utils.py +++ b/src/sessions/twitter/utils.py @@ -133,7 +133,7 @@ def if_user_exists(twitter, user): return data except TweepError as err: if err.error_code == 50: - return None + return None else: return user From fa49637d0eba034c6e228d98273a349a9e7299b9 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Tue, 5 Jan 2021 09:34:52 -0600 Subject: [PATCH 14/34] Replaced twython old exception handling by tweepy --- src/controller/buffers/twitterBuffers.py | 33 +++++++++++------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 46ca1023..6693e3b8 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -1,7 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals -from builtins import str -from builtins import range import time import platform if platform.system() == "Windows": @@ -24,7 +21,7 @@ from audio_services import youtube_utils from controller.buffers import baseBuffers from sessions.twitter import compose, utils from mysc.thread_utils import call_threaded -from twython import TwythonError +from tweepy.error import TweepError from pubsub import pub from sessions.twitter.long_tweets import twishort, tweets @@ -137,7 +134,7 @@ class baseBufferController(baseBuffers.buffer): try: tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended") tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities) - except TwythonError as e: + except TweepError as e: utils.twitter_error(e) return if message != None: @@ -148,7 +145,7 @@ class baseBufferController(baseBuffers.buffer): try: tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True) tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities) - except TwythonError as e: + except TweepError as e: utils.twitter_error(e) return l = tweets.is_long(tweet) @@ -202,8 +199,8 @@ class baseBufferController(baseBuffers.buffer): last_id = self.session.db[self.name][-1]["id"] try: items = self.session.get_more_items(self.function, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs) - except TwythonError as e: - output.speak(e.message, True) + except TweepError as e: + output.speak(e.reason, True) if items == None: return for i in items: @@ -578,7 +575,7 @@ class baseBufferController(baseBuffers.buffer): self.session.twitter.destroy_status(id=self.get_right_tweet().id) self.session.db[self.name].pop(index) self.buffer.list.remove_item(index) - except TwythonError: + except TweepError: self.session.sound.play("error.ogg") @_tweets_exist @@ -615,8 +612,8 @@ class directMessagesController(baseBufferController): def get_more_items(self): try: items = self.session.get_more_items(self.function, dm=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs) - except TwythonError as e: - output.speak(e.message, True) + except TweepError as e: + output.speak(e.reason, True) return if items == None: return @@ -862,8 +859,8 @@ class peopleBufferController(baseBufferController): def get_more_items(self): try: items = self.session.get_more_items(self.function, users=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs) - except TwythonError as e: - output.speak(e.message, True) + except TweepError as e: + output.speak(e.reason, True) return if items == None: return @@ -1008,8 +1005,8 @@ class searchBufferController(baseBufferController): last_id = self.session.db[self.name][-1]["id"] try: items = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs) - except TwythonError as e: - output.speak(e.message, True) + except TweepError as e: + output.speak(e.reason, True) if items == None: return for i in items: @@ -1074,8 +1071,8 @@ class searchPeopleBufferController(peopleBufferController): self.kwargs["page"] += 1 try: items = self.session.get_more_items(self.function, users=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs) - except TwythonError as e: - output.speak(e.message, True) + except TweepError as e: + output.speak(e.reason, True) return if items == None: return @@ -1256,7 +1253,7 @@ class conversationBufferController(searchBufferController): while tweet["in_reply_to_status_id"] != None: try: tweet = self.session.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended") - except TwythonError as err: + except TweepError as err: break self.statuses.insert(0, tweet) self.ids.append(tweet["id"]) From 3db8b7b021025a9630b376fc42495cb44866cd21 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Tue, 5 Jan 2021 11:04:06 -0600 Subject: [PATCH 15/34] Fixed some rendering for dm's and people --- src/sessions/twitter/compose.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/sessions/twitter/compose.py b/src/sessions/twitter/compose.py index a1019bc6..d2a73e9f 100644 --- a/src/sessions/twitter/compose.py +++ b/src/sessions/twitter/compose.py @@ -20,7 +20,6 @@ import config from .long_tweets import twishort, tweets log = logging.getLogger("compose") - def StripChars(s): """Converts any html entities in s to their unicode-decoded equivalents and returns a string.""" entity_re = re.compile(r"&(#\d+|\w+);") @@ -92,19 +91,19 @@ def compose_direct_message(item, db, relative_times, show_screen_names=False, se ts = item.created_timestamp text = StripChars(item.message_create.message_data.text) source = "DM" - sender = session.get_user(item.message_create.sender_id) - if db["user_name"] == sender.screen_name: + sender = session.get_user(item.message_create["sender_id"]) + if db["user_name"] == sender["screen_name"]: if show_screen_names: - user = _(u"Dm to %s ") % (session.get_user(item.message_create.target.recipient_id).screen_name) + user = _(u"Dm to %s ") % (session.get_user(item.message_create["target"]["recipient_id"]).screen_name) else: - user = _(u"Dm to %s ") % (session.get_user(item.message_create.target.recipient_id).name) + user = _(u"Dm to %s ") % (session.get_user(item["message_create"]["target"]["recipient_id"]).name) else: if show_screen_names: - user = sender.screen_name + user = sender["screen_name"] else: - user = sender.name + user = sender["name"] if text[-1] in chars: text=text+"." - text = utils.expand_urls(text, item.message_create.message_data.entities) + text = utils.expand_urls(text, item.message_create["message_data"]["entities"]) return [user+", ", text, ts+", ", source] def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, session=None): @@ -125,7 +124,7 @@ def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, quoting_user = quoted_tweet.user.screen_name else: quoting_user = quoted_tweet.user.name - source = re.sub(r"(?s)<.*?>", "", quoted_tweet.source) + source = quoted_tweet.source if hasattr(quoted_tweet, "retweeted_status"): text = "rt @%s: %s" % (quoted_tweet.retweeted_status.user.screen_name, text) if text[-1] in chars: text=text+"." @@ -143,7 +142,7 @@ def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, def compose_followers_list(tweet, db, relative_times=True, show_screen_names=False, session=None): if system == "Windows": - original_date = arrow.get(tweet.created_at, "ddd MMM D H:m:s Z YYYY", locale="en") + original_date = arrow.get(tweet.created_at, locale="en") if relative_times == True: ts = original_date.humanize(locale=languageHandler.curLang[:2]) else: @@ -152,7 +151,7 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal ts = tweet.created_at if hasattr(tweet, "status"): if len(tweet.status) > 4 and system == "Windows": - original_date2 = arrow.get(tweet.status.created_at, "ddd MMM D H:m:s Z YYYY", locale="en") + original_date2 = arrow.get(tweet.status.created_at, locale="en") if relative_times: ts2 = original_date2.humanize(locale=languageHandler.curLang[:2]) else: From 76c678d4ba08891c1fa5878a18fa607c56516968 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Tue, 5 Jan 2021 11:10:55 -0600 Subject: [PATCH 16/34] Fixed replies, retweets and iand tweet deletion --- src/controller/buffers/twitterBuffers.py | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 6693e3b8..6a3f1253 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -171,7 +171,7 @@ class baseBufferController(baseBuffers.buffer): if "-timeline" in self.name: self.username = val[0].user.screen_name elif "-favorite" in self.name: - self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"] + self.username = self.session.api_call("get_user", **self.kwargs).screen_name self.finished_timeline = True if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True: self.session.sound.play(self.sound) @@ -262,7 +262,7 @@ class baseBufferController(baseBuffers.buffer): def remove_tweet(self, id): if type(self.session.db[self.name]) == dict: return for i in range(0, len(self.session.db[self.name])): - if self.session.db[self.name][i]["id"] == id: + if self.session.db[self.name][i].id == id: self.session.db[self.name].pop(i) self.remove_item(i) @@ -387,9 +387,9 @@ class baseBufferController(baseBuffers.buffer): @_tweets_exist def reply(self, *args, **kwargs): tweet = self.get_right_tweet() - screen_name = tweet.user["screen_name"] + screen_name = tweet.user.screen_name id = tweet.id - twishort_enabled = getattr(tweet, "twishort") + twishort_enabled = hasattr(tweet, "twishort") users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name") ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str") # Build the window title @@ -434,7 +434,7 @@ class baseBufferController(baseBuffers.buffer): def send_message(self, *args, **kwargs): tweet = self.get_right_tweet() if self.type == "dm": - screen_name = self.session.get_user(tweet.message_create["sender_id"])["screen_name"] + screen_name = self.session.get_user(tweet.message_create["sender_id"]).screen_name users = [screen_name] elif self.type == "people": screen_name = tweet.screen_name @@ -451,10 +451,10 @@ class baseBufferController(baseBuffers.buffer): val = self.session.api_call(call_name="send_direct_message", recipient_id=recipient_id, text=text) if val != None: if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db["sent_direct_messages"]["items"].append(val["event"]) + self.session.db["sent_direct_messages"]["items"].append(val) else: - self.session.db["sent_direct_messages"]["items"].insert(0, val["event"]) - pub.sendMessage("sent-dm", data=val["event"], user=self.session.db["user_name"]) + self.session.db["sent_direct_messages"]["items"].insert(0, val) + pub.sendMessage("sent-dm", data=val, user=self.session.db["user_name"]) if hasattr(dm.message, "destroy"): dm.message.destroy() @_tweets_exist @@ -480,12 +480,12 @@ class baseBufferController(baseBuffers.buffer): comments = tweet.full_text else: comments = tweet.text - retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet.user["screen_name"], comments), max=256, messageType="retweet") + retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet.user.screen_name, comments), max=256, messageType="retweet") if comment != '': retweet.message.set_text(comment) if retweet.message.get_response() == widgetUtils.OK: text = retweet.message.get_text() - text = text+" https://twitter.com/{0}/status/{1}".format(tweet.user["screen_name"], id) + text = text+" https://twitter.com/{0}/status/{1}".format(tweet.user.screen_name, id) if retweet.image == None: item = self.session.api_call(call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id, tweet_mode="extended") if item != None: @@ -496,7 +496,7 @@ class baseBufferController(baseBuffers.buffer): if hasattr(retweet.message, "destroy"): retweet.message.destroy() def _direct_retweet(self, id): - item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id, tweet_mode="extended") + item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id) if item != None: # Retweets are returned as non-extended tweets, so let's get the object as extended # just before sending the event message. See https://github.com/manuelcortez/TWBlue/issues/253 @@ -582,7 +582,7 @@ class baseBufferController(baseBuffers.buffer): def user_details(self): tweet = self.get_right_tweet() if self.type == "dm": - users = [self.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [self.session.get_user(tweet.message_create["sender_id"]).screen_name] elif self.type == "people": users = [tweet.screen_name] else: @@ -604,7 +604,7 @@ class baseBufferController(baseBuffers.buffer): def open_in_browser(self, *args, **kwargs): tweet = self.get_tweet() output.speak(_(u"Opening item in web browser...")) - url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet.user["screen_name"], tweet_id=tweet.id) + url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet.user.screen_name, tweet_id=tweet.id) webbrowser.open(url) class directMessagesController(baseBufferController): From fc0da0bdbb720466cb47c808e3a13688fabd54f6 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 13 Jan 2021 08:41:32 -0600 Subject: [PATCH 17/34] Migrated the main controller to use tweepy --- src/controller/mainController.py | 108 +++++++++++++++---------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 8c8db69b..ec605f68 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -30,7 +30,7 @@ from sessions.twitter import session as session_ from pubsub import pub import sound import output -from twython import TwythonError, TwythonAuthError +from tweepy.error import TweepError from mysc.thread_utils import call_threaded from mysc.repeating_timer import RepeatingTimer from mysc import restart @@ -526,9 +526,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) @@ -543,9 +543,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) @@ -557,23 +557,23 @@ class Controller(object): dlg.populate_list([compose.compose_list(item) for item in buff.session.db["lists"]]) if dlg.get_response() == widgetUtils.OK: try: - list = buff.session.twitter.add_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user) - older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()]["id"], buff.session.db["lists"]) - listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()]["name"].lower()), buff.session.db["user_name"]) + list = buff.session.twitter.add_list_member(list_id=buff.session.db["lists"][dlg.get_item()].id, screen_name=user) + older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()].id, buff.session.db["lists"]) + listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()].name.lower()), buff.session.db["user_name"]) if listBuffer != None: listBuffer.get_user_ids() buff.session.db["lists"].pop(older_list) buff.session.db["lists"].append(list) - except TwythonError as e: - output.speak("error %s: %s" % (e.error_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.error_code, e.reason)) def remove_from_list(self, *args, **kwargs): buff = self.get_best_buffer() if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) @@ -585,14 +585,14 @@ class Controller(object): dlg.populate_list([compose.compose_list(item) for item in buff.session.db["lists"]]) if dlg.get_response() == widgetUtils.OK: try: - list = buff.session.twitter.delete_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user) - older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()]["id"], buff.session.db["lists"]) - listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()]["name"].lower()), buff.session.db["user_name"]) + list = buff.session.twitter.remove_list_member(list_id=buff.session.db["lists"][dlg.get_item()].id, screen_name=user) + older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()].id, buff.session.db["lists"]) + listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()].name.lower()), buff.session.db["user_name"]) if listBuffer != None: listBuffer.get_user_ids() buff.session.db["lists"].pop(older_list) buff.session.db["lists"].append(list) - except TwythonError as e: - output.speak("error %s: %s" % (e.error_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.error_code, e.reason)) def list_manager(self, *args, **kwargs): s = self.get_best_buffer().session @@ -665,9 +665,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users) @@ -677,9 +677,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "unfollow") @@ -689,9 +689,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "mute") @@ -701,9 +701,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "unmute") @@ -713,9 +713,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "block") @@ -725,9 +725,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "unblock") @@ -737,9 +737,9 @@ class Controller(object): if not hasattr(buff, "get_right_tweet"): return tweet = buff.get_right_tweet() if buff.type == "people": - users = [tweet["screen_name"]] + users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "report") @@ -771,7 +771,7 @@ class Controller(object): if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": return else: - id = buffer.get_tweet()["id"] + id = buffer.get_tweet().id call_threaded(buffer.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id) def remove_from_favourites(self, *args, **kwargs): @@ -779,7 +779,7 @@ class Controller(object): if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": return else: - id = buffer.get_tweet()["id"] + id = buffer.get_tweet().id call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id) def toggle_like(self, *args, **kwargs): @@ -787,9 +787,9 @@ class Controller(object): if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": return else: - id = buffer.get_tweet()["id"] - tweet = buffer.session.twitter.show_status(id=id, include_ext_alt_text=True, tweet_mode="extended") - if tweet["favorited"] == False: + id = buffer.get_tweet().id + tweet = buffer.session.twitter.get_status(id=id, include_ext_alt_text=True, tweet_mode="extended") + if tweet.favorited == False: call_threaded(buffer.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id) else: call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id) @@ -923,8 +923,8 @@ class Controller(object): def open_conversation(self, *args, **kwargs): buffer = self.get_current_buffer() - id = buffer.get_right_tweet()["id_str"] - user = buffer.get_right_tweet()["user"]["screen_name"] + id = buffer.get_right_tweet().id_str + user = buffer.get_right_tweet().user["screen_name"] search = twitterBuffers.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,)) search.tweet = buffer.get_right_tweet() search.start_stream(start=True) @@ -964,9 +964,9 @@ class Controller(object): def reverse_geocode(self, event=None): try: tweet = self.get_current_buffer().get_tweet() - if tweet["coordinates"] != None: - x = tweet["coordinates"]["coordinates"][0] - y = tweet["coordinates"]["coordinates"][1] + if tweet.coordinates != None: + x = tweet.coordinates["coordinates"][0] + y = tweet.coordinates["coordinates"][1] address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang) if event == None: output.speak(address[0].__str__()) else: self.view.show_address(address[0].__str__()) @@ -984,9 +984,9 @@ class Controller(object): def view_reverse_geocode(self, event=None): try: tweet = self.get_current_buffer().get_right_tweet() - if tweet["coordinates"] != None: - x = tweet["coordinates"]["coordinates"][0] - y = tweet["coordinates"]["coordinates"][1] + if tweet.coordinates != None: + x = tweet.coordinates["coordinates"][0] + y = tweet.coordinates["coordinates"][1] address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang) dlg = commonMessageDialogs.view_geodata(address[0].__str__()) else: @@ -1259,7 +1259,7 @@ class Controller(object): def manage_sent_dm(self, data, user): buffer = self.search_buffer("sent_direct_messages", user) - if buffer == None: return + if buffer == Nogne: return play_sound = "dm_sent.ogg" if "sent_direct_messages" not in buffer.session.settings["other_buffers"]["muted_buffers"]: self.notify(buffer.session, play_sound=play_sound) @@ -1326,7 +1326,7 @@ class Controller(object): i.start_stream() else: i.start_stream(play_sound=False) - except TwythonAuthError: + except TweepError: buff = self.view.search(i.name, i.account) i.remove_buffer(force=True) commonMessageDialogs.blocked_timeline() @@ -1350,34 +1350,34 @@ class Controller(object): try: if sessions.sessions[i].is_logged == False: continue sessions.sessions[i].check_connection() - except TwythonError: # We shouldn't allow this function to die. + except TweepError: # We shouldn't allow this function to die. pass def create_new_buffer(self, buffer, account, create): buff = self.search_buffer("home_timeline", account) if create == True: if buffer == "favourites": - favourites = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended") + favourites = twitterBuffers.baseBufferController(self.view.nb, "favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended") self.buffers.append(favourites) self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) favourites.start_stream(play_sound=False) if buffer == "followers": - followers = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) + followers = twitterBuffers.peopleBufferController(self.view.nb, "followers", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) self.buffers.append(followers) self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) followers.start_stream(play_sound=False) elif buffer == "friends": - friends = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) + friends = twitterBuffers.peopleBufferController(self.view.nb, "friends", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) self.buffers.append(friends) self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) friends.start_stream(play_sound=False) elif buffer == "blocked": - blocks = twitterBuffers.peopleBufferController(self.view.nb, "list_blocks", "blocked", buff.session, buff.session.db["user_name"]) + blocks = twitterBuffers.peopleBufferController(self.view.nb, "blocks", "blocked", buff.session, buff.session.db["user_name"]) self.buffers.append(blocks) self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) blocks.start_stream(play_sound=False) elif buffer == "muted": - muted = twitterBuffers.peopleBufferController(self.view.nb, "get_muted_users_list", "muted", buff.session, buff.session.db["user_name"]) + muted = twitterBuffers.peopleBufferController(self.view.nb, "mutes", "muted", buff.session, buff.session.db["user_name"]) self.buffers.append(muted) self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) muted.start_stream(play_sound=False) @@ -1391,7 +1391,7 @@ class Controller(object): if create in buff.session.settings["other_buffers"]["lists"]: output.speak(_(u"This list is already opened"), True) return - tl = twitterBuffers.listBufferController(self.view.nb, "get_list_statuses", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]), tweet_mode="extended") + tl = twitterBuffers.listBufferController(self.view.nb, "list_timeline", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]), tweet_mode="extended") buff.session.lists.append(tl) pos=self.view.search("lists", buff.session.db["user_name"]) self.insert_buffer(tl, pos) @@ -1532,7 +1532,7 @@ class Controller(object): if i.session != None and i.session.is_logged == True: try: i.start_stream(mandatory=True) - except TwythonAuthError: + except TweepError: buff = self.view.search(i.name, i.account) i.remove_buffer(force=True) commonMessageDialogs.blocked_timeline() From 4064582583093b0380425af0d82eb89a180307ff Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 13 Jan 2021 08:47:13 -0600 Subject: [PATCH 18/34] Remove old reference to Twython error handling --- src/sessions/twitter/session.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 9e106405..00dcbeae 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -209,14 +209,14 @@ class Session(base.baseSession): try: val = getattr(self.twitter, call_name)(*args, **kwargs) finished = True - except TwythonError as e: - output.speak(e.msg) + except TweepError as e: + output.speak(e.reason) val = None if e.error_code != 403 and e.error_code != 404: tries = tries+1 time.sleep(5) - elif report_failure and hasattr(e, 'message'): - output.speak(_("%s failed. Reason: %s") % (action, e.msg)) + elif report_failure and hasattr(e, 'reason'): + output.speak(_("%s failed. Reason: %s") % (action, e.reason)) finished = True # except: # tries = tries + 1 From a26136568280004ad2568772987f71f5cd96c347 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 13 Jan 2021 10:31:37 -0600 Subject: [PATCH 19/34] Fixed some stuff in main controller. Likes work again --- src/controller/mainController.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index ec605f68..05205489 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -564,7 +564,7 @@ class Controller(object): buff.session.db["lists"].pop(older_list) buff.session.db["lists"].append(list) except TweepError as e: - output.speak("error %s: %s" % (e.error_code, e.reason)) + output.speak("error %s: %s" % (e.api_code, e.reason)) def remove_from_list(self, *args, **kwargs): buff = self.get_best_buffer() @@ -592,7 +592,7 @@ class Controller(object): buff.session.db["lists"].pop(older_list) buff.session.db["lists"].append(list) except TweepError as e: - output.speak("error %s: %s" % (e.error_code, e.reason)) + output.speak("error %s: %s" % (e.api_code, e.reason)) def list_manager(self, *args, **kwargs): s = self.get_best_buffer().session From 33b6000b416c35510c91a260dc9bfdcbfc5eb488 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 13 Jan 2021 10:32:03 -0600 Subject: [PATCH 20/34] Implemented user profile viewer --- src/controller/user.py | 78 +++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/controller/user.py b/src/controller/user.py index 9fb07388..9293b5c7 100644 --- a/src/controller/user.py +++ b/src/controller/user.py @@ -6,7 +6,7 @@ import output from wxUI.dialogs import update_profile, show_user import logging log = logging.getLogger("controller.user") -from twython import TwythonError +from tweepy.error import TweepError from sessions.twitter import utils class profileController(object): @@ -24,36 +24,36 @@ class profileController(object): else: try: self.get_data(screen_name=self.user) - except TwythonError as err: - if err.error_code == 404: + except TweepError as err: + if err.api_code == 50: wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal() - if err.error_code == 403: + if err.api_code == 403: wx.MessageDialog(None, _(u"User has been suspended"), _(u"Error"), wx.ICON_ERROR).ShowModal() - log.error("error %d: %s" % (err.error_code, err.msg)) + log.error("error %d: %s" % (err.api_code, err.reason)) return self.dialog = show_user.showUserProfile() string = self.get_user_info() self.dialog.set("text", string) - self.dialog.set_title(_(u"Information for %s") % (self.data["screen_name"])) - if self.data["url"] != None: + self.dialog.set_title(_(u"Information for %s") % (self.data.screen_name)) + if self.data.url != None: self.dialog.enable_url() widgetUtils.connect_event(self.dialog.url, widgetUtils.BUTTON_PRESSED, self.visit_url) if self.dialog.get_response() == widgetUtils.OK and self.user == None: self.do_update() def get_data(self, screen_name): - self.data = self.session.twitter.show_user(screen_name=screen_name) + self.data = self.session.twitter.get_user(screen_name=screen_name) if screen_name != self.session.db["user_name"]: self.friendship_status = self.session.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name) def fill_profile_fields(self): - self.dialog.set_name(self.data["name"]) - if self.data["url"] != None: - self.dialog.set_url(self.data["url"]) - if len(self.data["location"]) > 0: - self.dialog.set_location(self.data["location"]) - if len(self.data["description"]) > 0: - self.dialog.set_description(self.data["description"]) + self.dialog.set_name(self.data.name) + if self.data.url != None: + self.dialog.set_url(self.data.url) + if len(self.data.location) > 0: + self.dialog.set_location(self.data.location) + if len(self.data.description) > 0: + self.dialog.set_description(self.data.description) def get_image(self): file = self.dialog.upload_picture() @@ -83,46 +83,46 @@ class profileController(object): if self.file != None: try: self.session.twitter.update_profile_image(image=self.file) - except TwythonError as e: - output.speak(u"Error %s. %s" % (e.error_code, e.msg)) + except TweepError as e: + output.speak(u"Error %s. %s" % (e.api_code, e.reason)) try: self.session.twitter.update_profile(name=name, description=description, location=location, url=url) - except TwythonError as e: - output.speak(u"Error %s. %s" % (e.error_code, e.msg)) + except TweepError as e: + output.speak(u"Error %s. %s" % (e.api_code, e.reason)) def get_user_info(self): string = u"" - string = string + _(u"Username: @%s\n") % (self.data["screen_name"]) - string = string + _(u"Name: %s\n") % (self.data["name"]) - if self.data["location"] != "": - string = string + _(u"Location: %s\n") % (self.data["location"]) - if self.data["url"] != None: - string = string+ _(u"URL: %s\n") % (self.data["entities"]["url"]["urls"][0]["expanded_url"]) - if self.data["description"] != "": - if self.data["entities"].get("description") != None and self.data["entities"]["description"].get("urls"): - self.data["description"] = utils.expand_urls(self.data["description"], self.data["entities"]["description"]) - string = string+ _(u"Bio: %s\n") % (self.data["description"]) - if self.data["protected"] == True: protected = _(u"Yes") + string = string + _(u"Username: @%s\n") % (self.data.screen_name) + string = string + _(u"Name: %s\n") % (self.data.name) + if self.data.location != "": + string = string + _(u"Location: %s\n") % (self.data.location) + if self.data.url != None: + string = string+ _(u"URL: %s\n") % (self.data.entities["url"]["urls"][0]["expanded_url"]) + if self.data.description != "": + if self.data.entities.get("description") != None and self.data.entities["description"].get("urls"): + self.data.description = utils.expand_urls(self.data.description, self.data.entities["description"]) + string = string+ _(u"Bio: %s\n") % (self.data.description) + if self.data.protected == True: protected = _(u"Yes") else: protected = _(u"No") string = string+ _(u"Protected: %s\n") % (protected) if hasattr(self, "friendship_status"): relation = False friendship = "Relationship: " - if self.friendship_status["relationship"]["target"]["followed_by"]: - friendship += _(u"You follow {0}. ").format(self.data["name"],) + if self.friendship_status[0].following: + friendship += _(u"You follow {0}. ").format(self.data.name,) relation = True - if self.friendship_status["relationship"]["target"]["following"]: - friendship += _(u"{0} is following you.").format(self.data["name"],) + if self.friendship_status[1].following: + friendship += _(u"{0} is following you.").format(self.data.name,) relation = True if relation == True: string = string+friendship+"\n" - string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data["followers_count"], self.data["friends_count"]) - if self.data["verified"] == True: verified = _(u"Yes") + string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data.followers_count, self.data.friends_count) + if self.data.verified == True: verified = _(u"Yes") else: verified = _(u"No") string = string+ _(u"Verified: %s\n") % (verified) - string = string+ _(u"Tweets: %s\n") % (self.data["statuses_count"]) - string = string+ _(u"Likes: %s") % (self.data["favourites_count"]) + string = string+ _(u"Tweets: %s\n") % (self.data.statuses_count) + string = string+ _(u"Likes: %s") % (self.data.favourites_count) return string def visit_url(self, *args, **kwargs): - webbrowser.open_new_tab(self.data["url"]) \ No newline at end of file + webbrowser.open_new_tab(self.data.url) \ No newline at end of file From db13c96baad554348364e771cfef159ee6fc8da6 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 13 Jan 2021 10:33:49 -0600 Subject: [PATCH 21/34] Fixed some incorrect error handling on utils --- src/sessions/twitter/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sessions/twitter/utils.py b/src/sessions/twitter/utils.py index e2e12950..57e02f3a 100644 --- a/src/sessions/twitter/utils.py +++ b/src/sessions/twitter/utils.py @@ -132,7 +132,7 @@ def if_user_exists(twitter, user): data = twitter.get_user(screen_name=user) return data except TweepError as err: - if err.error_code == 50: + if err.api_code == 50: return None else: return user @@ -201,7 +201,7 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name): def twitter_error(error): if error.api_code == 179: msg = _(u"Sorry, you are not authorised to see this status.") - elif error.error_code == 144: + elif error.api_code == 144: msg = _(u"No status found with that ID") else: msg = _(u"Error code {0}").format(error.api_code,) From 85fe94ec0c763ed907dfbc1267b303019e4bf589 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 13 Jan 2021 10:38:26 -0600 Subject: [PATCH 22/34] Implemented user actions (needs testing) --- src/controller/userActionsController.py | 37 ++++++++++++------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/controller/userActionsController.py b/src/controller/userActionsController.py index b77f321e..54f4ba16 100644 --- a/src/controller/userActionsController.py +++ b/src/controller/userActionsController.py @@ -1,12 +1,9 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals -from builtins import object -import re import widgetUtils import output from wxUI.dialogs import userActions from pubsub import pub -from twython import TwythonError +from tweepy.error import TweepError from extra import autocompletionUsers class userActionsController(object): @@ -32,51 +29,51 @@ class userActionsController(object): def follow(self, user): try: self.session.twitter.create_friendship(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def unfollow(self, user): try: id = self.session.twitter.destroy_friendship(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def mute(self, user): try: id = self.session.twitter.create_mute(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def unmute(self, user): try: id = self.session.twitter.destroy_mute(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def report(self, user): try: id = self.session.twitter.report_spam(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def block(self, user): try: id = self.session.twitter.create_block(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def unblock(self, user): try: id = self.session.twitter.destroy_block(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) + except TweepError as err: + output.speak("Error %s: %s" % (err.api_code, err.reason), True) def ignore_client(self, user): tweet = self.buffer.get_right_tweet() - if "sender" in tweet: + if hasattr(tweet, "sender"): output.speak(_(u"You can't ignore direct messages")) return - client = re.sub(r"(?s)<.*?>", "", tweet["source"]) + client = tweet.source if client not in self.session.settings["twitter"]["ignored_clients"]: self.session.settings["twitter"]["ignored_clients"].append(client) self.session.settings.write() \ No newline at end of file From f546543e9bc5599d55274805f281961e271a1902 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 14 Jan 2021 09:18:57 -0600 Subject: [PATCH 23/34] Implemented tweet searches and conversation fupport --- src/controller/buffers/twitterBuffers.py | 18 +++++++++--------- src/controller/mainController.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 6a3f1253..2dfcb11f 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -1248,23 +1248,23 @@ class conversationBufferController(searchBufferController): self.statuses = [] self.ids = [] self.statuses.append(self.tweet) - self.ids.append(self.tweet["id"]) + self.ids.append(self.tweet.id) tweet = self.tweet - while tweet["in_reply_to_status_id"] != None: + while tweet.in_reply_to_status_id != None: try: - tweet = self.session.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended") + tweet = self.session.twitter.get_status(id=tweet.in_reply_to_status_id, tweet_mode="extended") except TweepError as err: break self.statuses.insert(0, tweet) - self.ids.append(tweet["id"]) - if tweet["in_reply_to_status_id"] == None: - self.kwargs["since_id"] = tweet["id"] - self.ids.append(tweet["id"]) + self.ids.append(tweet.id) + if tweet.in_reply_to_status_id == None: + self.kwargs["since_id"] = tweet.id + self.ids.append(tweet.id) val2 = self.session.search(self.name, tweet_mode="extended", *self.args, **self.kwargs) for i in val2: - if i["in_reply_to_status_id"] in self.ids: + if i.in_reply_to_status_id in self.ids: self.statuses.append(i) - self.ids.append(i["id"]) + self.ids.append(i.id) tweet = i number_of_items = self.session.order_buffer(self.name, self.statuses) log.debug("Number of items retrieved: %d" % (number_of_items,)) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 05205489..5f8c672a 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -924,7 +924,7 @@ class Controller(object): def open_conversation(self, *args, **kwargs): buffer = self.get_current_buffer() id = buffer.get_right_tweet().id_str - user = buffer.get_right_tweet().user["screen_name"] + user = buffer.get_right_tweet().user.screen_name search = twitterBuffers.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,)) search.tweet = buffer.get_right_tweet() search.start_stream(start=True) From 46433017641ba07edcd1e4f859f304a13ed31139 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Tue, 19 Jan 2021 17:47:54 -0600 Subject: [PATCH 24/34] Implemented list creation, edition and removal --- src/controller/listsController.py | 48 ++++++++++++++++--------------- src/wxUI/dialogs/lists.py | 8 +++--- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/controller/listsController.py b/src/controller/listsController.py index 19f8932a..776b0604 100644 --- a/src/controller/listsController.py +++ b/src/controller/listsController.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals -from builtins import object import widgetUtils import output +import logging from wxUI.dialogs import lists -from twython import TwythonError +from tweepy.error import TweepError from sessions.twitter import compose, utils from pubsub import pub +log = logging.getLogger("controller.listsController") + class listsController(object): def __init__(self, session, user=None): super(listsController, self).__init__() @@ -31,7 +32,7 @@ class listsController(object): return [compose.compose_list(item) for item in self.session.db["lists"]] def get_user_lists(self, user): - self.lists = self.session.twitter.show_lists(reverse=True, screen_name=user) + self.lists = self.session.twitter.lists_all(reverse=True, screen_name=user) return [compose.compose_list(item) for item in self.lists] def create_list(self, *args, **kwargs): @@ -48,8 +49,9 @@ class listsController(object): new_list = self.session.twitter.create_list(name=name, description=description, mode=mode) self.session.db["lists"].append(new_list) self.dialog.lista.insert_item(False, *compose.compose_list(new_list)) - except TwythonError as e: - output.speak("error %s: %s" % (e.status_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.api_code, e.reason)) + log.exception("error %s: %s" % (e.api_code, e.reason)) dialog.destroy() def edit_list(self, *args, **kwargs): @@ -65,44 +67,44 @@ class listsController(object): else: mode = "private" try: - self.session.twitter.update_list(list_id=list["id"], name=name, description=description, mode=mode) + self.session.twitter.update_list(list_id=list.id, name=name, description=description, mode=mode) self.session.get_lists() self.dialog.populate_list(self.get_all_lists(), True) - except TwythonError as e: - output.speak("error %s: %s" % (e.error_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.api_code, e.reason)) dialog.destroy() def remove_list(self, *args, **kwargs): if self.dialog.lista.get_count() == 0: return - list = self.session.db["lists"][self.dialog.get_item()]["id"] + list = self.session.db["lists"][self.dialog.get_item()].id if lists.remove_list() == widgetUtils.YES: try: - self.session.twitter.delete_list(list_id=list) + self.session.twitter.destroy_list(list_id=list) self.session.db["lists"].pop(self.dialog.get_item()) self.dialog.lista.remove_item(self.dialog.get_item()) - except TwythonError as e: - output.speak("error %s: %s" % (e.error_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.api_code, e.reason)) def open_list_as_buffer(self, *args, **kwargs): if self.dialog.lista.get_count() == 0: return list = self.session.db["lists"][self.dialog.get_item()] - pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["name"]) + pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list.name) def subscribe(self, *args, **kwargs): if self.dialog.lista.get_count() == 0: return - list_id = self.lists[self.dialog.get_item()]["id"] + list_id = self.lists[self.dialog.get_item()].id try: - list = self.session.twitter.subscribe_to_list(list_id=list_id) - item = utils.find_item(list["id"], self.session.db["lists"]) + list = self.session.twitter.subscribe_list(list_id=list_id) + item = utils.find_item(list.id, self.session.db["lists"]) self.session.db["lists"].append(list) - except TwythonError as e: - output.speak("error %s: %s" % (e.status_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.api_code, e.reason)) def unsubscribe(self, *args, **kwargs): if self.dialog.lista.get_count() == 0: return - list_id = self.lists[self.dialog.get_item()]["id"] + list_id = self.lists[self.dialog.get_item()].id try: - list = self.session.twitter.unsubscribe_from_list(list_id=list_id) + list = self.session.twitter.unsubscribe_list(list_id=list_id) self.session.db["lists"].remove(list) - except TwythonError as e: - output.speak("error %s: %s" % (e.status_code, e.msg)) + except TweepError as e: + output.speak("error %s: %s" % (e.api_code, e.reason)) diff --git a/src/wxUI/dialogs/lists.py b/src/wxUI/dialogs/lists.py index 4dbf55a8..9a30a4a3 100644 --- a/src/wxUI/dialogs/lists.py +++ b/src/wxUI/dialogs/lists.py @@ -94,10 +94,10 @@ class editListDialog(createListDialog): def __init__(self, list, *args, **kwargs): super(editListDialog, self).__init__(*args, **kwargs) - self.SetTitle(_(u"Editing the list %s") % (list["name"])) - self.name.ChangeValue(list["name"]) - self.description.ChangeValue(list["description"]) - if list["mode"] == "public": + self.SetTitle(_(u"Editing the list %s") % (list.name)) + self.name.ChangeValue(list.name) + self.description.ChangeValue(list.description) + if list.mode == "public": self.public.SetValue(True) else: self.private.SetValue(True) From cdc285e3622270c7af4a976fb96bd7796f0a87a0 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 09:21:50 -0600 Subject: [PATCH 25/34] Implemented support to list buffer creation --- src/controller/buffers/twitterBuffers.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 2dfcb11f..10532030 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -22,6 +22,7 @@ from controller.buffers import baseBuffers from sessions.twitter import compose, utils from mysc.thread_utils import call_threaded from tweepy.error import TweepError +from tweepy.cursor import Cursor from pubsub import pub from sessions.twitter.long_tweets import twishort, tweets @@ -737,13 +738,9 @@ class listBufferController(baseBufferController): super(listBufferController, self).start_stream(mandatory, play_sound, avoid_autoreading) def get_user_ids(self): - next_cursor = -1 - while(next_cursor): - users = self.session.twitter.get_list_members(list_id=self.list_id, cursor=next_cursor, include_entities=False, skip_status=True) - for i in users['users']: - if i["id"] not in self.users: - self.users.append(i["id"]) - next_cursor = users["next_cursor"] + for i in Cursor(self.session.twitter.list_members, list_id=self.list_id, include_entities=False, skip_status=True).items(): + if i.id not in self.users: + self.users.append(i.id) def remove_buffer(self, force=False): if force == False: From 52154ac271f7221ce2e91a80be99e6a918af99e5 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 09:59:38 -0600 Subject: [PATCH 26/34] Migrated support to Trending Topics --- src/controller/buffers/twitterBuffers.py | 6 +++--- src/controller/trendingTopics.py | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 10532030..fb07cb2e 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -1134,9 +1134,9 @@ class trendsBufferController(baseBuffers.buffer): if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True: self.execution_time = current_time try: - data = self.session.call_paged("get_place_trends", id=self.trendsFor) - except: - return + data = self.session.twitter.trends_place(id=self.trendsFor) + except TweepError as err: + log.error("Error %s: %s" % (err.api_code, err.reason)) if not hasattr(self, "name_"): self.name_ = data[0]["locations"][0]["name"] self.trends = data[0]["trends"] diff --git a/src/controller/trendingTopics.py b/src/controller/trendingTopics.py index 4982c7d7..5b6bd270 100644 --- a/src/controller/trendingTopics.py +++ b/src/controller/trendingTopics.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals -from builtins import object from wxUI.dialogs import trends import widgetUtils @@ -10,7 +8,7 @@ class trendingTopicsController(object): self.countries = {} self.cities = {} self.dialog = trends.trendingTopicsDialog() - self.information = session.twitter.get_available_trends() + self.information = session.twitter.trends_available() self.split_information() widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places) widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places) From 366b61134e6d5c2af1f7a6cadcb663517340e254 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 10:00:19 -0600 Subject: [PATCH 27/34] Fixed trending topics dialog --- src/wxUI/dialogs/trends.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/wxUI/dialogs/trends.py b/src/wxUI/dialogs/trends.py index 1a670b1c..d2d6ae75 100644 --- a/src/wxUI/dialogs/trends.py +++ b/src/wxUI/dialogs/trends.py @@ -1,7 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import unicode_literals -# -*- coding: utf-8 -*- from . import baseDialog import wx @@ -11,8 +8,7 @@ class trendingTopicsDialog(baseDialog.BaseWXDialog): panel = wx.Panel(self) sizer = wx.BoxSizer(wx.VERTICAL) self.SetTitle(_(u"View trending topics")) - label = wx.StaticText(panel, -1, _(u"Trending topics by")) - sizer.Add(label, 0, wx.ALL, 5) + label = wx.StaticText(panel, wx.NewId(), _(u"Trending topics by")) self.country = wx.RadioButton(panel, -1, _(u"Country"), style=wx.RB_GROUP) self.city = wx.RadioButton(panel, -1, _(u"City")) radioSizer = wx.BoxSizer(wx.HORIZONTAL) From 7457521398cf0f6fe2d004923f2d194754cc7ccc Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 10:35:11 -0600 Subject: [PATCH 28/34] Restored media uploading (needs testing). Fixes #240 --- src/controller/buffers/twitterBuffers.py | 17 +++++++++-------- src/wxUI/dialogs/attach.py | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index fb07cb2e..227eaaeb 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -84,6 +84,7 @@ class baseBufferController(baseBuffers.buffer): return _(u"Unknown buffer") def post_status(self, *args, **kwargs): + item = None title = _(u"Tweet") caption = _(u"Write the tweet here") tweet = messages.tweet(self.session, title, caption, "") @@ -99,22 +100,22 @@ class baseBufferController(baseBuffers.buffer): text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1) if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0: item = self.session.api_call(call_name="update_status", status=text, _sound="tweet_send.ogg", tweet_mode="extended") -# else: -# call_threaded(self.post_with_media, text=text, attachments=tweet.attachments, _sound="tweet_send.ogg") + else: + call_threaded(self.post_with_media, text=text, attachments=tweet.attachments) if item != None: pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"]) if hasattr(tweet.message, "destroy"): tweet.message.destroy() self.session.settings.write() - # ToDo: Update to tweepy. def post_with_media(self, text, attachments): media_ids = [] for i in attachments: - photo = open(i["file"], "rb") - img = self.session.twitter.upload_media(media=photo) - self.session.twitter.create_metadata(media_id=img["media_id"], alt_text=dict(text=i["description"])) - media_ids.append(img["media_id"]) - self.session.twitter.update_status(status=text, media_ids=media_ids) + img = self.session.twitter.media_upload(i["file"]) + self.session.twitter.create_media_metadata(media_id=img.media_id, alt_text=i["description"]) + media_ids.append(img.media_id) + item = self.session.twitter.update_status(status=text, media_ids=media_ids) + if item != None: + pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"]) def get_formatted_message(self): if self.type == "dm" or self.name == "direct_messages": diff --git a/src/wxUI/dialogs/attach.py b/src/wxUI/dialogs/attach.py index 37ac6f21..ea8d35c1 100644 --- a/src/wxUI/dialogs/attach.py +++ b/src/wxUI/dialogs/attach.py @@ -41,7 +41,7 @@ class attachDialog(widgetUtils.BaseDialog): return (openFileDialog.GetPath(), dsc) def ask_description(self): - dlg = wx.TextEntryDialog(self, _(u"please provide a description"), _(u"Description"), defaultValue="") + dlg = wx.TextEntryDialog(self, _(u"please provide a description"), _(u"Description")) dlg.ShowModal() result = dlg.GetValue() dlg.Destroy() From 999cbba46407c6dbbcee5ba8b44e6b29cde4eb20 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 11:02:21 -0600 Subject: [PATCH 29/34] Implemented function to get previous item for tweets and searches --- src/controller/buffers/twitterBuffers.py | 48 +++--------------------- 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 227eaaeb..2b07c02c 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -196,17 +196,18 @@ class baseBufferController(baseBuffers.buffer): def get_more_items(self): elements = [] if self.session.settings["general"]["reverse_timelines"] == False: - last_id = self.session.db[self.name][0]["id"] + last_id = self.session.db[self.name][0].id else: - last_id = self.session.db[self.name][-1]["id"] + last_id = self.session.db[self.name][-1].id try: - items = self.session.get_more_items(self.function, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs) + items = Cursor(getattr(self.session.twitter, self.function), max_id=last_id, *self.args, **self.kwargs).items(self.session.settings["general"]["max_tweets_per_call"]) except TweepError as e: - output.speak(e.reason, True) + log.error("Error %s: %s" % (e.api_code, e.reason)) + return if items == None: return for i in items: - if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i["id"], self.session.db[self.name]) == None: + if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i.id, self.session.db[self.name]) == None: i = self.session.check_quoted_status(i) i = self.session.check_long_tweet(i) elements.append(i) @@ -223,8 +224,6 @@ class baseBufferController(baseBuffers.buffer): for i in items: tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) self.buffer.list.insert_item(False, *tweet) -# self.buffer.list.select_item(selection+elements) -# else: self.buffer.list.select_item(selection) output.speak(_(u"%s items retrieved") % (str(len(elements))), True) @@ -995,41 +994,6 @@ class searchBufferController(baseBufferController): elif dlg == widgetUtils.NO: return False - def get_more_items(self): - elements = [] - if self.session.settings["general"]["reverse_timelines"] == False: - last_id = self.session.db[self.name][0]["id"] - else: - last_id = self.session.db[self.name][-1]["id"] - try: - items = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs) - except TweepError as e: - output.speak(e.reason, True) - if items == None: - return - for i in items: - if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i["id"], self.session.db[self.name]) == None: - i = self.session.check_quoted_status(i) - i = self.session.check_long_tweet(i) - elements.append(i) - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[self.name].insert(0, i) - else: - self.session.db[self.name].append(i) - selection = self.buffer.list.get_selected() - if self.session.settings["general"]["reverse_timelines"] == False: - for i in elements: - tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) - self.buffer.list.insert_item(True, *tweet) - else: - for i in items: - tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) - self.buffer.list.insert_item(False, *tweet) -# self.buffer.list.select_item(selection+elements) -# else: - self.buffer.list.select_item(selection) - output.speak(_(u"%s items retrieved") % (str(len(elements))), True) - class searchPeopleBufferController(peopleBufferController): def __init__(self, parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs): From 8bdc933bceacb576cc596b2802386013752740c9 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 15:56:20 -0600 Subject: [PATCH 30/34] Migrated direct messages. Cursor support still require testing --- src/controller/buffers/twitterBuffers.py | 113 ++++++++++++++--------- src/controller/mainController.py | 26 +++--- src/sessions/twitter/compose.py | 12 +-- src/sessions/twitter/session.py | 42 +++++---- 4 files changed, 110 insertions(+), 83 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index 2b07c02c..ed2393cd 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -162,12 +162,29 @@ class baseBufferController(baseBuffers.buffer): self.execution_time = current_time log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type)) log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) - if self.name == "direct_messages": - number_of_items = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs) - else: + if self.name != "direct_messages": val = self.session.call_paged(self.function, *self.args, **self.kwargs) - number_of_items = self.session.order_buffer(self.name, val) - log.debug("Number of items retrieved: %d" % (number_of_items,)) + else: + # 50 results are allowed per API call, so let's assume max value can be 50. + # reference: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events + if self.session.settings["general"]["max_tweets_per_call"] > 50: + count = 50 + else: + count = self.session.settings["general"]["max_tweets_per_call"] + # try to retrieve the cursor for the current buffer. + cursor = self.session.db["cursors"].get(self.name) + try: + # We need to assign all results somewhere else so the cursor variable would b generated. + val = Cursor(getattr(self.session.twitter, self.function), *self.args, **self.kwargs).items(count) + results = [i for i in val] + self.session.db["cursors"][self.name] = val.page_iterator.next_cursor + val = results + val.reverse() + except TweepError as e: + log.error("Error %s: %s" % (e.api_code, e.reason)) + return + number_of_items = self.session.order_buffer(self.name, val) + log.debug("Number of items retrieved: %d" % (number_of_items,)) self.put_items_on_list(number_of_items) if hasattr(self, "finished_timeline") and self.finished_timeline == False: if "-timeline" in self.name: @@ -268,11 +285,7 @@ class baseBufferController(baseBuffers.buffer): self.remove_item(i) def put_items_on_list(self, number_of_items): - # Define the list we're going to use as cursored stuff are a bit different. - if self.name != "direct_messages" and self.name != "sent_direct_messages": - list_to_use = self.session.db[self.name] - else: - list_to_use = self.session.db[self.name]["items"] + list_to_use = self.session.db[self.name] if number_of_items == 0 and self.session.settings["general"]["persist_size"] == 0: return log.debug("The list contains %d items " % (self.buffer.list.get_count(),)) log.debug("Putting %d items on the list" % (number_of_items,)) @@ -441,7 +454,7 @@ class baseBufferController(baseBuffers.buffer): screen_name = tweet.screen_name users = [screen_name] else: - screen_name = tweet.user["screen_name"] + screen_name = tweet.user.screen_name users = utils.get_all_users(tweet, self.session.db) dm = messages.dm(self.session, _(u"Direct message to %s") % (screen_name,), _(u"New direct message"), users) if dm.message.get_response() == widgetUtils.OK: @@ -452,9 +465,9 @@ class baseBufferController(baseBuffers.buffer): val = self.session.api_call(call_name="send_direct_message", recipient_id=recipient_id, text=text) if val != None: if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db["sent_direct_messages"]["items"].append(val) + self.session.db["sent_direct_messages"].append(val) else: - self.session.db["sent_direct_messages"]["items"].insert(0, val) + self.session.db["sent_direct_messages"].insert(0, val) pub.sendMessage("sent-dm", data=val, user=self.session.db["user_name"]) if hasattr(dm.message, "destroy"): dm.message.destroy() @@ -611,53 +624,65 @@ class baseBufferController(baseBuffers.buffer): class directMessagesController(baseBufferController): def get_more_items(self): + # 50 results are allowed per API call, so let's assume max value can be 50. + # reference: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events + if self.session.settings["general"]["max_tweets_per_call"] > 50: + count = 50 + else: + count = self.session.settings["general"]["max_tweets_per_call"] + total = 0 + # try to retrieve the cursor for the current buffer. + cursor = self.session.db["cursors"].get(self.name) try: - items = self.session.get_more_items(self.function, dm=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs) + items = Cursor(getattr(self.session.twitter, self.function), cursor=cursor, *self.args, **self.kwargs).items(count) + results = [i for i in items] + self.session.db["cursors"][self.name] = items.page_iterator.next_cursor + items = results except TweepError as e: - output.speak(e.reason, True) + log.error("Error %s: %s" % (e.api_code, e.reason)) return if items == None: return sent = [] + received = [] for i in items: - if i["message_create"]["sender_id"] == self.session.db["user_id"]: + if int(i.message_create["sender_id"]) == self.session.db["user_id"]: if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db["sent_direct_messages"]["items"].insert(0, i) + self.session.db["sent_direct_messages"].insert(0, i) + sent.append(i) else: - self.session.db["sent_direct_messages"]["items"].append(i) - sent.append(i) + self.session.db["sent_direct_messages"].append(i) + sent.insert(0, i) else: if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[self.name]["items"].insert(0, i) + self.session.db[self.name].insert(0, i) + received.append(i) else: - self.session.db[self.name]["items"].append(i) + self.session.db[self.name].append(i) + received.insert(0, i) + total = total+1 pub.sendMessage("more-sent-dms", data=sent, account=self.session.db["user_name"]) selected = self.buffer.list.get_selected() + if self.session.settings["general"]["reverse_timelines"] == True: - for i in items: - if i["message_create"]["sender_id"] == self.session.db["user_id"]: + for i in received: + if int(i.message_create["sender_id"]) == self.session.db["user_id"]: continue tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) self.buffer.list.insert_item(True, *tweet) self.buffer.list.select_item(selected) else: - for i in items: - if i["message_create"]["sender_id"] == self.session.db["user_id"]: + for i in received: + if int(i.message_create["sender_id"]) == self.session.db["user_id"]: continue tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) self.buffer.list.insert_item(True, *tweet) - output.speak(_(u"%s items retrieved") % (len(items)), True) - - def get_tweet(self): - tweet = self.session.db[self.name]["items"][self.buffer.list.get_selected()] - return tweet - - get_right_tweet = get_tweet + output.speak(_(u"%s items retrieved") % (total), True) @_tweets_exist def reply(self, *args, **kwargs): tweet = self.get_right_tweet() - screen_name = self.session.get_user(tweet.message_create["sender_id"])["screen_name"] + screen_name = self.session.get_user(tweet.message_create["sender_id"]).screen_name message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,]) if message.message.get_response() == widgetUtils.OK: if config.app["app-settings"]["remember_mention_and_longtweet"]: @@ -675,7 +700,7 @@ class directMessagesController(baseBufferController): tweet = self.get_tweet() if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True: # fix this: - original_date = arrow.get(int(tweet["created_timestamp"][:-3])) + original_date = arrow.get(int(tweet.created_timestamp)) ts = original_date.humanize(locale=languageHandler.getLanguage()) self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts) if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet): @@ -686,15 +711,15 @@ class directMessagesController(baseBufferController): def clear_list(self): dlg = commonMessageDialogs.clear_list() if dlg == widgetUtils.YES: - self.session.db[self.name]["items"] = [] + self.session.db[self.name] = [] self.buffer.list.clear() def auto_read(self, number_of_items): if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False: if self.session.settings["general"]["reverse_timelines"] == False: - tweet = self.session.db[self.name]["items"][-1] + tweet = self.session.db[self.name][-1] else: - tweet = self.session.db[self.name]["items"][0] + tweet = self.session.db[self.name][0] output.speak(_(u"New direct message")) output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session))) elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False: @@ -708,7 +733,7 @@ class sentDirectMessagesController(directMessagesController): def __init__(self, *args, **kwargs): super(sentDirectMessagesController, self).__init__(*args, **kwargs) if ("sent_direct_messages" in self.session.db) == False: - self.session.db["sent_direct_messages"] = {"items": []} + self.session.db["sent_direct_messages"] = [] def get_more_items(self): output.speak(_(u"Getting more items cannot be done in this buffer. Use the direct messages buffer instead.")) @@ -720,11 +745,11 @@ class sentDirectMessagesController(directMessagesController): if self.session.settings["general"]["reverse_timelines"] == True: for i in items: tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) - self.buffer.list.insert_item(True, *tweet) + self.buffer.list.insert_item(False, *tweet) else: for i in items: tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session) - self.buffer.list.insert_item(True, *tweet) + self.buffer.list.insert_item(False, *tweet) class listBufferController(baseBufferController): def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs): @@ -820,7 +845,7 @@ class peopleBufferController(baseBufferController): @_tweets_exist def reply(self, *args, **kwargs): tweet = self.get_right_tweet() - screen_name = tweet["screen_name"] + screen_name = tweet.screen_name message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,]) if message.message.get_response() == widgetUtils.OK: if config.app["app-settings"]["remember_mention_and_longtweet"]: @@ -844,7 +869,7 @@ class peopleBufferController(baseBufferController): val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs) self.put_items_on_list(val) if hasattr(self, "finished_timeline") and self.finished_timeline == False: - self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"] + self.username = self.session.api_call("get_user", **self.kwargs).screen_name self.finished_timeline = True if val > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True: self.session.sound.play(self.sound) @@ -921,7 +946,7 @@ class peopleBufferController(baseBufferController): self.buffer.list.clear() def interact(self): - user.profileController(self.session, user=self.get_right_tweet()["screen_name"]) + user.profileController(self.session, user=self.get_right_tweet().screen_name) def show_menu(self, ev, pos=0, *args, **kwargs): menu = menus.peoplePanelMenu() @@ -954,7 +979,7 @@ class peopleBufferController(baseBufferController): def open_in_browser(self, *args, **kwargs): tweet = self.get_tweet() output.speak(_(u"Opening item in web browser...")) - url = "https://twitter.com/{screen_name}".format(screen_name=tweet["screen_name"]) + url = "https://twitter.com/{screen_name}".format(screen_name=tweet.screen_name) webbrowser.open(url) class searchBufferController(baseBufferController): diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 5f8c672a..608dc900 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -528,7 +528,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) @@ -545,7 +545,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) @@ -573,7 +573,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) @@ -667,7 +667,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users) @@ -679,7 +679,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "unfollow") @@ -691,7 +691,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "mute") @@ -703,7 +703,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "unmute") @@ -715,7 +715,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "block") @@ -727,7 +727,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "unblock") @@ -739,7 +739,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) u = userActionsController.userActionsController(buff, users, "report") @@ -804,7 +804,7 @@ class Controller(object): elif buffer.type == "dm": non_tweet = buffer.get_formatted_message() item = buffer.get_right_tweet() - original_date = arrow.get(int(item["created_timestamp"][:-3])) + original_date = arrow.get(int(item.created_timestamp)) date = original_date.shift(seconds=buffer.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage()) msg = messages.viewTweet(non_tweet, [], False, date=date) else: @@ -826,7 +826,7 @@ class Controller(object): if buff.type == "people": users = [tweet.screen_name] elif buff.type == "dm": - users = [buff.session.get_user(tweet.message_create["sender_id"])["screen_name"]] + users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] else: users = utils.get_all_users(tweet, buff.session.db) dlg = dialogs.userSelection.selectUserDialog(users=users, default=default) @@ -1259,7 +1259,7 @@ class Controller(object): def manage_sent_dm(self, data, user): buffer = self.search_buffer("sent_direct_messages", user) - if buffer == Nogne: return + if buffer == None: return play_sound = "dm_sent.ogg" if "sent_direct_messages" not in buffer.session.settings["other_buffers"]["muted_buffers"]: self.notify(buffer.session, play_sound=play_sound) diff --git a/src/sessions/twitter/compose.py b/src/sessions/twitter/compose.py index d2a73e9f..7f5c3620 100644 --- a/src/sessions/twitter/compose.py +++ b/src/sessions/twitter/compose.py @@ -82,26 +82,26 @@ def compose_direct_message(item, db, relative_times, show_screen_names=False, se if system == "Windows": # Let's remove the last 3 digits in the timestamp string. # Twitter sends their "epoch" timestamp with 3 digits for milliseconds and arrow doesn't like it. - original_date = arrow.get(int(item.created_timestamp[:-3])) + original_date = arrow.get(int(item.created_timestamp)) if relative_times == True: ts = original_date.humanize(locale=languageHandler.curLang[:2]) else: ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2]) else: ts = item.created_timestamp - text = StripChars(item.message_create.message_data.text) + text = StripChars(item.message_create["message_data"]["text"]) source = "DM" sender = session.get_user(item.message_create["sender_id"]) - if db["user_name"] == sender["screen_name"]: + if db["user_name"] == sender.screen_name: if show_screen_names: user = _(u"Dm to %s ") % (session.get_user(item.message_create["target"]["recipient_id"]).screen_name) else: - user = _(u"Dm to %s ") % (session.get_user(item["message_create"]["target"]["recipient_id"]).name) + user = _(u"Dm to %s ") % (session.get_user(item.message_create["target"]["recipient_id"]).name) else: if show_screen_names: - user = sender["screen_name"] + user = sender.screen_name else: - user = sender["name"] + user = sender.name if text[-1] in chars: text=text+"." text = utils.expand_urls(text, item.message_create["message_data"]["entities"]) return [user+", ", text, ts+", ", source] diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 00dcbeae..0105678a 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- """ This is the main session needed to access all Twitter Features.""" -from __future__ import absolute_import -from __future__ import unicode_literals -from builtins import range import os import time import logging @@ -12,8 +9,8 @@ import config import output import application from pubsub import pub -from twython import Twython import tweepy +from tweepy.error import TweepError from mysc.thread_utils import call_threaded from keys import keyring from sessions import base @@ -32,6 +29,8 @@ class Session(base.baseSession): data list: A list with tweets. ignore_older bool: if set to True, items older than the first element on the list will be ignored. returns the number of items that have been added in this execution""" + if name == "direct_messages": + return self.order_direct_messages(data) num = 0 last_id = None if (name in self.db) == False: @@ -87,24 +86,27 @@ class Session(base.baseSession): incoming = 0 sent = 0 if ("direct_messages" in self.db) == False: - self.db["direct_messages"] = {} - self.db["direct_messages"]["items"] = [] + self.db["direct_messages"] = [] for i in data: - if i.message_create.sender_id == self.db["user_id"]: - if "sent_direct_messages" in self.db and utils.find_item(i.id, self.db["sent_direct_messages"]["items"]) == None: - if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"]["items"].append(i) - else: self.db["sent_direct_messages"]["items"].insert(0, i) + # Twitter returns sender_id as str, which must be converted to int in order to match to our user_id object. + if int(i.message_create["sender_id"]) == self.db["user_id"]: + if "sent_direct_messages" in self.db and utils.find_item(i.id, self.db["sent_direct_messages"]) == None: + if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"].append(i) + else: self.db["sent_direct_messages"].insert(0, i) sent = sent+1 else: - if utils.find_item(i.id, self.db["direct_messages"]["items"]) == None: - if self.settings["general"]["reverse_timelines"] == False: self.db["direct_messages"]["items"].append(i) - else: self.db["direct_messages"]["items"].insert(0, i) + if utils.find_item(i.id, self.db["direct_messages"]) == None: + if self.settings["general"]["reverse_timelines"] == False: self.db["direct_messages"].append(i) + else: self.db["direct_messages"].insert(0, i) incoming = incoming+1 pub.sendMessage("sent-dms-updated", total=sent, account=self.db["user_name"]) return incoming def __init__(self, *args, **kwargs): super(Session, self).__init__(*args, **kwargs) + # Adds here the optional cursors objects. + cursors = dict(direct_messages=-1) + self.db["cursors"] = cursors self.reconnection_function_active = False self.counter = 0 self.lists = [] @@ -410,11 +412,11 @@ class Session(base.baseSession): returns an user dict.""" if ("users" in self.db) == False or (id in self.db["users"]) == False: try: - user = self.twitter.show_user(id=id) - except TwythonError: + user = self.twitter.get_user(id=id) + except TweepError as err: user = dict(screen_name="deleted_account", name="Deleted account") return user - self.db["users"][user["id_str"]] = user + self.db["users"][user.id_str] = user return user else: return self.db["users"][id] @@ -429,8 +431,8 @@ class Session(base.baseSession): return user["id_str"] else: for i in list(self.db["users"].keys()): - if self.db["users"][i]["screen_name"] == screen_name: - return self.db["users"][i]["id_str"] + if self.db["users"][i].screen_name == screen_name: + return self.db["users"][i].id_str user = utils.if_user_exists(self.twitter, screen_name) - self.db["users"][user["id_str"]] = user - return user["id_str"] \ No newline at end of file + self.db["users"][user.id_str] = user + return user.id_str \ No newline at end of file From 1f11ea7aa0f6121ee5bd2fd7c0c163386ffbbdcd Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 17:05:39 -0600 Subject: [PATCH 31/34] fixed an issue in compose for followers --- src/sessions/twitter/compose.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sessions/twitter/compose.py b/src/sessions/twitter/compose.py index 7f5c3620..98370391 100644 --- a/src/sessions/twitter/compose.py +++ b/src/sessions/twitter/compose.py @@ -150,7 +150,7 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal else: ts = tweet.created_at if hasattr(tweet, "status"): - if len(tweet.status) > 4 and system == "Windows": + if system == "Windows": original_date2 = arrow.get(tweet.status.created_at, locale="en") if relative_times: ts2 = original_date2.humanize(locale=languageHandler.curLang[:2]) From 979a3d3e9975cb6a5bb04474b38a544db61c1b7d Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 17:06:15 -0600 Subject: [PATCH 32/34] Changed a function to order people buffers after being retrieved from Twitter --- src/sessions/twitter/session.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/sessions/twitter/session.py b/src/sessions/twitter/session.py index 0105678a..fcdbea79 100644 --- a/src/sessions/twitter/session.py +++ b/src/sessions/twitter/session.py @@ -59,23 +59,18 @@ class Session(base.baseSession): self.db["users"][i.user.id] = i.user return num - def order_cursored_buffer(self, name, data): + def order_people(self, name, data): """ Put new items on the local database. Useful for cursored buffers (followers, friends, users of a list and searches) name str: The name for the buffer stored in the dictionary. data list: A list with items and some information about cursors. returns the number of items that have been added in this execution""" - # Direct messages should be added to db in other function. - # Because they will be populating two buffers with one endpoint. - if name == "direct_messages": - return self.order_direct_messages(data) num = 0 if (name in self.db) == False: - self.db[name] = {} - self.db[name]["items"] = [] + self.db[name] = [] for i in data: - if utils.find_item(i.id, self.db[name]["items"]) == None: - if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].append(i) - else: self.db[name]["items"].insert(0, i) + if utils.find_item(i.id, self.db[name]) == None: + if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i) + else: self.db[name].insert(0, i) num = num+1 return num From da7a208c1fffe0fdb444d350c3d1332ed8c3f56f Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 17:06:59 -0600 Subject: [PATCH 33/34] Implemented people buffers and searches --- src/controller/buffers/twitterBuffers.py | 55 ++++++++++++++++-------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/src/controller/buffers/twitterBuffers.py b/src/controller/buffers/twitterBuffers.py index ed2393cd..092d556e 100644 --- a/src/controller/buffers/twitterBuffers.py +++ b/src/controller/buffers/twitterBuffers.py @@ -584,7 +584,7 @@ class baseBufferController(baseBuffers.buffer): try: if self.name == "direct_messages" or self.name == "sent_direct_messages": self.session.twitter.destroy_direct_message(id=self.get_right_tweet().id) - self.session.db[self.name]["items"].pop(index) + self.session.db[self.name].pop(index) else: self.session.twitter.destroy_status(id=self.get_right_tweet().id) self.session.db[self.name].pop(index) @@ -866,31 +866,48 @@ class peopleBufferController(baseBufferController): self.execution_time = current_time log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,)) log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) - val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs) + # try to retrieve the cursor for the current buffer. + cursor = self.session.db["cursors"].get(self.name) + try: + # We need to assign all results somewhere else so the cursor variable would b generated. + val = Cursor(getattr(self.session.twitter, self.function), *self.args, **self.kwargs).items(self.session.settings["general"]["max_tweets_per_call"]) + results = [i for i in val] + self.session.db["cursors"][self.name] = val.page_iterator.next_cursor + val = results + val.reverse() + except TweepError as e: + log.error("Error %s: %s" % (e.api_code, e.reason)) + return + number_of_items = self.session.order_people(self.name, val) + log.debug("Number of items retrieved: %d" % (number_of_items,)) self.put_items_on_list(val) if hasattr(self, "finished_timeline") and self.finished_timeline == False: self.username = self.session.api_call("get_user", **self.kwargs).screen_name self.finished_timeline = True - if val > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True: + if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True: self.session.sound.play(self.sound) # Autoread settings if avoid_autoreading == False and mandatory == True and val > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]: - self.auto_read(val) - return val + self.auto_read(number_of_items) + return number_of_items def get_more_items(self): try: - items = self.session.get_more_items(self.function, users=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs) + cursor = self.session.db["cursors"].get(self.name) + items = Cursor(getattr(self.session.twitter, self.function), users=True, cursor=cursor, *self.args, **self.kwargs).items(self.session.settings["general"]["max_tweets_per_call"]) + results = [i for i in items] + self.session.db["cursors"][self.name] = items.page_iterator.next_cursor + items = results except TweepError as e: - output.speak(e.reason, True) + log.error("Error %s: %s" % (e.api_code, e.reason)) return if items == None: return for i in items: if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[self.name]["items"].insert(0, i) + self.session.db[self.name].insert(0, i) else: - self.session.db[self.name]["items"].append(i) + self.session.db[self.name].append(i) selected = self.buffer.list.get_selected() if self.session.settings["general"]["reverse_timelines"] == True: for i in items: @@ -907,18 +924,18 @@ class peopleBufferController(baseBufferController): log.debug("The list contains %d items" % (self.buffer.list.get_count(),)) # log.debug("Putting %d items on the list..." % (number_of_items,)) if self.buffer.list.get_count() == 0: - for i in self.session.db[self.name]["items"]: + for i in self.session.db[self.name]: tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session) self.buffer.list.insert_item(False, *tweet) self.buffer.set_position(self.session.settings["general"]["reverse_timelines"]) # self.buffer.set_list_position() elif self.buffer.list.get_count() > 0: if self.session.settings["general"]["reverse_timelines"] == False: - for i in self.session.db[self.name]["items"][len(self.session.db[self.name]["items"])-number_of_items:]: + for i in self.session.db[self.name][len(self.session.db[self.name])-number_of_items:]: tweet = self.compose_function(i, self.session.db) self.buffer.list.insert_item(False, *tweet) else: - items = self.session.db[self.name]["items"][0:number_of_items] + items = self.session.db[self.name][0:number_of_items] items.reverse() for i in items: tweet = self.compose_function(i, self.session.db) @@ -926,7 +943,7 @@ class peopleBufferController(baseBufferController): log.debug("now the list contains %d items" % (self.buffer.list.get_count(),)) def get_right_tweet(self): - tweet = self.session.db[self.name]["items"][self.buffer.list.get_selected()] + tweet = self.session.db[self.name][self.buffer.list.get_selected()] return tweet def add_new_item(self, item): @@ -941,8 +958,8 @@ class peopleBufferController(baseBufferController): def clear_list(self): dlg = commonMessageDialogs.clear_list() if dlg == widgetUtils.YES: - self.session.db[self.name]["items"] = [] - self.session.db[self.name]["cursor"] = -1 + self.session.db[self.name] = [] + self.session.db["cursors"][self.name] = -1 self.buffer.list.clear() def interact(self): @@ -969,9 +986,9 @@ class peopleBufferController(baseBufferController): def auto_read(self, number_of_items): if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False: if self.session.settings["general"]["reverse_timelines"] == False: - tweet = self.session.db[self.name]["items"][-1] + tweet = self.session.db[self.name][-1] else: - tweet = self.session.db[self.name["items"]][0] + tweet = self.session.db[self.name][0] output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session))) elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False: output.speak(_(u"{0} new followers.").format(number_of_items)) @@ -1065,9 +1082,9 @@ class searchPeopleBufferController(peopleBufferController): return for i in items: if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[self.name]["items"].insert(0, i) + self.session.db[self.name].insert(0, i) else: - self.session.db[self.name]["items"].append(i) + self.session.db[self.name].append(i) selected = self.buffer.list.get_selected() # self.put_items_on_list(len(items)) if self.session.settings["general"]["reverse_timelines"] == True: From a2a8cc5b798c9ea04a6cbfeea4b5329d0fe41ad4 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Wed, 20 Jan 2021 17:44:29 -0600 Subject: [PATCH 34/34] Updated changelog --- doc/changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/changelog.md b/doc/changelog.md index 734e6c10..869ff841 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -3,11 +3,13 @@ ## changes in this version * Fixed error when displaying an URL at the end of a line, when the tweet or direct message contained multiple lines. Now the URL should be displayed correctly. ([#305,](https://github.com/manuelcortez/TWBlue/issues/305)) -* TWBlue has been migrated completely to Python 3 (currently, the software builds with Python 3.7). +* TWBlue has been migrated completely to Python 3 (currently, the software builds with Python 3.8). * TWBlue should be restarted gracefully. Before, the application was alerting users of not being closed properly every time the application restarted by itself. * If TWBlue attemps to load an account with invalid tokens (this happens when reactivating a previously deactivated account, or when access to the ap is revoqued), TWBlue will inform the user about this error and will skip the account. Before, the app was unable to start due to a critical error. ([#328,](https://github.com/manuelcortez/TWBlue/issues/328)) * When sending a direct message, the title of the window will change appropiately when the recipient is edited. ([#276,](https://github.com/manuelcortez/TWBlue/issues/276)) * URL'S in user profiles are expanded automatically. ([#275,](https://github.com/manuelcortez/TWBlue/issues/275)) +* TWBlue now uses [Tweepy,](https://github.com/tweepy/tweepy) to connect with Twitter. We have adopted this change in order to support Twitter'S API V 2 in the very near future. ([#333,](https://github.com/manuelcortez/TWBlue/issues/337) [#347](https://github.com/manuelcortez/TWBlue/pull/347)) +* TWBlue can upload images in Tweets and replies again. ([#240,](https://github.com/manuelcortez/TWBlue/issues/240)) ## Changes in version 0.95