From 2ce59cf2082af3b0581d1f8b891d2f5ab1205817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Cort=C3=A9z?= Date: Tue, 9 Dec 2014 17:56:43 -0600 Subject: [PATCH 1/2] Autocompletion improvements. Adding/removing users manually is now possible. --- src/extra/autocompletionUsers/manage.py | 43 ++++++++++++++++++++ src/extra/autocompletionUsers/settings.py | 6 +++ src/extra/autocompletionUsers/storage.py | 4 ++ src/extra/autocompletionUsers/wx_manage.py | 42 +++++++++++++++++++ src/extra/autocompletionUsers/wx_settings.py | 2 + 5 files changed, 97 insertions(+) create mode 100644 src/extra/autocompletionUsers/manage.py create mode 100644 src/extra/autocompletionUsers/wx_manage.py diff --git a/src/extra/autocompletionUsers/manage.py b/src/extra/autocompletionUsers/manage.py new file mode 100644 index 00000000..d0e8b42c --- /dev/null +++ b/src/extra/autocompletionUsers/manage.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +import storage +import wx +import wx_manage + +class autocompletionManage(object): + def __init__(self, window): + super(autocompletionManage, self).__init__() + self.window = window + self.dialog = wx_manage.autocompletionManageDialog() + self.database = storage.storage() + self.users = self.database.get_all_users() + self.dialog.put_users(self.users) + self.dialog.add.Bind(wx.EVT_BUTTON, self.add_user) + self.dialog.remove.Bind(wx.EVT_BUTTON, self.remove_user) + self.dialog.ShowModal() + + def update_list(self): + item = self.dialog.users.get_selected() + self.dialog.users.clear() + self.users = self.database.get_all_users() + self.dialog.put_users(self.users) + self.dialog.users.select_item(item) + + def add_user(self, event=None): + usr = self.dialog.get_user() + if usr == False: + return + try: + data = self.window.twitter.twitter.show_user(screen_name=usr) + except: + self.dialog.show_invalid_user_error() + return + self.database.set_user(data["screen_name"], data["name"], 0) + self.update_list() + + def remove_user(self, ev): + ask = wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear on the autocomplete results anymore."), _(u"Confirm"), wx.YES_NO|wx.ICON_QUESTION) + if ask.ShowModal() == wx.ID_YES: + item = self.dialog.users.get_selected() + user = self.users[item] + self.database.remove_user(user[0]) + self.update_list() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/settings.py b/src/extra/autocompletionUsers/settings.py index 92cf4257..4d57ed6e 100644 --- a/src/extra/autocompletionUsers/settings.py +++ b/src/extra/autocompletionUsers/settings.py @@ -3,6 +3,7 @@ import storage import wx import config import wx_settings +import manage import output from mysc.thread_utils import call_threaded @@ -13,6 +14,7 @@ class autocompletionSettings(object): self.dialog = wx_settings.autocompletionSettingsDialog() self.dialog.friends_buffer.SetValue(config.main["mysc"]["save_friends_in_autocompletion_db"]) self.dialog.followers_buffer.SetValue(config.main["mysc"]["save_followers_in_autocompletion_db"]) + self.dialog.viewList.Bind(wx.EVT_BUTTON, self.view_list) if self.dialog.ShowModal() == wx.ID_OK: call_threaded(self.add_users_to_database) @@ -36,6 +38,10 @@ class autocompletionSettings(object): wx_settings.show_success_dialog() self.dialog.Destroy() + def view_list(self, ev): + q = manage.autocompletionManage(self.window) + + def execute_at_startup(window): database = storage.storage() if config.main["mysc"]["save_followers_in_autocompletion_db"] == True: diff --git a/src/extra/autocompletionUsers/storage.py b/src/extra/autocompletionUsers/storage.py index a2af1c1e..477608e5 100644 --- a/src/extra/autocompletionUsers/storage.py +++ b/src/extra/autocompletionUsers/storage.py @@ -17,6 +17,10 @@ class storage(object): else: return True + def get_all_users(self): + self.cursor.execute("""select * from users""") + return self.cursor.fetchall() + def get_users(self, term): self.cursor.execute("""SELECT * FROM users WHERE user LIKE ?""", ('{}%'.format(term),)) return self.cursor.fetchall() diff --git a/src/extra/autocompletionUsers/wx_manage.py b/src/extra/autocompletionUsers/wx_manage.py new file mode 100644 index 00000000..93fa0deb --- /dev/null +++ b/src/extra/autocompletionUsers/wx_manage.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import wx +from multiplatform_widgets import widgets + +class autocompletionManageDialog(wx.Dialog): + def __init__(self): + super(autocompletionManageDialog, self).__init__(parent=None, id=-1, title=_(u"Manage Autocomplete users’ database")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + label = wx.StaticText(panel, -1, _(u"Users in your database")) + self.users = widgets.list(panel, _(u"Username"), _(u"Name"), style=wx.LC_REPORT) + sizer.Add(label, 0, wx.ALL, 5) + sizer.Add(self.users.list, 0, wx.ALL, 5) + self.add = wx.Button(panel, -1, _(u"Add new user")) + self.remove = wx.Button(panel, -1, _(u"Remove user")) + optionsBox = wx.BoxSizer(wx.HORIZONTAL) + optionsBox.Add(self.add, 0, wx.ALL, 5) + optionsBox.Add(self.remove, 0, wx.ALL, 5) + sizer.Add(optionsBox, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK) + cancel = wx.Button(panel, wx.ID_CANCEL) + sizerBtn = wx.BoxSizer(wx.HORIZONTAL) + sizerBtn.Add(ok, 0, wx.ALL, 5) + sizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(sizerBtn, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def put_users(self, users): + for i in users: + j = [i[0], i[1]] + self.users.insert_item(False, *j) + + def get_user(self): + usr = False + userDlg = wx.TextEntryDialog(None, _(u"Twitter username"), _(u"Add user to database")) + if userDlg.ShowModal() == wx.ID_OK: + usr = userDlg.GetValue() + return usr + + def show_invalid_user_error(self): + wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error!"), wx.ICON_ERROR).ShowModal() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/wx_settings.py b/src/extra/autocompletionUsers/wx_settings.py index f4be9212..e50416a2 100644 --- a/src/extra/autocompletionUsers/wx_settings.py +++ b/src/extra/autocompletionUsers/wx_settings.py @@ -10,6 +10,8 @@ class autocompletionSettingsDialog(wx.Dialog): self.friends_buffer = wx.CheckBox(panel, -1, _(u"Add users from friends buffer")) sizer.Add(self.followers_buffer, 0, wx.ALL, 5) sizer.Add(self.friends_buffer, 0, wx.ALL, 5) + self.viewList = wx.Button(panel, -1, _(u"See the user list")) + sizer.Add(self.viewList, 0, wx.ALL, 5) ok = wx.Button(panel, wx.ID_OK) cancel = wx.Button(panel, wx.ID_CANCEL) sizerBtn = wx.BoxSizer(wx.HORIZONTAL) From b232a0b0ad00b1e28ff281adbbe64a4d6cb4adca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Cort=C3=A9z?= Date: Wed, 10 Dec 2014 11:19:38 -0600 Subject: [PATCH 2/2] Ignoring clients improvements: adding clients from the action users dialog does always work, no matters the buffer the client is added --- src/gui/buffers/base.py | 21 +++++++++-------- src/gui/dialogs/follow.py | 12 ++++++++++ src/twitter/buffers/indibidual.py | 4 ++-- src/twitter/compose.py | 2 +- src/twitter/starting.py | 38 +++++++++++++++++-------------- src/twitter/utils.py | 15 +++++++----- 6 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/gui/buffers/base.py b/src/gui/buffers/base.py index e5c9b9bb..c8160920 100644 --- a/src/gui/buffers/base.py +++ b/src/gui/buffers/base.py @@ -186,18 +186,21 @@ class basePanel(wx.Panel): except TwythonError as e: output.speak(e.message) for i in items: - if config.main["general"]["reverse_timelines"] == False: - self.db.settings[self.name_buffer].insert(0, i) - else: - self.db.settings[self.name_buffer].append(i) + if twitter.utils.is_allowed(i) == True: + if config.main["general"]["reverse_timelines"] == False: + self.db.settings[self.name_buffer].insert(0, i) + else: + self.db.settings[self.name_buffer].append(i) if config.main["general"]["reverse_timelines"] == False: for i in items: - tweet = self.compose_function(i, self.db) - self.list.insert_item(True, *tweet) + if twitter.utils.is_allowed(i) == True: + tweet = self.compose_function(i, self.db) + self.list.insert_item(True, *tweet) else: for i in items: - tweet = self.compose_function(i, self.db) - self.list.insert_item(False, *tweet) + if twitter.utils.is_allowed(i) == True: + tweet = self.compose_function(i, self.db) + self.list.insert_item(False, *tweet) output.speak(_(u"%s items retrieved") % (len(items))) def put_items(self, num): @@ -205,7 +208,7 @@ class basePanel(wx.Panel): for i in self.db.settings[self.name_buffer]: tweet = self.compose_function(i, self.db) self.list.insert_item(False, *tweet) - self.set_list_position() + self.set_list_position() elif self.list.get_count() > 0: if config.main["general"]["reverse_timelines"] == False: for i in self.db.settings[self.name_buffer][:num]: diff --git a/src/gui/dialogs/follow.py b/src/gui/dialogs/follow.py index e5f2a9a6..6b5b896b 100644 --- a/src/gui/dialogs/follow.py +++ b/src/gui/dialogs/follow.py @@ -23,6 +23,7 @@ import twitter from twitter import utils from twython import TwythonError import output +import re class follow(wx.Dialog): def __init__(self, parent, default="follow"): @@ -48,6 +49,7 @@ class follow(wx.Dialog): self.block = wx.RadioButton(panel, -1, _(u"Block")) self.unblock = wx.RadioButton(panel, -1, _(u"Unblock")) self.reportSpam = wx.RadioButton(panel, -1, _(u"Report as spam")) + self.ignore_client = wx.RadioButton(panel, -1, _(u"Ignore tweets from this client")) self.setup_default(default) actionSizer.Add(label2) actionSizer.Add(self.follow) @@ -57,6 +59,7 @@ class follow(wx.Dialog): actionSizer.Add(self.block) actionSizer.Add(self.unblock) actionSizer.Add(self.reportSpam) + actionSizer.Add(self.ignore_client) sizer = wx.BoxSizer(wx.VERTICAL) ok = wx.Button(panel, wx.ID_OK, _(u"OK")) ok.Bind(wx.EVT_BUTTON, self.onok) @@ -133,6 +136,15 @@ class follow(wx.Dialog): self.Destroy() except TwythonError as err: output.speak("Error %s: %s" % (err.error_code, err.msg), True) + elif self.ignore_client.GetValue() == True: + tweet = self.parent.get_tweet() + if tweet.has_key("sender"): + output.speak(_(u"You can't ignore direct messages")) + return + else: + client = re.sub(r"(?s)<.*?>", "", tweet["source"]) + if client not in config.main["twitter"]["ignored_clients"]: + config.main["twitter"]["ignored_clients"].append(client) def setup_default(self, default): if default == "follow": diff --git a/src/twitter/buffers/indibidual.py b/src/twitter/buffers/indibidual.py index 20d1987b..80868b0e 100644 --- a/src/twitter/buffers/indibidual.py +++ b/src/twitter/buffers/indibidual.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from twitter import compose +from twitter import compose, utils from twython import TwythonStreamer import sound from mysc import event @@ -44,7 +44,7 @@ class streamer(TwythonStreamer): def on_success(self, data): try: - if data.has_key("text"): + if data.has_key("text") and utils.is_allowed(data): self.check_tls(data) elif "friends" in data: self.friends = data["friends"] diff --git a/src/twitter/compose.py b/src/twitter/compose.py index cf80437b..22593f26 100644 --- a/src/twitter/compose.py +++ b/src/twitter/compose.py @@ -153,7 +153,7 @@ def compose_tweet(tweet, db): else: user = tweet["sender"]["name"] elif tweet.has_key("user"): user = tweet["user"]["name"] - source = re.sub(r"(?s)<.*?>", " ", tweet["source"]) + source = re.sub(r"(?s)<.*?>", "", tweet["source"]) try: text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(tweet["retweeted_status"]["text"])) except KeyError: text = "%s" % (StripChars(tweet["text"])) if text[-1] in chars: text=text+"." diff --git a/src/twitter/starting.py b/src/twitter/starting.py index b31c32b6..eb84d1be 100644 --- a/src/twitter/starting.py +++ b/src/twitter/starting.py @@ -75,15 +75,16 @@ def start_stream(db, twitter, name, function, param=None): last_id = 0 if len(db.settings[name]) > 0: for i in tl: - if int(i["id"]) > int(last_id): + if int(i["id"]) > int(last_id) and utils.is_allowed(i) == True: if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) else: db.settings[name].insert(0, i) num = num+1 elif len(db.settings[name]) == 0: for i in tl: - if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) - else: db.settings[name].insert(0, i) - num = num+1 + if utils.is_allowed(i) == True: + if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) + else: db.settings[name].insert(0, i) + num = num+1 # db.settings.update() return num @@ -121,7 +122,7 @@ def update_stream(config, twitter, name, function, param=None, sndFile=""): tl = function(sinze_id=config.settings[name][-1]["id"], screen_name=param, count=config.main["general"]["max_tweets_per_call"]) tl.reverse() for i in tl: - if i["id"] > config.settings[name][-1]["id"]: + if i["id"] > config.settings[name][-1]["id"] and utils.is_allowed(i) == True: config.settings[name].append(i) sounded = True num = num+1 @@ -189,15 +190,16 @@ def start_list(db, twitter, name, list_id, *args, **kwargs): last_id = 0 if len(db.settings[name]) > 0: for i in tl: - if int(i["id"]) > int(last_id): + if int(i["id"]) > int(last_id) and utils.is_allowed(i) == True: if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) else: db.settings[name].insert(0, i) num = num+1 elif len(db.settings[name]) == 0: for i in tl: - if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) - else: db.settings[name].insert(0, i) - num = num+1 + if utils.is_allowed(i) == True: + if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) + else: db.settings[name].insert(0, i) + num = num+1 db.settings.update() return num @@ -209,15 +211,16 @@ def search(db, twitter, name, *args, **kwargs): tl["statuses"].reverse() if len(db.settings[name]) > 0: for i in tl["statuses"]: - if utils.find_item(i["id"], db.settings[name]) == None: + if utils.find_item(i["id"], db.settings[name]) == None and utils.is_allowed(i): if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) else: db.settings[name].insert(0, i) num = num+1 elif len(db.settings[name]) == 0: for i in tl["statuses"]: - if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) - else: db.settings[name].insert(0, i) - num = num+1 + if utils.is_allowed(i) == True: + if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) + else: db.settings[name].insert(0, i) + num = num+1 return num def search_users(db, twitter, name, *args, **kwargs): @@ -247,13 +250,14 @@ def get_favourites_timeline(db, twitter, name, param, *args, **kwargs): tl.reverse() if len(db.settings[name]) > 0: for i in tl: - if utils.find_item(i["id"], db.settings[name]) == None: + if utils.find_item(i["id"], db.settings[name]) == None and utils.is_allowed(i) == True: if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) else: db.settings[name].insert(0, i) num = num+1 elif len(db.settings[name]) == 0: for i in tl: - if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) - else: db.settings[name].insert(0, i) - num = num+1 + if utils.is_allowed(i) == True: + if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i) + else: db.settings[name].insert(0, i) + num = num+1 return num \ No newline at end of file diff --git a/src/twitter/utils.py b/src/twitter/utils.py index 47cfc0c1..0fb878d2 100644 --- a/src/twitter/utils.py +++ b/src/twitter/utils.py @@ -109,9 +109,12 @@ def api_call(parent=None, call_name=None, preexec_message="", success="", succes return val def is_allowed(tweet): - allowed = True - if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"] - source = re.sub(r"(?s)<.*?>", "", tweet["source"]) - for i in config.main["twitter"]["ignored_clients"]: - if i.lower() == source.lower(): allowed = False - return allowed \ No newline at end of file + try: + allowed = True + if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"] + source = re.sub(r"(?s)<.*?>", "", tweet["source"]) + for i in config.main["twitter"]["ignored_clients"]: + if i.lower() == source.lower(): allowed = False + return allowed + except KeyError: + return True \ No newline at end of file