From 4bdc2b2a6a4764b891e16fbc6f86c20dd5adb451 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Fri, 16 Jun 2017 21:06:26 +0000 Subject: [PATCH] Prepare for py3 port. --- src/controller/buffersController.py | 2565 ++++++------- src/controller/mainController.py | 3239 +++++++++-------- src/controller/messages.py | 553 +-- src/controller/userActionsController.py | 158 +- src/extra/AudioUploader/audioUploader.py | 357 +- src/extra/AudioUploader/transfer.py | 3 +- .../AudioUploader/wx_transfer_dialogs.py | 123 +- src/extra/SoundsTutorial/__init__.py | 3 +- src/extra/SoundsTutorial/soundsTutorial.py | 67 +- .../soundsTutorial_constants.py | 58 +- src/extra/SpellChecker/__init__.py | 9 +- src/extra/SpellChecker/spellchecker.py | 139 +- src/extra/autocompletionUsers/__init__.py | 6 +- src/extra/autocompletionUsers/completion.py | 93 +- src/extra/autocompletionUsers/manage.py | 86 +- src/extra/autocompletionUsers/settings.py | 118 +- src/extra/ocr/__init__.py | 6 +- src/extra/translator/__init__.py | 11 +- src/extra/translator/wx_ui.py | 107 +- src/fixes/__init__.py | 29 +- src/issueReporter/issueReporter.py | 129 +- src/keyboard_handler/__init__.py | 7 +- src/keyboard_handler/global_handler.py | 15 +- src/keyboard_handler/linux.py | 117 +- src/keyboard_handler/main.py | 176 +- src/keyboard_handler/osx.py | 113 +- src/keyboard_handler/windows.py | 81 +- src/keyboard_handler/wx_handler.py | 240 +- src/keystrokeEditor/__init__.py | 3 +- src/keystrokeEditor/keystrokeEditor.py | 115 +- src/keystrokeEditor/wx_ui.py | 160 +- src/long_tweets/tweets.py | 66 +- src/long_tweets/twishort.py | 175 +- src/multiplatform_widgets/__init__.py | 3 +- src/notifier/__init__.py | 41 +- src/platform_utils/autostart/windows.py | 83 +- src/sessionmanager/manager.py | 97 +- src/sessionmanager/session.py | 963 ++--- src/sessionmanager/sessionManager.py | 235 +- src/twitter/__init__.py | 3 +- src/twitter/buffers/__init__.py | 3 +- src/twitter/buffers/indibidual.py | 142 +- src/twitter/buffers/stream.py | 364 +- src/twitter/compose.py | 419 +-- src/twitter/twitter.py | 77 +- src/twitter/utils.py | 287 +- src/update/updater.py | 39 +- src/update/wxUpdater.py | 59 +- src/url_shortener/__init__.py | 5 +- src/url_shortener/__main__.py | 91 +- src/url_shortener/shorteners/__init__.py | 19 +- src/url_shortener/shorteners/clckru.py | 41 +- src/url_shortener/shorteners/hkcim.py | 39 +- src/url_shortener/shorteners/isgd.py | 41 +- src/url_shortener/shorteners/onjme.py | 39 +- src/url_shortener/shorteners/tinyarrows.py | 33 +- src/url_shortener/shorteners/tinyurl.py | 37 +- src/url_shortener/shorteners/url_shortener.py | 66 +- src/url_shortener/shorteners/xedcc.py | 39 +- src/widgetUtils/__init__.py | 11 +- src/wxUI/buffers/__init__.py | 23 +- src/wxUI/buffers/dm.py | 21 +- src/wxUI/buffers/favourites.py | 15 +- src/wxUI/buffers/lists.py | 17 +- src/wxUI/buffers/people.py | 33 +- src/wxUI/buffers/tweet_searches.py | 17 +- src/wxUI/buffers/user_searches.py | 27 +- src/wxUI/dialogs/__init__.py | 3 +- src/wxUI/dialogs/configuration.py | 756 ++-- src/wxUI/dialogs/find.py | 52 +- src/wxUI/dialogs/search.py | 137 +- src/wxUI/dialogs/show_user.py | 51 +- src/wxUI/dialogs/trends.py | 92 +- src/wxUI/dialogs/update_profile.py | 195 +- src/wxUI/dialogs/utils.py | 97 +- 75 files changed, 7017 insertions(+), 6922 deletions(-) diff --git a/src/controller/buffersController.py b/src/controller/buffersController.py index 3f5f7abf..0b951e32 100644 --- a/src/controller/buffersController.py +++ b/src/controller/buffersController.py @@ -1,1282 +1,1283 @@ -# -*- coding: utf-8 -*- -import time -import platform -if platform.system() == "Windows": - import wx - from wxUI import buffers, dialogs, commonMessageDialogs, menus - import user -elif platform.system() == "Linux": - from gi.repository import Gtk - from gtkUI import buffers, dialogs, commonMessageDialogs -import messages -import widgetUtils -import arrow -import webbrowser -import output -import config -import sound -import languageHandler -import logging -from twitter import compose, utils -from mysc.thread_utils import call_threaded -from twython import TwythonError -from pubsub import pub -from long_tweets import twishort, tweets - -log = logging.getLogger("controller.buffers") - -def _tweets_exist(function): - """ A decorator to execute a function only if the selected buffer contains at least one item.""" - def function_(self, *args, **kwargs): - if self.buffer.list.get_count() > 0: - function(self, *args, **kwargs) - return function_ - -class bufferController(object): - def __init__(self, parent=None, function=None, session=None, *args, **kwargs): - super(bufferController, self).__init__() - self.function = function - self.compose_function = None - self.args = args - self.kwargs = kwargs - self.buffer = None - self.account = "" - self.needs_init = True - self.invisible = False # False if the buffer will be ignored on the invisible interface. - self.execution_time = 0 - - def clear_list(self): pass - - - def get_event(self, ev): - """ Catches key presses in the WX interface and generate the corresponding event names.""" - if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio" - elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url" - elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down" - elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up" - elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list" - elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status" - else: - event = None - ev.Skip() - if event != None: - try: - getattr(self, event)() - except AttributeError: - pass - - def volume_down(self): - if self.session.settings["sound"]["volume"] > 0.0: - if self.session.settings["sound"]["volume"] <= 0.05: - self.session.settings["sound"]["volume"] = 0.0 - else: - self.session.settings["sound"]["volume"] -=0.05 - if hasattr(sound.URLPlayer, "stream"): - sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"] - self.session.sound.play("volume_changed.ogg") - self.session.settings.write() - - def volume_up(self): - if self.session.settings["sound"]["volume"] < 1.0: - if self.session.settings["sound"]["volume"] >= 0.95: - self.session.settings["sound"]["volume"] = 1.0 - else: - self.session.settings["sound"]["volume"] +=0.05 - if hasattr(sound.URLPlayer, "stream"): - sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"] - self.session.sound.play("volume_changed.ogg") - self.session.settings.write() - - def start_stream(self, mandatory=False): - if mandatory == True: - output.speak(_(u"Unable to update this buffer.")) - pass - - def get_more_items(self): - output.speak(_(u"This action is not supported for this buffer"), True) - - def put_items_on_list(self, items): - pass - - def remove_buffer(self): - return False - - def remove_item(self, item): - f = self.buffer.list.get_selected() - self.buffer.list.remove_item(item) - self.buffer.list.select_item(f) - - def bind_events(self): - pass - - def get_object(self): - return self.buffer - - def get_message(self): - pass - - def set_list_position(self, reversed=False): - if reversed == False: - self.buffer.list.select_item(-1) - else: - self.buffer.list.select_item(0) - - def reply(self): - pass - - def direct_message(self): - pass - - def retweet(self): - pass - - def destroy_status(self): - pass - - def post_tweet(self, *args, **kwargs): - title = _(u"Tweet") - caption = _(u"Write the tweet here") - tweet = messages.tweet(self.session, title, caption, "", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"]) - if tweet.message.get_response() == widgetUtils.OK: - self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue() - text = tweet.message.get_text() - if len(text) > 140 and tweet.message.get("long_tweet") == True: - if not hasattr(tweet, "attachments"): - text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text) - else: - 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: - call_threaded(self.session.api_call, call_name="update_status", status=text) - else: - call_threaded(self.post_with_media, text=text, attachments=tweet.attachments) - if hasattr(tweet.message, "destroy"): tweet.message.destroy() - self.session.settings.write() - - def post_with_media(self, text, attachments): - media_ids = [] - for i in attachments: - photo = open(i["file"], "rb") - img = self.session.twitter.twitter.upload_media(media=photo) - self.session.twitter.twitter.set_description(media_id=img["media_id"], alt_text=dict(text=i["description"])) - media_ids.append(img["media_id"]) - self.session.twitter.twitter.update_status(status=text, media_ids=media_ids) - - def save_positions(self): - try: - self.session.db[self.name+"_pos"]=self.buffer.list.get_selected() - except AttributeError: - pass - - -class accountPanel(bufferController): - def __init__(self, parent, name, account, account_id): - super(accountPanel, self).__init__(parent, None, name) - log.debug("Initializing buffer %s, account %s" % (name, account,)) - self.buffer = buffers.accountPanel(parent, name) - self.type = self.buffer.type - self.compose_function = None - self.session = None - self.needs_init = False - self.account = account - self.buffer.account = account - self.name = name - self.account_id = account_id - - def setup_account(self): - widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account) - if self.account_id in config.app["sessions"]["ignored_sessions"]: - self.buffer.change_autostart(False) - else: - self.buffer.change_autostart(True) - if not hasattr(self, "logged"): - self.buffer.change_login(login=False) - widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout) - else: - self.buffer.change_login(login=True) - widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login) - - def login(self, *args, **kwargs): - del self.logged - self.setup_account() - pub.sendMessage("login", session_id=self.account_id) - - def logout(self, *args, **kwargs): - self.logged = False - self.setup_account() - pub.sendMessage("logout", session_id=self.account_id) - - def autostart(self, *args, **kwargs): - if self.account_id in config.app["sessions"]["ignored_sessions"]: - self.buffer.change_autostart(True) - config.app["sessions"]["ignored_sessions"].remove(self.account_id) - else: - self.buffer.change_autostart(False) - config.app["sessions"]["ignored_sessions"].append(self.account_id) - config.app.write() - -class emptyPanel(bufferController): - def __init__(self, parent, name, account): - super(emptyPanel, self).__init__(parent=parent) - log.debug("Initializing buffer %s, account %s" % (name, account,)) - self.buffer = buffers.emptyPanel(parent, name) - self.type = self.buffer.type - self.compose_function = None - self.account = account - self.buffer.account = account - self.name = name - self.session = None - self.needs_init = True - -class baseBufferController(bufferController): - def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, compose_func="compose_tweet", *args, **kwargs): - super(baseBufferController, self).__init__(parent, function, *args, **kwargs) - log.debug("Initializing buffer %s, account %s" % (name, account,)) - if bufferType != None: - self.buffer = getattr(buffers, bufferType)(parent, name) - else: - self.buffer = buffers.basePanel(parent, name) - self.invisible = True - self.name = name - self.type = self.buffer.type - self.session = sessionObject - self.compose_function = getattr(compose, compose_func) - log.debug("Compose_function: %s" % (self.compose_function,)) - self.account = account - self.buffer.account = account - self.bind_events() - self.sound = sound - if "-timeline" in self.name or "-favorite" in self.name: - self.finished_timeline = False - # Add a compatibility layer for username based timelines from config. - # ToDo: Remove this in some new versions of the client, when user ID timelines become mandatory. - try: - int(self.kwargs["user_id"]) - except ValueError: - self.is_screen_name = True - self.kwargs["screen_name"] = self.kwargs["user_id"] - self.kwargs.pop("user_id") - - def get_formatted_message(self): - if self.type == "dm" or self.name == "sent_tweets" or self.name == "sent_direct_messages": return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])[1] - return self.get_message() - - def get_message(self): - tweet = self.get_right_tweet() - return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])) - - def get_full_tweet(self): - tweet = self.get_right_tweet() - tweetsList = [] - tweet_id = tweet["id"] - message = None - if tweet.has_key("message"): - message = tweet["message"] - try: - tweet = self.session.twitter.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended") - urls = utils.find_urls_in_text(tweet["full_text"]) - for url in range(0, len(urls)): - try: tweet["full_text"] = tweet["full_text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass - except TwythonError as e: - utils.twitter_error(e) - return - if message != None: - tweet["message"] = message - l = tweets.is_long(tweet) - while l != False: - tweetsList.append(tweet) - try: - tweet = self.session.twitter.twitter.show_status(id=l, include_ext_alt_text=True, tweet_mode="extended") - urls = utils.find_urls_in_text(tweet["full_text"]) - for url in range(0, len(urls)): - try: tweet["full_text"] = tweet["full_text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass - except TwythonError as e: - utils.twitter_error(e) - return - l = tweets.is_long(tweet) - if l == False: - tweetsList.append(tweet) - return (tweet, tweetsList) - - def start_stream(self, mandatory=False): - # starts stream every 3 minutes. - current_time = time.time() - if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: - 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)) - 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,)) - 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"] - elif "-favorite" in self.name: - self.username = self.session.api_call("show_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: - self.session.sound.play(self.sound) - return number_of_items - - 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.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) - for i in items: - if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == 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.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.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) - - def remove_buffer(self, force=False): - if "-timeline" in self.name: - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]: - self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9]) - self.session.settings.write() - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - return True - elif dlg == widgetUtils.NO: - return False - elif "favorite" in self.name: - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]: - self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9]) - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - self.session.settings.write() - return True - elif dlg == widgetUtils.NO: - return False - else: - output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True) - return False - - def remove_tweet(self, id): - if type(self.session.db[self.name]) == dict: return - for i in xrange(0, len(self.session.db[self.name])): - if self.session.db[self.name][i]["id"] == id: - self.session.db[self.name].pop(i) - self.remove_item(i) - - def put_items_on_list(self, number_of_items): - 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,)) - if self.buffer.list.get_count() == 0: - for i in self.session.db[self.name]: - tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"]) - self.buffer.list.insert_item(False, *tweet) - self.buffer.set_position(self.session.settings["general"]["reverse_timelines"]) - elif self.buffer.list.get_count() > 0 and number_of_items > 0: - if self.session.settings["general"]["reverse_timelines"] == False: - items = self.session.db[self.name][len(self.session.db[self.name])-number_of_items:] - 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.buffer.list.insert_item(False, *tweet) - else: - items = self.session.db[self.name][0:number_of_items] - items.reverse() - 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.buffer.list.insert_item(True, *tweet) - log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),)) - - def add_new_item(self, item): - tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"]) - if self.session.settings["general"]["reverse_timelines"] == False: - self.buffer.list.insert_item(False, *tweet) - else: - self.buffer.list.insert_item(True, *tweet) - if 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(" ".join(tweet[:2])) - #Improve performance on Windows -# if platform.system() == "Windows": -# call_threaded(utils.is_audio,item) - - def bind_events(self): - log.debug("Binding events...") - self.buffer.set_focus_function(self.onFocus) - widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event) - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet) -# if self.type == "baseBuffer": - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet) - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm) - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply) - # Replace for the correct way in other platforms. - widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu) - widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key) - - def show_menu(self, ev, pos=0, *args, **kwargs): - if self.buffer.list.get_count() == 0: return - if self.name == "sent_tweets" or self.name == "sent_direct_messages": - menu = menus.sentPanelMenu() - elif self.name == "direct_messages": - menu = menus.dmPanelMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) - else: - menu = menus.basePanelMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.retweet, menuitem=menu.retweet) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.audio, menuitem=menu.play) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove) - if pos != 0: - self.buffer.PopupMenu(menu, pos) - else: - self.buffer.PopupMenu(menu, ev.GetPosition()) - - def view(self, *args, **kwargs): - pub.sendMessage("execute-action", action="view_item") - - def copy(self, *args, **kwargs): - pub.sendMessage("execute-action", action="copy_to_clipboard") - - def user_actions(self, *args, **kwargs): - pub.sendMessage("execute-action", action="follow") - - def fav(self, *args, **kwargs): - pub.sendMessage("execute-action", action="add_to_favourites") - - def unfav(self, *args, **kwargs): - pub.sendMessage("execute-action", action="remove_from_favourites") - - def delete_item_(self, *args, **kwargs): - pub.sendMessage("execute-action", action="delete_item") - - def url_(self, *args, **kwargs): - self.url() - - def show_menu_by_key(self, ev): - if self.buffer.list.get_count() == 0: - return - if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: - self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition()) - - def get_tweet(self): - if self.session.db[self.name][self.buffer.list.get_selected()].has_key("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 - - def get_right_tweet(self): - tweet = self.session.db[self.name][self.buffer.list.get_selected()] - return tweet - - @_tweets_exist - def reply(self, *args, **kwargs): - tweet = self.get_right_tweet() - screen_name = tweet["user"]["screen_name"] - id = tweet["id"] - twishort_enabled = tweet.has_key("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") - message = messages.reply(self.session, _(u"Reply"), _(u"Reply to %s") % (screen_name,), "", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"], users=users, ids=ids) - if message.message.get_response() == widgetUtils.OK: - params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id,} - self.session.settings["mysc"]["twishort_enabled"] = message.message.long_tweet.GetValue() - if len(message.users) > 0: - self.session.settings["mysc"]["mention_all"] = message.message.mentionAll.GetValue() - text = message.message.get_text() - if twishort_enabled == False: - excluded_ids = message.get_ids() - params["exclude_reply_user_ids"] =excluded_ids - params["auto_populate_reply_metadata"] =True - else: - mentioned_people = message.get_people() - text = "@"+screen_name+" "+mentioned_people+u" "+text - if len(text) > 140 and message.message.get("long_tweet") == True: - if message.image == None: - text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text) - else: - text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1) - params["status"] = text - if message.image == None: - params["call_name"] = "update_status" - else: - params["call_name"] = "update_status_with_media" - params["media"] = message.file - call_threaded(self.session.api_call, **params) - if hasattr(message.message, "destroy"): message.message.destroy() - self.session.settings.write() - - @_tweets_exist - def direct_message(self, *args, **kwargs): - tweet = self.get_right_tweet() - if self.type == "dm": - screen_name = tweet["sender"]["screen_name"] - users = utils.get_all_users(tweet, self.session.db) - elif self.type == "people": - screen_name = tweet["screen_name"] - users = [screen_name] - else: - 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: - val = self.session.api_call(call_name="send_direct_message", text=dm.message.get_text(), screen_name=dm.message.get("cb")) - if val != None: - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db["sent_direct_messages"].append(val) - else: - 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() - - @_tweets_exist - def retweet(self, *args, **kwargs): - tweet = self.get_right_tweet() - id = tweet["id"] - if self.session.settings["general"]["retweet_mode"] == "ask": - answer = commonMessageDialogs.retweet_question(self.buffer) - if answer == widgetUtils.YES: - self._retweet_with_comment(tweet, id) - elif answer == widgetUtils.NO: - self._direct_retweet(id) - elif self.session.settings["general"]["retweet_mode"] == "direct": - self._direct_retweet(id) - else: - self._retweet_with_comment(tweet, id) - - def _retweet_with_comment(self, tweet, id, comment=''): - if tweet.has_key("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=116, messageType="retweet", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"]) - 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) - if retweet.image == None: - call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id) - else: - call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image) - if hasattr(retweet.message, "destroy"): retweet.message.destroy() - - def _direct_retweet(self, id): - call_threaded(self.session.api_call, call_name="retweet", _sound="retweet_send.ogg", id=id) - - 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") - ts = original_date.humanize(locale=languageHandler.getLanguage()) - self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, unicode(ts)) - if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet): - self.session.sound.play("audio.ogg") - if self.session.settings['sound']['indicate_geo'] and utils.is_geocoded(tweet): - self.session.sound.play("geo.ogg") - if self.session.settings['sound']['indicate_img'] and utils.is_media(tweet): - self.session.sound.play("image.ogg") - -# @_tweets_exist - def audio(self, url='', *args, **kwargs): - if hasattr(sound.URLPlayer,'stream') and sound.URLPlayer.stream.is_playing == True: - return sound.URLPlayer.stop_audio(delete=True) - tweet = self.get_tweet() - if tweet == None: return - urls = utils.find_urls(tweet) - if len(urls) == 1: - url=urls[0] - elif len(urls) > 1: - urls_list = dialogs.urlList.urlList() - urls_list.populate_list(urls) - if urls_list.get_response() == widgetUtils.OK: - url=urls_list.get_string() - if hasattr(urls_list, "destroy"): urls_list.destroy() - if url != '': -# try: - sound.URLPlayer.play(url, self.session.settings["sound"]["volume"]) -# except: -# log.error("Exception while executing audio method.") - -# @_tweets_exist - def url(self, url='', announce=True, *args, **kwargs): - if url == '': - tweet = self.get_tweet() - urls = utils.find_urls(tweet) - if len(urls) == 1: - url=urls[0] - elif len(urls) > 1: - urls_list = dialogs.urlList.urlList() - urls_list.populate_list(urls) - if urls_list.get_response() == widgetUtils.OK: - url=urls_list.get_string() - if hasattr(urls_list, "destroy"): urls_list.destroy() - if url != '': - if announce: - output.speak(_(u"Opening URL..."), True) - webbrowser.open_new_tab(url) - - def clear_list(self): - dlg = commonMessageDialogs.clear_list() - if dlg == widgetUtils.YES: - self.session.db[self.name] = [] - self.buffer.list.clear() - - @_tweets_exist - def destroy_status(self, *args, **kwargs): - index = self.buffer.list.get_selected() - if self.type == "events" or self.type == "people" or self.type == "empty" or self.type == "account": return - answer = commonMessageDialogs.delete_tweet_dialog(None) - if answer == widgetUtils.YES: - try: - if self.name == "direct_messages" or self.name == "sent_direct_messages": - self.session.twitter.twitter.destroy_direct_message(id=self.get_right_tweet()["id"]) - else: - self.session.twitter.twitter.destroy_status(id=self.get_right_tweet()["id"]) - self.session.db[self.name].pop(index) - self.buffer.list.remove_item(index) -# if index > 0: - except TwythonError: - self.session.sound.play("error") - - @_tweets_exist - def user_details(self): - tweet = self.get_right_tweet() - if self.type == "dm": - users = utils.get_all_users(tweet, self.session.db) - elif self.type == "people": - users = [tweet["screen_name"]] - else: - users = utils.get_all_users(tweet, self.session.db) - dlg = dialogs.utils.selectUserDialog(title=_(u"User details"), users=users) - if dlg.get_response() == widgetUtils.OK: - user.profileController(session=self.session, user=dlg.get_user()) - if hasattr(dlg, "destroy"): dlg.destroy() - - def get_quoted_tweet(self, tweet): -# try: - quoted_tweet = self.session.twitter.twitter.show_status(id=tweet["id"]) - urls = utils.find_urls_in_text(quoted_tweet["text"]) - for url in range(0, len(urls)): - try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass -# except TwythonError as e: -# utils.twitter_error(e) -# return - l = tweets.is_long(quoted_tweet) - id = tweets.get_id(l) -# try: - original_tweet = self.session.twitter.twitter.show_status(id=id) - urls = utils.find_urls_in_text(original_tweet["text"]) - for url in range(0, len(urls)): - try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass - return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"]) - -class listBufferController(baseBufferController): - def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs): - super(listBufferController, self).__init__(parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs) - self.users = [] - self.list_id = list_id - self.kwargs["list_id"] = list_id - - def start_stream(self, mandatory=False): - self.get_user_ids() - super(listBufferController, self).start_stream(mandatory) - - def get_user_ids(self): - next_cursor = -1 - while(next_cursor): - users = self.session.twitter.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"] - - def remove_buffer(self, force=False): - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-5] in self.session.settings["other_buffers"]["lists"]: - self.session.settings["other_buffers"]["lists"].remove(self.name[:-5]) - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - self.session.settings.write() - return True - elif dlg == widgetUtils.NO: - return False - -class eventsBufferController(bufferController): - def __init__(self, parent, name, session, account, *args, **kwargs): - super(eventsBufferController, self).__init__(parent, *args, **kwargs) - log.debug("Initializing buffer %s, account %s" % (name, account,)) - self.invisible = True - self.buffer = buffers.eventsPanel(parent, name) - self.name = name - self.account = account - self.buffer.account = self.account - self.compose_function = compose.compose_event - self.session = session - self.type = self.buffer.type - self.get_formatted_message = self.get_message - - def get_message(self): - if self.buffer.list.get_count() == 0: return _(u"Empty") - # fix this: - return "%s. %s" % (self.buffer.list.list.GetItemText(self.buffer.list.get_selected()), self.buffer.list.list.GetItemText(self.buffer.list.get_selected(), 1)) - - def add_new_item(self, item): - tweet = self.compose_function(item, self.session.db["user_name"], self.session.settings["general"]["show_screen_names"]) - if self.session.settings["general"]["reverse_timelines"] == False: - self.buffer.list.insert_item(False, *tweet) - else: - self.buffer.list.insert_item(True, *tweet) - if 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(" ".join(tweet)) - if self.buffer.list.get_count() == 1: - self.buffer.list.select_item(0) - - def clear_list(self): - dlg = commonMessageDialogs.clear_list() - if dlg == widgetUtils.YES: - self.buffer.list.clear() - - def show_menu(self, ev, pos=0, *args, **kwargs): - if self.buffer.list.get_count() == 0: return - menu = menus.eventsPanelMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove) - if pos != 0: - self.buffer.PopupMenu(menu, pos) - else: - self.buffer.PopupMenu(menu, ev.GetPosition()) - - def view(self, *args, **kwargs): - pub.sendMessage("execute-action", action="view_item") - - def copy(self, *args, **kwargs): - pub.sendMessage("execute-action", action="copy_to_clipboard") - -class peopleBufferController(baseBufferController): - def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs): - super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs) - log.debug("Initializing buffer %s, account %s" % (name, account,)) - self.compose_function = compose.compose_followers_list - log.debug("Compose_function: %s" % (self.compose_function,)) - self.get_tweet = self.get_right_tweet - self.url = self.interact - if "-followers" in self.name or "-friends" in self.name: - self.finished_timeline = False - # Add a compatibility layer for username based timelines from config. - # ToDo: Remove this in some new versions of the client, when user ID timelines become mandatory. - try: - int(self.kwargs["user_id"]) - except ValueError: - self.is_screen_name = True - self.kwargs["screen_name"] = self.kwargs["user_id"] - self.kwargs.pop("user_id") - - def remove_buffer(self, force=True): - if "-followers" in self.name: - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]: - self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10]) - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - self.session.settings.write() - return True - elif dlg == widgetUtils.NO: - return False - elif "-friends" in self.name: - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]: - self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8]) - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - self.session.settings.write() - return True - elif dlg == widgetUtils.NO: - return False - else: - output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True) - return False - - def onFocus(self, ev): - pass - - def get_message(self): - return " ".join(self.compose_function(self.get_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])) - - def delete_item(self): pass - - @_tweets_exist - def reply(self, *args, **kwargs): - tweet = self.get_right_tweet() - 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 message.image == None: - call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text()) - else: - call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file) - if hasattr(message.message, "destroy"): message.message.destroy() - - def start_stream(self, mandatory=False): - # starts stream every 3 minutes. - current_time = time.time() - if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: - 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) - 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.finished_timeline = True - return val - - 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) - return - for i in items: - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[self.name]["items"].insert(0, i) - else: - self.session.db[self.name]["items"].append(i) - selected = self.buffer.list.get_selected() -# self.put_items_on_list(len(items)) - 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.buffer.list.insert_item(True, *tweet) - self.buffer.list.select_item(selected) - else: - for i in items: - tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) - self.buffer.list.insert_item(True, *tweet) -# self.buffer.list.select_item(selection) -# else: -# self.buffer.list.select_item(selection-elements) - output.speak(_(u"%s items retrieved") % (len(items)), True) - - def put_items_on_list(self, number_of_items): - 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"]: - tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) - 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:]: - tweet = self.compose_function(i, self.session.db) - self.buffer.list.insert_item(False, *tweet) - else: - for i in self.session.db[self.name]["items"][0:number_of_items]: - tweet = self.compose_function(i, self.session.db) - self.buffer.list.insert_item(True, *tweet) - 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()] - return tweet - - def add_new_item(self, item): - tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"]) - if self.session.settings["general"]["reverse_timelines"] == False: - self.buffer.list.insert_item(False, *tweet) - else: - self.buffer.list.insert_item(True, *tweet) - if 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(" ".join(tweet)) - - 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.buffer.list.clear() - - def interact(self): - user.profileController(self.session, user=self.get_right_tweet()["screen_name"]) - - def show_menu(self, ev, pos=0, *args, **kwargs): - menu = menus.peoplePanelMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.details, menuitem=menu.details) -# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) - if pos != 0: - self.buffer.PopupMenu(menu, pos) - else: - self.buffer.PopupMenu(menu, ev.GetPosition()) - - def details(self, *args, **kwargs): - pub.sendMessage("execute-action", action="user_details") - -class searchBufferController(baseBufferController): - def start_stream(self, mandatory=False): - # starts stream every 3 minutes. - current_time = time.time() - if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: - self.execution_time = current_time - log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type)) - log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) - log.debug("Function: %s" % (self.function,)) -# try: - val = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs) -# except: -# return None - num = self.session.order_buffer(self.name, val) - self.put_items_on_list(num) - if num > 0: - self.session.sound.play("search_updated.ogg") - return num - - def remove_buffer(self, force=False): - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]: - self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11]) - self.session.settings.write() - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - return True - 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 TwythonError as e: - output.speak(e.message, True) - for i in items: - if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == 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.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.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): - super(searchPeopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs) - log.debug("Initializing buffer %s, account %s" % (name, account,)) -# self.compose_function = compose.compose_followers_list - log.debug("Compose_function: %s" % (self.compose_function,)) - self.args = args - self.kwargs = kwargs - self.function = function - if self.kwargs.has_key("page") == False: - self.kwargs["page"] = 1 - - def start_stream(self, mandatory=False): - # starts stream every 3 minutes. - current_time = time.time() - if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: - self.execution_time = current_time - log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type)) - log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) - log.debug("Function: %s" % (self.function,)) -# try: - val = self.session.call_paged(self.function, *self.args, **self.kwargs) -# except: -# return - number_of_items = self.session.order_cursored_buffer(self.name, val) - log.debug("Number of items retrieved: %d" % (number_of_items,)) - self.put_items_on_list(number_of_items) - if number_of_items > 0: - self.session.sound.play("search_updated.ogg") - return number_of_items - - def get_more_items(self, *args, **kwargs): - 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) - return - for i in items: - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[self.name]["items"].insert(0, i) - else: - self.session.db[self.name]["items"].append(i) - selected = self.buffer.list.get_selected() -# self.put_items_on_list(len(items)) - 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.buffer.list.insert_item(True, *tweet) - self.buffer.list.select_item(selected) - else: - for i in items: - tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) - self.buffer.list.insert_item(True, *tweet) -# self.buffer.list.select_item(selection) -# else: -# self.buffer.list.select_item(selection-elements) - output.speak(_(u"%s items retrieved") % (len(items)), True) - - - def remove_buffer(self, force=False): - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]: - self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11]) - self.session.settings.write() - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - return True - elif dlg == widgetUtils.NO: - return False - -class trendsBufferController(bufferController): - def __init__(self, parent, name, session, account, trendsFor, *args, **kwargs): - super(trendsBufferController, self).__init__(parent=parent, session=session) - self.trendsFor = trendsFor - self.session = session - self.account = account - self.invisible = True - self.buffer = buffers.trendsPanel(parent, name) - self.buffer.account = account - self.type = self.buffer.type - self.bind_events() - self.sound = "trends_updated.ogg" - self.trends = [] - self.name = name - self.buffer.name = name - self.compose_function = self.compose_function_ - self.get_formatted_message = self.get_message - self.reply = self.search_topic - - def start_stream(self, mandatory=False): - # starts stream every 3 minutes. - current_time = time.time() - 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 - if not hasattr(self, "name_"): - self.name_ = data[0]["locations"][0]["name"] - self.trends = data[0]["trends"] - self.put_items_on_the_list() - self.session.sound.play(self.sound) - - def put_items_on_the_list(self): - selected_item = self.buffer.list.get_selected() - self.buffer.list.clear() - for i in self.trends: - tweet = self.compose_function(i) - self.buffer.list.insert_item(False, *tweet) - self.buffer.set_position(self.session.settings["general"]["reverse_timelines"]) - - def compose_function_(self, trend): - return [trend["name"]] - - def bind_events(self): - log.debug("Binding events...") - self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event) - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.tweet_about_this_trend, self.buffer.tweetTrendBtn) - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet) - widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu) - widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key) - widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.search_topic, self.buffer.search_topic) - - def get_message(self): - return self.compose_function(self.trends[self.buffer.list.get_selected()])[0] - - def remove_buffer(self, force=False): - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]: - self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3]) - self.session.settings.write() - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - return True - elif dlg == widgetUtils.NO: - return False - - def url(self, *args, **kwargs): - self.tweet_about_this_trend() - - def search_topic(self, *args, **kwargs): - topic = self.trends[self.buffer.list.get_selected()]["name"] - pub.sendMessage("search", term=topic) - - def show_menu(self, ev, pos=0, *args, **kwargs): - menu = menus.trendsPanelMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.search_topic, menuitem=menu.search_topic) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.tweet_about_this_trend, menuitem=menu.tweetThisTrend) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) - if pos != 0: - self.buffer.PopupMenu(menu, pos) - else: - self.buffer.PopupMenu(menu, ev.GetPosition()) - - def view(self, *args, **kwargs): - pub.sendMessage("execute-action", action="view_item") - - def copy(self, *args, **kwargs): - pub.sendMessage("execute-action", action="copy_to_clipboard") - - def tweet_about_this_trend(self, *args, **kwargs): - if self.buffer.list.get_count() == 0: return - title = _(u"Tweet") - caption = _(u"Write the tweet here") - tweet = messages.tweet(self.session, title, caption, self.get_message()+ " ", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"]) - tweet.message.set_cursor_at_end() - if tweet.message.get_response() == widgetUtils.OK: - self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue() - text = tweet.message.get_text() - if len(text) > 140 and tweet.message.get("long_tweet") == True: - if tweet.image == None: - text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text) - else: - text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1) - if tweet.image == None: - call_threaded(self.session.api_call, call_name="update_status", status=text) - else: - call_threaded(self.session.api_call, call_name="update_status_with_media", status=text, media=tweet.image) - if hasattr(tweet.message, "destroy"): tweet.message.destroy() - - def show_menu_by_key(self, ev): - if self.buffer.list.get_count() == 0: - return - if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: - self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition()) - -class conversationBufferController(searchBufferController): - - def start_stream(self, start=False, mandatory=False): - # starts stream every 3 minutes. - current_time = time.time() - if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True: - self.execution_time = current_time - if start == True: - self.statuses = [] - self.ids = [] - self.statuses.append(self.tweet) - self.ids.append(self.tweet["id"]) - tweet = self.tweet - while tweet["in_reply_to_status_id"] != None: - try: - tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended") - except TwythonError 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"]) - 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: - self.statuses.append(i) - 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,)) - self.put_items_on_list(number_of_items) - if number_of_items > 0: - self.session.sound.play("search_updated.ogg") - return number_of_items - - def remove_buffer(self, force=False): - if force == False: - dlg = commonMessageDialogs.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - if self.session.db.has_key(self.name): - self.session.db.pop(self.name) - return True - elif dlg == widgetUtils.NO: - return False +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import time +import platform +if platform.system() == "Windows": + import wx + from wxUI import buffers, dialogs, commonMessageDialogs, menus + from . import user +elif platform.system() == "Linux": + from gi.repository import Gtk + from gtkUI import buffers, dialogs, commonMessageDialogs +from . import messages +import widgetUtils +import arrow +import webbrowser +import output +import config +import sound +import languageHandler +import logging +from twitter import compose, utils +from mysc.thread_utils import call_threaded +from twython import TwythonError +from pubsub import pub +from long_tweets import twishort, tweets + +log = logging.getLogger("controller.buffers") + +def _tweets_exist(function): + """ A decorator to execute a function only if the selected buffer contains at least one item.""" + def function_(self, *args, **kwargs): + if self.buffer.list.get_count() > 0: + function(self, *args, **kwargs) + return function_ + +class bufferController(object): + def __init__(self, parent=None, function=None, session=None, *args, **kwargs): + super(bufferController, self).__init__() + self.function = function + self.compose_function = None + self.args = args + self.kwargs = kwargs + self.buffer = None + self.account = "" + self.needs_init = True + self.invisible = False # False if the buffer will be ignored on the invisible interface. + self.execution_time = 0 + + def clear_list(self): pass + + + def get_event(self, ev): + """ Catches key presses in the WX interface and generate the corresponding event names.""" + if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio" + elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url" + elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down" + elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up" + elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list" + elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status" + else: + event = None + ev.Skip() + if event != None: + try: + getattr(self, event)() + except AttributeError: + pass + + def volume_down(self): + if self.session.settings["sound"]["volume"] > 0.0: + if self.session.settings["sound"]["volume"] <= 0.05: + self.session.settings["sound"]["volume"] = 0.0 + else: + self.session.settings["sound"]["volume"] -=0.05 + if hasattr(sound.URLPlayer, "stream"): + sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"] + self.session.sound.play("volume_changed.ogg") + self.session.settings.write() + + def volume_up(self): + if self.session.settings["sound"]["volume"] < 1.0: + if self.session.settings["sound"]["volume"] >= 0.95: + self.session.settings["sound"]["volume"] = 1.0 + else: + self.session.settings["sound"]["volume"] +=0.05 + if hasattr(sound.URLPlayer, "stream"): + sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"] + self.session.sound.play("volume_changed.ogg") + self.session.settings.write() + + def start_stream(self, mandatory=False): + if mandatory == True: + output.speak(_(u"Unable to update this buffer.")) + pass + + def get_more_items(self): + output.speak(_(u"This action is not supported for this buffer"), True) + + def put_items_on_list(self, items): + pass + + def remove_buffer(self): + return False + + def remove_item(self, item): + f = self.buffer.list.get_selected() + self.buffer.list.remove_item(item) + self.buffer.list.select_item(f) + + def bind_events(self): + pass + + def get_object(self): + return self.buffer + + def get_message(self): + pass + + def set_list_position(self, reversed=False): + if reversed == False: + self.buffer.list.select_item(-1) + else: + self.buffer.list.select_item(0) + + def reply(self): + pass + + def direct_message(self): + pass + + def retweet(self): + pass + + def destroy_status(self): + pass + + def post_tweet(self, *args, **kwargs): + title = _(u"Tweet") + caption = _(u"Write the tweet here") + tweet = messages.tweet(self.session, title, caption, "", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"]) + if tweet.message.get_response() == widgetUtils.OK: + self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue() + text = tweet.message.get_text() + if len(text) > 140 and tweet.message.get("long_tweet") == True: + if not hasattr(tweet, "attachments"): + text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text) + else: + 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: + call_threaded(self.session.api_call, call_name="update_status", status=text) + else: + call_threaded(self.post_with_media, text=text, attachments=tweet.attachments) + if hasattr(tweet.message, "destroy"): tweet.message.destroy() + self.session.settings.write() + + def post_with_media(self, text, attachments): + media_ids = [] + for i in attachments: + photo = open(i["file"], "rb") + img = self.session.twitter.twitter.upload_media(media=photo) + self.session.twitter.twitter.set_description(media_id=img["media_id"], alt_text=dict(text=i["description"])) + media_ids.append(img["media_id"]) + self.session.twitter.twitter.update_status(status=text, media_ids=media_ids) + + def save_positions(self): + try: + self.session.db[self.name+"_pos"]=self.buffer.list.get_selected() + except AttributeError: + pass + + +class accountPanel(bufferController): + def __init__(self, parent, name, account, account_id): + super(accountPanel, self).__init__(parent, None, name) + log.debug("Initializing buffer %s, account %s" % (name, account,)) + self.buffer = buffers.accountPanel(parent, name) + self.type = self.buffer.type + self.compose_function = None + self.session = None + self.needs_init = False + self.account = account + self.buffer.account = account + self.name = name + self.account_id = account_id + + def setup_account(self): + widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account) + if self.account_id in config.app["sessions"]["ignored_sessions"]: + self.buffer.change_autostart(False) + else: + self.buffer.change_autostart(True) + if not hasattr(self, "logged"): + self.buffer.change_login(login=False) + widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout) + else: + self.buffer.change_login(login=True) + widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login) + + def login(self, *args, **kwargs): + del self.logged + self.setup_account() + pub.sendMessage("login", session_id=self.account_id) + + def logout(self, *args, **kwargs): + self.logged = False + self.setup_account() + pub.sendMessage("logout", session_id=self.account_id) + + def autostart(self, *args, **kwargs): + if self.account_id in config.app["sessions"]["ignored_sessions"]: + self.buffer.change_autostart(True) + config.app["sessions"]["ignored_sessions"].remove(self.account_id) + else: + self.buffer.change_autostart(False) + config.app["sessions"]["ignored_sessions"].append(self.account_id) + config.app.write() + +class emptyPanel(bufferController): + def __init__(self, parent, name, account): + super(emptyPanel, self).__init__(parent=parent) + log.debug("Initializing buffer %s, account %s" % (name, account,)) + self.buffer = buffers.emptyPanel(parent, name) + self.type = self.buffer.type + self.compose_function = None + self.account = account + self.buffer.account = account + self.name = name + self.session = None + self.needs_init = True + +class baseBufferController(bufferController): + def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, compose_func="compose_tweet", *args, **kwargs): + super(baseBufferController, self).__init__(parent, function, *args, **kwargs) + log.debug("Initializing buffer %s, account %s" % (name, account,)) + if bufferType != None: + self.buffer = getattr(buffers, bufferType)(parent, name) + else: + self.buffer = buffers.basePanel(parent, name) + self.invisible = True + self.name = name + self.type = self.buffer.type + self.session = sessionObject + self.compose_function = getattr(compose, compose_func) + log.debug("Compose_function: %s" % (self.compose_function,)) + self.account = account + self.buffer.account = account + self.bind_events() + self.sound = sound + if "-timeline" in self.name or "-favorite" in self.name: + self.finished_timeline = False + # Add a compatibility layer for username based timelines from config. + # ToDo: Remove this in some new versions of the client, when user ID timelines become mandatory. + try: + int(self.kwargs["user_id"]) + except ValueError: + self.is_screen_name = True + self.kwargs["screen_name"] = self.kwargs["user_id"] + self.kwargs.pop("user_id") + + def get_formatted_message(self): + if self.type == "dm" or self.name == "sent_tweets" or self.name == "sent_direct_messages": return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])[1] + return self.get_message() + + def get_message(self): + tweet = self.get_right_tweet() + return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])) + + def get_full_tweet(self): + tweet = self.get_right_tweet() + tweetsList = [] + tweet_id = tweet["id"] + message = None + if "message" in tweet: + message = tweet["message"] + try: + tweet = self.session.twitter.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended") + urls = utils.find_urls_in_text(tweet["full_text"]) + for url in range(0, len(urls)): + try: tweet["full_text"] = tweet["full_text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass + except TwythonError as e: + utils.twitter_error(e) + return + if message != None: + tweet["message"] = message + l = tweets.is_long(tweet) + while l != False: + tweetsList.append(tweet) + try: + tweet = self.session.twitter.twitter.show_status(id=l, include_ext_alt_text=True, tweet_mode="extended") + urls = utils.find_urls_in_text(tweet["full_text"]) + for url in range(0, len(urls)): + try: tweet["full_text"] = tweet["full_text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass + except TwythonError as e: + utils.twitter_error(e) + return + l = tweets.is_long(tweet) + if l == False: + tweetsList.append(tweet) + return (tweet, tweetsList) + + def start_stream(self, mandatory=False): + # starts stream every 3 minutes. + current_time = time.time() + if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: + 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)) + 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,)) + 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"] + elif "-favorite" in self.name: + self.username = self.session.api_call("show_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: + self.session.sound.play(self.sound) + return number_of_items + + 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.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) + for i in items: + if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == 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.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.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) + + def remove_buffer(self, force=False): + if "-timeline" in self.name: + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]: + self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9]) + self.session.settings.write() + if self.name in self.session.db: + self.session.db.pop(self.name) + return True + elif dlg == widgetUtils.NO: + return False + elif "favorite" in self.name: + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]: + self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9]) + if self.name in self.session.db: + self.session.db.pop(self.name) + self.session.settings.write() + return True + elif dlg == widgetUtils.NO: + return False + else: + output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True) + return False + + def remove_tweet(self, id): + if type(self.session.db[self.name]) == dict: return + for i in xrange(0, len(self.session.db[self.name])): + if self.session.db[self.name][i]["id"] == id: + self.session.db[self.name].pop(i) + self.remove_item(i) + + def put_items_on_list(self, number_of_items): + 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,)) + if self.buffer.list.get_count() == 0: + for i in self.session.db[self.name]: + tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"]) + self.buffer.list.insert_item(False, *tweet) + self.buffer.set_position(self.session.settings["general"]["reverse_timelines"]) + elif self.buffer.list.get_count() > 0 and number_of_items > 0: + if self.session.settings["general"]["reverse_timelines"] == False: + items = self.session.db[self.name][len(self.session.db[self.name])-number_of_items:] + 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.buffer.list.insert_item(False, *tweet) + else: + items = self.session.db[self.name][0:number_of_items] + items.reverse() + 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.buffer.list.insert_item(True, *tweet) + log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),)) + + def add_new_item(self, item): + tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"]) + if self.session.settings["general"]["reverse_timelines"] == False: + self.buffer.list.insert_item(False, *tweet) + else: + self.buffer.list.insert_item(True, *tweet) + if 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(" ".join(tweet[:2])) + #Improve performance on Windows +# if platform.system() == "Windows": +# call_threaded(utils.is_audio,item) + + def bind_events(self): + log.debug("Binding events...") + self.buffer.set_focus_function(self.onFocus) + widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event) + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet) +# if self.type == "baseBuffer": + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet) + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm) + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply) + # Replace for the correct way in other platforms. + widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu) + widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key) + + def show_menu(self, ev, pos=0, *args, **kwargs): + if self.buffer.list.get_count() == 0: return + if self.name == "sent_tweets" or self.name == "sent_direct_messages": + menu = menus.sentPanelMenu() + elif self.name == "direct_messages": + menu = menus.dmPanelMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) + else: + menu = menus.basePanelMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.retweet, menuitem=menu.retweet) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.audio, menuitem=menu.play) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove) + if pos != 0: + self.buffer.PopupMenu(menu, pos) + else: + self.buffer.PopupMenu(menu, ev.GetPosition()) + + def view(self, *args, **kwargs): + pub.sendMessage("execute-action", action="view_item") + + def copy(self, *args, **kwargs): + pub.sendMessage("execute-action", action="copy_to_clipboard") + + def user_actions(self, *args, **kwargs): + pub.sendMessage("execute-action", action="follow") + + def fav(self, *args, **kwargs): + pub.sendMessage("execute-action", action="add_to_favourites") + + def unfav(self, *args, **kwargs): + pub.sendMessage("execute-action", action="remove_from_favourites") + + def delete_item_(self, *args, **kwargs): + pub.sendMessage("execute-action", action="delete_item") + + def url_(self, *args, **kwargs): + self.url() + + def show_menu_by_key(self, ev): + if self.buffer.list.get_count() == 0: + return + if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: + 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"] + else: + tweet = self.session.db[self.name][self.buffer.list.get_selected()] + return tweet + + def get_right_tweet(self): + tweet = self.session.db[self.name][self.buffer.list.get_selected()] + return tweet + + @_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 + users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name") + ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str") + message = messages.reply(self.session, _(u"Reply"), _(u"Reply to %s") % (screen_name,), "", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"], users=users, ids=ids) + if message.message.get_response() == widgetUtils.OK: + params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id,} + self.session.settings["mysc"]["twishort_enabled"] = message.message.long_tweet.GetValue() + if len(message.users) > 0: + self.session.settings["mysc"]["mention_all"] = message.message.mentionAll.GetValue() + text = message.message.get_text() + if twishort_enabled == False: + excluded_ids = message.get_ids() + params["exclude_reply_user_ids"] =excluded_ids + params["auto_populate_reply_metadata"] =True + else: + mentioned_people = message.get_people() + text = "@"+screen_name+" "+mentioned_people+u" "+text + if len(text) > 140 and message.message.get("long_tweet") == True: + if message.image == None: + text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text) + else: + text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1) + params["status"] = text + if message.image == None: + params["call_name"] = "update_status" + else: + params["call_name"] = "update_status_with_media" + params["media"] = message.file + call_threaded(self.session.api_call, **params) + if hasattr(message.message, "destroy"): message.message.destroy() + self.session.settings.write() + + @_tweets_exist + def direct_message(self, *args, **kwargs): + tweet = self.get_right_tweet() + if self.type == "dm": + screen_name = tweet["sender"]["screen_name"] + users = utils.get_all_users(tweet, self.session.db) + elif self.type == "people": + screen_name = tweet["screen_name"] + users = [screen_name] + else: + 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: + val = self.session.api_call(call_name="send_direct_message", text=dm.message.get_text(), screen_name=dm.message.get("cb")) + if val != None: + if self.session.settings["general"]["reverse_timelines"] == False: + self.session.db["sent_direct_messages"].append(val) + else: + 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() + + @_tweets_exist + def retweet(self, *args, **kwargs): + tweet = self.get_right_tweet() + id = tweet["id"] + if self.session.settings["general"]["retweet_mode"] == "ask": + answer = commonMessageDialogs.retweet_question(self.buffer) + if answer == widgetUtils.YES: + self._retweet_with_comment(tweet, id) + elif answer == widgetUtils.NO: + self._direct_retweet(id) + elif self.session.settings["general"]["retweet_mode"] == "direct": + self._direct_retweet(id) + else: + self._retweet_with_comment(tweet, id) + + def _retweet_with_comment(self, tweet, id, comment=''): + if "full_text" in tweet: + 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=116, messageType="retweet", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"]) + 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) + if retweet.image == None: + call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id) + else: + call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image) + if hasattr(retweet.message, "destroy"): retweet.message.destroy() + + def _direct_retweet(self, id): + call_threaded(self.session.api_call, call_name="retweet", _sound="retweet_send.ogg", id=id) + + 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") + ts = original_date.humanize(locale=languageHandler.getLanguage()) + self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, unicode(ts)) + if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet): + self.session.sound.play("audio.ogg") + if self.session.settings['sound']['indicate_geo'] and utils.is_geocoded(tweet): + self.session.sound.play("geo.ogg") + if self.session.settings['sound']['indicate_img'] and utils.is_media(tweet): + self.session.sound.play("image.ogg") + +# @_tweets_exist + def audio(self, url='', *args, **kwargs): + if hasattr(sound.URLPlayer,'stream') and sound.URLPlayer.stream.is_playing == True: + return sound.URLPlayer.stop_audio(delete=True) + tweet = self.get_tweet() + if tweet == None: return + urls = utils.find_urls(tweet) + if len(urls) == 1: + url=urls[0] + elif len(urls) > 1: + urls_list = dialogs.urlList.urlList() + urls_list.populate_list(urls) + if urls_list.get_response() == widgetUtils.OK: + url=urls_list.get_string() + if hasattr(urls_list, "destroy"): urls_list.destroy() + if url != '': +# try: + sound.URLPlayer.play(url, self.session.settings["sound"]["volume"]) +# except: +# log.error("Exception while executing audio method.") + +# @_tweets_exist + def url(self, url='', announce=True, *args, **kwargs): + if url == '': + tweet = self.get_tweet() + urls = utils.find_urls(tweet) + if len(urls) == 1: + url=urls[0] + elif len(urls) > 1: + urls_list = dialogs.urlList.urlList() + urls_list.populate_list(urls) + if urls_list.get_response() == widgetUtils.OK: + url=urls_list.get_string() + if hasattr(urls_list, "destroy"): urls_list.destroy() + if url != '': + if announce: + output.speak(_(u"Opening URL..."), True) + webbrowser.open_new_tab(url) + + def clear_list(self): + dlg = commonMessageDialogs.clear_list() + if dlg == widgetUtils.YES: + self.session.db[self.name] = [] + self.buffer.list.clear() + + @_tweets_exist + def destroy_status(self, *args, **kwargs): + index = self.buffer.list.get_selected() + if self.type == "events" or self.type == "people" or self.type == "empty" or self.type == "account": return + answer = commonMessageDialogs.delete_tweet_dialog(None) + if answer == widgetUtils.YES: + try: + if self.name == "direct_messages" or self.name == "sent_direct_messages": + self.session.twitter.twitter.destroy_direct_message(id=self.get_right_tweet()["id"]) + else: + self.session.twitter.twitter.destroy_status(id=self.get_right_tweet()["id"]) + self.session.db[self.name].pop(index) + self.buffer.list.remove_item(index) +# if index > 0: + except TwythonError: + self.session.sound.play("error") + + @_tweets_exist + def user_details(self): + tweet = self.get_right_tweet() + if self.type == "dm": + users = utils.get_all_users(tweet, self.session.db) + elif self.type == "people": + users = [tweet["screen_name"]] + else: + users = utils.get_all_users(tweet, self.session.db) + dlg = dialogs.utils.selectUserDialog(title=_(u"User details"), users=users) + if dlg.get_response() == widgetUtils.OK: + user.profileController(session=self.session, user=dlg.get_user()) + if hasattr(dlg, "destroy"): dlg.destroy() + + def get_quoted_tweet(self, tweet): +# try: + quoted_tweet = self.session.twitter.twitter.show_status(id=tweet["id"]) + urls = utils.find_urls_in_text(quoted_tweet["text"]) + for url in range(0, len(urls)): + try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass +# except TwythonError as e: +# utils.twitter_error(e) +# return + l = tweets.is_long(quoted_tweet) + id = tweets.get_id(l) +# try: + original_tweet = self.session.twitter.twitter.show_status(id=id) + urls = utils.find_urls_in_text(original_tweet["text"]) + for url in range(0, len(urls)): + try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass + return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"]) + +class listBufferController(baseBufferController): + def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs): + super(listBufferController, self).__init__(parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs) + self.users = [] + self.list_id = list_id + self.kwargs["list_id"] = list_id + + def start_stream(self, mandatory=False): + self.get_user_ids() + super(listBufferController, self).start_stream(mandatory) + + def get_user_ids(self): + next_cursor = -1 + while(next_cursor): + users = self.session.twitter.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"] + + def remove_buffer(self, force=False): + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-5] in self.session.settings["other_buffers"]["lists"]: + self.session.settings["other_buffers"]["lists"].remove(self.name[:-5]) + if self.name in self.session.db: + self.session.db.pop(self.name) + self.session.settings.write() + return True + elif dlg == widgetUtils.NO: + return False + +class eventsBufferController(bufferController): + def __init__(self, parent, name, session, account, *args, **kwargs): + super(eventsBufferController, self).__init__(parent, *args, **kwargs) + log.debug("Initializing buffer %s, account %s" % (name, account,)) + self.invisible = True + self.buffer = buffers.eventsPanel(parent, name) + self.name = name + self.account = account + self.buffer.account = self.account + self.compose_function = compose.compose_event + self.session = session + self.type = self.buffer.type + self.get_formatted_message = self.get_message + + def get_message(self): + if self.buffer.list.get_count() == 0: return _(u"Empty") + # fix this: + return "%s. %s" % (self.buffer.list.list.GetItemText(self.buffer.list.get_selected()), self.buffer.list.list.GetItemText(self.buffer.list.get_selected(), 1)) + + def add_new_item(self, item): + tweet = self.compose_function(item, self.session.db["user_name"], self.session.settings["general"]["show_screen_names"]) + if self.session.settings["general"]["reverse_timelines"] == False: + self.buffer.list.insert_item(False, *tweet) + else: + self.buffer.list.insert_item(True, *tweet) + if 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(" ".join(tweet)) + if self.buffer.list.get_count() == 1: + self.buffer.list.select_item(0) + + def clear_list(self): + dlg = commonMessageDialogs.clear_list() + if dlg == widgetUtils.YES: + self.buffer.list.clear() + + def show_menu(self, ev, pos=0, *args, **kwargs): + if self.buffer.list.get_count() == 0: return + menu = menus.eventsPanelMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove) + if pos != 0: + self.buffer.PopupMenu(menu, pos) + else: + self.buffer.PopupMenu(menu, ev.GetPosition()) + + def view(self, *args, **kwargs): + pub.sendMessage("execute-action", action="view_item") + + def copy(self, *args, **kwargs): + pub.sendMessage("execute-action", action="copy_to_clipboard") + +class peopleBufferController(baseBufferController): + def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs): + super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs) + log.debug("Initializing buffer %s, account %s" % (name, account,)) + self.compose_function = compose.compose_followers_list + log.debug("Compose_function: %s" % (self.compose_function,)) + self.get_tweet = self.get_right_tweet + self.url = self.interact + if "-followers" in self.name or "-friends" in self.name: + self.finished_timeline = False + # Add a compatibility layer for username based timelines from config. + # ToDo: Remove this in some new versions of the client, when user ID timelines become mandatory. + try: + int(self.kwargs["user_id"]) + except ValueError: + self.is_screen_name = True + self.kwargs["screen_name"] = self.kwargs["user_id"] + self.kwargs.pop("user_id") + + def remove_buffer(self, force=True): + if "-followers" in self.name: + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]: + self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10]) + if self.name in self.session.db: + self.session.db.pop(self.name) + self.session.settings.write() + return True + elif dlg == widgetUtils.NO: + return False + elif "-friends" in self.name: + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]: + self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8]) + if self.name in self.session.db: + self.session.db.pop(self.name) + self.session.settings.write() + return True + elif dlg == widgetUtils.NO: + return False + else: + output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True) + return False + + def onFocus(self, ev): + pass + + def get_message(self): + return " ".join(self.compose_function(self.get_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])) + + def delete_item(self): pass + + @_tweets_exist + def reply(self, *args, **kwargs): + tweet = self.get_right_tweet() + 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 message.image == None: + call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text()) + else: + call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file) + if hasattr(message.message, "destroy"): message.message.destroy() + + def start_stream(self, mandatory=False): + # starts stream every 3 minutes. + current_time = time.time() + if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: + 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) + 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.finished_timeline = True + return val + + 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) + return + for i in items: + if self.session.settings["general"]["reverse_timelines"] == False: + self.session.db[self.name]["items"].insert(0, i) + else: + self.session.db[self.name]["items"].append(i) + selected = self.buffer.list.get_selected() +# self.put_items_on_list(len(items)) + 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.buffer.list.insert_item(True, *tweet) + self.buffer.list.select_item(selected) + else: + for i in items: + tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) + self.buffer.list.insert_item(True, *tweet) +# self.buffer.list.select_item(selection) +# else: +# self.buffer.list.select_item(selection-elements) + output.speak(_(u"%s items retrieved") % (len(items)), True) + + def put_items_on_list(self, number_of_items): + 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"]: + tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) + 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:]: + tweet = self.compose_function(i, self.session.db) + self.buffer.list.insert_item(False, *tweet) + else: + for i in self.session.db[self.name]["items"][0:number_of_items]: + tweet = self.compose_function(i, self.session.db) + self.buffer.list.insert_item(True, *tweet) + 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()] + return tweet + + def add_new_item(self, item): + tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"]) + if self.session.settings["general"]["reverse_timelines"] == False: + self.buffer.list.insert_item(False, *tweet) + else: + self.buffer.list.insert_item(True, *tweet) + if 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(" ".join(tweet)) + + 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.buffer.list.clear() + + def interact(self): + user.profileController(self.session, user=self.get_right_tweet()["screen_name"]) + + def show_menu(self, ev, pos=0, *args, **kwargs): + menu = menus.peoplePanelMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.details, menuitem=menu.details) +# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) + if pos != 0: + self.buffer.PopupMenu(menu, pos) + else: + self.buffer.PopupMenu(menu, ev.GetPosition()) + + def details(self, *args, **kwargs): + pub.sendMessage("execute-action", action="user_details") + +class searchBufferController(baseBufferController): + def start_stream(self, mandatory=False): + # starts stream every 3 minutes. + current_time = time.time() + if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: + self.execution_time = current_time + log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type)) + log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) + log.debug("Function: %s" % (self.function,)) +# try: + val = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs) +# except: +# return None + num = self.session.order_buffer(self.name, val) + self.put_items_on_list(num) + if num > 0: + self.session.sound.play("search_updated.ogg") + return num + + def remove_buffer(self, force=False): + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]: + self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11]) + self.session.settings.write() + if self.name in self.session.db: + self.session.db.pop(self.name) + return True + 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 TwythonError as e: + output.speak(e.message, True) + for i in items: + if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == 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.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.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): + super(searchPeopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs) + log.debug("Initializing buffer %s, account %s" % (name, account,)) +# self.compose_function = compose.compose_followers_list + log.debug("Compose_function: %s" % (self.compose_function,)) + self.args = args + self.kwargs = kwargs + self.function = function + if ("page" in self.kwargs) == False: + self.kwargs["page"] = 1 + + def start_stream(self, mandatory=False): + # starts stream every 3 minutes. + current_time = time.time() + if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True: + self.execution_time = current_time + log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type)) + log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) + log.debug("Function: %s" % (self.function,)) +# try: + val = self.session.call_paged(self.function, *self.args, **self.kwargs) +# except: +# return + number_of_items = self.session.order_cursored_buffer(self.name, val) + log.debug("Number of items retrieved: %d" % (number_of_items,)) + self.put_items_on_list(number_of_items) + if number_of_items > 0: + self.session.sound.play("search_updated.ogg") + return number_of_items + + def get_more_items(self, *args, **kwargs): + 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) + return + for i in items: + if self.session.settings["general"]["reverse_timelines"] == False: + self.session.db[self.name]["items"].insert(0, i) + else: + self.session.db[self.name]["items"].append(i) + selected = self.buffer.list.get_selected() +# self.put_items_on_list(len(items)) + 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.buffer.list.insert_item(True, *tweet) + self.buffer.list.select_item(selected) + else: + for i in items: + tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) + self.buffer.list.insert_item(True, *tweet) +# self.buffer.list.select_item(selection) +# else: +# self.buffer.list.select_item(selection-elements) + output.speak(_(u"%s items retrieved") % (len(items)), True) + + + def remove_buffer(self, force=False): + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]: + self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11]) + self.session.settings.write() + if self.name in self.session.db: + self.session.db.pop(self.name) + return True + elif dlg == widgetUtils.NO: + return False + +class trendsBufferController(bufferController): + def __init__(self, parent, name, session, account, trendsFor, *args, **kwargs): + super(trendsBufferController, self).__init__(parent=parent, session=session) + self.trendsFor = trendsFor + self.session = session + self.account = account + self.invisible = True + self.buffer = buffers.trendsPanel(parent, name) + self.buffer.account = account + self.type = self.buffer.type + self.bind_events() + self.sound = "trends_updated.ogg" + self.trends = [] + self.name = name + self.buffer.name = name + self.compose_function = self.compose_function_ + self.get_formatted_message = self.get_message + self.reply = self.search_topic + + def start_stream(self, mandatory=False): + # starts stream every 3 minutes. + current_time = time.time() + 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 + if not hasattr(self, "name_"): + self.name_ = data[0]["locations"][0]["name"] + self.trends = data[0]["trends"] + self.put_items_on_the_list() + self.session.sound.play(self.sound) + + def put_items_on_the_list(self): + selected_item = self.buffer.list.get_selected() + self.buffer.list.clear() + for i in self.trends: + tweet = self.compose_function(i) + self.buffer.list.insert_item(False, *tweet) + self.buffer.set_position(self.session.settings["general"]["reverse_timelines"]) + + def compose_function_(self, trend): + return [trend["name"]] + + def bind_events(self): + log.debug("Binding events...") + self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event) + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.tweet_about_this_trend, self.buffer.tweetTrendBtn) + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet) + widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu) + widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key) + widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.search_topic, self.buffer.search_topic) + + def get_message(self): + return self.compose_function(self.trends[self.buffer.list.get_selected()])[0] + + def remove_buffer(self, force=False): + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]: + self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3]) + self.session.settings.write() + if self.name in self.session.db: + self.session.db.pop(self.name) + return True + elif dlg == widgetUtils.NO: + return False + + def url(self, *args, **kwargs): + self.tweet_about_this_trend() + + def search_topic(self, *args, **kwargs): + topic = self.trends[self.buffer.list.get_selected()]["name"] + pub.sendMessage("search", term=topic) + + def show_menu(self, ev, pos=0, *args, **kwargs): + menu = menus.trendsPanelMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.search_topic, menuitem=menu.search_topic) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.tweet_about_this_trend, menuitem=menu.tweetThisTrend) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy) + if pos != 0: + self.buffer.PopupMenu(menu, pos) + else: + self.buffer.PopupMenu(menu, ev.GetPosition()) + + def view(self, *args, **kwargs): + pub.sendMessage("execute-action", action="view_item") + + def copy(self, *args, **kwargs): + pub.sendMessage("execute-action", action="copy_to_clipboard") + + def tweet_about_this_trend(self, *args, **kwargs): + if self.buffer.list.get_count() == 0: return + title = _(u"Tweet") + caption = _(u"Write the tweet here") + tweet = messages.tweet(self.session, title, caption, self.get_message()+ " ", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"]) + tweet.message.set_cursor_at_end() + if tweet.message.get_response() == widgetUtils.OK: + self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue() + text = tweet.message.get_text() + if len(text) > 140 and tweet.message.get("long_tweet") == True: + if tweet.image == None: + text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text) + else: + text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1) + if tweet.image == None: + call_threaded(self.session.api_call, call_name="update_status", status=text) + else: + call_threaded(self.session.api_call, call_name="update_status_with_media", status=text, media=tweet.image) + if hasattr(tweet.message, "destroy"): tweet.message.destroy() + + def show_menu_by_key(self, ev): + if self.buffer.list.get_count() == 0: + return + if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: + self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition()) + +class conversationBufferController(searchBufferController): + + def start_stream(self, start=False, mandatory=False): + # starts stream every 3 minutes. + current_time = time.time() + if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True: + self.execution_time = current_time + if start == True: + self.statuses = [] + self.ids = [] + self.statuses.append(self.tweet) + self.ids.append(self.tweet["id"]) + tweet = self.tweet + while tweet["in_reply_to_status_id"] != None: + try: + tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended") + except TwythonError 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"]) + 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: + self.statuses.append(i) + 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,)) + self.put_items_on_list(number_of_items) + if number_of_items > 0: + self.session.sound.play("search_updated.ogg") + return number_of_items + + def remove_buffer(self, force=False): + if force == False: + dlg = commonMessageDialogs.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + if self.name in self.session.db: + self.session.db.pop(self.name) + return True + elif dlg == widgetUtils.NO: + return False diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 0e0c0cf4..80b04015 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -1,1620 +1,1621 @@ -# -*- coding: utf-8 -*- -import platform -system = platform.system() -import application -if system == "Windows": - from update import updater - from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon) - import settings - from extra import SoundsTutorial, ocr - import keystrokeEditor - from keyboard_handler.wx_handler import WXKeyboardHandler - import userActionsController - import trendingTopics - import user - import listsController -# from issueReporter import issueReporter -elif system == "Linux": - from gtkUI import (view, commonMessageDialogs) -from twitter import utils, compose -from sessionmanager import manager, sessionManager - -import buffersController -import messages -from sessionmanager import session as session_ -from pubsub import pub -import sound -import output -from twython import TwythonError, TwythonAuthError -from mysc.thread_utils import call_threaded -from mysc.repeating_timer import RepeatingTimer -from mysc import restart -import config -import widgetUtils -import pygeocoder -from pygeolib import GeocoderError -import logging -import webbrowser -from mysc import localization -import os - -log = logging.getLogger("mainController") - -geocoder = pygeocoder.Geocoder() - -class Controller(object): - - """ Main Controller for TWBlue. It manages the main window and sessions.""" - - def search_buffer(self, name_, user): - - """ Searches a buffer. - name_ str: The name for the buffer - user str: The account for the buffer. - for example you may want to search the home_timeline buffer for the tw_blue2 user. - returns buffersController.buffer object with the result if there is one.""" - for i in self.buffers: - if i.name == name_ and i.account == user: return i - - def get_current_buffer(self): - """ Get the current bufferObject""" - buffer = self.view.get_current_buffer() - if hasattr(buffer, "account"): - buffer = self.search_buffer(buffer.name, buffer.account) - return buffer - - def get_best_buffer(self): - """ Gets the best buffer for doing something using the session object. - This function is useful when you need to open a timeline or post a tweet, and the user is in a buffer without a session, for example the events buffer. - This returns a bufferObject.""" - # Gets the parent buffer to know what account is doing an action - view_buffer = self.view.get_current_buffer() - # If the account has no session attached, we will need to search the home_timeline for that account to use its session. - if view_buffer.type == "account" or view_buffer.type == "empty": - buffer = self.search_buffer("home_timeline", view_buffer.account) - else: - buffer = self.search_buffer(view_buffer.name, view_buffer.account) - if buffer != None: return buffer - - def get_first_buffer(self, account): - """ Gets the first valid buffer for an account. - account str: A twitter username. - The first valid buffer is the home timeline.""" - for i in self.buffers: - if i.account == account and i.invisible == True: - buff = i - break - return self.view.search(buff.name, buff.account) - - def get_last_buffer(self, account): - """ Gets the last valid buffer for an account. - account str: A twitter username. - The last valid buffer is the last buffer that contains a session object assigned.""" -# results = self.get_buffers_for_account(account) - results = self.get_buffers_for_account(account) - return self.view.search(results[-1].name, results[-1].account) - - def get_buffers_for_account(self, account): - results = [] - buffers = self.view.get_buffers() - [results.append(self.search_buffer(i.name, i.account)) for i in buffers if i.account == account and (i.type != "account")] - return results - - def bind_stream_events(self): - """ Binds all the streaming events with their functions.""" - log.debug("Binding events for the Twitter stream API...") - pub.subscribe(self.manage_home_timelines, "item-in-home") - pub.subscribe(self.manage_mentions, "mention") - pub.subscribe(self.manage_direct_messages, "direct-message") - pub.subscribe(self.manage_sent_dm, "sent-dm") - pub.subscribe(self.manage_sent_tweets, "sent-tweet") - pub.subscribe(self.manage_events, "event") - pub.subscribe(self.manage_followers, "follower") - pub.subscribe(self.manage_friend, "friend") - pub.subscribe(self.manage_unfollowing, "unfollowing") - pub.subscribe(self.manage_favourite, "favourite") - pub.subscribe(self.manage_unfavourite, "unfavourite") - pub.subscribe(self.manage_blocked_user, "blocked-user") - pub.subscribe(self.manage_unblocked_user, "unblocked-user") - pub.subscribe(self.manage_item_in_timeline, "item-in-timeline") - pub.subscribe(self.manage_item_in_list, "item-in-list") - pub.subscribe(self.restart_streams_, "restart_streams") - pub.subscribe(self.on_tweet_deleted, "tweet-deleted") - pub.subscribe(self.buffer_title_changed, "buffer-title-changed") - widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit_) - - def bind_other_events(self): - """ Binds the local application events with their functions.""" - log.debug("Binding other application events...") - pub.subscribe(self.logout_account, "logout") - pub.subscribe(self.login_account, "login") - pub.subscribe(self.manage_stream_errors, "stream-error") - pub.subscribe(self.create_new_buffer, "create-new-buffer") - pub.subscribe(self.restart_streams, "restart-streams") - pub.subscribe(self.execute_action, "execute-action") - pub.subscribe(self.search_topic, "search") - if system == "Windows": - pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed") - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.search, menuitem=self.view.menuitem_search) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.list_manager, menuitem=self.view.lists) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_trending_topics, menuitem=self.view.trends) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.find, menuitem=self.view.find) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.accountConfiguration, menuitem=self.view.account_settings) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.configuration, menuitem=self.view.prefs) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.ocr_image, menuitem=self.view.ocr) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.learn_sounds, menuitem=self.view.sounds_tutorial) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.exit, menuitem=self.view.close) - widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit) - if widgetUtils.toolkit == "wx": - log.debug("Binding the exit function...") - widgetUtils.connectExitFunction(self.exit_) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.edit_keystrokes, menuitem=self.view.keystroke_editor) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_tweet, self.view.compose) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_reply, self.view.reply) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_retweet, self.view.retweet) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_favourites, self.view.fav) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.unfav) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.reverse_geocode, menuitem=self.view.view_coordinates) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.follow, menuitem=self.view.follow) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.send_dm, self.view.dm) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_more_items, menuitem=self.view.load_previous_items) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.clear_buffer, menuitem=self.view.clear) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_buffer, self.view.deleteTl) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.check_for_updates, self.view.check_for_updates) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.about, menuitem=self.view.about) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.visit_website, menuitem=self.view.visit_website) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.manage_accounts, self.view.manage_accounts) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_profile, menuitem=self.view.updateProfile) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.user_details, menuitem=self.view.details) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.toggle_autoread, menuitem=self.view.autoread) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.toggle_buffer_mute, self.view.mute_buffer) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.open_timeline, self.view.timeline) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.open_favs_timeline, self.view.favs) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.open_conversation, menuitem=self.view.view_conversation) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.seekLeft, menuitem=self.view.seekLeft) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.seekRight, menuitem=self.view.seekRight) - if widgetUtils.toolkit == "wx": - widgetUtils.connect_event(self.view.nb, widgetUtils.NOTEBOOK_PAGE_CHANGED, self.buffer_changed) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.report_error, self.view.reportError) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_documentation, self.view.doc) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_changelog, self.view.changelog) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_list, self.view.addToList) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_list, self.view.removeFromList) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_buffer, self.view.update_buffer) - - def set_systray_icon(self): - self.systrayIcon = sysTrayIcon.SysTrayIcon() - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.post_tweet, menuitem=self.systrayIcon.tweet) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.configuration, menuitem=self.systrayIcon.global_settings) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.accountConfiguration, menuitem=self.systrayIcon.account_settings) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.update_profile, menuitem=self.systrayIcon.update_profile) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.show_hide, menuitem=self.systrayIcon.show_hide) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.check_for_updates, menuitem=self.systrayIcon.check_for_updates) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.view_documentation, menuitem=self.systrayIcon.doc) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.exit, menuitem=self.systrayIcon.exit) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_LEFT_CLICK, self.taskbar_left_click) - widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_RIGHT_CLICK, self.taskbar_right_click) - - def taskbar_left_click(self, *args, **kwargs): - if self.showing == True: - self.view.set_focus() - else: - self.show_hide() - - def taskbar_right_click(self, *args, **kwargs): - self.systrayIcon.show_menu() - - def __init__(self): - super(Controller, self).__init__() - # Visibility state. - self.showing = True - # main window - self.view = view.mainFrame() - # buffers list. - self.buffers = [] - self.started = False - # accounts list. - self.accounts = [] - # This saves the current account (important in invisible mode) - self.current_account = "" - self.view.prepare() - self.bind_stream_events() - self.bind_other_events() - if system == "Windows": - self.set_systray_icon() - - def check_invisible_at_startup(self): - # Visibility check. It does only work for windows. - if system != "Windows": return - if config.app["app-settings"]["hide_gui"] == True: - self.show_hide() - self.view.Show() - self.view.Hide() - # Invisible keyboard Shorcuts check. - if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == True: - km = self.create_invisible_keyboard_shorcuts() - self.register_invisible_keyboard_shorcuts(km) - - def do_work(self): - """ Creates the buffer objects for all accounts. This does not starts the buffer streams, only creates the objects.""" - log.debug("Creating buffers for all sessions...") - for i in session_.sessions: - log.debug("Working on session %s" % (i,)) - if session_.sessions[i].is_logged == False: - self.create_ignored_session_buffer(session_.sessions[i]) - continue - self.create_buffers(session_.sessions[i]) - - # Connection checker executed each minute. - self.checker_function = RepeatingTimer(60, self.check_connection) - self.checker_function.start() - self.save_db = RepeatingTimer(300, self.save_data_in_db) - self.save_db.start() - - def start(self): - """ Starts all buffer objects. Loads their items.""" - for i in session_.sessions: - if session_.sessions[i].is_logged == False: continue - self.start_buffers(session_.sessions[i]) - self.set_buffer_positions(session_.sessions[i]) - if config.app["app-settings"]["play_ready_sound"] == True: - session_.sessions[session_.sessions.keys()[0]].sound.play("ready.ogg") - if config.app["app-settings"]["speak_ready_msg"] == True: - output.speak(_(u"Ready")) - self.started = True - - def create_ignored_session_buffer(self, session): - self.accounts.append(session.settings["twitter"]["user_name"]) - account = buffersController.accountPanel(self.view.nb, session.settings["twitter"]["user_name"], session.settings["twitter"]["user_name"], session.session_id) - account.logged = False - account.setup_account() - self.buffers.append(account) - self.view.add_buffer(account.buffer , name=session.settings["twitter"]["user_name"]) - - def login_account(self, session_id): - for i in session_.sessions: - if session_.sessions[i].session_id == session_id: session = session_.sessions[i] - session.login() - session.db = dict() - self.create_buffers(session, False) - self.start_buffers(session) - - def create_buffers(self, session, createAccounts=True): - """ Generates buffer objects for an user account. - session SessionObject: a sessionmanager.session.Session Object""" - session.get_user_info() - if createAccounts == True: - self.accounts.append(session.db["user_name"]) - account = buffersController.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"], session.session_id) - account.setup_account() - self.buffers.append(account) - self.view.add_buffer(account.buffer , name=session.db["user_name"]) - for i in session.settings['general']['buffer_order']: - if i == 'home': - home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], 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 = buffersController.baseBufferController(self.view.nb, "get_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 = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_dm", sound="dm_received.ogg", full_text=True) - 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': - sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_dm", full_text=True) - 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 = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], bufferType="dmPanel", 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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], 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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], 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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "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 = buffersController.peopleBufferController(self.view.nb, "list_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 = buffersController.peopleBufferController(self.view.nb, "list_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"])) - elif i == 'events': - events = buffersController.eventsBufferController(self.view.nb, "events", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"]) - self.buffers.append(events) - self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) - timelines = buffersController.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 = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], 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 = buffersController.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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, 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"])) - tl.timer = RepeatingTimer(300, tl.start_stream) - tl.timer.start() - followers_timelines = buffersController.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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], 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"])) - tl.timer = RepeatingTimer(300, tl.start_stream) - tl.timer.start() - friends_timelines = buffersController.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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], 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"])) - tl.timer = RepeatingTimer(300, tl.start_stream) - tl.timer.start() - lists = buffersController.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 = buffersController.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, 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"])) - searches = buffersController.emptyPanel(self.view.nb, "searches", session.db["user_name"]) - self.buffers.append(searches) - self.view.insert_buffer(searches.buffer , name=_(u"Searches"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) - for i in session.settings["other_buffers"]["tweet_searches"]: - tl = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", q=i, tweet_mode="extended") - self.buffers.append(tl) - self.view.insert_buffer(tl.buffer, name=_(u"Search for {}").format(i), pos=self.view.search("searches", session.db["user_name"])) - tl.timer = RepeatingTimer(180, tl.start_stream) - tl.timer.start() - for i in session.settings["other_buffers"]["trending_topic_buffers"]: - buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i) - buffer.start_stream() - buffer.searchfunction = self.search - self.buffers.append(buffer) - buffer.timer = RepeatingTimer(300, buffer.start_stream) - buffer.timer.start() - self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"])) - - def set_buffer_positions(self, session): - "Sets positions for buffers if values exist in the database." - for i in self.buffers: - if i.account == session.db["user_name"] and session.db.has_key(i.name+"_pos") and hasattr(i.buffer,'list'): - i.buffer.list.select_item(session.db[str(i.name+"_pos")]) - - def logout_account(self, session_id): - for i in session_.sessions: - if session_.sessions[i].session_id == session_id: session = session_.sessions[i] - user = session.db["user_name"] - delete_buffers = [] - for i in self.buffers: - if i.account == user and i.name != user: - delete_buffers.append(i.name) - for i in delete_buffers: - self.destroy_buffer(i, user) - session.db = None - - def destroy_buffer(self, buffer_name, account): - buffer = self.search_buffer(buffer_name, account) - if buffer == None: return - buff = self.view.search(buffer.name, buffer.account) - if buff == None: return - self.view.delete_buffer(buff) - self.buffers.remove(buffer) - del buffer - - def search_topic(self, term): - self.search(value=term) - - def search(self, event=None, value="", *args, **kwargs): - """ Searches words or users in twitter. This creates a new buffer containing the search results.""" - log.debug("Creating a new search...") - dlg = dialogs.search.searchDialog(value) - if dlg.get_response() == widgetUtils.OK and dlg.get("term") != "": - term = dlg.get("term") - buffer = self.get_best_buffer() - if dlg.get("tweets") == True: - if term not in buffer.session.settings["other_buffers"]["tweet_searches"]: - buffer.session.settings["other_buffers"]["tweet_searches"].append(term) - buffer.session.settings.write() - args = {"lang": dlg.get_language(), "result_type": dlg.get_result_type()} - search = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", q=term, **args) - else: - log.error("A buffer for the %s search term is already created. You can't create a duplicate buffer." % (term,)) - return - elif dlg.get("users") == True: - search = buffersController.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, q=term) - search.start_stream(mandatory=True) - pos=self.view.search("searches", buffer.session.db["user_name"]) - self.insert_buffer(search, pos) - self.view.insert_buffer(search.buffer, name=_(u"Search for {}").format(term), pos=pos) - search.timer = RepeatingTimer(180, search.start_stream) - search.timer.start() - dlg.Destroy() - - def find(self, *args, **kwargs): - if 'string' in kwargs: - string=kwargs['string'] - else: - string='' - dlg = dialogs.find.findDialog(string) - if dlg.get_response() == widgetUtils.OK and dlg.get("string") != "": - string = dlg.get("string") - #If we still have an empty string for some reason (I.E. user clicked cancel, etc), return here. - if string == '': - log.debug("Find canceled.") - return - page = self.get_current_buffer() - if not hasattr(page.buffer, "list"): - output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) - return - count = page.buffer.list.get_count() - if count < 1: - output.speak(_(u"Empty buffer."), True) - return - start = page.buffer.list.get_selected() - for i in xrange(start,count): - page.buffer.list.select_item(i) - if string.lower() in page.get_message().lower(): - return output.speak(page.get_message(), True) - output.speak(_(u"{0} not found.").format(string,), True) - page.buffer.list.select_item(start) - - def seekLeft(self, *args, **kwargs): - try: - sound.URLPlayer.seek(-5) - except: - output.speak("Unable to seek.",True) - - def seekRight(self, *args, **kwargs): - try: - sound.URLPlayer.seek(5) - except: - output.speak("Unable to seek.",True) - - def edit_keystrokes(self, *args, **kwargs): - editor = keystrokeEditor.KeystrokeEditor() - if editor.changed == True: - config.keymap.write() - register = False - # determines if we need to reassign the keymap. - if self.showing == False: - register = True - elif config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == True: - register = True - # If there is a keyboard handler instance we need unregister all old keystrokes before register the new ones. - if hasattr(self, "keyboard_handler"): - keymap = {} - for i in editor.hold_map: - if hasattr(self, i): keymap[editor.hold_map[i]] = getattr(self, i) - self.unregister_invisible_keyboard_shorcuts(keymap) - self.invisible_shorcuts_changed(registered=register) - - def learn_sounds(self, *args, **kwargs): - """ Opens the sounds tutorial for the current account.""" - buffer = self.get_best_buffer() - SoundsTutorial.soundsTutorial(buffer.session) - - def view_user_lists(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 = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) - if dlg.get_response() == widgetUtils.OK: - user = dlg.get_user() - else: - return - l = listsController.listsController(buff.session, user=user) - - def add_to_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 = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) - if dlg.get_response() == widgetUtils.OK: - user = dlg.get_user() - else: - return - dlg = dialogs.lists.addUserListDialog() - 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.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) - if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) - except TwythonError as e: - output.speak("error %s: %s" % (e.error_code, e.msg)) - - 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 = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) - if dlg.get_response() == widgetUtils.OK: - user = dlg.get_user() - else: - return - dlg = dialogs.lists.removeUserListDialog() - 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.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"]) - if listBuffer != None: listBuffer.get_user_ids() - buff.session.db["lists"].pop(older_list) - buff.session.db["lists"].append(list) - if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) - except TwythonError as e: - output.speak("error %s: %s" % (e.error_code, e.msg)) - - def list_manager(self, *args, **kwargs): - s = self.get_best_buffer().session - l = listsController.listsController(s) - - def configuration(self, *args, **kwargs): - """ Opens the global settings dialogue.""" - d = settings.globalSettingsController() - if d.response == widgetUtils.OK: - d.save_configuration() - if d.needs_restart == True: - commonMessageDialogs.needs_restart() - restart.restart_program() - - def accountConfiguration(self, *args, **kwargs): - """ Opens the account settings dialogue for the current account.""" - buff = self.get_best_buffer() - manager.manager.set_current_session(buff.session.session_id) - d = settings.accountSettingsController(buff, self) - if d.response == widgetUtils.OK: - d.save_configuration() - if d.needs_restart == True: - commonMessageDialogs.needs_restart() - buff.session.settings.write() - restart.restart_program() - - def report_error(self, *args, **kwargs): - r = issueReporter.reportBug(self.get_best_buffer().session.db["user_name"]) - - def check_for_updates(self, *args, **kwargs): - update = updater.do_update() - if update == False: - view.no_update_available() - - def delete(self, *args, **kwargs): - """ Deletes an item in the current buffer. - Users can only remove their tweets and direct messages, other users' tweets and people (followers, friends, blocked, etc) can not be removed using this method.""" - buffer = self.view.get_current_buffer() - if hasattr(buffer, "account"): - buffer = self.search_buffer(buffer.name, buffer.account) - buffer.destroy_status() - - def exit(self, *args, **kwargs): - if config.app["app-settings"]["ask_at_exit"] == True: - answer = commonMessageDialogs.exit_dialog(self.view) - if answer == widgetUtils.YES: - self.exit_() - else: - self.exit_() - - def exit_(self, *args, **kwargs): - for i in self.buffers: i.save_positions() - log.debug("Exiting...") - log.debug("Saving global configuration...") - for item in session_.sessions: - if session_.sessions[item].logged == False: continue - log.debug("Disconnecting streams for %s session" % (session_.sessions[item].session_id,)) - if hasattr(session_.sessions[item], "main_stream"): session_.sessions[item].main_stream.disconnect() - if hasattr(session_.sessions[item], "timelinesStream"): session_.sessions[item].timelinesStream.disconnect() - session_.sessions[item].sound.cleaner.cancel() - log.debug("Shelving database for " + session_.sessions[item].session_id) - session_.sessions[item].shelve() - - if system == "Windows": - self.systrayIcon.RemoveIcon() - widgetUtils.exit_application() - - def follow(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users) - - def unfollow(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users, "unfollow") - - def mute(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users, "mute") - - def unmute(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users, "unmute") - - def block(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users, "block") - - def unblock(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users, "unblock") - - def report(self, *args, **kwargs): - buff = self.get_current_buffer() - if not hasattr(buff, "get_right_tweet"): return - tweet = buff.get_right_tweet() - if buff.type != "people": - users = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - u = userActionsController.userActionsController(buff, users, "report") - - def post_tweet(self, event=None): - buffer = self.get_best_buffer() - buffer.post_tweet() - - def post_reply(self, *args, **kwargs): - buffer = self.get_current_buffer() - if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return - elif buffer.name == "direct_messages": - buffer.direct_message() - else: - buffer.reply() - - def send_dm(self, *args, **kwargs): - buffer = self.get_current_buffer() - if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return - else: - buffer.direct_message() - - def post_retweet(self, *args, **kwargs): - buffer = self.get_current_buffer() - if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": - return - else: - buffer.retweet() - - def add_to_favourites(self, *args, **kwargs): - buffer = self.get_current_buffer() - if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": - return - else: - 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): - buffer = self.get_current_buffer() - if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": - return - else: - id = buffer.get_tweet()["id"] - call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id) - - def view_item(self, *args, **kwargs): - buffer = self.get_current_buffer() - if buffer.type == "baseBuffer" or buffer.type == "favourites_timeline" or buffer.type == "list" or buffer.type == "search": - tweet, tweetsList = buffer.get_full_tweet() - msg = messages.viewTweet(tweet, tweetsList) - elif buffer.type == "account" or buffer.type == "empty": - return - elif buffer.name == "sent_tweets": - tweet, tweetsList = buffer.get_full_tweet() - msg = messages.viewTweet(tweet, tweetsList) - else: - non_tweet = buffer.get_formatted_message() - msg = messages.viewTweet(non_tweet, [], False) - - def open_favs_timeline(self, *args, **kwargs): - self.open_timeline(default="favourites") - - def open_timeline(self, default="tweets", *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 = utils.get_all_users(tweet, buff.session.db) - else: - users = [tweet["screen_name"]] - dlg = dialogs.userSelection.selectUserDialog(users=users, default=default) - if dlg.get_response() == widgetUtils.OK: - usr = utils.if_user_exists(buff.session.twitter.twitter, dlg.get_user()) - if usr != None: - if usr == dlg.get_user(): - commonMessageDialogs.suspended_user() - return - if usr["protected"] == True: - if usr["following"] == False: - commonMessageDialogs.no_following() - return - answer = commonMessageDialogs.protected_user() - if answer == widgetUtils.NO: return - tl_type = dlg.get_action() - if tl_type == "tweets": - if usr["statuses_count"] == 0: - commonMessageDialogs.no_tweets() - return - if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]: - commonMessageDialogs.timeline_exist() - return - tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, user_id=usr["id_str"], tweet_mode="extended") - try: - tl.start_stream() - except TwythonAuthError: - 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"]) - pub.sendMessage("buffer-title-changed", buffer=tl) - pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) - buff.session.sound.play("create_timeline.ogg") - elif tl_type == "favourites": - if usr["favourites_count"] == 0: - commonMessageDialogs.no_favs() - return - if usr["id_str"] in buff.session.settings["other_buffers"]["favourites_timelines"]: - commonMessageDialogs.timeline_exist() - return - tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, user_id=usr["id_str"], tweet_mode="extended") - try: - tl.start_stream() - except TwythonAuthError: - 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) - tl.timer = RepeatingTimer(300, tl.start_stream) - tl.timer.start() - buff.session.settings["other_buffers"]["favourites_timelines"].append(usr["id_str"]) - pub.sendMessage("buffer-title-changed", buffer=i) - buff.session.sound.play("create_timeline.ogg") - elif tl_type == "followers": - if usr["followers_count"] == 0: - commonMessageDialogs.no_followers() - return - if usr["id_str"] in buff.session.settings["other_buffers"]["followers_timelines"]: - commonMessageDialogs.timeline_exist() - return - tl = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], user_id=usr["id_str"]) - try: - tl.start_stream() - except TwythonAuthError: - 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) - tl.timer = RepeatingTimer(300, tl.start_stream) - tl.timer.start() - 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: - commonMessageDialogs.no_friends() - return - if usr["id_str"] in buff.session.settings["other_buffers"]["friends_timelines"]: - commonMessageDialogs.timeline_exist() - return - tl = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], user_id=usr["id_str"]) - try: - tl.start_stream() - except TwythonAuthError: - 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) - tl.timer = RepeatingTimer(300, tl.start_stream) - tl.timer.start() - 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: - commonMessageDialogs.user_not_exist() - buff.session.settings.write() - - 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"] - search = buffersController.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", since_id=id, q="@{0}".format(user,)) - search.tweet = buffer.get_right_tweet() - search.start_stream(start=True) - pos=self.view.search("searches", buffer.session.db["user_name"]) -# self.buffers.append(search) - self.insert_buffer(search, pos) - self.view.insert_buffer(search.buffer, name=_(u"Conversation with {0}").format(user), pos=pos) - search.timer = RepeatingTimer(300, search.start_stream) - search.timer.start() - - def show_hide(self, *args, **kwargs): - km = self.create_invisible_keyboard_shorcuts() - if self.showing == True: - if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == False: - self.register_invisible_keyboard_shorcuts(km) - self.view.Hide() - self.fix_wrong_buffer() - self.showing = False - else: - if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == False: - self.unregister_invisible_keyboard_shorcuts(km) - self.view.Show() - self.showing = True - - def get_trending_topics(self, *args, **kwargs): - buff = self.get_best_buffer() - trends = trendingTopics.trendingTopicsController(buff.session) - if trends.dialog.get_response() == widgetUtils.OK: - woeid = trends.get_woeid() - if woeid in buff.session.settings["other_buffers"]["trending_topic_buffers"]: return - buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (woeid,), buff.session, buff.account, woeid) - buffer.searchfunction = self.search - pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]) - self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (trends.get_string()), pos=pos) - self.buffers.append(buffer) - buffer.start_stream() - timer = RepeatingTimer(300, buffer.start_stream) - timer.start() - buffer.session.settings["other_buffers"]["trending_topic_buffers"].append(woeid) - buffer.session.settings.write() - - 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] - address = geocoder.reverse_geocode(y, x) - if event == None: output.speak(address[0].__str__().decode("utf-8")) - else: self.view.show_address(address[0].__str__().decode("utf-8")) - else: - output.speak(_(u"There are no coordinates in this tweet")) - except GeocoderError: - output.speak(_(u"There are no results for the coordinates in this tweet")) - except ValueError: - output.speak(_(u"Error decoding coordinates. Try again later.")) - except KeyError: - pass - except AttributeError: - pass - - 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] - address = geocoder.reverse_geocode(y, x) - dlg = commonMessageDialogs.view_geodata(address[0].__str__()) - else: - output.speak(_(u"There are no coordinates in this tweet")) - except GeocoderError: - output.speak(_(u"There are no results for the coordinates in this tweet")) - except ValueError: - output.speak(_(u"Error decoding coordinates. Try again later.")) - except KeyError: - pass - except AttributeError: - pass - - def get_more_items(self, *args, **kwargs): - self.get_current_buffer().get_more_items() - - def clear_buffer(self, *args, **kwargs): - self.get_current_buffer().clear_list() - - def remove_buffer(self, *args, **kwargs): - buffer = self.get_current_buffer() - if not hasattr(buffer, "account"): return - buff = self.view.search(buffer.name, buffer.account) - answer = buffer.remove_buffer() - if answer == False: return - if hasattr(buff, "timer"): - log.debug("Stopping timer...") - buff.timer.cancel() - log.debug("Timer cancelled.") - self.right() - self.view.delete_buffer(buff) - buffer.session.sound.play("delete_timeline.ogg") - self.buffers.remove(buffer) - del buffer - - def skip_buffer(self, forward=True): - buff = self.get_current_buffer() - if buff.invisible == False: - self.view.advance_selection(forward) - - def buffer_changed(self, *args, **kwargs): - buffer = self.get_current_buffer() - if buffer.account != self.current_account: - self.current_account = buffer.account - if not hasattr(buffer, "session") or buffer.session == None: return - muted = autoread = False - if buffer.name in buffer.session.settings["other_buffers"]["muted_buffers"]: - muted = True - elif buffer.name in buffer.session.settings["other_buffers"]["autoread_buffers"]: - autoread = True - self.view.check_menuitem("mute_buffer", muted) - self.view.check_menuitem("autoread", autoread) - - def fix_wrong_buffer(self): - buf = self.get_best_buffer() - if buf == None: - for i in self.accounts: - buffer = self.view.search("home_timeline", i) - if buffer != None: break - else: - buffer = self.view.search("home_timeline", buf.session.db["user_name"]) - if buffer!=None: - self.view.change_buffer(buffer) - - def up(self, *args, **kwargs): - page = self.get_current_buffer() - if not hasattr(page.buffer, "list"): - output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) - return - position = page.buffer.list.get_selected() - index = position-1 - try: - page.buffer.list.select_item(index) - except: - pass - if position == page.buffer.list.get_selected(): - page.session.sound.play("limit.ogg") - - try: - output.speak(page.get_message(), True) - except: - pass - - def down(self, *args, **kwargs): - page = self.get_current_buffer() - if not hasattr(page.buffer, "list"): - output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) - return - position = page.buffer.list.get_selected() - index = position+1 - try: - page.buffer.list.select_item(index) - except: - pass - if position == page.buffer.list.get_selected(): - page.session.sound.play("limit.ogg") - try: - output.speak(page.get_message(), True) - except: - pass - - def left(self, *args, **kwargs): - buff = self.view.get_current_buffer_pos() - buffer = self.get_current_buffer() - if not hasattr(buffer.buffer, "list"): - output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) - return - if buff == self.get_first_buffer(buffer.account) or buff == 0: - self.view.change_buffer(self.get_last_buffer(buffer.account)) - else: - self.view.change_buffer(buff-1) - while self.get_current_buffer().invisible == False: self.skip_buffer(False) - buffer = self.get_current_buffer() - if self.showing == True: buffer.buffer.set_focus_in_list() - try: - msg = _(u"%s, %s of %s") % (self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) - except: - msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) - output.speak(msg, True) - - def right(self, *args, **kwargs): - buff = self.view.get_current_buffer_pos() - buffer = self.get_current_buffer() - if not hasattr(buffer.buffer, "list"): - output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) - return - if buff == self.get_last_buffer(buffer.account) or buff+1 == self.view.get_buffer_count(): - self.view.change_buffer(self.get_first_buffer(buffer.account)) - else: - self.view.change_buffer(buff+1) - while self.get_current_buffer().invisible == False: self.skip_buffer(True) - buffer = self.get_current_buffer() - if self.showing == True: buffer.buffer.set_focus_in_list() - try: - msg = _(u"%s, %s of %s") % (self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) - except: - msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) - output.speak(msg, True) - - def next_account(self, *args, **kwargs): - index = self.accounts.index(self.current_account) - if index+1 == len(self.accounts): - index = 0 - else: - index = index+1 - account = self.accounts[index] - self.current_account = account - buff = self.view.search("home_timeline", account) - if buff == None: - output.speak(_(u"{0}: This account is not logged into Twitter.").format(account), True) - return - self.view.change_buffer(buff) - buffer = self.get_current_buffer() - if self.showing == True: buffer.buffer.set_focus_in_list() - try: - msg = _(u"%s. %s, %s of %s") % (buffer.account, self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) - except: - msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) - output.speak(msg, True) - - def previous_account(self, *args, **kwargs): - index = self.accounts.index(self.current_account) - if index-1 < 0: - index = len(self.accounts)-1 - else: - index = index-1 - account = self.accounts[index] - self.current_account = account - buff = self.view.search("home_timeline", account) - if buff == None: - output.speak(_(u"{0}: This account is not logged into twitter.").format(account), True) - return - self.view.change_buffer(buff) - buffer = self.get_current_buffer() - if self.showing == True: buffer.buffer.set_focus_in_list() - try: - msg = _(u"%s. %s, %s of %s") % (buffer.account, self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) - except: - msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) - output.speak(msg, True) - - def go_home(self): - buffer = self.get_current_buffer() - buffer.buffer.list.select_item(0) - try: - output.speak(buffer.get_message(), True) - except: - pass - - def go_end(self): - buffer = self.get_current_buffer() - buffer.buffer.list.select_item(buffer.buffer.list.get_count()-1) - try: - output.speak(buffer.get_message(), True) - except: - pass - - def go_page_up(self): - buffer = self.get_current_buffer() - if buffer.buffer.list.get_selected() <= 20: - index = 0 - else: - index = buffer.buffer.list.get_selected() - 20 - buffer.buffer.list.select_item(index) - try: - output.speak(buffer.get_message(), True) - except: - pass - - def go_page_down(self): - buffer = self.get_current_buffer() - if buffer.buffer.list.get_selected() >= buffer.buffer.list.get_count() - 20: - index = buffer.buffer.list.get_count()-1 - else: - index = buffer.buffer.list.get_selected() + 20 - buffer.buffer.list.select_item(index) - try: - output.speak(buffer.get_message(), True) - except: - pass - - def url(self, *args, **kwargs): - buffer = self.get_current_buffer() - buffer.url() - - def audio(self, *args, **kwargs): - self.get_current_buffer().audio() - - def volume_down(self, *args, **kwargs): - self.get_current_buffer().volume_down() - - def volume_up(self, *args, **kwargs): - self.get_current_buffer().volume_up() - - def create_invisible_keyboard_shorcuts(self): - keymap = {} - for i in config.keymap["keymap"]: - if hasattr(self, i): - keymap[config.keymap["keymap"][i]] = getattr(self, i) - return keymap - - def register_invisible_keyboard_shorcuts(self, keymap): - if config.changed_keymap: - commonMessageDialogs.changed_keymap() - self.keyboard_handler = WXKeyboardHandler(self.view) - self.keyboard_handler.register_keys(keymap) - - def unregister_invisible_keyboard_shorcuts(self, keymap): - try: - self.keyboard_handler.unregister_keys(keymap) - del self.keyboard_handler - except AttributeError: - pass - - def notify(self, session, play_sound=None, message=None, notification=False): - if session.settings["sound"]["session_mute"] == True: return - if play_sound != None: - session.sound.play(play_sound) - if message != None: - output.speak(message) - - def manage_home_timelines(self, data, user): - buffer = self.search_buffer("home_timeline", user) - if buffer == None: return - play_sound = "tweet_received.ogg" - if "home_timeline" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound) - buffer.add_new_item(data) - - def manage_mentions(self, data, user): - buffer = self.search_buffer("mentions", user) - if buffer == None: return - play_sound = "mention_received.ogg" - message = _(u"One mention from %s ") % (data["user"]["name"]) - if "mentions" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound, message=message) - buffer.add_new_item(data) - - def manage_direct_messages(self, data, user): - buffer = self.search_buffer("direct_messages", user) - if buffer == None: return - play_sound = "dm_received.ogg" - message = _(u"New direct message") - if "direct_messages" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound, message=message) - buffer.add_new_item(data) - - def manage_sent_dm(self, data, user): - buffer = self.search_buffer("sent_direct_messages", user) - 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) - buffer.add_new_item(data) - - def manage_sent_tweets(self, data, user): - buffer = self.search_buffer("sent_tweets", user) - if buffer == None: return - play_sound = "tweet_send.ogg" - if "sent_tweets" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound) - buffer.add_new_item(data) - - def manage_events(self, data, user): - buffer = self.search_buffer("events", user) - if buffer == None: return - play_sound = "new_event.ogg" - if "events" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound) - buffer.add_new_item(data) - - def manage_followers(self, data, user): - buffer = self.search_buffer("followers", user) - if buffer == None: return - play_sound = "update_followers.ogg" - if "followers" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound) - buffer.add_new_item(data) - - def manage_friend(self, data, user): - buffer = self.search_buffer("friends", user) - if buffer == None: return - buffer.add_new_item(data) - pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) - - def manage_unfollowing(self, item, user): - buffer = self.search_buffer("friends", user) - if buffer == None: return - buffer.remove_item(item) - pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) - - def manage_favourite(self, data, user): - buffer = self.search_buffer("favourites", user) - if buffer == None: return - play_sound = "favourite.ogg" - if "favourites" not in buffer.session.settings["other_buffers"]["muted_buffers"]: - self.notify(buffer.session, play_sound=play_sound) - buffer.add_new_item(data) - - def manage_unfavourite(self, item, user): - buffer = self.search_buffer("favourites", user) - if buffer == None: return - buffer.remove_item(item) - - def manage_blocked_user(self, data, user): - buffer = self.search_buffer("blocked", user) - if buffer == None: return - buffer.add_new_item(data) - pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) - - def manage_unblocked_user(self, item, user): - buffer = self.search_buffer("blocked", user) - if buffer == None: return - buffer.remove_item(item) - pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) - - def manage_item_in_timeline(self, data, user, who): - buffer = self.search_buffer("%s-timeline" % (who,), user) - if buffer == None: return - play_sound = "tweet_timeline.ogg" - if "%s-timeline" % (who,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False: - self.notify(buffer.session, play_sound=play_sound) - output.speak(_(u"One tweet from %s") % (data["user"]["name"])) - buffer.add_new_item(data) - - def manage_item_in_list(self, data, user, where): - buffer = self.search_buffer("%s" % (where,), user) - if buffer == None: return - play_sound = "list_tweet.ogg" - if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False: - self.notify(buffer.session, play_sound=play_sound) - output.speak(_(u"One tweet from %s") % (data["user"]["name"])) - buffer.add_new_item(data) - - def start_buffers(self, session): - log.debug("starting buffers... Session %s" % (session.session_id,)) - for i in self.buffers: - if i.session == session and i.needs_init == True: - if hasattr(i, "finished_timeline") and i.finished_timeline == False: - change_title = True - else: - change_title = False - try: - i.start_stream() - except TwythonAuthError: - buff = self.view.search(i.name, i.account) - i.remove_buffer(force=True) - commonMessageDialogs.blocked_timeline() - if self.get_current_buffer() == i: - self.right() - self.view.delete_buffer(buff) - self.buffers.remove(i) - del i - continue - if change_title: - pub.sendMessage("buffer-title-changed", buffer=i) - log.debug("Starting the streaming endpoint") - session.start_streaming() - - def set_positions(self): - for i in session_.sessions: - self.set_buffer_positions(i) - - def manage_stream_errors(self, session): - log.error(" Restarting %s session streams. It will be destroyed" % (session,)) - s = session_.sessions[session] - try: - if hasattr(s, "main_stream"): - s.main_stream.disconnect() - log.error("main stream disconnected") - del s.main_stream - if hasattr(s, "timelinesStream"): - s.timelinesStream.disconnect() - del s.timelinesStream - except AttributeError: - pass - s.counter = 0 -# s.listen_stream_error() - - def check_connection(self): - if self.started == False: - return - for i in session_.sessions: - try: - if session_.sessions[i].is_logged == False: continue - session_.sessions[i].check_connection() - except TwythonError: # 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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"]) - 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() - if buffer == "followers": - followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "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() - elif buffer == "friends": - friends = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "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() - elif buffer == "blocked": - blocks = buffersController.peopleBufferController(self.view.nb, "list_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() - elif buffer == "muted": - muted = buffersController.peopleBufferController(self.view.nb, "get_muted_users_list", "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() - elif buffer == "events": - events = buffersController.eventsBufferController(self.view.nb, "events", buff.session, buff.session.db["user_name"], bufferType="dmPanel", screen_name=buff.session.db["user_name"]) - self.buffers.append(events) - self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) - elif create == False: - self.destroy_buffer(buffer, buff.session.db["user_name"]) - elif buffer == "list": - if create in buff.session.settings["other_buffers"]["lists"]: - output.speak(_(u"This list is already opened"), True) - return - tl = buffersController.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"])) - buff.session.lists.append(tl) - pos=self.view.search("lists", buff.session.db["user_name"]) - self.insert_buffer(tl, pos) - self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(create), pos=self.view.search("lists", buff.session.db["user_name"])) - tl.start_stream() - buff.session.settings["other_buffers"]["lists"].append(create) - buff.session.settings.write() - pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) - - def restart_streams(self, streams=[], session=None): - for i in streams: - log.debug("Restarting the %s stream" % (i,)) - session.remove_stream(i) - session.check_connection() - - def invisible_shorcuts_changed(self, registered): - if registered == True: - km = self.create_invisible_keyboard_shorcuts() - self.register_invisible_keyboard_shorcuts(km) - elif registered == False: - km = self.create_invisible_keyboard_shorcuts() - self.unregister_invisible_keyboard_shorcuts(km) - - def about(self, *args, **kwargs): - self.view.about_dialog() - - def visit_website(self, *args, **kwargs): - webbrowser.open(application.url) - - def manage_accounts(self, *args, **kwargs): - sm = sessionManager.sessionManagerController(started=True) - sm.fill_list() - sm.show() - for i in sm.new_sessions: - self.create_buffers(session_.sessions[i]) - call_threaded(self.start_buffers, session_.sessions[i]) - for i in sm.removed_sessions: - if session_.sessions[i].logged == True: - self.logout_account(session_.sessions[i].session_id) - self.destroy_buffer(session_.sessions[i].settings["twitter"]["user_name"], session_.sessions[i].settings["twitter"]["user_name"]) - self.accounts.remove(session_.sessions[i].settings["twitter"]["user_name"]) - session_.sessions.pop(i) - - def update_profile(self, *args, **kwargs): - r = user.profileController(self.get_best_buffer().session) - - def user_details(self, *args, **kwargs): - buffer = self.get_current_buffer() - if not hasattr(buffer, "session") or buffer.session == None: return - if hasattr(buffer, "user_details"): - buffer.user_details() - - def toggle_autoread(self, *args, **kwargs): - buffer = self.get_current_buffer() - if hasattr(buffer, "session") and buffer.session == None: return - if buffer.name not in buffer.session.settings["other_buffers"]["autoread_buffers"]: - buffer.session.settings["other_buffers"]["autoread_buffers"].append(buffer.name) - output.speak(_(u"The auto-reading of new tweets is enabled for this buffer"), True) - elif buffer.name in buffer.session.settings["other_buffers"]["autoread_buffers"]: - buffer.session.settings["other_buffers"]["autoread_buffers"].remove(buffer.name) - output.speak(_(u"The auto-reading of new tweets is disabled for this buffer"), True) - buffer.session.settings.write() - - def toggle_session_mute(self, *args, **kwargs): - buffer = self.get_best_buffer() - if buffer.session.settings["sound"]["session_mute"] == False: - buffer.session.settings["sound"]["session_mute"] = True - output.speak(_(u"Session mute on"), True) - elif buffer.session.settings["sound"]["session_mute"] == True: - buffer.session.settings["sound"]["session_mute"] = False - output.speak(_(u"Session mute off"), True) - buffer.session.settings.write() - - def toggle_buffer_mute(self, *args, **kwargs): - buffer = self.get_current_buffer() - if hasattr(buffer, "session") and buffer.session == None: return - if buffer.name not in buffer.session.settings["other_buffers"]["muted_buffers"]: - buffer.session.settings["other_buffers"]["muted_buffers"].append(buffer.name) - output.speak(_(u"Buffer mute on"), True) - elif buffer.name in buffer.session.settings["other_buffers"]["muted_buffers"]: - buffer.session.settings["other_buffers"]["muted_buffers"].remove(buffer.name) - output.speak(_(u"Buffer mute off"), True) - buffer.session.settings.write() - - def view_documentation(self, *args, **kwargs): - lang = localization.get("documentation") - os.chdir("documentation/%s" % (lang,)) - webbrowser.open("manual.html") - os.chdir("../../") - - def view_changelog(self, *args, **kwargs): - lang = localization.get("documentation") - os.chdir("documentation/%s" % (lang,)) - webbrowser.open("changelog.html") - os.chdir("../../") - - def insert_buffer(self, buffer, position): - self.buffers.insert(position, buffer) - - def copy_to_clipboard(self, *args, **kwargs): - output.copy(self.get_current_buffer().get_message()) - output.speak(_(u"Copied")) - - def repeat_item(self, *args, **kwargs): - output.speak(self.get_current_buffer().get_message()) - - def execute_action(self, action): - if hasattr(self, action): - getattr(self, action)() - - def restart_streams_(self, session): - for i in self.buffers[:]: - if i.session != None and i.session.session_id == session: - try: - i.start_stream() - except TwythonAuthError: - buff = self.view.search(i.name, i.account) - i.remove_buffer(force=True) - commonMessageDialogs.blocked_timeline() - if self.get_current_buffer() == i: - self.right() - self.view.delete_buffer(buff) - self.buffers.remove(i) - del i - - def update_buffer(self, *args, **kwargs): - bf = self.get_current_buffer() - if not hasattr(bf, "start_stream"): - output.speak(_(u"Unable to update this buffer.")) - return - else: - output.speak(_(u"Updating buffer...")) - n = bf.start_stream(mandatory=True) - if n != None: - output.speak(_(u"{0} items retrieved").format(n,)) - - def on_tweet_deleted(self, data): - id = data["delete"]["status"]["id"] - for i in self.buffers: - if hasattr(i, "remove_tweet") and hasattr(i, "name"): - i.remove_tweet(id) - - def buffer_title_changed(self, buffer): - if "-timeline" in buffer.name: - title = _(u"Timeline for {}").format(buffer.username,) - elif "-favorite" in buffer.name: - title = _(u"Likes for {}").format(buffer.username,) - elif "-followers" in buffer.name: - title = _(u"Followers for {}").format(buffer.username,) - elif "-friends" in buffer.name: - title = _(u"Friends for {}").format(buffer.username,) - buffer_index = self.view.search(buffer.name, buffer.account) - self.view.set_page_title(buffer_index, title) - - def ocr_image(self, *args, **kwargs): - buffer = self.get_current_buffer() - if hasattr(buffer, "get_right_tweet") == False: - output.speak(_(u"Invalid buffer")) - return - tweet = buffer.get_tweet() - if tweet.has_key("entities") == False or tweet["entities"].has_key("media") == False: - output.speak(_(u"This tweet doesn't contain images")) - return - if len(tweet["entities"]["media"]) > 1: - image_list = [_(u"Picture {0}").format(i,) for i in xrange(0, len(tweet["entities"]["media"]))] - dialog = dialogs.urlList.urlList(title=_(u"Select the picture")) - if dialog.get_response() == widgetUtils.OK: - img = tweet["entities"]["media"][dialog.get_item()] - else: - return - else: - img = tweet["entities"]["media"][0] - if buffer.session.settings["mysc"]["ocr_language"] != "": - ocr_lang = buffer.session.settings["mysc"]["ocr_language"] - else: - ocr_lang = ocr.OCRSpace.short_langs.index(tweet["lang"]) - ocr_lang = ocr.OCRSpace.OcrLangs[ocr_lang] - api = ocr.OCRSpace.OCRSpaceAPI() - try: - text = api.OCR_URL(img["media_url"], lang=ocr_lang) - except ocr.OCRSpace.APIError as er: - output.speak(_(u"Unable to extract text")) - return - msg = messages.viewTweet(text["ParsedText"], [], False) - - def save_data_in_db(self): - for i in session_.sessions: +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import platform +system = platform.system() +import application +if system == "Windows": + from update import updater + from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon) + from . import settings + from extra import SoundsTutorial, ocr + import keystrokeEditor + from keyboard_handler.wx_handler import WXKeyboardHandler + from . import userActionsController + from . import trendingTopics + from . import user + from . import listsController +# from issueReporter import issueReporter +elif system == "Linux": + from gtkUI import (view, commonMessageDialogs) +from twitter import utils, compose +from sessionmanager import manager, sessionManager + +from . import buffersController +from . import messages +from sessionmanager import session as session_ +from pubsub import pub +import sound +import output +from twython import TwythonError, TwythonAuthError +from mysc.thread_utils import call_threaded +from mysc.repeating_timer import RepeatingTimer +from mysc import restart +import config +import widgetUtils +import pygeocoder +from pygeolib import GeocoderError +import logging +import webbrowser +from mysc import localization +import os + +log = logging.getLogger("mainController") + +geocoder = pygeocoder.Geocoder() + +class Controller(object): + + """ Main Controller for TWBlue. It manages the main window and sessions.""" + + def search_buffer(self, name_, user): + + """ Searches a buffer. + name_ str: The name for the buffer + user str: The account for the buffer. + for example you may want to search the home_timeline buffer for the tw_blue2 user. + returns buffersController.buffer object with the result if there is one.""" + for i in self.buffers: + if i.name == name_ and i.account == user: return i + + def get_current_buffer(self): + """ Get the current bufferObject""" + buffer = self.view.get_current_buffer() + if hasattr(buffer, "account"): + buffer = self.search_buffer(buffer.name, buffer.account) + return buffer + + def get_best_buffer(self): + """ Gets the best buffer for doing something using the session object. + This function is useful when you need to open a timeline or post a tweet, and the user is in a buffer without a session, for example the events buffer. + This returns a bufferObject.""" + # Gets the parent buffer to know what account is doing an action + view_buffer = self.view.get_current_buffer() + # If the account has no session attached, we will need to search the home_timeline for that account to use its session. + if view_buffer.type == "account" or view_buffer.type == "empty": + buffer = self.search_buffer("home_timeline", view_buffer.account) + else: + buffer = self.search_buffer(view_buffer.name, view_buffer.account) + if buffer != None: return buffer + + def get_first_buffer(self, account): + """ Gets the first valid buffer for an account. + account str: A twitter username. + The first valid buffer is the home timeline.""" + for i in self.buffers: + if i.account == account and i.invisible == True: + buff = i + break + return self.view.search(buff.name, buff.account) + + def get_last_buffer(self, account): + """ Gets the last valid buffer for an account. + account str: A twitter username. + The last valid buffer is the last buffer that contains a session object assigned.""" +# results = self.get_buffers_for_account(account) + results = self.get_buffers_for_account(account) + return self.view.search(results[-1].name, results[-1].account) + + def get_buffers_for_account(self, account): + results = [] + buffers = self.view.get_buffers() + [results.append(self.search_buffer(i.name, i.account)) for i in buffers if i.account == account and (i.type != "account")] + return results + + def bind_stream_events(self): + """ Binds all the streaming events with their functions.""" + log.debug("Binding events for the Twitter stream API...") + pub.subscribe(self.manage_home_timelines, "item-in-home") + pub.subscribe(self.manage_mentions, "mention") + pub.subscribe(self.manage_direct_messages, "direct-message") + pub.subscribe(self.manage_sent_dm, "sent-dm") + pub.subscribe(self.manage_sent_tweets, "sent-tweet") + pub.subscribe(self.manage_events, "event") + pub.subscribe(self.manage_followers, "follower") + pub.subscribe(self.manage_friend, "friend") + pub.subscribe(self.manage_unfollowing, "unfollowing") + pub.subscribe(self.manage_favourite, "favourite") + pub.subscribe(self.manage_unfavourite, "unfavourite") + pub.subscribe(self.manage_blocked_user, "blocked-user") + pub.subscribe(self.manage_unblocked_user, "unblocked-user") + pub.subscribe(self.manage_item_in_timeline, "item-in-timeline") + pub.subscribe(self.manage_item_in_list, "item-in-list") + pub.subscribe(self.restart_streams_, "restart_streams") + pub.subscribe(self.on_tweet_deleted, "tweet-deleted") + pub.subscribe(self.buffer_title_changed, "buffer-title-changed") + widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit_) + + def bind_other_events(self): + """ Binds the local application events with their functions.""" + log.debug("Binding other application events...") + pub.subscribe(self.logout_account, "logout") + pub.subscribe(self.login_account, "login") + pub.subscribe(self.manage_stream_errors, "stream-error") + pub.subscribe(self.create_new_buffer, "create-new-buffer") + pub.subscribe(self.restart_streams, "restart-streams") + pub.subscribe(self.execute_action, "execute-action") + pub.subscribe(self.search_topic, "search") + if system == "Windows": + pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed") + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.search, menuitem=self.view.menuitem_search) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.list_manager, menuitem=self.view.lists) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_trending_topics, menuitem=self.view.trends) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.find, menuitem=self.view.find) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.accountConfiguration, menuitem=self.view.account_settings) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.configuration, menuitem=self.view.prefs) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.ocr_image, menuitem=self.view.ocr) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.learn_sounds, menuitem=self.view.sounds_tutorial) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.exit, menuitem=self.view.close) + widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit) + if widgetUtils.toolkit == "wx": + log.debug("Binding the exit function...") + widgetUtils.connectExitFunction(self.exit_) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.edit_keystrokes, menuitem=self.view.keystroke_editor) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_tweet, self.view.compose) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_reply, self.view.reply) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_retweet, self.view.retweet) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_favourites, self.view.fav) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.unfav) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.reverse_geocode, menuitem=self.view.view_coordinates) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.follow, menuitem=self.view.follow) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.send_dm, self.view.dm) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_more_items, menuitem=self.view.load_previous_items) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.clear_buffer, menuitem=self.view.clear) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_buffer, self.view.deleteTl) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.check_for_updates, self.view.check_for_updates) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.about, menuitem=self.view.about) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.visit_website, menuitem=self.view.visit_website) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.manage_accounts, self.view.manage_accounts) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_profile, menuitem=self.view.updateProfile) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.user_details, menuitem=self.view.details) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.toggle_autoread, menuitem=self.view.autoread) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.toggle_buffer_mute, self.view.mute_buffer) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.open_timeline, self.view.timeline) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.open_favs_timeline, self.view.favs) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.open_conversation, menuitem=self.view.view_conversation) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.seekLeft, menuitem=self.view.seekLeft) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.seekRight, menuitem=self.view.seekRight) + if widgetUtils.toolkit == "wx": + widgetUtils.connect_event(self.view.nb, widgetUtils.NOTEBOOK_PAGE_CHANGED, self.buffer_changed) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.report_error, self.view.reportError) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_documentation, self.view.doc) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_changelog, self.view.changelog) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_list, self.view.addToList) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_list, self.view.removeFromList) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_buffer, self.view.update_buffer) + + def set_systray_icon(self): + self.systrayIcon = sysTrayIcon.SysTrayIcon() + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.post_tweet, menuitem=self.systrayIcon.tweet) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.configuration, menuitem=self.systrayIcon.global_settings) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.accountConfiguration, menuitem=self.systrayIcon.account_settings) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.update_profile, menuitem=self.systrayIcon.update_profile) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.show_hide, menuitem=self.systrayIcon.show_hide) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.check_for_updates, menuitem=self.systrayIcon.check_for_updates) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.view_documentation, menuitem=self.systrayIcon.doc) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.exit, menuitem=self.systrayIcon.exit) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_LEFT_CLICK, self.taskbar_left_click) + widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_RIGHT_CLICK, self.taskbar_right_click) + + def taskbar_left_click(self, *args, **kwargs): + if self.showing == True: + self.view.set_focus() + else: + self.show_hide() + + def taskbar_right_click(self, *args, **kwargs): + self.systrayIcon.show_menu() + + def __init__(self): + super(Controller, self).__init__() + # Visibility state. + self.showing = True + # main window + self.view = view.mainFrame() + # buffers list. + self.buffers = [] + self.started = False + # accounts list. + self.accounts = [] + # This saves the current account (important in invisible mode) + self.current_account = "" + self.view.prepare() + self.bind_stream_events() + self.bind_other_events() + if system == "Windows": + self.set_systray_icon() + + def check_invisible_at_startup(self): + # Visibility check. It does only work for windows. + if system != "Windows": return + if config.app["app-settings"]["hide_gui"] == True: + self.show_hide() + self.view.Show() + self.view.Hide() + # Invisible keyboard Shorcuts check. + if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == True: + km = self.create_invisible_keyboard_shorcuts() + self.register_invisible_keyboard_shorcuts(km) + + def do_work(self): + """ Creates the buffer objects for all accounts. This does not starts the buffer streams, only creates the objects.""" + log.debug("Creating buffers for all sessions...") + for i in session_.sessions: + log.debug("Working on session %s" % (i,)) + if session_.sessions[i].is_logged == False: + self.create_ignored_session_buffer(session_.sessions[i]) + continue + self.create_buffers(session_.sessions[i]) + + # Connection checker executed each minute. + self.checker_function = RepeatingTimer(60, self.check_connection) + self.checker_function.start() + self.save_db = RepeatingTimer(300, self.save_data_in_db) + self.save_db.start() + + def start(self): + """ Starts all buffer objects. Loads their items.""" + for i in session_.sessions: + if session_.sessions[i].is_logged == False: continue + self.start_buffers(session_.sessions[i]) + self.set_buffer_positions(session_.sessions[i]) + if config.app["app-settings"]["play_ready_sound"] == True: + session_.sessions[session_.sessions.keys()[0]].sound.play("ready.ogg") + if config.app["app-settings"]["speak_ready_msg"] == True: + output.speak(_(u"Ready")) + self.started = True + + def create_ignored_session_buffer(self, session): + self.accounts.append(session.settings["twitter"]["user_name"]) + account = buffersController.accountPanel(self.view.nb, session.settings["twitter"]["user_name"], session.settings["twitter"]["user_name"], session.session_id) + account.logged = False + account.setup_account() + self.buffers.append(account) + self.view.add_buffer(account.buffer , name=session.settings["twitter"]["user_name"]) + + def login_account(self, session_id): + for i in session_.sessions: + if session_.sessions[i].session_id == session_id: session = session_.sessions[i] + session.login() + session.db = dict() + self.create_buffers(session, False) + self.start_buffers(session) + + def create_buffers(self, session, createAccounts=True): + """ Generates buffer objects for an user account. + session SessionObject: a sessionmanager.session.Session Object""" + session.get_user_info() + if createAccounts == True: + self.accounts.append(session.db["user_name"]) + account = buffersController.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"], session.session_id) + account.setup_account() + self.buffers.append(account) + self.view.add_buffer(account.buffer , name=session.db["user_name"]) + for i in session.settings['general']['buffer_order']: + if i == 'home': + home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], 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 = buffersController.baseBufferController(self.view.nb, "get_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 = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_dm", sound="dm_received.ogg", full_text=True) + 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': + sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_dm", full_text=True) + 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 = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], bufferType="dmPanel", 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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], 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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], 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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "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 = buffersController.peopleBufferController(self.view.nb, "list_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 = buffersController.peopleBufferController(self.view.nb, "list_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"])) + elif i == 'events': + events = buffersController.eventsBufferController(self.view.nb, "events", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"]) + self.buffers.append(events) + self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) + timelines = buffersController.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 = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], 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 = buffersController.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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, 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"])) + tl.timer = RepeatingTimer(300, tl.start_stream) + tl.timer.start() + followers_timelines = buffersController.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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], 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"])) + tl.timer = RepeatingTimer(300, tl.start_stream) + tl.timer.start() + friends_timelines = buffersController.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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], 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"])) + tl.timer = RepeatingTimer(300, tl.start_stream) + tl.timer.start() + lists = buffersController.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 = buffersController.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, 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"])) + searches = buffersController.emptyPanel(self.view.nb, "searches", session.db["user_name"]) + self.buffers.append(searches) + self.view.insert_buffer(searches.buffer , name=_(u"Searches"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) + for i in session.settings["other_buffers"]["tweet_searches"]: + tl = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", q=i, tweet_mode="extended") + self.buffers.append(tl) + self.view.insert_buffer(tl.buffer, name=_(u"Search for {}").format(i), pos=self.view.search("searches", session.db["user_name"])) + tl.timer = RepeatingTimer(180, tl.start_stream) + tl.timer.start() + for i in session.settings["other_buffers"]["trending_topic_buffers"]: + buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i) + buffer.start_stream() + buffer.searchfunction = self.search + self.buffers.append(buffer) + buffer.timer = RepeatingTimer(300, buffer.start_stream) + buffer.timer.start() + self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"])) + + def set_buffer_positions(self, session): + "Sets positions for buffers if values exist in the database." + for i in self.buffers: + if i.account == session.db["user_name"] and i.name+"_pos" in session.db and hasattr(i.buffer,'list'): + i.buffer.list.select_item(session.db[str(i.name+"_pos")]) + + def logout_account(self, session_id): + for i in session_.sessions: + if session_.sessions[i].session_id == session_id: session = session_.sessions[i] + user = session.db["user_name"] + delete_buffers = [] + for i in self.buffers: + if i.account == user and i.name != user: + delete_buffers.append(i.name) + for i in delete_buffers: + self.destroy_buffer(i, user) + session.db = None + + def destroy_buffer(self, buffer_name, account): + buffer = self.search_buffer(buffer_name, account) + if buffer == None: return + buff = self.view.search(buffer.name, buffer.account) + if buff == None: return + self.view.delete_buffer(buff) + self.buffers.remove(buffer) + del buffer + + def search_topic(self, term): + self.search(value=term) + + def search(self, event=None, value="", *args, **kwargs): + """ Searches words or users in twitter. This creates a new buffer containing the search results.""" + log.debug("Creating a new search...") + dlg = dialogs.search.searchDialog(value) + if dlg.get_response() == widgetUtils.OK and dlg.get("term") != "": + term = dlg.get("term") + buffer = self.get_best_buffer() + if dlg.get("tweets") == True: + if term not in buffer.session.settings["other_buffers"]["tweet_searches"]: + buffer.session.settings["other_buffers"]["tweet_searches"].append(term) + buffer.session.settings.write() + args = {"lang": dlg.get_language(), "result_type": dlg.get_result_type()} + search = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", q=term, **args) + else: + log.error("A buffer for the %s search term is already created. You can't create a duplicate buffer." % (term,)) + return + elif dlg.get("users") == True: + search = buffersController.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, q=term) + search.start_stream(mandatory=True) + pos=self.view.search("searches", buffer.session.db["user_name"]) + self.insert_buffer(search, pos) + self.view.insert_buffer(search.buffer, name=_(u"Search for {}").format(term), pos=pos) + search.timer = RepeatingTimer(180, search.start_stream) + search.timer.start() + dlg.Destroy() + + def find(self, *args, **kwargs): + if 'string' in kwargs: + string=kwargs['string'] + else: + string='' + dlg = dialogs.find.findDialog(string) + if dlg.get_response() == widgetUtils.OK and dlg.get("string") != "": + string = dlg.get("string") + #If we still have an empty string for some reason (I.E. user clicked cancel, etc), return here. + if string == '': + log.debug("Find canceled.") + return + page = self.get_current_buffer() + if not hasattr(page.buffer, "list"): + output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) + return + count = page.buffer.list.get_count() + if count < 1: + output.speak(_(u"Empty buffer."), True) + return + start = page.buffer.list.get_selected() + for i in xrange(start,count): + page.buffer.list.select_item(i) + if string.lower() in page.get_message().lower(): + return output.speak(page.get_message(), True) + output.speak(_(u"{0} not found.").format(string,), True) + page.buffer.list.select_item(start) + + def seekLeft(self, *args, **kwargs): + try: + sound.URLPlayer.seek(-5) + except: + output.speak("Unable to seek.",True) + + def seekRight(self, *args, **kwargs): + try: + sound.URLPlayer.seek(5) + except: + output.speak("Unable to seek.",True) + + def edit_keystrokes(self, *args, **kwargs): + editor = keystrokeEditor.KeystrokeEditor() + if editor.changed == True: + config.keymap.write() + register = False + # determines if we need to reassign the keymap. + if self.showing == False: + register = True + elif config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == True: + register = True + # If there is a keyboard handler instance we need unregister all old keystrokes before register the new ones. + if hasattr(self, "keyboard_handler"): + keymap = {} + for i in editor.hold_map: + if hasattr(self, i): keymap[editor.hold_map[i]] = getattr(self, i) + self.unregister_invisible_keyboard_shorcuts(keymap) + self.invisible_shorcuts_changed(registered=register) + + def learn_sounds(self, *args, **kwargs): + """ Opens the sounds tutorial for the current account.""" + buffer = self.get_best_buffer() + SoundsTutorial.soundsTutorial(buffer.session) + + def view_user_lists(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 = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) + if dlg.get_response() == widgetUtils.OK: + user = dlg.get_user() + else: + return + l = listsController.listsController(buff.session, user=user) + + def add_to_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 = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) + if dlg.get_response() == widgetUtils.OK: + user = dlg.get_user() + else: + return + dlg = dialogs.lists.addUserListDialog() + 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.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) + if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) + except TwythonError as e: + output.speak("error %s: %s" % (e.error_code, e.msg)) + + 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 = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users) + if dlg.get_response() == widgetUtils.OK: + user = dlg.get_user() + else: + return + dlg = dialogs.lists.removeUserListDialog() + 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.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"]) + if listBuffer != None: listBuffer.get_user_ids() + buff.session.db["lists"].pop(older_list) + buff.session.db["lists"].append(list) + if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) + except TwythonError as e: + output.speak("error %s: %s" % (e.error_code, e.msg)) + + def list_manager(self, *args, **kwargs): + s = self.get_best_buffer().session + l = listsController.listsController(s) + + def configuration(self, *args, **kwargs): + """ Opens the global settings dialogue.""" + d = settings.globalSettingsController() + if d.response == widgetUtils.OK: + d.save_configuration() + if d.needs_restart == True: + commonMessageDialogs.needs_restart() + restart.restart_program() + + def accountConfiguration(self, *args, **kwargs): + """ Opens the account settings dialogue for the current account.""" + buff = self.get_best_buffer() + manager.manager.set_current_session(buff.session.session_id) + d = settings.accountSettingsController(buff, self) + if d.response == widgetUtils.OK: + d.save_configuration() + if d.needs_restart == True: + commonMessageDialogs.needs_restart() + buff.session.settings.write() + restart.restart_program() + + def report_error(self, *args, **kwargs): + r = issueReporter.reportBug(self.get_best_buffer().session.db["user_name"]) + + def check_for_updates(self, *args, **kwargs): + update = updater.do_update() + if update == False: + view.no_update_available() + + def delete(self, *args, **kwargs): + """ Deletes an item in the current buffer. + Users can only remove their tweets and direct messages, other users' tweets and people (followers, friends, blocked, etc) can not be removed using this method.""" + buffer = self.view.get_current_buffer() + if hasattr(buffer, "account"): + buffer = self.search_buffer(buffer.name, buffer.account) + buffer.destroy_status() + + def exit(self, *args, **kwargs): + if config.app["app-settings"]["ask_at_exit"] == True: + answer = commonMessageDialogs.exit_dialog(self.view) + if answer == widgetUtils.YES: + self.exit_() + else: + self.exit_() + + def exit_(self, *args, **kwargs): + for i in self.buffers: i.save_positions() + log.debug("Exiting...") + log.debug("Saving global configuration...") + for item in session_.sessions: + if session_.sessions[item].logged == False: continue + log.debug("Disconnecting streams for %s session" % (session_.sessions[item].session_id,)) + if hasattr(session_.sessions[item], "main_stream"): session_.sessions[item].main_stream.disconnect() + if hasattr(session_.sessions[item], "timelinesStream"): session_.sessions[item].timelinesStream.disconnect() + session_.sessions[item].sound.cleaner.cancel() + log.debug("Shelving database for " + session_.sessions[item].session_id) + session_.sessions[item].shelve() + + if system == "Windows": + self.systrayIcon.RemoveIcon() + widgetUtils.exit_application() + + def follow(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users) + + def unfollow(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users, "unfollow") + + def mute(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users, "mute") + + def unmute(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users, "unmute") + + def block(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users, "block") + + def unblock(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users, "unblock") + + def report(self, *args, **kwargs): + buff = self.get_current_buffer() + if not hasattr(buff, "get_right_tweet"): return + tweet = buff.get_right_tweet() + if buff.type != "people": + users = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + u = userActionsController.userActionsController(buff, users, "report") + + def post_tweet(self, event=None): + buffer = self.get_best_buffer() + buffer.post_tweet() + + def post_reply(self, *args, **kwargs): + buffer = self.get_current_buffer() + if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return + elif buffer.name == "direct_messages": + buffer.direct_message() + else: + buffer.reply() + + def send_dm(self, *args, **kwargs): + buffer = self.get_current_buffer() + if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return + else: + buffer.direct_message() + + def post_retweet(self, *args, **kwargs): + buffer = self.get_current_buffer() + if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": + return + else: + buffer.retweet() + + def add_to_favourites(self, *args, **kwargs): + buffer = self.get_current_buffer() + if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": + return + else: + 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): + buffer = self.get_current_buffer() + if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events": + return + else: + id = buffer.get_tweet()["id"] + call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id) + + def view_item(self, *args, **kwargs): + buffer = self.get_current_buffer() + if buffer.type == "baseBuffer" or buffer.type == "favourites_timeline" or buffer.type == "list" or buffer.type == "search": + tweet, tweetsList = buffer.get_full_tweet() + msg = messages.viewTweet(tweet, tweetsList) + elif buffer.type == "account" or buffer.type == "empty": + return + elif buffer.name == "sent_tweets": + tweet, tweetsList = buffer.get_full_tweet() + msg = messages.viewTweet(tweet, tweetsList) + else: + non_tweet = buffer.get_formatted_message() + msg = messages.viewTweet(non_tweet, [], False) + + def open_favs_timeline(self, *args, **kwargs): + self.open_timeline(default="favourites") + + def open_timeline(self, default="tweets", *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 = utils.get_all_users(tweet, buff.session.db) + else: + users = [tweet["screen_name"]] + dlg = dialogs.userSelection.selectUserDialog(users=users, default=default) + if dlg.get_response() == widgetUtils.OK: + usr = utils.if_user_exists(buff.session.twitter.twitter, dlg.get_user()) + if usr != None: + if usr == dlg.get_user(): + commonMessageDialogs.suspended_user() + return + if usr["protected"] == True: + if usr["following"] == False: + commonMessageDialogs.no_following() + return + answer = commonMessageDialogs.protected_user() + if answer == widgetUtils.NO: return + tl_type = dlg.get_action() + if tl_type == "tweets": + if usr["statuses_count"] == 0: + commonMessageDialogs.no_tweets() + return + if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]: + commonMessageDialogs.timeline_exist() + return + tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, user_id=usr["id_str"], tweet_mode="extended") + try: + tl.start_stream() + except TwythonAuthError: + 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"]) + pub.sendMessage("buffer-title-changed", buffer=tl) + pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) + buff.session.sound.play("create_timeline.ogg") + elif tl_type == "favourites": + if usr["favourites_count"] == 0: + commonMessageDialogs.no_favs() + return + if usr["id_str"] in buff.session.settings["other_buffers"]["favourites_timelines"]: + commonMessageDialogs.timeline_exist() + return + tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, user_id=usr["id_str"], tweet_mode="extended") + try: + tl.start_stream() + except TwythonAuthError: + 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) + tl.timer = RepeatingTimer(300, tl.start_stream) + tl.timer.start() + buff.session.settings["other_buffers"]["favourites_timelines"].append(usr["id_str"]) + pub.sendMessage("buffer-title-changed", buffer=i) + buff.session.sound.play("create_timeline.ogg") + elif tl_type == "followers": + if usr["followers_count"] == 0: + commonMessageDialogs.no_followers() + return + if usr["id_str"] in buff.session.settings["other_buffers"]["followers_timelines"]: + commonMessageDialogs.timeline_exist() + return + tl = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], user_id=usr["id_str"]) + try: + tl.start_stream() + except TwythonAuthError: + 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) + tl.timer = RepeatingTimer(300, tl.start_stream) + tl.timer.start() + 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: + commonMessageDialogs.no_friends() + return + if usr["id_str"] in buff.session.settings["other_buffers"]["friends_timelines"]: + commonMessageDialogs.timeline_exist() + return + tl = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], user_id=usr["id_str"]) + try: + tl.start_stream() + except TwythonAuthError: + 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) + tl.timer = RepeatingTimer(300, tl.start_stream) + tl.timer.start() + 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: + commonMessageDialogs.user_not_exist() + buff.session.settings.write() + + 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"] + search = buffersController.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", since_id=id, q="@{0}".format(user,)) + search.tweet = buffer.get_right_tweet() + search.start_stream(start=True) + pos=self.view.search("searches", buffer.session.db["user_name"]) +# self.buffers.append(search) + self.insert_buffer(search, pos) + self.view.insert_buffer(search.buffer, name=_(u"Conversation with {0}").format(user), pos=pos) + search.timer = RepeatingTimer(300, search.start_stream) + search.timer.start() + + def show_hide(self, *args, **kwargs): + km = self.create_invisible_keyboard_shorcuts() + if self.showing == True: + if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == False: + self.register_invisible_keyboard_shorcuts(km) + self.view.Hide() + self.fix_wrong_buffer() + self.showing = False + else: + if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == False: + self.unregister_invisible_keyboard_shorcuts(km) + self.view.Show() + self.showing = True + + def get_trending_topics(self, *args, **kwargs): + buff = self.get_best_buffer() + trends = trendingTopics.trendingTopicsController(buff.session) + if trends.dialog.get_response() == widgetUtils.OK: + woeid = trends.get_woeid() + if woeid in buff.session.settings["other_buffers"]["trending_topic_buffers"]: return + buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (woeid,), buff.session, buff.account, woeid) + buffer.searchfunction = self.search + pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]) + self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (trends.get_string()), pos=pos) + self.buffers.append(buffer) + buffer.start_stream() + timer = RepeatingTimer(300, buffer.start_stream) + timer.start() + buffer.session.settings["other_buffers"]["trending_topic_buffers"].append(woeid) + buffer.session.settings.write() + + 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] + address = geocoder.reverse_geocode(y, x) + if event == None: output.speak(address[0].__str__().decode("utf-8")) + else: self.view.show_address(address[0].__str__().decode("utf-8")) + else: + output.speak(_(u"There are no coordinates in this tweet")) + except GeocoderError: + output.speak(_(u"There are no results for the coordinates in this tweet")) + except ValueError: + output.speak(_(u"Error decoding coordinates. Try again later.")) + except KeyError: + pass + except AttributeError: + pass + + 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] + address = geocoder.reverse_geocode(y, x) + dlg = commonMessageDialogs.view_geodata(address[0].__str__()) + else: + output.speak(_(u"There are no coordinates in this tweet")) + except GeocoderError: + output.speak(_(u"There are no results for the coordinates in this tweet")) + except ValueError: + output.speak(_(u"Error decoding coordinates. Try again later.")) + except KeyError: + pass + except AttributeError: + pass + + def get_more_items(self, *args, **kwargs): + self.get_current_buffer().get_more_items() + + def clear_buffer(self, *args, **kwargs): + self.get_current_buffer().clear_list() + + def remove_buffer(self, *args, **kwargs): + buffer = self.get_current_buffer() + if not hasattr(buffer, "account"): return + buff = self.view.search(buffer.name, buffer.account) + answer = buffer.remove_buffer() + if answer == False: return + if hasattr(buff, "timer"): + log.debug("Stopping timer...") + buff.timer.cancel() + log.debug("Timer cancelled.") + self.right() + self.view.delete_buffer(buff) + buffer.session.sound.play("delete_timeline.ogg") + self.buffers.remove(buffer) + del buffer + + def skip_buffer(self, forward=True): + buff = self.get_current_buffer() + if buff.invisible == False: + self.view.advance_selection(forward) + + def buffer_changed(self, *args, **kwargs): + buffer = self.get_current_buffer() + if buffer.account != self.current_account: + self.current_account = buffer.account + if not hasattr(buffer, "session") or buffer.session == None: return + muted = autoread = False + if buffer.name in buffer.session.settings["other_buffers"]["muted_buffers"]: + muted = True + elif buffer.name in buffer.session.settings["other_buffers"]["autoread_buffers"]: + autoread = True + self.view.check_menuitem("mute_buffer", muted) + self.view.check_menuitem("autoread", autoread) + + def fix_wrong_buffer(self): + buf = self.get_best_buffer() + if buf == None: + for i in self.accounts: + buffer = self.view.search("home_timeline", i) + if buffer != None: break + else: + buffer = self.view.search("home_timeline", buf.session.db["user_name"]) + if buffer!=None: + self.view.change_buffer(buffer) + + def up(self, *args, **kwargs): + page = self.get_current_buffer() + if not hasattr(page.buffer, "list"): + output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) + return + position = page.buffer.list.get_selected() + index = position-1 + try: + page.buffer.list.select_item(index) + except: + pass + if position == page.buffer.list.get_selected(): + page.session.sound.play("limit.ogg") + + try: + output.speak(page.get_message(), True) + except: + pass + + def down(self, *args, **kwargs): + page = self.get_current_buffer() + if not hasattr(page.buffer, "list"): + output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) + return + position = page.buffer.list.get_selected() + index = position+1 + try: + page.buffer.list.select_item(index) + except: + pass + if position == page.buffer.list.get_selected(): + page.session.sound.play("limit.ogg") + try: + output.speak(page.get_message(), True) + except: + pass + + def left(self, *args, **kwargs): + buff = self.view.get_current_buffer_pos() + buffer = self.get_current_buffer() + if not hasattr(buffer.buffer, "list"): + output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) + return + if buff == self.get_first_buffer(buffer.account) or buff == 0: + self.view.change_buffer(self.get_last_buffer(buffer.account)) + else: + self.view.change_buffer(buff-1) + while self.get_current_buffer().invisible == False: self.skip_buffer(False) + buffer = self.get_current_buffer() + if self.showing == True: buffer.buffer.set_focus_in_list() + try: + msg = _(u"%s, %s of %s") % (self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) + except: + msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) + output.speak(msg, True) + + def right(self, *args, **kwargs): + buff = self.view.get_current_buffer_pos() + buffer = self.get_current_buffer() + if not hasattr(buffer.buffer, "list"): + output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True) + return + if buff == self.get_last_buffer(buffer.account) or buff+1 == self.view.get_buffer_count(): + self.view.change_buffer(self.get_first_buffer(buffer.account)) + else: + self.view.change_buffer(buff+1) + while self.get_current_buffer().invisible == False: self.skip_buffer(True) + buffer = self.get_current_buffer() + if self.showing == True: buffer.buffer.set_focus_in_list() + try: + msg = _(u"%s, %s of %s") % (self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) + except: + msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) + output.speak(msg, True) + + def next_account(self, *args, **kwargs): + index = self.accounts.index(self.current_account) + if index+1 == len(self.accounts): + index = 0 + else: + index = index+1 + account = self.accounts[index] + self.current_account = account + buff = self.view.search("home_timeline", account) + if buff == None: + output.speak(_(u"{0}: This account is not logged into Twitter.").format(account), True) + return + self.view.change_buffer(buff) + buffer = self.get_current_buffer() + if self.showing == True: buffer.buffer.set_focus_in_list() + try: + msg = _(u"%s. %s, %s of %s") % (buffer.account, self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) + except: + msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) + output.speak(msg, True) + + def previous_account(self, *args, **kwargs): + index = self.accounts.index(self.current_account) + if index-1 < 0: + index = len(self.accounts)-1 + else: + index = index-1 + account = self.accounts[index] + self.current_account = account + buff = self.view.search("home_timeline", account) + if buff == None: + output.speak(_(u"{0}: This account is not logged into twitter.").format(account), True) + return + self.view.change_buffer(buff) + buffer = self.get_current_buffer() + if self.showing == True: buffer.buffer.set_focus_in_list() + try: + msg = _(u"%s. %s, %s of %s") % (buffer.account, self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count()) + except: + msg = _(u"%s. Empty") % (self.view.get_buffer_text(),) + output.speak(msg, True) + + def go_home(self): + buffer = self.get_current_buffer() + buffer.buffer.list.select_item(0) + try: + output.speak(buffer.get_message(), True) + except: + pass + + def go_end(self): + buffer = self.get_current_buffer() + buffer.buffer.list.select_item(buffer.buffer.list.get_count()-1) + try: + output.speak(buffer.get_message(), True) + except: + pass + + def go_page_up(self): + buffer = self.get_current_buffer() + if buffer.buffer.list.get_selected() <= 20: + index = 0 + else: + index = buffer.buffer.list.get_selected() - 20 + buffer.buffer.list.select_item(index) + try: + output.speak(buffer.get_message(), True) + except: + pass + + def go_page_down(self): + buffer = self.get_current_buffer() + if buffer.buffer.list.get_selected() >= buffer.buffer.list.get_count() - 20: + index = buffer.buffer.list.get_count()-1 + else: + index = buffer.buffer.list.get_selected() + 20 + buffer.buffer.list.select_item(index) + try: + output.speak(buffer.get_message(), True) + except: + pass + + def url(self, *args, **kwargs): + buffer = self.get_current_buffer() + buffer.url() + + def audio(self, *args, **kwargs): + self.get_current_buffer().audio() + + def volume_down(self, *args, **kwargs): + self.get_current_buffer().volume_down() + + def volume_up(self, *args, **kwargs): + self.get_current_buffer().volume_up() + + def create_invisible_keyboard_shorcuts(self): + keymap = {} + for i in config.keymap["keymap"]: + if hasattr(self, i): + keymap[config.keymap["keymap"][i]] = getattr(self, i) + return keymap + + def register_invisible_keyboard_shorcuts(self, keymap): + if config.changed_keymap: + commonMessageDialogs.changed_keymap() + self.keyboard_handler = WXKeyboardHandler(self.view) + self.keyboard_handler.register_keys(keymap) + + def unregister_invisible_keyboard_shorcuts(self, keymap): + try: + self.keyboard_handler.unregister_keys(keymap) + del self.keyboard_handler + except AttributeError: + pass + + def notify(self, session, play_sound=None, message=None, notification=False): + if session.settings["sound"]["session_mute"] == True: return + if play_sound != None: + session.sound.play(play_sound) + if message != None: + output.speak(message) + + def manage_home_timelines(self, data, user): + buffer = self.search_buffer("home_timeline", user) + if buffer == None: return + play_sound = "tweet_received.ogg" + if "home_timeline" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound) + buffer.add_new_item(data) + + def manage_mentions(self, data, user): + buffer = self.search_buffer("mentions", user) + if buffer == None: return + play_sound = "mention_received.ogg" + message = _(u"One mention from %s ") % (data["user"]["name"]) + if "mentions" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound, message=message) + buffer.add_new_item(data) + + def manage_direct_messages(self, data, user): + buffer = self.search_buffer("direct_messages", user) + if buffer == None: return + play_sound = "dm_received.ogg" + message = _(u"New direct message") + if "direct_messages" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound, message=message) + buffer.add_new_item(data) + + def manage_sent_dm(self, data, user): + buffer = self.search_buffer("sent_direct_messages", user) + 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) + buffer.add_new_item(data) + + def manage_sent_tweets(self, data, user): + buffer = self.search_buffer("sent_tweets", user) + if buffer == None: return + play_sound = "tweet_send.ogg" + if "sent_tweets" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound) + buffer.add_new_item(data) + + def manage_events(self, data, user): + buffer = self.search_buffer("events", user) + if buffer == None: return + play_sound = "new_event.ogg" + if "events" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound) + buffer.add_new_item(data) + + def manage_followers(self, data, user): + buffer = self.search_buffer("followers", user) + if buffer == None: return + play_sound = "update_followers.ogg" + if "followers" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound) + buffer.add_new_item(data) + + def manage_friend(self, data, user): + buffer = self.search_buffer("friends", user) + if buffer == None: return + buffer.add_new_item(data) + pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) + + def manage_unfollowing(self, item, user): + buffer = self.search_buffer("friends", user) + if buffer == None: return + buffer.remove_item(item) + pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) + + def manage_favourite(self, data, user): + buffer = self.search_buffer("favourites", user) + if buffer == None: return + play_sound = "favourite.ogg" + if "favourites" not in buffer.session.settings["other_buffers"]["muted_buffers"]: + self.notify(buffer.session, play_sound=play_sound) + buffer.add_new_item(data) + + def manage_unfavourite(self, item, user): + buffer = self.search_buffer("favourites", user) + if buffer == None: return + buffer.remove_item(item) + + def manage_blocked_user(self, data, user): + buffer = self.search_buffer("blocked", user) + if buffer == None: return + buffer.add_new_item(data) + pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) + + def manage_unblocked_user(self, item, user): + buffer = self.search_buffer("blocked", user) + if buffer == None: return + buffer.remove_item(item) + pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session) + + def manage_item_in_timeline(self, data, user, who): + buffer = self.search_buffer("%s-timeline" % (who,), user) + if buffer == None: return + play_sound = "tweet_timeline.ogg" + if "%s-timeline" % (who,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False: + self.notify(buffer.session, play_sound=play_sound) + output.speak(_(u"One tweet from %s") % (data["user"]["name"])) + buffer.add_new_item(data) + + def manage_item_in_list(self, data, user, where): + buffer = self.search_buffer("%s" % (where,), user) + if buffer == None: return + play_sound = "list_tweet.ogg" + if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False: + self.notify(buffer.session, play_sound=play_sound) + output.speak(_(u"One tweet from %s") % (data["user"]["name"])) + buffer.add_new_item(data) + + def start_buffers(self, session): + log.debug("starting buffers... Session %s" % (session.session_id,)) + for i in self.buffers: + if i.session == session and i.needs_init == True: + if hasattr(i, "finished_timeline") and i.finished_timeline == False: + change_title = True + else: + change_title = False + try: + i.start_stream() + except TwythonAuthError: + buff = self.view.search(i.name, i.account) + i.remove_buffer(force=True) + commonMessageDialogs.blocked_timeline() + if self.get_current_buffer() == i: + self.right() + self.view.delete_buffer(buff) + self.buffers.remove(i) + del i + continue + if change_title: + pub.sendMessage("buffer-title-changed", buffer=i) + log.debug("Starting the streaming endpoint") + session.start_streaming() + + def set_positions(self): + for i in session_.sessions: + self.set_buffer_positions(i) + + def manage_stream_errors(self, session): + log.error(" Restarting %s session streams. It will be destroyed" % (session,)) + s = session_.sessions[session] + try: + if hasattr(s, "main_stream"): + s.main_stream.disconnect() + log.error("main stream disconnected") + del s.main_stream + if hasattr(s, "timelinesStream"): + s.timelinesStream.disconnect() + del s.timelinesStream + except AttributeError: + pass + s.counter = 0 +# s.listen_stream_error() + + def check_connection(self): + if self.started == False: + return + for i in session_.sessions: + try: + if session_.sessions[i].is_logged == False: continue + session_.sessions[i].check_connection() + except TwythonError: # 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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"]) + 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() + if buffer == "followers": + followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "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() + elif buffer == "friends": + friends = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "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() + elif buffer == "blocked": + blocks = buffersController.peopleBufferController(self.view.nb, "list_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() + elif buffer == "muted": + muted = buffersController.peopleBufferController(self.view.nb, "get_muted_users_list", "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() + elif buffer == "events": + events = buffersController.eventsBufferController(self.view.nb, "events", buff.session, buff.session.db["user_name"], bufferType="dmPanel", screen_name=buff.session.db["user_name"]) + self.buffers.append(events) + self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + elif create == False: + self.destroy_buffer(buffer, buff.session.db["user_name"]) + elif buffer == "list": + if create in buff.session.settings["other_buffers"]["lists"]: + output.speak(_(u"This list is already opened"), True) + return + tl = buffersController.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"])) + buff.session.lists.append(tl) + pos=self.view.search("lists", buff.session.db["user_name"]) + self.insert_buffer(tl, pos) + self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(create), pos=self.view.search("lists", buff.session.db["user_name"])) + tl.start_stream() + buff.session.settings["other_buffers"]["lists"].append(create) + buff.session.settings.write() + pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session) + + def restart_streams(self, streams=[], session=None): + for i in streams: + log.debug("Restarting the %s stream" % (i,)) + session.remove_stream(i) + session.check_connection() + + def invisible_shorcuts_changed(self, registered): + if registered == True: + km = self.create_invisible_keyboard_shorcuts() + self.register_invisible_keyboard_shorcuts(km) + elif registered == False: + km = self.create_invisible_keyboard_shorcuts() + self.unregister_invisible_keyboard_shorcuts(km) + + def about(self, *args, **kwargs): + self.view.about_dialog() + + def visit_website(self, *args, **kwargs): + webbrowser.open(application.url) + + def manage_accounts(self, *args, **kwargs): + sm = sessionManager.sessionManagerController(started=True) + sm.fill_list() + sm.show() + for i in sm.new_sessions: + self.create_buffers(session_.sessions[i]) + call_threaded(self.start_buffers, session_.sessions[i]) + for i in sm.removed_sessions: + if session_.sessions[i].logged == True: + self.logout_account(session_.sessions[i].session_id) + self.destroy_buffer(session_.sessions[i].settings["twitter"]["user_name"], session_.sessions[i].settings["twitter"]["user_name"]) + self.accounts.remove(session_.sessions[i].settings["twitter"]["user_name"]) + session_.sessions.pop(i) + + def update_profile(self, *args, **kwargs): + r = user.profileController(self.get_best_buffer().session) + + def user_details(self, *args, **kwargs): + buffer = self.get_current_buffer() + if not hasattr(buffer, "session") or buffer.session == None: return + if hasattr(buffer, "user_details"): + buffer.user_details() + + def toggle_autoread(self, *args, **kwargs): + buffer = self.get_current_buffer() + if hasattr(buffer, "session") and buffer.session == None: return + if buffer.name not in buffer.session.settings["other_buffers"]["autoread_buffers"]: + buffer.session.settings["other_buffers"]["autoread_buffers"].append(buffer.name) + output.speak(_(u"The auto-reading of new tweets is enabled for this buffer"), True) + elif buffer.name in buffer.session.settings["other_buffers"]["autoread_buffers"]: + buffer.session.settings["other_buffers"]["autoread_buffers"].remove(buffer.name) + output.speak(_(u"The auto-reading of new tweets is disabled for this buffer"), True) + buffer.session.settings.write() + + def toggle_session_mute(self, *args, **kwargs): + buffer = self.get_best_buffer() + if buffer.session.settings["sound"]["session_mute"] == False: + buffer.session.settings["sound"]["session_mute"] = True + output.speak(_(u"Session mute on"), True) + elif buffer.session.settings["sound"]["session_mute"] == True: + buffer.session.settings["sound"]["session_mute"] = False + output.speak(_(u"Session mute off"), True) + buffer.session.settings.write() + + def toggle_buffer_mute(self, *args, **kwargs): + buffer = self.get_current_buffer() + if hasattr(buffer, "session") and buffer.session == None: return + if buffer.name not in buffer.session.settings["other_buffers"]["muted_buffers"]: + buffer.session.settings["other_buffers"]["muted_buffers"].append(buffer.name) + output.speak(_(u"Buffer mute on"), True) + elif buffer.name in buffer.session.settings["other_buffers"]["muted_buffers"]: + buffer.session.settings["other_buffers"]["muted_buffers"].remove(buffer.name) + output.speak(_(u"Buffer mute off"), True) + buffer.session.settings.write() + + def view_documentation(self, *args, **kwargs): + lang = localization.get("documentation") + os.chdir("documentation/%s" % (lang,)) + webbrowser.open("manual.html") + os.chdir("../../") + + def view_changelog(self, *args, **kwargs): + lang = localization.get("documentation") + os.chdir("documentation/%s" % (lang,)) + webbrowser.open("changelog.html") + os.chdir("../../") + + def insert_buffer(self, buffer, position): + self.buffers.insert(position, buffer) + + def copy_to_clipboard(self, *args, **kwargs): + output.copy(self.get_current_buffer().get_message()) + output.speak(_(u"Copied")) + + def repeat_item(self, *args, **kwargs): + output.speak(self.get_current_buffer().get_message()) + + def execute_action(self, action): + if hasattr(self, action): + getattr(self, action)() + + def restart_streams_(self, session): + for i in self.buffers[:]: + if i.session != None and i.session.session_id == session: + try: + i.start_stream() + except TwythonAuthError: + buff = self.view.search(i.name, i.account) + i.remove_buffer(force=True) + commonMessageDialogs.blocked_timeline() + if self.get_current_buffer() == i: + self.right() + self.view.delete_buffer(buff) + self.buffers.remove(i) + del i + + def update_buffer(self, *args, **kwargs): + bf = self.get_current_buffer() + if not hasattr(bf, "start_stream"): + output.speak(_(u"Unable to update this buffer.")) + return + else: + output.speak(_(u"Updating buffer...")) + n = bf.start_stream(mandatory=True) + if n != None: + output.speak(_(u"{0} items retrieved").format(n,)) + + def on_tweet_deleted(self, data): + id = data["delete"]["status"]["id"] + for i in self.buffers: + if hasattr(i, "remove_tweet") and hasattr(i, "name"): + i.remove_tweet(id) + + def buffer_title_changed(self, buffer): + if "-timeline" in buffer.name: + title = _(u"Timeline for {}").format(buffer.username,) + elif "-favorite" in buffer.name: + title = _(u"Likes for {}").format(buffer.username,) + elif "-followers" in buffer.name: + title = _(u"Followers for {}").format(buffer.username,) + elif "-friends" in buffer.name: + title = _(u"Friends for {}").format(buffer.username,) + buffer_index = self.view.search(buffer.name, buffer.account) + self.view.set_page_title(buffer_index, title) + + def ocr_image(self, *args, **kwargs): + buffer = self.get_current_buffer() + if hasattr(buffer, "get_right_tweet") == False: + output.speak(_(u"Invalid buffer")) + return + tweet = buffer.get_tweet() + if ("entities" in tweet) == False or ("media" in tweet["entities"]) == False: + output.speak(_(u"This tweet doesn't contain images")) + return + if len(tweet["entities"]["media"]) > 1: + image_list = [_(u"Picture {0}").format(i,) for i in xrange(0, len(tweet["entities"]["media"]))] + dialog = dialogs.urlList.urlList(title=_(u"Select the picture")) + if dialog.get_response() == widgetUtils.OK: + img = tweet["entities"]["media"][dialog.get_item()] + else: + return + else: + img = tweet["entities"]["media"][0] + if buffer.session.settings["mysc"]["ocr_language"] != "": + ocr_lang = buffer.session.settings["mysc"]["ocr_language"] + else: + ocr_lang = ocr.OCRSpace.short_langs.index(tweet["lang"]) + ocr_lang = ocr.OCRSpace.OcrLangs[ocr_lang] + api = ocr.OCRSpace.OCRSpaceAPI() + try: + text = api.OCR_URL(img["media_url"], lang=ocr_lang) + except ocr.OCRSpace.APIError as er: + output.speak(_(u"Unable to extract text")) + return + msg = messages.viewTweet(text["ParsedText"], [], False) + + def save_data_in_db(self): + for i in session_.sessions: session_.sessions[i].shelve() \ No newline at end of file diff --git a/src/controller/messages.py b/src/controller/messages.py index dde3a9ee..48c464b5 100644 --- a/src/controller/messages.py +++ b/src/controller/messages.py @@ -1,276 +1,277 @@ -# -*- coding: utf-8 -*- -import re -import platform -import attach -system = platform.system() -import widgetUtils -import output -import url_shortener -import sound -from pubsub import pub -if system == "Windows": - from wxUI.dialogs import message, urlList - from extra import translator, SpellChecker, autocompletionUsers - from extra.AudioUploader import audioUploader -elif system == "Linux": - from gtkUI.dialogs import message -from twitter import utils - -class basicTweet(object): - """ This class handles the tweet main features. Other classes should derive from this class.""" - def __init__(self, session, title, caption, text, messageType="tweet", max=140, *args, **kwargs): - super(basicTweet, self).__init__() - self.max = max - self.title = title - self.session = session - self.message = getattr(message, messageType)(title, caption, text, *args, **kwargs) - widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck) - widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach) -# if system == "Windows": -# if messageType != "dm": - widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor) - widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten) - widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten) - widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate) - if hasattr(self.message, "long_tweet"): - widgetUtils.connect_event(self.message.long_tweet, widgetUtils.CHECKBOX, self.text_processor) - self.attachments = [] - - def translate(self, event=None): - dlg = translator.gui.translateDialog() - if dlg.get_response() == widgetUtils.OK: - text_to_translate = self.message.get_text() - source = [x[0] for x in translator.translator.available_languages()][dlg.get("source_lang")] - dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")] - msg = translator.translator.translate(text=text_to_translate, source=source, target=dest) - self.message.set_text(msg) - self.text_processor() - self.message.text_focus() - output.speak(_(u"Translated")) - else: - return - - def shorten(self, event=None): - urls = utils.find_urls_in_text(self.message.get_text()) - if len(urls) == 0: - output.speak(_(u"There's no URL to be shortened")) - self.message.text_focus() - elif len(urls) == 1: - self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.shorten(urls[0]))) - output.speak(_(u"URL shortened")) - self.text_processor() - self.message.text_focus() - elif len(urls) > 1: - list_urls = urlList.urlList() - list_urls.populate_list(urls) - if list_urls.get_response() == widgetUtils.OK: - self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.shorten(list_urls.get_string()))) - output.speak(_(u"URL shortened")) - self.text_processor() - self.message.text_focus() - - def unshorten(self, event=None): - urls = utils.find_urls_in_text(self.message.get_text()) - if len(urls) == 0: - output.speak(_(u"There's no URL to be expanded")) - self.message.text_focus() - elif len(urls) == 1: - self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.unshorten(urls[0]))) - output.speak(_(u"URL expanded")) - self.text_processor() - self.message.text_focus() - elif len(urls) > 1: - list_urls = urlList.urlList() - list_urls.populate_list(urls) - if list_urls.get_response() == widgetUtils.OK: - self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.unshorten(list_urls.get_string()))) - output.speak(_(u"URL expanded")) - self.text_processor() - self.message.text_focus() - - def text_processor(self, *args, **kwargs): - if len(self.message.get_text()) > 1: - self.message.enable_button("shortenButton") - self.message.enable_button("unshortenButton") - else: - self.message.disable_button("shortenButton") - self.message.disable_button("unshortenButton") - if self.message.get("long_tweet") == False: - self.message.set_title(_(u"%s - %s of %d characters") % (self.title, len(self.message.get_text()), self.max)) - if len(self.message.get_text()) > self.max: - self.session.sound.play("max_length.ogg") - else: - self.message.set_title(_(u"%s - %s characters") % (self.title, len(self.message.get_text()))) - - def spellcheck(self, event=None): - text = self.message.get_text() - checker = SpellChecker.spellchecker.spellChecker(text, "") - if hasattr(checker, "fixed_text"): - self.message.set_text(checker.fixed_text) - self.text_processor() - self.message.text_focus() - - def attach(self, *args, **kwargs): - def completed_callback(dlg): - url = dlg.uploaderFunction.get_url() - pub.unsubscribe(dlg.uploaderDialog.update, "uploading") - dlg.uploaderDialog.destroy() - if url != 0: - self.message.set_text(self.message.get_text()+url+" #audio") - self.text_processor() - else: - output.speak(_(u"Unable to upload the audio")) - dlg.cleanup() - dlg = audioUploader.audioUploader(self.session.settings, completed_callback) - self.message.text_focus() - -class tweet(basicTweet): - def __init__(self, session, title, caption, text, twishort_enabled, messageType="tweet", max=140, *args, **kwargs): - super(tweet, self).__init__(session, title, caption, text, messageType, max, *args, **kwargs) - self.image = None - widgetUtils.connect_event(self.message.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image) - widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) - if twishort_enabled == False: - try: self.message.long_tweet.SetValue(False) - except AttributeError: pass - self.text_processor() - - def upload_image(self, *args, **kwargs): - a = attach.attach() - if len(a.attachments) != 0: - self.attachments = a.attachments - - def autocomplete_users(self, *args, **kwargs): - c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id) - c.show_menu() - -class reply(tweet): - def __init__(self, session, title, caption, text, twishort_enabled, users=[], ids=[]): - super(reply, self).__init__(session, title, caption, text, twishort_enabled, messageType="reply", users=users) - self.ids = ids - self.users = users - if len(users) > 0: - widgetUtils.connect_event(self.message.mentionAll, widgetUtils.CHECKBOX, self.mention_all) - self.message.enable_button("mentionAll") - self.message.mentionAll.SetValue(self.session.settings["mysc"]["mention_all"]) - if self.message.mentionAll.GetValue() == True: - self.mention_all() - self.message.set_cursor_at_end() - self.text_processor() - - def mention_all(self, *args, **kwargs): - if self.message.mentionAll.GetValue() == True: - for i in self.message.checkboxes: - i.SetValue(True) - i.Hide() - else: - for i in self.message.checkboxes: - i.SetValue(False) - i.Show() - - - def get_ids(self): - excluded_ids = "" - for i in xrange(0, len(self.message.checkboxes)): - if self.message.checkboxes[i].GetValue() == False: - excluded_ids = excluded_ids + "{0},".format(self.ids[i],) - return excluded_ids - - def get_people(self): - people = "" - for i in xrange(0, len(self.message.checkboxes)): - if self.message.checkboxes[i].GetValue() == True: - people = people + "{0} ".format(self.message.checkboxes[i].GetLabel(),) - return people - -class dm(basicTweet): - def __init__(self, session, title, caption, text): - super(dm, self).__init__(session, title, caption, text, messageType="dm", max=10000) - widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) - self.text_processor() - - def autocomplete_users(self, *args, **kwargs): - c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id) - c.show_menu("dm") - -class viewTweet(basicTweet): - def __init__(self, tweet, tweetList, is_tweet=True): - """ This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event. - param tweet: A dictionary that represents a full tweet or a string for non-tweets. - param tweetList: If is_tweet is set to True, this could be a list of quoted tweets. - param is_tweet: True or false, depending wether the passed object is a tweet or not.""" - if is_tweet == True: - image_description = [] - text = "" - for i in xrange(0, len(tweetList)): - # tweets with message keys are longer tweets, the message value is the full messaje taken from twishort. - if tweetList[i].has_key("message") and tweetList[i]["is_quote_status"] == False: - value = "message" - else: - value = "full_text" - if tweetList[i].has_key("retweeted_status") and tweetList[i]["is_quote_status"] == False: - if tweetList[i].has_key("message") == False: - 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]) - else: - text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value]) - # tweets with extended_entities could include image descriptions. - if tweetList[i].has_key("extended_entities") and tweetList[i]["extended_entities"].has_key("media"): - for z in tweetList[i]["extended_entities"]["media"]: - if z.has_key("ext_alt_text") and z["ext_alt_text"] != None: - image_description.append(z["ext_alt_text"]) - if tweetList[i].has_key("retweeted_status") and tweetList[i]["retweeted_status"].has_key("extended_entities") and tweetList[i]["retweeted_status"]["extended_entities"].has_key("media"): - for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]: - if z.has_key("ext_alt_text") 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"]) - # Gets the client from where this tweet was made. - source = str(re.sub(r"(?s)<.*?>", "", tweet["source"].encode("utf-8"))) - if text == "": - if tweet.has_key("message"): - value = "message" - else: - value = "full_text" - if tweet.has_key("retweeted_status"): - if tweet.has_key("message") == False: - 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]) - else: - text = tweet[value] - text = self.clear_text(text) - if tweet.has_key("extended_entities") and tweet["extended_entities"].has_key("media"): - for z in tweet["extended_entities"]["media"]: - if z.has_key("ext_alt_text") and z["ext_alt_text"] != None: - image_description.append(z["ext_alt_text"]) - if tweet.has_key("retweeted_status") and tweet["retweeted_status"].has_key("extended_entities") and tweet["retweeted_status"]["extended_entities"].has_key("media"): - for z in tweet["retweeted_status"]["extended_entities"]["media"]: - if z.has_key("ext_alt_text") and z["ext_alt_text"] != None: - image_description.append(z["ext_alt_text"]) - self.message = message.viewTweet(text, rt_count, favs_count, source.decode("utf-8")) - self.message.set_title(len(text)) - [self.message.set_image_description(i) for i in image_description] - else: - text = tweet - self.message = message.viewNonTweet(text) - widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck) - widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate) - if self.contain_urls() == True: - self.message.enable_button("unshortenButton") - widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten) - self.message.get_response() - - def contain_urls(self): - if len(utils.find_urls_in_text(self.message.get_text())) > 0: - return True - return False - - def clear_text(self, text): - urls = utils.find_urls_in_text(text) - for i in urls: - if "https://twitter.com/" in i: - text = text.replace(i, "\n") - return text +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import re +import platform +from . import attach +system = platform.system() +import widgetUtils +import output +import url_shortener +import sound +from pubsub import pub +if system == "Windows": + from wxUI.dialogs import message, urlList + from extra import translator, SpellChecker, autocompletionUsers + from extra.AudioUploader import audioUploader +elif system == "Linux": + from gtkUI.dialogs import message +from twitter import utils + +class basicTweet(object): + """ This class handles the tweet main features. Other classes should derive from this class.""" + def __init__(self, session, title, caption, text, messageType="tweet", max=140, *args, **kwargs): + super(basicTweet, self).__init__() + self.max = max + self.title = title + self.session = session + self.message = getattr(message, messageType)(title, caption, text, *args, **kwargs) + widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck) + widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach) +# if system == "Windows": +# if messageType != "dm": + widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor) + widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten) + widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten) + widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate) + if hasattr(self.message, "long_tweet"): + widgetUtils.connect_event(self.message.long_tweet, widgetUtils.CHECKBOX, self.text_processor) + self.attachments = [] + + def translate(self, event=None): + dlg = translator.gui.translateDialog() + if dlg.get_response() == widgetUtils.OK: + text_to_translate = self.message.get_text() + source = [x[0] for x in translator.translator.available_languages()][dlg.get("source_lang")] + dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")] + msg = translator.translator.translate(text=text_to_translate, source=source, target=dest) + self.message.set_text(msg) + self.text_processor() + self.message.text_focus() + output.speak(_(u"Translated")) + else: + return + + def shorten(self, event=None): + urls = utils.find_urls_in_text(self.message.get_text()) + if len(urls) == 0: + output.speak(_(u"There's no URL to be shortened")) + self.message.text_focus() + elif len(urls) == 1: + self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.shorten(urls[0]))) + output.speak(_(u"URL shortened")) + self.text_processor() + self.message.text_focus() + elif len(urls) > 1: + list_urls = urlList.urlList() + list_urls.populate_list(urls) + if list_urls.get_response() == widgetUtils.OK: + self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.shorten(list_urls.get_string()))) + output.speak(_(u"URL shortened")) + self.text_processor() + self.message.text_focus() + + def unshorten(self, event=None): + urls = utils.find_urls_in_text(self.message.get_text()) + if len(urls) == 0: + output.speak(_(u"There's no URL to be expanded")) + self.message.text_focus() + elif len(urls) == 1: + self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.unshorten(urls[0]))) + output.speak(_(u"URL expanded")) + self.text_processor() + self.message.text_focus() + elif len(urls) > 1: + list_urls = urlList.urlList() + list_urls.populate_list(urls) + if list_urls.get_response() == widgetUtils.OK: + self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.unshorten(list_urls.get_string()))) + output.speak(_(u"URL expanded")) + self.text_processor() + self.message.text_focus() + + def text_processor(self, *args, **kwargs): + if len(self.message.get_text()) > 1: + self.message.enable_button("shortenButton") + self.message.enable_button("unshortenButton") + else: + self.message.disable_button("shortenButton") + self.message.disable_button("unshortenButton") + if self.message.get("long_tweet") == False: + self.message.set_title(_(u"%s - %s of %d characters") % (self.title, len(self.message.get_text()), self.max)) + if len(self.message.get_text()) > self.max: + self.session.sound.play("max_length.ogg") + else: + self.message.set_title(_(u"%s - %s characters") % (self.title, len(self.message.get_text()))) + + def spellcheck(self, event=None): + text = self.message.get_text() + checker = SpellChecker.spellchecker.spellChecker(text, "") + if hasattr(checker, "fixed_text"): + self.message.set_text(checker.fixed_text) + self.text_processor() + self.message.text_focus() + + def attach(self, *args, **kwargs): + def completed_callback(dlg): + url = dlg.uploaderFunction.get_url() + pub.unsubscribe(dlg.uploaderDialog.update, "uploading") + dlg.uploaderDialog.destroy() + if url != 0: + self.message.set_text(self.message.get_text()+url+" #audio") + self.text_processor() + else: + output.speak(_(u"Unable to upload the audio")) + dlg.cleanup() + dlg = audioUploader.audioUploader(self.session.settings, completed_callback) + self.message.text_focus() + +class tweet(basicTweet): + def __init__(self, session, title, caption, text, twishort_enabled, messageType="tweet", max=140, *args, **kwargs): + super(tweet, self).__init__(session, title, caption, text, messageType, max, *args, **kwargs) + self.image = None + widgetUtils.connect_event(self.message.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image) + widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) + if twishort_enabled == False: + try: self.message.long_tweet.SetValue(False) + except AttributeError: pass + self.text_processor() + + def upload_image(self, *args, **kwargs): + a = attach.attach() + if len(a.attachments) != 0: + self.attachments = a.attachments + + def autocomplete_users(self, *args, **kwargs): + c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id) + c.show_menu() + +class reply(tweet): + def __init__(self, session, title, caption, text, twishort_enabled, users=[], ids=[]): + super(reply, self).__init__(session, title, caption, text, twishort_enabled, messageType="reply", users=users) + self.ids = ids + self.users = users + if len(users) > 0: + widgetUtils.connect_event(self.message.mentionAll, widgetUtils.CHECKBOX, self.mention_all) + self.message.enable_button("mentionAll") + self.message.mentionAll.SetValue(self.session.settings["mysc"]["mention_all"]) + if self.message.mentionAll.GetValue() == True: + self.mention_all() + self.message.set_cursor_at_end() + self.text_processor() + + def mention_all(self, *args, **kwargs): + if self.message.mentionAll.GetValue() == True: + for i in self.message.checkboxes: + i.SetValue(True) + i.Hide() + else: + for i in self.message.checkboxes: + i.SetValue(False) + i.Show() + + + def get_ids(self): + excluded_ids = "" + for i in xrange(0, len(self.message.checkboxes)): + if self.message.checkboxes[i].GetValue() == False: + excluded_ids = excluded_ids + "{0},".format(self.ids[i],) + return excluded_ids + + def get_people(self): + people = "" + for i in xrange(0, len(self.message.checkboxes)): + if self.message.checkboxes[i].GetValue() == True: + people = people + "{0} ".format(self.message.checkboxes[i].GetLabel(),) + return people + +class dm(basicTweet): + def __init__(self, session, title, caption, text): + super(dm, self).__init__(session, title, caption, text, messageType="dm", max=10000) + widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) + self.text_processor() + + def autocomplete_users(self, *args, **kwargs): + c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id) + c.show_menu("dm") + +class viewTweet(basicTweet): + def __init__(self, tweet, tweetList, is_tweet=True): + """ This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event. + param tweet: A dictionary that represents a full tweet or a string for non-tweets. + param tweetList: If is_tweet is set to True, this could be a list of quoted tweets. + param is_tweet: True or false, depending wether the passed object is a tweet or not.""" + if is_tweet == True: + image_description = [] + text = "" + for i in xrange(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: + 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"]) + else: + text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value]) + else: + text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], 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 "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 "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"]) + # Gets the client from where this tweet was made. + source = str(re.sub(r"(?s)<.*?>", "", tweet["source"].encode("utf-8"))) + if text == "": + if "message" in tweet: + 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"]) + else: + text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value]) + else: + text = 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 "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 "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.decode("utf-8")) + self.message.set_title(len(text)) + [self.message.set_image_description(i) for i in image_description] + else: + text = tweet + self.message = message.viewNonTweet(text) + widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck) + widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate) + if self.contain_urls() == True: + self.message.enable_button("unshortenButton") + widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten) + self.message.get_response() + + def contain_urls(self): + if len(utils.find_urls_in_text(self.message.get_text())) > 0: + return True + return False + + def clear_text(self, text): + urls = utils.find_urls_in_text(text) + for i in urls: + if "https://twitter.com/" in i: + text = text.replace(i, "\n") + return text diff --git a/src/controller/userActionsController.py b/src/controller/userActionsController.py index 372becf3..a4041839 100644 --- a/src/controller/userActionsController.py +++ b/src/controller/userActionsController.py @@ -1,80 +1,80 @@ -# -*- coding: utf-8 -*- -import re -import widgetUtils -import output -from wxUI.dialogs import userActions -from pubsub import pub -from twython import TwythonError -from extra import autocompletionUsers - -class userActionsController(object): - def __init__(self, buffer, users=[], default="follow"): - super(userActionsController, self).__init__() - self.buffer = buffer - self.session = buffer.session - self.dialog = userActions.UserActionsDialog(users, default) - widgetUtils.connect_event(self.dialog.autocompletion, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) - if self.dialog.get_response() == widgetUtils.OK: - self.process_action() - - def autocomplete_users(self, *args, **kwargs): - c = autocompletionUsers.completion.autocompletionUsers(self.dialog, self.session.session_id) - c.show_menu("dm") - - def process_action(self): - action = self.dialog.get_action() - user = self.dialog.get_user() - if user == "": return - getattr(self, action)(user) - - def follow(self, user): - try: - self.session.twitter.twitter.create_friendship(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def unfollow(self, user): - try: - id = self.session.twitter.twitter.destroy_friendship(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def mute(self, user): - try: - id = self.session.twitter.twitter.create_mute(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def unmute(self, user): - try: - id = self.session.twitter.twitter.destroy_mute(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def report(self, user): - try: - id = self.session.twitter.twitter.report_spam(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def block(self, user): - try: - id = self.session.twitter.twitter.create_block(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def unblock(self, user): - try: - id = self.session.twitter.twitter.destroy_block(screen_name=user ) - except TwythonError as err: - output.speak("Error %s: %s" % (err.error_code, err.msg), True) - - def ignore_client(self, user): - tweet = self.buffer.get_right_tweet() - if tweet.has_key("sender"): - output.speak(_(u"You can't ignore direct messages")) - return - client = re.sub(r"(?s)<.*?>", "", tweet["source"]) - if client not in self.session.settings["twitter"]["ignored_clients"]: - self.session.settings["twitter"]["ignored_clients"].append(client) +# -*- coding: utf-8 -*- +import re +import widgetUtils +import output +from wxUI.dialogs import userActions +from pubsub import pub +from twython import TwythonError +from extra import autocompletionUsers + +class userActionsController(object): + def __init__(self, buffer, users=[], default="follow"): + super(userActionsController, self).__init__() + self.buffer = buffer + self.session = buffer.session + self.dialog = userActions.UserActionsDialog(users, default) + widgetUtils.connect_event(self.dialog.autocompletion, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) + if self.dialog.get_response() == widgetUtils.OK: + self.process_action() + + def autocomplete_users(self, *args, **kwargs): + c = autocompletionUsers.completion.autocompletionUsers(self.dialog, self.session.session_id) + c.show_menu("dm") + + def process_action(self): + action = self.dialog.get_action() + user = self.dialog.get_user() + if user == "": return + getattr(self, action)(user) + + def follow(self, user): + try: + self.session.twitter.twitter.create_friendship(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def unfollow(self, user): + try: + id = self.session.twitter.twitter.destroy_friendship(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def mute(self, user): + try: + id = self.session.twitter.twitter.create_mute(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def unmute(self, user): + try: + id = self.session.twitter.twitter.destroy_mute(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def report(self, user): + try: + id = self.session.twitter.twitter.report_spam(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def block(self, user): + try: + id = self.session.twitter.twitter.create_block(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def unblock(self, user): + try: + id = self.session.twitter.twitter.destroy_block(screen_name=user ) + except TwythonError as err: + output.speak("Error %s: %s" % (err.error_code, err.msg), True) + + def ignore_client(self, user): + tweet = self.buffer.get_right_tweet() + if "sender" in tweet: + output.speak(_(u"You can't ignore direct messages")) + return + client = re.sub(r"(?s)<.*?>", "", 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 diff --git a/src/extra/AudioUploader/audioUploader.py b/src/extra/AudioUploader/audioUploader.py index 8f812701..ea1aff8b 100644 --- a/src/extra/AudioUploader/audioUploader.py +++ b/src/extra/AudioUploader/audioUploader.py @@ -1,178 +1,179 @@ -# -*- coding: utf-8 -*- -############################################################ -# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################ -import widgetUtils -import wx_ui -import wx_transfer_dialogs -import transfer -import output -import tempfile -import sound -import os -import config -from pubsub import pub -from mysc.thread_utils import call_threaded -import sound_lib -import logging - -log = logging.getLogger("extra.AudioUploader.audioUploader") - -class audioUploader(object): - def __init__(self, configFile, completed_callback): - self.config = configFile - super(audioUploader, self).__init__() - self.dialog = wx_ui.audioDialog(services=self.get_available_services()) - self.file = None - self.recorded = False - self.recording = None - self.playing = None - widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play) - widgetUtils.connect_event(self.dialog.pause, widgetUtils.BUTTON_PRESSED, self.on_pause) - widgetUtils.connect_event(self.dialog.record, widgetUtils.BUTTON_PRESSED, self.on_record) - widgetUtils.connect_event(self.dialog.attach_exists, widgetUtils.BUTTON_PRESSED, self.on_attach_exists) - widgetUtils.connect_event(self.dialog.discard, widgetUtils.BUTTON_PRESSED, self.on_discard) - if self.dialog.get_response() == widgetUtils.OK: - self.postprocess() - log.debug("Uploading file %s to %s..." % (self.file, self.dialog.get("services"))) - self.uploaderDialog = wx_transfer_dialogs.UploadDialog(self.file) - output.speak(_(u"Attaching...")) - if self.dialog.get("services") == "SNDUp": - base_url = "http://sndup.net/post.php" - if len(self.config["sound"]["sndup_api_key"]) > 0: - url = base_url + '?apikey=' + self.config['sound']['sndup_api_key'] - else: - url = base_url - self.uploaderFunction = transfer.Upload(obj=self, field='file', url=url, filename=self.file, completed_callback=completed_callback) - pub.subscribe(self.uploaderDialog.update, "uploading") - self.uploaderDialog.get_response(self.uploaderFunction.perform_threaded) - - def get_available_services(self): - services = [] - services.append("SNDUp") - return services - - def on_pause(self, *args, **kwargs): - if self.dialog.get("pause") == _(u"Pause"): - self.recording.pause() - self.dialog.set("pause", _(u"&Resume")) - elif self.dialog.get("pause") == _(u"Resume"): - self.recording.play() - self.dialog.set("pause", _(U"&Pause")) - - def on_record(self, *args, **kwargs): - if self.recording != None: - self.stop_recording() - self.dialog.disable_control("pause") - else: - self.start_recording() - self.dialog.enable_control("pause") - - def start_recording(self): - self.dialog.disable_control("attach_exists") - self.file = tempfile.mktemp(suffix='.wav') - self.recording = sound.recording(self.file) - self.recording.play() - self.dialog.set("record", _(u"&Stop")) - output.speak(_(u"Recording")) - - def stop_recording(self): - self.recording.stop() - self.recording.free() - output.speak(_(u"Stopped")) - self.recorded = True - self.dialog.set("record", _(u"&Record")) - self.file_attached() - - def file_attached(self): - self.dialog.set("pause", _(u"&Pause")) - self.dialog.disable_control("record") - self.dialog.enable_control("play") - self.dialog.enable_control("discard") - self.dialog.disable_control("attach_exists") - self.dialog.enable_control("attach") - self.dialog.play.SetFocus() - - def on_discard(self, *args, **kwargs): - if self.playing: - self._stop() - if self.recording != None: - self.cleanup() - self.dialog.disable_control("attach") - self.dialog.disable_control("play") - self.file = None - self.dialog.enable_control("record") - self.dialog.enable_control("attach_exists") - self.dialog.record.SetFocus() - self.dialog.disable_control("discard") - self.recording = None - output.speak(_(u"Discarded")) - - def on_play(self, *args, **kwargs): - if not self.playing: - call_threaded(self._play) - else: - self._stop() - - def _play(self): - output.speak(_(u"Playing...")) -# try: - self.playing = sound_lib.stream.FileStream(file=unicode(self.file), flags=sound_lib.stream.BASS_UNICODE) - self.playing.play() - self.dialog.set("play", _(u"&Stop")) - try: - while self.playing.is_playing: - pass - self.dialog.set("play", _(u"&Play")) - self.playing.free() - self.playing = None - except: - pass - - def _stop(self): - output.speak(_(u"Stopped")) - self.playing.stop() - self.playing.free() - self.dialog.set("play", _(u"&Play")) - self.playing = None - - def postprocess(self): - if self.file.lower().endswith('.wav'): - output.speak(_(u"Recoding audio...")) - sound.recode_audio(self.file) - self.wav_file = self.file - self.file = '%s.ogg' % self.file[:-4] - - def cleanup(self): - if self.playing and self.playing.is_playing: - self.playing.stop() - if self.recording != None: - if self.recording.is_playing: - self.recording.stop() - try: - self.recording.free() - except: - pass - os.remove(self.file) - if hasattr(self, 'wav_file'): - os.remove(self.wav_file) - - def on_attach_exists(self, *args, **kwargs): - self.file = self.dialog.get_file() - if self.file != False: - self.file_attached() - +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from __future__ import absolute_import +import widgetUtils +from . import wx_ui +from . import wx_transfer_dialogs +from . import transfer +import output +import tempfile +import sound +import os +import config +from pubsub import pub +from mysc.thread_utils import call_threaded +import sound_lib +import logging + +log = logging.getLogger("extra.AudioUploader.audioUploader") + +class audioUploader(object): + def __init__(self, configFile, completed_callback): + self.config = configFile + super(audioUploader, self).__init__() + self.dialog = wx_ui.audioDialog(services=self.get_available_services()) + self.file = None + self.recorded = False + self.recording = None + self.playing = None + widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play) + widgetUtils.connect_event(self.dialog.pause, widgetUtils.BUTTON_PRESSED, self.on_pause) + widgetUtils.connect_event(self.dialog.record, widgetUtils.BUTTON_PRESSED, self.on_record) + widgetUtils.connect_event(self.dialog.attach_exists, widgetUtils.BUTTON_PRESSED, self.on_attach_exists) + widgetUtils.connect_event(self.dialog.discard, widgetUtils.BUTTON_PRESSED, self.on_discard) + if self.dialog.get_response() == widgetUtils.OK: + self.postprocess() + log.debug("Uploading file %s to %s..." % (self.file, self.dialog.get("services"))) + self.uploaderDialog = wx_transfer_dialogs.UploadDialog(self.file) + output.speak(_(u"Attaching...")) + if self.dialog.get("services") == "SNDUp": + base_url = "http://sndup.net/post.php" + if len(self.config["sound"]["sndup_api_key"]) > 0: + url = base_url + '?apikey=' + self.config['sound']['sndup_api_key'] + else: + url = base_url + self.uploaderFunction = transfer.Upload(obj=self, field='file', url=url, filename=self.file, completed_callback=completed_callback) + pub.subscribe(self.uploaderDialog.update, "uploading") + self.uploaderDialog.get_response(self.uploaderFunction.perform_threaded) + + def get_available_services(self): + services = [] + services.append("SNDUp") + return services + + def on_pause(self, *args, **kwargs): + if self.dialog.get("pause") == _(u"Pause"): + self.recording.pause() + self.dialog.set("pause", _(u"&Resume")) + elif self.dialog.get("pause") == _(u"Resume"): + self.recording.play() + self.dialog.set("pause", _(U"&Pause")) + + def on_record(self, *args, **kwargs): + if self.recording != None: + self.stop_recording() + self.dialog.disable_control("pause") + else: + self.start_recording() + self.dialog.enable_control("pause") + + def start_recording(self): + self.dialog.disable_control("attach_exists") + self.file = tempfile.mktemp(suffix='.wav') + self.recording = sound.recording(self.file) + self.recording.play() + self.dialog.set("record", _(u"&Stop")) + output.speak(_(u"Recording")) + + def stop_recording(self): + self.recording.stop() + self.recording.free() + output.speak(_(u"Stopped")) + self.recorded = True + self.dialog.set("record", _(u"&Record")) + self.file_attached() + + def file_attached(self): + self.dialog.set("pause", _(u"&Pause")) + self.dialog.disable_control("record") + self.dialog.enable_control("play") + self.dialog.enable_control("discard") + self.dialog.disable_control("attach_exists") + self.dialog.enable_control("attach") + self.dialog.play.SetFocus() + + def on_discard(self, *args, **kwargs): + if self.playing: + self._stop() + if self.recording != None: + self.cleanup() + self.dialog.disable_control("attach") + self.dialog.disable_control("play") + self.file = None + self.dialog.enable_control("record") + self.dialog.enable_control("attach_exists") + self.dialog.record.SetFocus() + self.dialog.disable_control("discard") + self.recording = None + output.speak(_(u"Discarded")) + + def on_play(self, *args, **kwargs): + if not self.playing: + call_threaded(self._play) + else: + self._stop() + + def _play(self): + output.speak(_(u"Playing...")) +# try: + self.playing = sound_lib.stream.FileStream(file=unicode(self.file), flags=sound_lib.stream.BASS_UNICODE) + self.playing.play() + self.dialog.set("play", _(u"&Stop")) + try: + while self.playing.is_playing: + pass + self.dialog.set("play", _(u"&Play")) + self.playing.free() + self.playing = None + except: + pass + + def _stop(self): + output.speak(_(u"Stopped")) + self.playing.stop() + self.playing.free() + self.dialog.set("play", _(u"&Play")) + self.playing = None + + def postprocess(self): + if self.file.lower().endswith('.wav'): + output.speak(_(u"Recoding audio...")) + sound.recode_audio(self.file) + self.wav_file = self.file + self.file = '%s.ogg' % self.file[:-4] + + def cleanup(self): + if self.playing and self.playing.is_playing: + self.playing.stop() + if self.recording != None: + if self.recording.is_playing: + self.recording.stop() + try: + self.recording.free() + except: + pass + os.remove(self.file) + if hasattr(self, 'wav_file'): + os.remove(self.wav_file) + + def on_attach_exists(self, *args, **kwargs): + self.file = self.dialog.get_file() + if self.file != False: + self.file_attached() + diff --git a/src/extra/AudioUploader/transfer.py b/src/extra/AudioUploader/transfer.py index 080d00d4..25d492e9 100644 --- a/src/extra/AudioUploader/transfer.py +++ b/src/extra/AudioUploader/transfer.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import sys import threading import time import logging -from utils import convert_bytes +from .utils import convert_bytes from pubsub import pub log = logging.getLogger("extra.AudioUploader.transfer") from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor diff --git a/src/extra/AudioUploader/wx_transfer_dialogs.py b/src/extra/AudioUploader/wx_transfer_dialogs.py index 61bb17a1..e8253fdb 100644 --- a/src/extra/AudioUploader/wx_transfer_dialogs.py +++ b/src/extra/AudioUploader/wx_transfer_dialogs.py @@ -1,61 +1,62 @@ -# -*- coding: utf-8 -*- -import wx -from utils import * -import widgetUtils - -class UploadDialog(widgetUtils.BaseDialog): - - def __init__(self, filename, *args, **kwargs): - super(UploadDialog, self).__init__(parent=None, id=wx.NewId(), *args, **kwargs) - self.pane = wx.Panel(self) - self.progress_bar = wx.Gauge(parent=self.pane) - fileBox = wx.BoxSizer(wx.HORIZONTAL) - fileLabel = wx.StaticText(self.pane, -1, _(u"File")) - self.file = wx.TextCtrl(self.pane, -1, value=filename, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(200, 100)) - self.file.SetFocus() - fileBox.Add(fileLabel) - fileBox.Add(self.file) - currentAmountBox = wx.BoxSizer(wx.HORIZONTAL) - current_amount_label = wx.StaticText(self.pane, -1, _(u"Transferred")) - self.current_amount = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE) - currentAmountBox.Add(current_amount_label) - currentAmountBox.Add(self.current_amount) - totalSizeBox = wx.BoxSizer(wx.HORIZONTAL) - total_size_label = wx.StaticText(self.pane, -1, _(u"Total file size")) - self.total_size = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE) - totalSizeBox.Add(total_size_label) - totalSizeBox.Add(self.total_size) - speedBox = wx.BoxSizer(wx.HORIZONTAL) - speedLabel = wx.StaticText(self.pane, -1, _(u"Transfer rate")) - self.speed = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="0 Kb/s") - speedBox.Add(speedLabel) - speedBox.Add(self.speed) - etaBox = wx.BoxSizer(wx.HORIZONTAL) - etaLabel = wx.StaticText(self.pane, -1, _(u"Time left")) - self.eta = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="Unknown", size=(200, 100)) - etaBox.Add(etaLabel) - etaBox.Add(self.eta) - self.create_buttons() - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.Add(fileBox) - sizer.Add(currentAmountBox) - sizer.Add(totalSizeBox) - sizer.Add(speedBox) - sizer.Add(etaBox) - sizer.Add(self.progress_bar) - self.pane.SetSizerAndFit(sizer) - - def update(self, data): - wx.CallAfter(self.progress_bar.SetValue, data["percent"]) - wx.CallAfter(self.current_amount.SetValue, '%s (%d%%)' % (convert_bytes(data["current"]), data["percent"])) - wx.CallAfter(self.total_size.SetValue, convert_bytes(data["total"])) - wx.CallAfter(self.speed.SetValue, data["speed"]) - if data["eta"]: - wx.CallAfter(self.eta.SetValue, seconds_to_string(data["eta"])) - - def create_buttons(self): - self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL) - - def get_response(self, fn): - wx.CallAfter(fn, 0.01) - self.ShowModal() +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from .utils import * +import widgetUtils + +class UploadDialog(widgetUtils.BaseDialog): + + def __init__(self, filename, *args, **kwargs): + super(UploadDialog, self).__init__(parent=None, id=wx.NewId(), *args, **kwargs) + self.pane = wx.Panel(self) + self.progress_bar = wx.Gauge(parent=self.pane) + fileBox = wx.BoxSizer(wx.HORIZONTAL) + fileLabel = wx.StaticText(self.pane, -1, _(u"File")) + self.file = wx.TextCtrl(self.pane, -1, value=filename, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(200, 100)) + self.file.SetFocus() + fileBox.Add(fileLabel) + fileBox.Add(self.file) + currentAmountBox = wx.BoxSizer(wx.HORIZONTAL) + current_amount_label = wx.StaticText(self.pane, -1, _(u"Transferred")) + self.current_amount = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE) + currentAmountBox.Add(current_amount_label) + currentAmountBox.Add(self.current_amount) + totalSizeBox = wx.BoxSizer(wx.HORIZONTAL) + total_size_label = wx.StaticText(self.pane, -1, _(u"Total file size")) + self.total_size = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE) + totalSizeBox.Add(total_size_label) + totalSizeBox.Add(self.total_size) + speedBox = wx.BoxSizer(wx.HORIZONTAL) + speedLabel = wx.StaticText(self.pane, -1, _(u"Transfer rate")) + self.speed = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="0 Kb/s") + speedBox.Add(speedLabel) + speedBox.Add(self.speed) + etaBox = wx.BoxSizer(wx.HORIZONTAL) + etaLabel = wx.StaticText(self.pane, -1, _(u"Time left")) + self.eta = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="Unknown", size=(200, 100)) + etaBox.Add(etaLabel) + etaBox.Add(self.eta) + self.create_buttons() + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(fileBox) + sizer.Add(currentAmountBox) + sizer.Add(totalSizeBox) + sizer.Add(speedBox) + sizer.Add(etaBox) + sizer.Add(self.progress_bar) + self.pane.SetSizerAndFit(sizer) + + def update(self, data): + wx.CallAfter(self.progress_bar.SetValue, data["percent"]) + wx.CallAfter(self.current_amount.SetValue, '%s (%d%%)' % (convert_bytes(data["current"]), data["percent"])) + wx.CallAfter(self.total_size.SetValue, convert_bytes(data["total"])) + wx.CallAfter(self.speed.SetValue, data["speed"]) + if data["eta"]: + wx.CallAfter(self.eta.SetValue, seconds_to_string(data["eta"])) + + def create_buttons(self): + self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL) + + def get_response(self, fn): + wx.CallAfter(fn, 0.01) + self.ShowModal() diff --git a/src/extra/SoundsTutorial/__init__.py b/src/extra/SoundsTutorial/__init__.py index 1e2e7e17..950f0a16 100644 --- a/src/extra/SoundsTutorial/__init__.py +++ b/src/extra/SoundsTutorial/__init__.py @@ -1 +1,2 @@ -from soundsTutorial import soundsTutorial +from __future__ import absolute_import +from .soundsTutorial import soundsTutorial diff --git a/src/extra/SoundsTutorial/soundsTutorial.py b/src/extra/SoundsTutorial/soundsTutorial.py index 37d9643a..863bebdc 100644 --- a/src/extra/SoundsTutorial/soundsTutorial.py +++ b/src/extra/SoundsTutorial/soundsTutorial.py @@ -1,34 +1,35 @@ -# -*- coding: utf-8 -*- -import platform -import widgetUtils -import os -import paths -import logging -log = logging.getLogger("extra.SoundsTutorial.soundsTutorial") -import soundsTutorial_constants -if platform.system() == "Windows": - import wx_ui as UI -elif platform.system() == "Linux": - import gtk_ui as UI - -class soundsTutorial(object): - def __init__(self, sessionObject): - log.debug("Creating sounds tutorial object...") - super(soundsTutorial, self).__init__() - self.session = sessionObject - self.actions = [] - log.debug("Loading actions for sounds tutorial...") - [self.actions.append(i[1]) for i in soundsTutorial_constants.actions] - self.files = [] - log.debug("Searching sound files...") - [self.files.append(i[0]) for i in soundsTutorial_constants.actions] - log.debug("Creating dialog...") - self.dialog = UI.soundsTutorialDialog(self.actions) - widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play) - self.dialog.get_response() - - def on_play(self, *args, **kwargs): - try: - self.session.sound.play(self.files[self.dialog.get_selection()]+".ogg") - except: +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import platform +import widgetUtils +import os +import paths +import logging +log = logging.getLogger("extra.SoundsTutorial.soundsTutorial") +from . import soundsTutorial_constants +if platform.system() == "Windows": + from . import wx_ui as UI +elif platform.system() == "Linux": + from . import gtk_ui as UI + +class soundsTutorial(object): + def __init__(self, sessionObject): + log.debug("Creating sounds tutorial object...") + super(soundsTutorial, self).__init__() + self.session = sessionObject + self.actions = [] + log.debug("Loading actions for sounds tutorial...") + [self.actions.append(i[1]) for i in soundsTutorial_constants.actions] + self.files = [] + log.debug("Searching sound files...") + [self.files.append(i[0]) for i in soundsTutorial_constants.actions] + log.debug("Creating dialog...") + self.dialog = UI.soundsTutorialDialog(self.actions) + widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play) + self.dialog.get_response() + + def on_play(self, *args, **kwargs): + try: + self.session.sound.play(self.files[self.dialog.get_selection()]+".ogg") + except: log.exception("Error playing the %s sound" % (self.files[self.dialog.items.GetSelection()],)) \ No newline at end of file diff --git a/src/extra/SoundsTutorial/soundsTutorial_constants.py b/src/extra/SoundsTutorial/soundsTutorial_constants.py index ae7cfe63..bed91d68 100644 --- a/src/extra/SoundsTutorial/soundsTutorial_constants.py +++ b/src/extra/SoundsTutorial/soundsTutorial_constants.py @@ -1,28 +1,30 @@ -#-*- coding: utf-8 -*- -import reverse_sort -import application -actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")), - ("create_timeline", _(u"User timeline buffer created.")), - ("delete_timeline", _(u"Buffer destroied.")), - ("dm_received", _(u"Direct message received.")), - ("dm_sent", _(u"Direct message sent.")), - ("error", _(u"Error.")), - ("favourite", _(u"Tweet liked.")), - ("favourites_timeline_updated", _(u"Likes buffer updated.")), - ("geo", _(u"Geotweet.")), -("image", _("Tweet contains one or more images")), -("limit", _(u"Boundary reached.")), - ("list_tweet", _(u"List updated.")), - ("max_length", _(u"Too many characters.")), - ("mention_received", _(u"Mention received.")), - ("new_event", _(u"New event.")), - ("ready", _(u"{0} is ready.").format(application.name,)), - ("reply_send", _(u"Mention sent.")), - ("retweet_send", _(u"Tweet retweeted.")), - ("search_updated", _(u"Search buffer updated.")), - ("tweet_received", _(u"Tweet received.")), - ("tweet_send", _(u"Tweet sent.")), - ("trends_updated", _(u"Trending topics buffer updated.")), - ("tweet_timeline", _(u"New tweet in user timeline buffer.")), - ("update_followers", _(u"New follower.")), - ("volume_changed", _(u"Volume changed."))]) +#-*- coding: utf-8 -*- +from __future__ import absolute_import +#-*- coding: utf-8 -*- +from . import reverse_sort +import application +actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")), + ("create_timeline", _(u"User timeline buffer created.")), + ("delete_timeline", _(u"Buffer destroied.")), + ("dm_received", _(u"Direct message received.")), + ("dm_sent", _(u"Direct message sent.")), + ("error", _(u"Error.")), + ("favourite", _(u"Tweet liked.")), + ("favourites_timeline_updated", _(u"Likes buffer updated.")), + ("geo", _(u"Geotweet.")), +("image", _("Tweet contains one or more images")), +("limit", _(u"Boundary reached.")), + ("list_tweet", _(u"List updated.")), + ("max_length", _(u"Too many characters.")), + ("mention_received", _(u"Mention received.")), + ("new_event", _(u"New event.")), + ("ready", _(u"{0} is ready.").format(application.name,)), + ("reply_send", _(u"Mention sent.")), + ("retweet_send", _(u"Tweet retweeted.")), + ("search_updated", _(u"Search buffer updated.")), + ("tweet_received", _(u"Tweet received.")), + ("tweet_send", _(u"Tweet sent.")), + ("trends_updated", _(u"Trending topics buffer updated.")), + ("tweet_timeline", _(u"New tweet in user timeline buffer.")), + ("update_followers", _(u"New follower.")), + ("volume_changed", _(u"Volume changed."))]) diff --git a/src/extra/SpellChecker/__init__.py b/src/extra/SpellChecker/__init__.py index fedad8a8..7cae11b7 100644 --- a/src/extra/SpellChecker/__init__.py +++ b/src/extra/SpellChecker/__init__.py @@ -1,4 +1,5 @@ -import spellchecker -import platform -if platform.system() == "Windows": - from wx_ui import * \ No newline at end of file +from __future__ import absolute_import +from . import spellchecker +import platform +if platform.system() == "Windows": + from .wx_ui import * \ No newline at end of file diff --git a/src/extra/SpellChecker/spellchecker.py b/src/extra/SpellChecker/spellchecker.py index 62305b80..ec689a29 100644 --- a/src/extra/SpellChecker/spellchecker.py +++ b/src/extra/SpellChecker/spellchecker.py @@ -1,70 +1,71 @@ -# -*- coding: utf-8 -*- -import logging -log = logging.getLogger("extra.SpellChecker.spellChecker") -import wx_ui -import widgetUtils -import output -import config -import languageHandler -from enchant.checker import SpellChecker -from enchant.errors import DictNotFoundError -from enchant import tokenize -import twitterFilter - -class spellChecker(object): - def __init__(self, text, dictionary): - super(spellChecker, self).__init__() - log.debug("Creating the SpellChecker object. Dictionary: %s" % (dictionary,)) - self.active = True - try: - if config.app["app-settings"]["language"] == "system": - log.debug("Using the system language") - self.checker = SpellChecker(languageHandler.curLang[:2], filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter]) - else: - log.debug("Using language: %s" % (languageHandler.getLanguage(),)) - self.checker = SpellChecker(languageHandler.getLanguage()[:2], filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter]) - self.checker.set_text(text) - except DictNotFoundError: - log.exception("Dictionary for language %s not found." % (dictionary,)) - wx_ui.dict_not_found_error() - self.active = False - if self.active == True: - log.debug("Creating dialog...") - self.dialog = wx_ui.spellCheckerDialog() - widgetUtils.connect_event(self.dialog.ignore, widgetUtils.BUTTON_PRESSED, self.ignore) - widgetUtils.connect_event(self.dialog.ignoreAll, widgetUtils.BUTTON_PRESSED, self.ignoreAll) - widgetUtils.connect_event(self.dialog.replace, widgetUtils.BUTTON_PRESSED, self.replace) - widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll) - self.check() - self.dialog.get_response() - self.fixed_text = self.checker.get_text() - - def check(self): - try: - self.checker.next() - textToSay = _(u"Misspelled word: %s") % (self.checker.word,) - context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10)) - self.dialog.set_title(textToSay) - output.speak(textToSay) - self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest()) - except StopIteration: - log.debug("Process finished.") - wx_ui.finished() - self.dialog.Destroy() -# except AttributeError: -# pass - - def ignore(self, ev): - self.check() - - def ignoreAll(self, ev): - self.checker.ignore_always(word=self.checker.word) - self.check() - - def replace(self, ev): - self.checker.replace(self.dialog.get_selected_suggestion()) - self.check() - - def replaceAll(self, ev): - self.checker.replace_always(self.dialog.get_selected_suggestion()) +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import logging +log = logging.getLogger("extra.SpellChecker.spellChecker") +from . import wx_ui +import widgetUtils +import output +import config +import languageHandler +from enchant.checker import SpellChecker +from enchant.errors import DictNotFoundError +from enchant import tokenize +from . import twitterFilter + +class spellChecker(object): + def __init__(self, text, dictionary): + super(spellChecker, self).__init__() + log.debug("Creating the SpellChecker object. Dictionary: %s" % (dictionary,)) + self.active = True + try: + if config.app["app-settings"]["language"] == "system": + log.debug("Using the system language") + self.checker = SpellChecker(languageHandler.curLang[:2], filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter]) + else: + log.debug("Using language: %s" % (languageHandler.getLanguage(),)) + self.checker = SpellChecker(languageHandler.getLanguage()[:2], filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter]) + self.checker.set_text(text) + except DictNotFoundError: + log.exception("Dictionary for language %s not found." % (dictionary,)) + wx_ui.dict_not_found_error() + self.active = False + if self.active == True: + log.debug("Creating dialog...") + self.dialog = wx_ui.spellCheckerDialog() + widgetUtils.connect_event(self.dialog.ignore, widgetUtils.BUTTON_PRESSED, self.ignore) + widgetUtils.connect_event(self.dialog.ignoreAll, widgetUtils.BUTTON_PRESSED, self.ignoreAll) + widgetUtils.connect_event(self.dialog.replace, widgetUtils.BUTTON_PRESSED, self.replace) + widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll) + self.check() + self.dialog.get_response() + self.fixed_text = self.checker.get_text() + + def check(self): + try: + next(self.checker) + textToSay = _(u"Misspelled word: %s") % (self.checker.word,) + context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10)) + self.dialog.set_title(textToSay) + output.speak(textToSay) + self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest()) + except StopIteration: + log.debug("Process finished.") + wx_ui.finished() + self.dialog.Destroy() +# except AttributeError: +# pass + + def ignore(self, ev): + self.check() + + def ignoreAll(self, ev): + self.checker.ignore_always(word=self.checker.word) + self.check() + + def replace(self, ev): + self.checker.replace(self.dialog.get_selected_suggestion()) + self.check() + + def replaceAll(self, ev): + self.checker.replace_always(self.dialog.get_selected_suggestion()) self.check() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/__init__.py b/src/extra/autocompletionUsers/__init__.py index 343ea6c0..02a417fc 100644 --- a/src/extra/autocompletionUsers/__init__.py +++ b/src/extra/autocompletionUsers/__init__.py @@ -1,2 +1,4 @@ -# -*- coding: utf-8 -*- -import completion, settings \ No newline at end of file +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import completion, settings \ No newline at end of file diff --git a/src/extra/autocompletionUsers/completion.py b/src/extra/autocompletionUsers/completion.py index f9c9a516..96aa74f3 100644 --- a/src/extra/autocompletionUsers/completion.py +++ b/src/extra/autocompletionUsers/completion.py @@ -1,47 +1,48 @@ -# -*- coding: utf-8 -*- -import output -import storage -import wx_menu - -class autocompletionUsers(object): - def __init__(self, window, session_id): - super(autocompletionUsers, self).__init__() - self.window = window - self.db = storage.storage(session_id) - - def show_menu(self, mode="tweet"): - position = self.window.get_position() - if mode == "tweet": - text = self.window.get_text() - text = text[:position] - try: - pattern = text.split()[-1] - except IndexError: - output.speak(_(u"You have to start writing")) - return - if pattern.startswith("@") == True: - menu = wx_menu.menu(self.window.text, pattern[1:], mode=mode) - users = self.db.get_users(pattern[1:]) - if len(users) > 0: - menu.append_options(users) - self.window.popup_menu(menu) - menu.destroy() - else: - output.speak(_(u"There are no results in your users database")) - else: - output.speak(_(u"Autocompletion only works for users.")) - elif mode == "dm": - text = self.window.get_user() - try: - pattern = text.split()[-1] - except IndexError: - output.speak(_(u"You have to start writing")) - return - menu = wx_menu.menu(self.window.cb, pattern, mode=mode) - users = self.db.get_users(pattern) - if len(users) > 0: - menu.append_options(users) - self.window.popup_menu(menu) - menu.destroy() - else: +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import output +from . import storage +from . import wx_menu + +class autocompletionUsers(object): + def __init__(self, window, session_id): + super(autocompletionUsers, self).__init__() + self.window = window + self.db = storage.storage(session_id) + + def show_menu(self, mode="tweet"): + position = self.window.get_position() + if mode == "tweet": + text = self.window.get_text() + text = text[:position] + try: + pattern = text.split()[-1] + except IndexError: + output.speak(_(u"You have to start writing")) + return + if pattern.startswith("@") == True: + menu = wx_menu.menu(self.window.text, pattern[1:], mode=mode) + users = self.db.get_users(pattern[1:]) + if len(users) > 0: + menu.append_options(users) + self.window.popup_menu(menu) + menu.destroy() + else: + output.speak(_(u"There are no results in your users database")) + else: + output.speak(_(u"Autocompletion only works for users.")) + elif mode == "dm": + text = self.window.get_user() + try: + pattern = text.split()[-1] + except IndexError: + output.speak(_(u"You have to start writing")) + return + menu = wx_menu.menu(self.window.cb, pattern, mode=mode) + users = self.db.get_users(pattern) + if len(users) > 0: + menu.append_options(users) + self.window.popup_menu(menu) + menu.destroy() + else: output.speak(_(u"There are no results in your users database")) \ No newline at end of file diff --git a/src/extra/autocompletionUsers/manage.py b/src/extra/autocompletionUsers/manage.py index 60e34ddc..858291cf 100644 --- a/src/extra/autocompletionUsers/manage.py +++ b/src/extra/autocompletionUsers/manage.py @@ -1,43 +1,45 @@ -# -*- coding: utf-8 -*- -import storage -import widgetUtils -import wx_manage -from wxUI import commonMessageDialogs - -class autocompletionManage(object): - def __init__(self, session): - super(autocompletionManage, self).__init__() - self.session = session - self.dialog = wx_manage.autocompletionManageDialog() - self.database = storage.storage(self.session.session_id) - self.users = self.database.get_all_users() - self.dialog.put_users(self.users) - widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_user) - widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_user) - self.dialog.get_response() - - 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, *args, **kwargs): - usr = self.dialog.get_user() - if usr == False: - return - try: - data = self.session.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): - if commonMessageDialogs.delete_user_from_db() == widgetUtils.YES: - item = self.dialog.users.get_selected() - user = self.users[item] - self.database.remove_user(user[0]) +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import storage +import widgetUtils +from . import wx_manage +from wxUI import commonMessageDialogs + +class autocompletionManage(object): + def __init__(self, session): + super(autocompletionManage, self).__init__() + self.session = session + self.dialog = wx_manage.autocompletionManageDialog() + self.database = storage.storage(self.session.session_id) + self.users = self.database.get_all_users() + self.dialog.put_users(self.users) + widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_user) + widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_user) + self.dialog.get_response() + + 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, *args, **kwargs): + usr = self.dialog.get_user() + if usr == False: + return + try: + data = self.session.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): + if commonMessageDialogs.delete_user_from_db() == widgetUtils.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 6eb0762d..9a72d4c5 100644 --- a/src/extra/autocompletionUsers/settings.py +++ b/src/extra/autocompletionUsers/settings.py @@ -1,59 +1,61 @@ -# -*- coding: utf-8 -*- -import storage -import widgetUtils -import wx_settings -import manage -import output -from mysc.thread_utils import call_threaded - -class autocompletionSettings(object): - def __init__(self, config, buffer, window): - super(autocompletionSettings, self).__init__() - self.config = config - self.buffer = buffer - self.window = window - self.dialog = wx_settings.autocompletionSettingsDialog() - self.dialog.set("friends_buffer", self.config["mysc"]["save_friends_in_autocompletion_db"]) - self.dialog.set("followers_buffer", self.config["mysc"]["save_followers_in_autocompletion_db"]) - widgetUtils.connect_event(self.dialog.viewList, widgetUtils.BUTTON_PRESSED, self.view_list) - if self.dialog.get_response() == widgetUtils.OK: - call_threaded(self.add_users_to_database) - - def add_users_to_database(self): - self.config["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.get("friends_buffer") - self.config["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.get("followers_buffer") - output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes.")) - database = storage.storage(self.buffer.session.session_id) - if self.dialog.get("followers_buffer") == True: - buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"]) - for i in buffer.session.db[buffer.name]["items"]: - database.set_user(i["screen_name"], i["name"], 1) - else: - database.remove_by_buffer(1) - if self.dialog.get("friends_buffer") == True: - buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"]) - for i in buffer.session.db[buffer.name]["items"]: - database.set_user(i["screen_name"], i["name"], 2) - else: - database.remove_by_buffer(2) - wx_settings.show_success_dialog() - self.dialog.destroy() - - def view_list(self, ev): - q = manage.autocompletionManage(self.buffer.session) - - -def execute_at_startup(window, buffer, config): - database = storage.storage(buffer.session.session_id) - if config["mysc"]["save_followers_in_autocompletion_db"] == True and config["other_buffers"]["show_followers"] == True: - buffer = window.search_buffer("followers", config["twitter"]["user_name"]) - for i in buffer.session.db[buffer.name]: - database.set_user(i["screen_name"], i["name"], 1) - else: - database.remove_by_buffer(1) - if config["mysc"]["save_friends_in_autocompletion_db"] == True and config["other_buffers"]["show_friends"] == True: - buffer = window.search_buffer("friends", config["twitter"]["user_name"]) - for i in buffer.session.db[buffer.name]: - database.set_user(i["screen_name"], i["name"], 2) - else: +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import storage +import widgetUtils +from . import wx_settings +from . import manage +import output +from mysc.thread_utils import call_threaded + +class autocompletionSettings(object): + def __init__(self, config, buffer, window): + super(autocompletionSettings, self).__init__() + self.config = config + self.buffer = buffer + self.window = window + self.dialog = wx_settings.autocompletionSettingsDialog() + self.dialog.set("friends_buffer", self.config["mysc"]["save_friends_in_autocompletion_db"]) + self.dialog.set("followers_buffer", self.config["mysc"]["save_followers_in_autocompletion_db"]) + widgetUtils.connect_event(self.dialog.viewList, widgetUtils.BUTTON_PRESSED, self.view_list) + if self.dialog.get_response() == widgetUtils.OK: + call_threaded(self.add_users_to_database) + + def add_users_to_database(self): + self.config["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.get("friends_buffer") + self.config["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.get("followers_buffer") + output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes.")) + database = storage.storage(self.buffer.session.session_id) + if self.dialog.get("followers_buffer") == True: + buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]["items"]: + database.set_user(i["screen_name"], i["name"], 1) + else: + database.remove_by_buffer(1) + if self.dialog.get("friends_buffer") == True: + buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]["items"]: + database.set_user(i["screen_name"], i["name"], 2) + else: + database.remove_by_buffer(2) + wx_settings.show_success_dialog() + self.dialog.destroy() + + def view_list(self, ev): + q = manage.autocompletionManage(self.buffer.session) + + +def execute_at_startup(window, buffer, config): + database = storage.storage(buffer.session.session_id) + if config["mysc"]["save_followers_in_autocompletion_db"] == True and config["other_buffers"]["show_followers"] == True: + buffer = window.search_buffer("followers", config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]: + database.set_user(i["screen_name"], i["name"], 1) + else: + database.remove_by_buffer(1) + if config["mysc"]["save_friends_in_autocompletion_db"] == True and config["other_buffers"]["show_friends"] == True: + buffer = window.search_buffer("friends", config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]: + database.set_user(i["screen_name"], i["name"], 2) + else: database.remove_by_buffer(2) \ No newline at end of file diff --git a/src/extra/ocr/__init__.py b/src/extra/ocr/__init__.py index d127ddeb..00b69bd8 100644 --- a/src/extra/ocr/__init__.py +++ b/src/extra/ocr/__init__.py @@ -1,2 +1,4 @@ -# -*- coding: utf-8 -*- -import OCRSpace \ No newline at end of file +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import OCRSpace \ No newline at end of file diff --git a/src/extra/translator/__init__.py b/src/extra/translator/__init__.py index be356d51..41de421d 100644 --- a/src/extra/translator/__init__.py +++ b/src/extra/translator/__init__.py @@ -1,6 +1,7 @@ -# -*- coding: utf-8 -*- -import translator -import platform -if platform.system() == "Windows": - import wx_ui as gui +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from . import translator +import platform +if platform.system() == "Windows": + from . import wx_ui as gui \ No newline at end of file diff --git a/src/extra/translator/wx_ui.py b/src/extra/translator/wx_ui.py index 24689421..29032146 100644 --- a/src/extra/translator/wx_ui.py +++ b/src/extra/translator/wx_ui.py @@ -1,45 +1,64 @@ -# -*- coding: utf-8 -*- -############################################################ -# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################ -import translator -import wx -from wxUI.dialogs import baseDialog - -class translateDialog(baseDialog.BaseWXDialog): - def __init__(self): - super(translateDialog, self).__init__(None, -1, title=_(u"Translate message")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - staticSource = wx.StaticText(panel, -1, _(u"Source language")) - self.source_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY) - self.source_lang.SetFocus() - staticDest = wx.StaticText(panel, -1, _(u"Target language")) - self.source_lang.SetSelection(0) - self.dest_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY) - listSizer = wx.BoxSizer(wx.HORIZONTAL) - listSizer.Add(staticSource) - listSizer.Add(self.source_lang) - listSizer.Add(staticDest) - listSizer.Add(self.dest_lang) - ok = wx.Button(panel, wx.ID_OK) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL) - self.SetEscapeId(wx.ID_CANCEL) - - def get(self, control): +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from __future__ import absolute_import +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from . import translator +import wx +from wxUI.dialogs import baseDialog + +class translateDialog(baseDialog.BaseWXDialog): + def __init__(self): + super(translateDialog, self).__init__(None, -1, title=_(u"Translate message")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + staticSource = wx.StaticText(panel, -1, _(u"Source language")) + self.source_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY) + self.source_lang.SetFocus() + staticDest = wx.StaticText(panel, -1, _(u"Target language")) + self.source_lang.SetSelection(0) + self.dest_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY) + listSizer = wx.BoxSizer(wx.HORIZONTAL) + listSizer.Add(staticSource) + listSizer.Add(self.source_lang) + listSizer.Add(staticDest) + listSizer.Add(self.dest_lang) + ok = wx.Button(panel, wx.ID_OK) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL) + self.SetEscapeId(wx.ID_CANCEL) + + def get(self, control): return getattr(self, control).GetSelection() \ No newline at end of file diff --git a/src/fixes/__init__.py b/src/fixes/__init__.py index 354a5875..9c80907f 100644 --- a/src/fixes/__init__.py +++ b/src/fixes/__init__.py @@ -1,15 +1,16 @@ -# -*- coding: utf-8 -*- -""" This module contains some bugfixes for packages used in TWBlue.""" -import sys -import fix_arrow # A few new locales for Three languages in arrow. -import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython. -import fix_win32com -import fix_requests #fix cacert.pem location for TWBlue binary copies -def setup(): - fix_arrow.fix() - if hasattr(sys, "frozen"): - fix_win32com.fix() - fix_requests.fix(True) - else: - fix_requests.fix(False) +# -*- coding: utf-8 -*- +""" This module contains some bugfixes for packages used in TWBlue.""" +from __future__ import absolute_import +import sys +from . import fix_arrow # A few new locales for Three languages in arrow. +from . import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython. +from . import fix_win32com +from . import fix_requests #fix cacert.pem location for TWBlue binary copies +def setup(): + fix_arrow.fix() + if hasattr(sys, "frozen"): + fix_win32com.fix() + fix_requests.fix(True) + else: + fix_requests.fix(False) fix_urllib3_warnings.fix() \ No newline at end of file diff --git a/src/issueReporter/issueReporter.py b/src/issueReporter/issueReporter.py index 21a1b809..937d9b3b 100644 --- a/src/issueReporter/issueReporter.py +++ b/src/issueReporter/issueReporter.py @@ -1,64 +1,65 @@ -# -*- coding: utf-8 -*- -############################################################ -# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################ -import keys -import wx -import wx_ui -import widgetUtils -import application -from suds.client import Client -import constants - -class reportBug(object): - def __init__(self, user_name): - self.user_name = user_name - self.categories = [_(u"General")] - self.reproducibilities = [_(u"always"), _(u"sometimes"), _(u"random"), _(u"have not tried"), _(u"unable to duplicate")] - self.severities = [_(u"block"), _(u"crash"), _(u"major"), _(u"minor"), _(u"tweak"), _(u"text"), _(u"trivial"), _(u"feature")] - self.dialog = wx_ui.reportBugDialog(self.categories, self.reproducibilities, self.severities) - widgetUtils.connect_event(self.dialog.ok, widgetUtils.BUTTON_PRESSED, self.send) - self.dialog.get_response() - - def send(self, *args, **kwargs): - if self.dialog.get("summary") == "" or self.dialog.get("description") == "": - self.dialog.no_filled() - return - if self.dialog.get("agree") == False: - self.dialog.no_checkbox() - return - try: - client = Client(application.report_bugs_url) - issue = client.factory.create('IssueData') - issue.project.name = application.name - issue.project.id = 0 - issue.summary = self.dialog.get("summary"), - issue.description = "Reported by @%s on version %s (snapshot = %s)\n\n" % (self.user_name, application.version, application.snapshot) + self.dialog.get("description") - # to do: Create getters for category, severity and reproducibility in wx_UI. - issue.category = constants.categories[self.dialog.category.GetSelection()] - issue.reproducibility.name = constants.reproducibilities[self.dialog.reproducibility.GetSelection()] - issue.severity.name = constants.severities[self.dialog.severity.GetSelection()] - issue.priority.name = "normal" - issue.view_state.name = "public" - issue.resolution.name = "open" - issue.projection.name = "none" - issue.eta.name = "eta" - issue.status.name = "new" - id = client.service.mc_issue_add(keys.keyring.get("bts_user"), keys.keyring.get("bts_password"), issue) - self.dialog.success(id) - except: - self.dialog.error() +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from __future__ import absolute_import +import keys +import wx +from . import wx_ui +import widgetUtils +import application +from suds.client import Client +from . import constants + +class reportBug(object): + def __init__(self, user_name): + self.user_name = user_name + self.categories = [_(u"General")] + self.reproducibilities = [_(u"always"), _(u"sometimes"), _(u"random"), _(u"have not tried"), _(u"unable to duplicate")] + self.severities = [_(u"block"), _(u"crash"), _(u"major"), _(u"minor"), _(u"tweak"), _(u"text"), _(u"trivial"), _(u"feature")] + self.dialog = wx_ui.reportBugDialog(self.categories, self.reproducibilities, self.severities) + widgetUtils.connect_event(self.dialog.ok, widgetUtils.BUTTON_PRESSED, self.send) + self.dialog.get_response() + + def send(self, *args, **kwargs): + if self.dialog.get("summary") == "" or self.dialog.get("description") == "": + self.dialog.no_filled() + return + if self.dialog.get("agree") == False: + self.dialog.no_checkbox() + return + try: + client = Client(application.report_bugs_url) + issue = client.factory.create('IssueData') + issue.project.name = application.name + issue.project.id = 0 + issue.summary = self.dialog.get("summary"), + issue.description = "Reported by @%s on version %s (snapshot = %s)\n\n" % (self.user_name, application.version, application.snapshot) + self.dialog.get("description") + # to do: Create getters for category, severity and reproducibility in wx_UI. + issue.category = constants.categories[self.dialog.category.GetSelection()] + issue.reproducibility.name = constants.reproducibilities[self.dialog.reproducibility.GetSelection()] + issue.severity.name = constants.severities[self.dialog.severity.GetSelection()] + issue.priority.name = "normal" + issue.view_state.name = "public" + issue.resolution.name = "open" + issue.projection.name = "none" + issue.eta.name = "eta" + issue.status.name = "new" + id = client.service.mc_issue_add(keys.keyring.get("bts_user"), keys.keyring.get("bts_password"), issue) + self.dialog.success(id) + except: + self.dialog.error() diff --git a/src/keyboard_handler/__init__.py b/src/keyboard_handler/__init__.py index 144513d0..6b20bb25 100644 --- a/src/keyboard_handler/__init__.py +++ b/src/keyboard_handler/__init__.py @@ -1,3 +1,4 @@ -from main import KeyboardHandler, KeyboardHandlerError -#from wx_handler import WXKeyboardHandler -__all__ = ["KeyboardHandler", "KeyboardHandlerError", "WXKeyboardHandler", "WXPanelKeyboardHandler"] +from __future__ import absolute_import +from .main import KeyboardHandler, KeyboardHandlerError +#from wx_handler import WXKeyboardHandler +__all__ = ["KeyboardHandler", "KeyboardHandlerError", "WXKeyboardHandler", "WXPanelKeyboardHandler"] diff --git a/src/keyboard_handler/global_handler.py b/src/keyboard_handler/global_handler.py index 2e798f71..fa21f12f 100644 --- a/src/keyboard_handler/global_handler.py +++ b/src/keyboard_handler/global_handler.py @@ -1,7 +1,8 @@ -import platform -if platform.system() == 'Linux': - from linux import LinuxKeyboardHandler as GlobalKeyboardHandler -elif platform.system() == 'Windows': - from wx_handler import WXKeyboardHandler as GlobalKeyboardHandler -elif platform.system() == 'Darwin': - from osx import OSXKeyboardHandler as GlobalKeyboardHandler +from __future__ import absolute_import +import platform +if platform.system() == 'Linux': + from .linux import LinuxKeyboardHandler as GlobalKeyboardHandler +elif platform.system() == 'Windows': + from .wx_handler import WXKeyboardHandler as GlobalKeyboardHandler +elif platform.system() == 'Darwin': + from .osx import OSXKeyboardHandler as GlobalKeyboardHandler diff --git a/src/keyboard_handler/linux.py b/src/keyboard_handler/linux.py index ba69d7ff..25b39114 100644 --- a/src/keyboard_handler/linux.py +++ b/src/keyboard_handler/linux.py @@ -1,58 +1,59 @@ -from main import KeyboardHandler -import threading -import thread -import pyatspi -def parse(s): - """parse a string like control+f into (modifier, key). -Unknown modifiers will return ValueError.""" - m = 0 - lst = s.split('+') - if not len(lst): return (0, s) -#Are these right? - d = { - "shift": 1< 1: #more than one key, parse error - raise ValueError, 'unknown modifier %s' % lst[0] - return (m, lst[0].lower()) -class AtspiThread(threading.Thread): - def run(self): - pyatspi.Registry.registerKeystrokeListener(handler, kind=(pyatspi.KEY_PRESSED_EVENT,), - mask=pyatspi.allModifiers()) - pyatspi.Registry.start() -#the keys we registered -keys = {} -def handler(e): - m,k = e.modifiers,e.event_string.lower() -#not sure why we can't catch control+f. Try to fix it. - if (not e.is_text) and e.id >= 97 <= 126: - k = chr(e.id) - if (m,k) not in keys: return False - thread.start_new(keys[(m,k)], ()) - return True #don't pass it on -class LinuxKeyboardHandler(KeyboardHandler): - def __init__(self, *args, **kwargs): - KeyboardHandler.__init__(self, *args, **kwargs) - t = AtspiThread() - t.start() - def register_key(self, key, function): - """key will be a string, such as control+shift+f. -We need to convert that, using parse_key, -into modifier and key to put into our dictionary.""" -#register key so we know if we have it on event receive. - t = parse(key) - keys[t] = function -#if we got this far, the key is valid. - KeyboardHandler.register_key(self, key, function) - - def unregister_key (self, key, function): - KeyboardHandler.unregister_key(self, key, function) - del keys[parse(key)] +from __future__ import absolute_import +from .main import KeyboardHandler +import threading +import thread +import pyatspi +def parse(s): + """parse a string like control+f into (modifier, key). +Unknown modifiers will return ValueError.""" + m = 0 + lst = s.split('+') + if not len(lst): return (0, s) +#Are these right? + d = { + "shift": 1< 1: #more than one key, parse error + raise ValueError('unknown modifier %s' % lst[0]) + return (m, lst[0].lower()) +class AtspiThread(threading.Thread): + def run(self): + pyatspi.Registry.registerKeystrokeListener(handler, kind=(pyatspi.KEY_PRESSED_EVENT,), + mask=pyatspi.allModifiers()) + pyatspi.Registry.start() +#the keys we registered +keys = {} +def handler(e): + m,k = e.modifiers,e.event_string.lower() +#not sure why we can't catch control+f. Try to fix it. + if (not e.is_text) and e.id >= 97 <= 126: + k = chr(e.id) + if (m,k) not in keys: return False + thread.start_new(keys[(m,k)], ()) + return True #don't pass it on +class LinuxKeyboardHandler(KeyboardHandler): + def __init__(self, *args, **kwargs): + KeyboardHandler.__init__(self, *args, **kwargs) + t = AtspiThread() + t.start() + def register_key(self, key, function): + """key will be a string, such as control+shift+f. +We need to convert that, using parse_key, +into modifier and key to put into our dictionary.""" +#register key so we know if we have it on event receive. + t = parse(key) + keys[t] = function +#if we got this far, the key is valid. + KeyboardHandler.register_key(self, key, function) + + def unregister_key (self, key, function): + KeyboardHandler.unregister_key(self, key, function) + del keys[parse(key)] diff --git a/src/keyboard_handler/main.py b/src/keyboard_handler/main.py index ea040f73..a69cbef6 100644 --- a/src/keyboard_handler/main.py +++ b/src/keyboard_handler/main.py @@ -1,88 +1,88 @@ -import platform -import time - -class KeyboardHandlerError (Exception): pass - -class KeyboardHandler(object): - - def __init__(self, repeat_rate=0.0, *args, **kwargs): - self.repeat_rate = repeat_rate #How long between accepting the same keystroke? - self._last_key = None - self._last_keypress_time = 0 - super(KeyboardHandler, self).__init__(*args, **kwargs) - self.active_keys = {} - if not hasattr(self, 'replacement_mods'): - self.replacement_mods = {} - if not hasattr(self, 'replacement_keys'): - self.replacement_keys = {} - - def register_key (self, key, function): - if key in self.active_keys: - raise KeyboardHandlerError, "Key %s is already registered to a function" % key - if not callable(function): - raise TypeError, "Must provide a callable to be invoked upon keypress" - self.active_keys[key] = function - - def unregister_key (self, key, function): - try: - if self.active_keys[key] != function: - raise KeyboardHandlerError, "key %s is not registered to that function" % key - except KeyError: - raise KeyboardHandlerError, "Key %s not currently registered" - del(self.active_keys[key]) - - def unregister_all_keys(self): - for key in list(self.active_keys): - self.unregister_key(key, self.active_keys[key]) - - def handle_key (self, key): - if self.repeat_rate and key == self._last_key and time.time() - self._last_keypress_time < self.repeat_rate: - return - try: - function = self.active_keys[key] - except KeyError: - return - self._last_key = key - self._last_keypress_time = time.time() - return function() - - def register_keys(self, keys): - """Given a mapping of keystrokes to functions, registers all keystrokes""" - for k in keys: - self.register_key(k, keys[k]) - - def unregister_keys(self, keys): - """Given a mapping of keys to their functions, unregisters all provided keys.""" - for k in keys: - self.unregister_key(k, keys[k]) - - def standardize_key(self, key): - """Takes a keystroke and places it in a standard case and order in a list.""" - working = key.split('+') - working = [i.lower() for i in working] - answer = [] - if "control" in working: - answer.append("control") - if "win" in working: - answer.append("win") - if "alt" in working: - answer.append("alt") - if "shift" in working: - answer.append("shift") - if working[-1] not in answer: - answer.append(working[-1]) - return answer - - def standardize_keymap(self, keymap): - """Given a keymap, returns the keymap standardized.""" - full = {} - for i in keymap: - answer = "" - new = self.standardize_key(keymap[i]) - for (c, j) in enumerate(new): - if c < len(new)-1: - answer = "%s%s+" % (answer, j) - else: - answer = "%s%s" % (answer, j) - full[i] = answer - return full +import platform +import time + +class KeyboardHandlerError (Exception): pass + +class KeyboardHandler(object): + + def __init__(self, repeat_rate=0.0, *args, **kwargs): + self.repeat_rate = repeat_rate #How long between accepting the same keystroke? + self._last_key = None + self._last_keypress_time = 0 + super(KeyboardHandler, self).__init__(*args, **kwargs) + self.active_keys = {} + if not hasattr(self, 'replacement_mods'): + self.replacement_mods = {} + if not hasattr(self, 'replacement_keys'): + self.replacement_keys = {} + + def register_key (self, key, function): + if key in self.active_keys: + raise KeyboardHandlerError("Key %s is already registered to a function" % key) + if not callable(function): + raise TypeError("Must provide a callable to be invoked upon keypress") + self.active_keys[key] = function + + def unregister_key (self, key, function): + try: + if self.active_keys[key] != function: + raise KeyboardHandlerError("key %s is not registered to that function" % key) + except KeyError: + raise KeyboardHandlerError("Key %s not currently registered") + del(self.active_keys[key]) + + def unregister_all_keys(self): + for key in list(self.active_keys): + self.unregister_key(key, self.active_keys[key]) + + def handle_key (self, key): + if self.repeat_rate and key == self._last_key and time.time() - self._last_keypress_time < self.repeat_rate: + return + try: + function = self.active_keys[key] + except KeyError: + return + self._last_key = key + self._last_keypress_time = time.time() + return function() + + def register_keys(self, keys): + """Given a mapping of keystrokes to functions, registers all keystrokes""" + for k in keys: + self.register_key(k, keys[k]) + + def unregister_keys(self, keys): + """Given a mapping of keys to their functions, unregisters all provided keys.""" + for k in keys: + self.unregister_key(k, keys[k]) + + def standardize_key(self, key): + """Takes a keystroke and places it in a standard case and order in a list.""" + working = key.split('+') + working = [i.lower() for i in working] + answer = [] + if "control" in working: + answer.append("control") + if "win" in working: + answer.append("win") + if "alt" in working: + answer.append("alt") + if "shift" in working: + answer.append("shift") + if working[-1] not in answer: + answer.append(working[-1]) + return answer + + def standardize_keymap(self, keymap): + """Given a keymap, returns the keymap standardized.""" + full = {} + for i in keymap: + answer = "" + new = self.standardize_key(keymap[i]) + for (c, j) in enumerate(new): + if c < len(new)-1: + answer = "%s%s+" % (answer, j) + else: + answer = "%s%s" % (answer, j) + full[i] = answer + return full diff --git a/src/keyboard_handler/osx.py b/src/keyboard_handler/osx.py index 12884859..f13de3ec 100644 --- a/src/keyboard_handler/osx.py +++ b/src/keyboard_handler/osx.py @@ -1,56 +1,57 @@ -from AppKit import * -from PyObjCTools import AppHelper -from Carbon.CarbonEvt import RegisterEventHotKey, GetApplicationEventTarget -from Carbon.Events import cmdKey, controlKey -import struct -from threading import Thread - -from main import KeyboardHandler - -kEventHotKeyPressedSubtype = 6 -kEventHotKeyReleasedSubtype = 9 - -class OSXKeyboardHandler(KeyboardHandler): - - def __init__(self): - super(OSXKeyboardHandler, self).__init__() - self.replacement_keys = dict() - self.app = KeyboardCapturingNSApplication.alloc().init() - self._event_thread = Thread(target=AppHelper.runEventLoop) - self._event_thread.start() - - def register_key (self, key, function): - super(OSXKeyboardHandler, self).register_key(key, function) - k, m = self.parse_key(key) - key_id = RegisterEventHotKey(k, m, (0, 0), GetApplicationEventTarget(), 0) - self.key_ids[key] = key_id - - def unregister_key (self, key, function): - super(OSXKeyboardHandler, self).unregister_key(key, function) - key_id = self.key_ids[key] - raise NotImplementedError - - def parse_key (self, key): - key=key.split("+") - #replacements - #Modifier keys: - for index, item in enumerate(key[0:-1]): - if self.replacement_mods.has_key(item): - key[index] = self.replacement_mods[item] - if self.replacement_keys.has_key(key[-1]): - key[-1] = self.replacement_keys[key[-1]] - elif len(key[-1])==1: - key[-1] = ord(str(key[-1]))-36 - mods = 0 - for i in key[:-1]: - mods = mods|i - return [key[-1], mods] - -class KeyboardCapturingNSApplication(NSApplication): - - def sendEvent_(self, theEvent): - if theEvent.type() == NSSystemDefined and theEvent.subtype() == kEventHotKeyPressedSubtype: - self.activateIgnoringOtherApps_(True) - NSRunAlertPanel(u'Hot Key Pressed', u'Hot Key Pressed', None, None, None) - super(NSApplication, self).sendEvent_(theEvent) - +from __future__ import absolute_import +from AppKit import * +from PyObjCTools import AppHelper +from Carbon.CarbonEvt import RegisterEventHotKey, GetApplicationEventTarget +from Carbon.Events import cmdKey, controlKey +import struct +from threading import Thread + +from .main import KeyboardHandler + +kEventHotKeyPressedSubtype = 6 +kEventHotKeyReleasedSubtype = 9 + +class OSXKeyboardHandler(KeyboardHandler): + + def __init__(self): + super(OSXKeyboardHandler, self).__init__() + self.replacement_keys = dict() + self.app = KeyboardCapturingNSApplication.alloc().init() + self._event_thread = Thread(target=AppHelper.runEventLoop) + self._event_thread.start() + + def register_key (self, key, function): + super(OSXKeyboardHandler, self).register_key(key, function) + k, m = self.parse_key(key) + key_id = RegisterEventHotKey(k, m, (0, 0), GetApplicationEventTarget(), 0) + self.key_ids[key] = key_id + + def unregister_key (self, key, function): + super(OSXKeyboardHandler, self).unregister_key(key, function) + key_id = self.key_ids[key] + raise NotImplementedError + + def parse_key (self, key): + key=key.split("+") + #replacements + #Modifier keys: + for index, item in enumerate(key[0:-1]): + if item in self.replacement_mods: + key[index] = self.replacement_mods[item] + if key[-1] in self.replacement_keys: + key[-1] = self.replacement_keys[key[-1]] + elif len(key[-1])==1: + key[-1] = ord(str(key[-1]))-36 + mods = 0 + for i in key[:-1]: + mods = mods|i + return [key[-1], mods] + +class KeyboardCapturingNSApplication(NSApplication): + + def sendEvent_(self, theEvent): + if theEvent.type() == NSSystemDefined and theEvent.subtype() == kEventHotKeyPressedSubtype: + self.activateIgnoringOtherApps_(True) + NSRunAlertPanel(u'Hot Key Pressed', u'Hot Key Pressed', None, None, None) + super(NSApplication, self).sendEvent_(theEvent) + diff --git a/src/keyboard_handler/windows.py b/src/keyboard_handler/windows.py index 4197400b..07144c21 100644 --- a/src/keyboard_handler/windows.py +++ b/src/keyboard_handler/windows.py @@ -1,40 +1,41 @@ -import win32api -import win32con - -from main import KeyboardHandler - -class WindowsKeyboardHandler(KeyboardHandler): - - def __init__ (self, *args, **kwargs): - super(WindowsKeyboardHandler, self).__init__(*args, **kwargs) - #Setup the replacement dictionaries. - for i in dir(win32con): - if i.startswith("VK_"): - key = i[3:].lower() - self.replacement_keys[key] = getattr(win32con, i) - elif i.startswith("MOD_"): - key = i[4:].lower() - self.replacement_mods[key] = getattr(win32con, i) - self.replacement_keys .update(dict(pageup=win32con.VK_PRIOR, pagedown=win32con.VK_NEXT)) - - def parse_key (self, keystroke, separator="+"): - keystroke = str(keystroke) #We don't want unicode - keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)] - mods = 0 - for i in keystroke[:-1]: - mods = mods | i #or everything together - return (mods, keystroke[-1]) - - def keycode_from_key(self, key): - if key in self.replacement_mods: - return self.replacement_mods[key] - if key in self.replacement_keys: - return self.replacement_keys[key] - if len(key) == 1: - return win32api.VkKeyScanEx(key, win32api.GetKeyboardLayout()) - - def is_key_pressed(self, key): - """Returns if the given key was pressed. Requires an active message loop or will simply give if the key was pressed recently.""" - key = self.keycode_from_key(key) - return win32api.GetAsyncKeyState(key) - +from __future__ import absolute_import +import win32api +import win32con + +from .main import KeyboardHandler + +class WindowsKeyboardHandler(KeyboardHandler): + + def __init__ (self, *args, **kwargs): + super(WindowsKeyboardHandler, self).__init__(*args, **kwargs) + #Setup the replacement dictionaries. + for i in dir(win32con): + if i.startswith("VK_"): + key = i[3:].lower() + self.replacement_keys[key] = getattr(win32con, i) + elif i.startswith("MOD_"): + key = i[4:].lower() + self.replacement_mods[key] = getattr(win32con, i) + self.replacement_keys .update(dict(pageup=win32con.VK_PRIOR, pagedown=win32con.VK_NEXT)) + + def parse_key (self, keystroke, separator="+"): + keystroke = str(keystroke) #We don't want unicode + keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)] + mods = 0 + for i in keystroke[:-1]: + mods = mods | i #or everything together + return (mods, keystroke[-1]) + + def keycode_from_key(self, key): + if key in self.replacement_mods: + return self.replacement_mods[key] + if key in self.replacement_keys: + return self.replacement_keys[key] + if len(key) == 1: + return win32api.VkKeyScanEx(key, win32api.GetKeyboardLayout()) + + def is_key_pressed(self, key): + """Returns if the given key was pressed. Requires an active message loop or will simply give if the key was pressed recently.""" + key = self.keycode_from_key(key) + return win32api.GetAsyncKeyState(key) + diff --git a/src/keyboard_handler/wx_handler.py b/src/keyboard_handler/wx_handler.py index 55c24208..8328abb5 100644 --- a/src/keyboard_handler/wx_handler.py +++ b/src/keyboard_handler/wx_handler.py @@ -1,119 +1,121 @@ -import functools -import wx -import platform -from main import KeyboardHandler - -__all__ = ['WXKeyboardHandler', 'WXControlKeyboardHandler'] - - -def call_after(func): - def wrapper(*args, **kwargs): - wx.CallAfter(func, *args, **kwargs) - functools.update_wrapper(wrapper, func) - return wrapper - - -class BaseWXKeyboardHandler(KeyboardHandler): - - def __init__(self, *args, **kwargs): - super(BaseWXKeyboardHandler, self).__init__(*args, **kwargs) - #Setup the replacement dictionaries. - for i in dir(wx): - if i.startswith('WXK_'): - key = i[4:].lower() - self.replacement_keys[key] = getattr(wx, i) - elif i.startswith('MOD_'): - key = i[4:].lower() - self.replacement_mods[key] = getattr(wx, i) - - def parse_key (self, keystroke, separator="+"): - keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)] - mods = 0 - for i in keystroke[:-1]: - mods = mods | i #or everything together - return (mods, keystroke[-1]) - - def keycode_from_key(self, key): - if key in self.replacement_mods: - result = self.replacement_mods[key] - elif key in self.replacement_keys: - result = self.replacement_keys[key] - if result >= 277: - result -= 277 - elif len(key) == 1: - result = ord(key.upper()) - print "result: ", result - return result - - - -#try: -if platform.system() == "Windows": - from windows import WindowsKeyboardHandler as keyboard_handler -elif platform.system() == "Linux": - from linux import LinuxKeyboardHandler as keyboard_handler -elif platform.system() == "Darwin": - from osx import OSXKeyboardHandler as keyboard_handler - -class WXKeyboardHandler(keyboard_handler): - def __init__ (self, parent, *args, **kwargs): - super(WXKeyboardHandler, self).__init__(*args, **kwargs) - self.parent = parent - self.key_ids = {} - - @call_after - def register_key(self, key, function): - super(WXKeyboardHandler, self).register_key(key, function) - key_id = wx.NewId() - parsed = self.parse_key(key) - self.parent.RegisterHotKey(key_id, *parsed) - self.parent.Bind(wx.EVT_HOTKEY, lambda evt: self.process_key(evt, key_id), id=key_id) - self.key_ids[key] = key_id - - @call_after - def unregister_key (self, key, function): - super(WXKeyboardHandler, self).unregister_key(key, function) - if key not in self.key_ids: - return #there's nothing we can do. - key_id = self.key_ids[key] - self.parent.UnregisterHotKey(key_id) - self.parent.Unbind( wx.EVT_HOTKEY, id=key_id) - self.key_ids.pop(key) - - def process_key (self, evt, id): - evt.Skip() - key_ids = self.key_ids.keys() - for i in key_ids: - if self.key_ids.get(i) == id: - self.handle_key(i) - -class WXControlKeyboardHandler(wx.StaticText, KeyboardHandler): - - def __init__(self, parent=None, *a, **k): - wx.StaticText.__init__(self, parent=parent) - KeyboardHandler.__init__(self, *a, **k) - self.wx_replacements = {} - for i in [d for d in dir(wx) if d.startswith('WXK_')]: - self.wx_replacements[getattr(wx, i)] = i[4:].lower() - self.Bind(wx.EVT_KEY_DOWN, self.process_key, self) - self.SetFocus() - - def process_key(self, evt): - keycode = evt.GetKeyCode() - keyname = self.wx_replacements.get(keycode, None) - modifiers = "" - replacements = ( (evt.ControlDown(), 'control+'), - (evt.AltDown(), 'alt+'), - (evt.ShiftDown(), 'shift+'), - (evt.MetaDown(), 'win+') - ) - for mod, ch in (replacements): - if mod: - modifiers += ch - if keyname is None: - if 27 < keycode < 256: - keyname = chr(keycode).lower() - else: - keyname = "(%s)unknown" % keycode - key = modifiers + keyname - self.handle_key(key) +from __future__ import print_function +from __future__ import absolute_import +import functools +import wx +import platform +from .main import KeyboardHandler + +__all__ = ['WXKeyboardHandler', 'WXControlKeyboardHandler'] + + +def call_after(func): + def wrapper(*args, **kwargs): + wx.CallAfter(func, *args, **kwargs) + functools.update_wrapper(wrapper, func) + return wrapper + + +class BaseWXKeyboardHandler(KeyboardHandler): + + def __init__(self, *args, **kwargs): + super(BaseWXKeyboardHandler, self).__init__(*args, **kwargs) + #Setup the replacement dictionaries. + for i in dir(wx): + if i.startswith('WXK_'): + key = i[4:].lower() + self.replacement_keys[key] = getattr(wx, i) + elif i.startswith('MOD_'): + key = i[4:].lower() + self.replacement_mods[key] = getattr(wx, i) + + def parse_key (self, keystroke, separator="+"): + keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)] + mods = 0 + for i in keystroke[:-1]: + mods = mods | i #or everything together + return (mods, keystroke[-1]) + + def keycode_from_key(self, key): + if key in self.replacement_mods: + result = self.replacement_mods[key] + elif key in self.replacement_keys: + result = self.replacement_keys[key] + if result >= 277: + result -= 277 + elif len(key) == 1: + result = ord(key.upper()) + print("result: ", result) + return result + + + +#try: +if platform.system() == "Windows": + from .windows import WindowsKeyboardHandler as keyboard_handler +elif platform.system() == "Linux": + from .linux import LinuxKeyboardHandler as keyboard_handler +elif platform.system() == "Darwin": + from .osx import OSXKeyboardHandler as keyboard_handler + +class WXKeyboardHandler(keyboard_handler): + def __init__ (self, parent, *args, **kwargs): + super(WXKeyboardHandler, self).__init__(*args, **kwargs) + self.parent = parent + self.key_ids = {} + + @call_after + def register_key(self, key, function): + super(WXKeyboardHandler, self).register_key(key, function) + key_id = wx.NewId() + parsed = self.parse_key(key) + self.parent.RegisterHotKey(key_id, *parsed) + self.parent.Bind(wx.EVT_HOTKEY, lambda evt: self.process_key(evt, key_id), id=key_id) + self.key_ids[key] = key_id + + @call_after + def unregister_key (self, key, function): + super(WXKeyboardHandler, self).unregister_key(key, function) + if key not in self.key_ids: + return #there's nothing we can do. + key_id = self.key_ids[key] + self.parent.UnregisterHotKey(key_id) + self.parent.Unbind( wx.EVT_HOTKEY, id=key_id) + self.key_ids.pop(key) + + def process_key (self, evt, id): + evt.Skip() + key_ids = self.key_ids.keys() + for i in key_ids: + if self.key_ids.get(i) == id: + self.handle_key(i) + +class WXControlKeyboardHandler(wx.StaticText, KeyboardHandler): + + def __init__(self, parent=None, *a, **k): + wx.StaticText.__init__(self, parent=parent) + KeyboardHandler.__init__(self, *a, **k) + self.wx_replacements = {} + for i in [d for d in dir(wx) if d.startswith('WXK_')]: + self.wx_replacements[getattr(wx, i)] = i[4:].lower() + self.Bind(wx.EVT_KEY_DOWN, self.process_key, self) + self.SetFocus() + + def process_key(self, evt): + keycode = evt.GetKeyCode() + keyname = self.wx_replacements.get(keycode, None) + modifiers = "" + replacements = ( (evt.ControlDown(), 'control+'), + (evt.AltDown(), 'alt+'), + (evt.ShiftDown(), 'shift+'), + (evt.MetaDown(), 'win+') + ) + for mod, ch in (replacements): + if mod: + modifiers += ch + if keyname is None: + if 27 < keycode < 256: + keyname = chr(keycode).lower() + else: + keyname = "(%s)unknown" % keycode + key = modifiers + keyname + self.handle_key(key) diff --git a/src/keystrokeEditor/__init__.py b/src/keystrokeEditor/__init__.py index aef2cc0f..5b846034 100644 --- a/src/keystrokeEditor/__init__.py +++ b/src/keystrokeEditor/__init__.py @@ -1 +1,2 @@ -from keystrokeEditor import KeystrokeEditor \ No newline at end of file +from __future__ import absolute_import +from .keystrokeEditor import KeystrokeEditor \ No newline at end of file diff --git a/src/keystrokeEditor/keystrokeEditor.py b/src/keystrokeEditor/keystrokeEditor.py index 3f47abbc..55651bfc 100644 --- a/src/keystrokeEditor/keystrokeEditor.py +++ b/src/keystrokeEditor/keystrokeEditor.py @@ -1,58 +1,59 @@ -# -*- coding: utf-8 -*- -import widgetUtils -import config -import wx_ui -import constants -from pubsub import pub - -class KeystrokeEditor(object): - def __init__(self): - super(KeystrokeEditor, self).__init__() - self.changed = False # Change it if the keyboard shorcuts are reassigned. - self.dialog = wx_ui.keystrokeEditorDialog() - self.map = config.keymap["keymap"] - # we need to copy the keymap before modify it, for unregistering the old keystrokes if is needed. - self.hold_map = self.map.copy() - self.dialog.put_keystrokes(constants.actions, self.map) - widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_keystroke) - widgetUtils.connect_event(self.dialog.execute, widgetUtils.BUTTON_PRESSED, self.execute_action) - self.dialog.get_response() - - def edit_keystroke(self, *args, **kwargs): - action = self.dialog.actions[self.dialog.get_action()] - edit_dialog = wx_ui.editKeystrokeDialog() - self.set_keystroke(self.map[action], edit_dialog) - answer = edit_dialog.get_response() - if answer == widgetUtils.OK: - new_keystroke = self.get_edited_keystroke(edit_dialog) - if new_keystroke != self.map[action]: - self.changed = True - self.map[action] = new_keystroke - self.dialog.put_keystrokes(constants.actions, self.map) - - def set_keystroke(self, keystroke, dialog): - for i in keystroke.split("+"): - if hasattr(dialog, i): - dialog.set(i, True) - dialog.set("key", keystroke.split("+")[-1]) - - def get_edited_keystroke(self, dialog): - keys = [] - if dialog.get("control") == True: - keys.append("control") - if dialog.get("win") == True: - keys.append("win") - if dialog.get("alt") == True: - keys.append("alt") - if dialog.get("shift") == True: - keys.append("shift") - if dialog.get("key") != "": - keys.append(dialog.get("key")) - else: - wx_ui.no_key() - return - return "+".join(keys) - - def execute_action(self, *args, **kwargs): - action = self.dialog.actions[self.dialog.get_action()] +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import widgetUtils +import config +from . import wx_ui +from . import constants +from pubsub import pub + +class KeystrokeEditor(object): + def __init__(self): + super(KeystrokeEditor, self).__init__() + self.changed = False # Change it if the keyboard shorcuts are reassigned. + self.dialog = wx_ui.keystrokeEditorDialog() + self.map = config.keymap["keymap"] + # we need to copy the keymap before modify it, for unregistering the old keystrokes if is needed. + self.hold_map = self.map.copy() + self.dialog.put_keystrokes(constants.actions, self.map) + widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_keystroke) + widgetUtils.connect_event(self.dialog.execute, widgetUtils.BUTTON_PRESSED, self.execute_action) + self.dialog.get_response() + + def edit_keystroke(self, *args, **kwargs): + action = self.dialog.actions[self.dialog.get_action()] + edit_dialog = wx_ui.editKeystrokeDialog() + self.set_keystroke(self.map[action], edit_dialog) + answer = edit_dialog.get_response() + if answer == widgetUtils.OK: + new_keystroke = self.get_edited_keystroke(edit_dialog) + if new_keystroke != self.map[action]: + self.changed = True + self.map[action] = new_keystroke + self.dialog.put_keystrokes(constants.actions, self.map) + + def set_keystroke(self, keystroke, dialog): + for i in keystroke.split("+"): + if hasattr(dialog, i): + dialog.set(i, True) + dialog.set("key", keystroke.split("+")[-1]) + + def get_edited_keystroke(self, dialog): + keys = [] + if dialog.get("control") == True: + keys.append("control") + if dialog.get("win") == True: + keys.append("win") + if dialog.get("alt") == True: + keys.append("alt") + if dialog.get("shift") == True: + keys.append("shift") + if dialog.get("key") != "": + keys.append(dialog.get("key")) + else: + wx_ui.no_key() + return + return "+".join(keys) + + def execute_action(self, *args, **kwargs): + action = self.dialog.actions[self.dialog.get_action()] pub.sendMessage("execute-action", action=action) \ No newline at end of file diff --git a/src/keystrokeEditor/wx_ui.py b/src/keystrokeEditor/wx_ui.py index c8162ffa..3a725a90 100644 --- a/src/keystrokeEditor/wx_ui.py +++ b/src/keystrokeEditor/wx_ui.py @@ -1,81 +1,81 @@ -# -*- coding: utf-8 -*- -import wx -from multiplatform_widgets import widgets -from wxUI.dialogs import baseDialog - -class keystrokeEditorDialog(baseDialog.BaseWXDialog): - def __init__(self): - super(keystrokeEditorDialog, self).__init__(parent=None, id=-1, title=_(u"Keystroke editor")) - panel = wx.Panel(self) - self.actions = [] - sizer = wx.BoxSizer(wx.VERTICAL) - keysText = wx.StaticText(panel, -1, _(u"Select a keystroke to edit")) - self.keys = widgets.list(self, _(u"Action"), _(u"Keystroke"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(400, 450)) - self.keys.list.SetFocus() - firstSizer = wx.BoxSizer(wx.HORIZONTAL) - firstSizer.Add(keysText, 0, wx.ALL, 5) - firstSizer.Add(self.keys.list, 0, wx.ALL, 5) - self.edit = wx.Button(panel, -1, _(u"Edit")) - self.edit.SetDefault() - self.execute = wx.Button(panel, -1, _(u"Execute action")) - close = wx.Button(panel, wx.ID_CANCEL, _(u"Close")) - secondSizer = wx.BoxSizer(wx.HORIZONTAL) - secondSizer.Add(self.edit, 0, wx.ALL, 5) - secondSizer.Add(self.execute, 0, wx.ALL, 5) - secondSizer.Add(close, 0, wx.ALL, 5) - sizer.Add(firstSizer, 0, wx.ALL, 5) - sizer.Add(secondSizer, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) - - def put_keystrokes(self, actions, keystrokes): - selection = self.keys.get_selected() - self.keys.clear() - for i in keystrokes: - if actions.has_key(i) == False: - continue - action = actions[i] - self.actions.append(i) - keystroke = keystrokes[i] - self.keys.insert_item(False, *[action, keystroke]) - self.keys.select_item(selection) - - def get_action(self): - return self.keys.get_selected() - -class editKeystrokeDialog(baseDialog.BaseWXDialog): - def __init__(self): - super(editKeystrokeDialog, self).__init__(parent=None, id=-1, title=_(u"Editing keystroke")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.control = wx.CheckBox(panel, -1, _(u"Control")) - self.alt = wx.CheckBox(panel, -1, _(u"Alt")) - self.shift = wx.CheckBox(panel, -1, _(u"Shift")) - self.win = wx.CheckBox(panel, -1, _(u"Windows")) - sizer1 = wx.BoxSizer(wx.HORIZONTAL) - sizer1.Add(self.control) - sizer1.Add(self.alt) - sizer1.Add(self.shift) - sizer1.Add(self.win) - charLabel = wx.StaticText(panel, -1, _(u"Key")) - self.key = wx.TextCtrl(panel, -1) - sizer2 = wx.BoxSizer(wx.HORIZONTAL) - sizer2.Add(charLabel) - sizer2.Add(self.key) - ok = wx.Button(panel, wx.ID_OK, _(u"OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL) - sizer3 = wx.BoxSizer(wx.HORIZONTAL) - sizer3.Add(ok) - sizer3.Add(cancel) - sizer.Add(sizer1) - sizer.Add(sizer2) - sizer.Add(sizer3) - panel.SetSizerAndFit(sizer) - - -def no_win_message(): - return wx.MessageDialog(None, _(u"You need to use the Windows key"), _(u"Invalid keystroke"), wx.OK|wx.ICON_ERROR).ShowModal() - -def no_key(): +# -*- coding: utf-8 -*- +import wx +from multiplatform_widgets import widgets +from wxUI.dialogs import baseDialog + +class keystrokeEditorDialog(baseDialog.BaseWXDialog): + def __init__(self): + super(keystrokeEditorDialog, self).__init__(parent=None, id=-1, title=_(u"Keystroke editor")) + panel = wx.Panel(self) + self.actions = [] + sizer = wx.BoxSizer(wx.VERTICAL) + keysText = wx.StaticText(panel, -1, _(u"Select a keystroke to edit")) + self.keys = widgets.list(self, _(u"Action"), _(u"Keystroke"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(400, 450)) + self.keys.list.SetFocus() + firstSizer = wx.BoxSizer(wx.HORIZONTAL) + firstSizer.Add(keysText, 0, wx.ALL, 5) + firstSizer.Add(self.keys.list, 0, wx.ALL, 5) + self.edit = wx.Button(panel, -1, _(u"Edit")) + self.edit.SetDefault() + self.execute = wx.Button(panel, -1, _(u"Execute action")) + close = wx.Button(panel, wx.ID_CANCEL, _(u"Close")) + secondSizer = wx.BoxSizer(wx.HORIZONTAL) + secondSizer.Add(self.edit, 0, wx.ALL, 5) + secondSizer.Add(self.execute, 0, wx.ALL, 5) + secondSizer.Add(close, 0, wx.ALL, 5) + sizer.Add(firstSizer, 0, wx.ALL, 5) + sizer.Add(secondSizer, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def put_keystrokes(self, actions, keystrokes): + selection = self.keys.get_selected() + self.keys.clear() + for i in keystrokes: + if (i in actions) == False: + continue + action = actions[i] + self.actions.append(i) + keystroke = keystrokes[i] + self.keys.insert_item(False, *[action, keystroke]) + self.keys.select_item(selection) + + def get_action(self): + return self.keys.get_selected() + +class editKeystrokeDialog(baseDialog.BaseWXDialog): + def __init__(self): + super(editKeystrokeDialog, self).__init__(parent=None, id=-1, title=_(u"Editing keystroke")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.control = wx.CheckBox(panel, -1, _(u"Control")) + self.alt = wx.CheckBox(panel, -1, _(u"Alt")) + self.shift = wx.CheckBox(panel, -1, _(u"Shift")) + self.win = wx.CheckBox(panel, -1, _(u"Windows")) + sizer1 = wx.BoxSizer(wx.HORIZONTAL) + sizer1.Add(self.control) + sizer1.Add(self.alt) + sizer1.Add(self.shift) + sizer1.Add(self.win) + charLabel = wx.StaticText(panel, -1, _(u"Key")) + self.key = wx.TextCtrl(panel, -1) + sizer2 = wx.BoxSizer(wx.HORIZONTAL) + sizer2.Add(charLabel) + sizer2.Add(self.key) + ok = wx.Button(panel, wx.ID_OK, _(u"OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL) + sizer3 = wx.BoxSizer(wx.HORIZONTAL) + sizer3.Add(ok) + sizer3.Add(cancel) + sizer.Add(sizer1) + sizer.Add(sizer2) + sizer.Add(sizer3) + panel.SetSizerAndFit(sizer) + + +def no_win_message(): + return wx.MessageDialog(None, _(u"You need to use the Windows key"), _(u"Invalid keystroke"), wx.OK|wx.ICON_ERROR).ShowModal() + +def no_key(): return wx.MessageDialog(None, _(u"You must provide a character for the keystroke"), _(u"Invalid keystroke"), wx.ICON_ERROR).ShowModal() \ No newline at end of file diff --git a/src/long_tweets/tweets.py b/src/long_tweets/tweets.py index 44253e14..74a0b832 100644 --- a/src/long_tweets/tweets.py +++ b/src/long_tweets/tweets.py @@ -1,34 +1,34 @@ -# -*- coding: utf-8 -*- -############################################################ -# Copyright (c) 2015 Manuel Eduardo Cortéz Vallejo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################ -from twitter import utils - -def is_long(tweet): - if tweet.has_key("is_quote_status") and tweet["is_quote_status"] == True and tweet.has_key("quoted_status"): - return tweet["quoted_status_id"] - return False - -def clear_url(tweet): - if tweet.has_key("full_text"): - value = "full_text" - else: - value = "text" - urls = utils.find_urls_in_text(tweet[value]) - try: tweet["message"] = tweet["message"].replace(urls[-1], "") - except IndexError: pass +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2015 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from twitter import utils + +def is_long(tweet): + if "is_quote_status" in tweet and tweet["is_quote_status"] == True and "quoted_status" in tweet: + return tweet["quoted_status_id"] + return False + +def clear_url(tweet): + if "full_text" in tweet: + value = "full_text" + else: + value = "text" + urls = utils.find_urls_in_text(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/long_tweets/twishort.py b/src/long_tweets/twishort.py index 32ed516f..57a55ac0 100644 --- a/src/long_tweets/twishort.py +++ b/src/long_tweets/twishort.py @@ -1,87 +1,88 @@ -# -*- coding: utf-8 -*- -############################################################ -# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################ -import requests -import keys -import logging -log = logging.getLogger("long_tweets.twishort") -from twitter import utils -from requests_oauthlib import OAuth1Session - -def get_twishort_uri(url): - try: - return url.split("twishort.com/")[1] - except ValueError: - return False - -def is_long(tweet): - long = False - 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"]) - 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 tweet.has_key("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"]) - except IndexError: - pass - except TypeError: - pass - return long - -def get_full_text(uri): - try: - r = requests.get("http://api.twishort.com/1.1/get.json", params={"uri": uri, "api_key": keys.keyring.get("twishort_api_key")}) - msg = r.json()["text"] - # Try to parse possible HTML entities. - from twitter.compose import StripChars - msg = StripChars(msg) - return msg - except: - return False - -def create_tweet(user_token, user_secret, text, media=0): - twitter = OAuth1Session(keys.keyring.get("api_key"), client_secret=keys.keyring.get("api_secret"), resource_owner_key=user_token, resource_owner_secret=user_secret) - twishort_key=keys.keyring.get("twishort_api_key") - x_auth_service_provider = "https://api.twitter.com/1.1/account/verify_credentials.json" - twishort_post_url = "http://api.twishort.com/1.1/post.json" - twishort_update_ids_url = "http://api.twishort.com/1.1/update_ids.json" - r=requests.Request('GET', x_auth_service_provider) - prep=twitter.prepare_request(r) - resp=twitter.send(prep) - twitter.headers={ - 'X-Auth-Service-Provider':x_auth_service_provider, - 'X-Verify-Credentials-Authorization':prep.headers['Authorization'], - } - data = {'api_key':twishort_key, - "text": text.encode("utf-8"), - "media": media} - response = twitter.post(twishort_post_url, data=data) - try: - return response.json()["text_to_tweet"] - except: - print "There was a problem creating a long tweet" - return 0 +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from __future__ import print_function +import requests +import keys +import logging +log = logging.getLogger("long_tweets.twishort") +from twitter import utils +from requests_oauthlib import OAuth1Session + +def get_twishort_uri(url): + try: + return url.split("twishort.com/")[1] + except ValueError: + return False + +def is_long(tweet): + long = False + 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"]) + 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"])): + 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"]) + except IndexError: + pass + except TypeError: + pass + return long + +def get_full_text(uri): + try: + r = requests.get("http://api.twishort.com/1.1/get.json", params={"uri": uri, "api_key": keys.keyring.get("twishort_api_key")}) + msg = r.json()["text"] + # Try to parse possible HTML entities. + from twitter.compose import StripChars + msg = StripChars(msg) + return msg + except: + return False + +def create_tweet(user_token, user_secret, text, media=0): + twitter = OAuth1Session(keys.keyring.get("api_key"), client_secret=keys.keyring.get("api_secret"), resource_owner_key=user_token, resource_owner_secret=user_secret) + twishort_key=keys.keyring.get("twishort_api_key") + x_auth_service_provider = "https://api.twitter.com/1.1/account/verify_credentials.json" + twishort_post_url = "http://api.twishort.com/1.1/post.json" + twishort_update_ids_url = "http://api.twishort.com/1.1/update_ids.json" + r=requests.Request('GET', x_auth_service_provider) + prep=twitter.prepare_request(r) + resp=twitter.send(prep) + twitter.headers={ + 'X-Auth-Service-Provider':x_auth_service_provider, + 'X-Verify-Credentials-Authorization':prep.headers['Authorization'], + } + data = {'api_key':twishort_key, + "text": text.encode("utf-8"), + "media": media} + response = twitter.post(twishort_post_url, data=data) + try: + return response.json()["text_to_tweet"] + except: + print("There was a problem creating a long tweet") + return 0 diff --git a/src/multiplatform_widgets/__init__.py b/src/multiplatform_widgets/__init__.py index 126802d0..1f4fb8e1 100644 --- a/src/multiplatform_widgets/__init__.py +++ b/src/multiplatform_widgets/__init__.py @@ -1 +1,2 @@ -import widgets \ No newline at end of file +from __future__ import absolute_import +from . import widgets \ No newline at end of file diff --git a/src/notifier/__init__.py b/src/notifier/__init__.py index 3bd1ff6e..5d95e458 100644 --- a/src/notifier/__init__.py +++ b/src/notifier/__init__.py @@ -1,21 +1,22 @@ -# -*- coding: utf-8 -*- -""" A cross platform notification system. -Under Linux, the wx.NotificationMessage does not show a notification on the taskbar, so we decided to use dbus for showing notifications for linux and wx for Windows.""" -import platform - -notify = None - -def setup(): - global notify - if platform.system() == "Windows": - import windows - notify = windows.notification() - elif platform.system() == "Linux": - import linux - notify = linux.notification() - -def send(title, text): - global notify - if not notify or notify is None: - setup() +# -*- coding: utf-8 -*- +""" A cross platform notification system. +Under Linux, the wx.NotificationMessage does not show a notification on the taskbar, so we decided to use dbus for showing notifications for linux and wx for Windows.""" +from __future__ import absolute_import +import platform + +notify = None + +def setup(): + global notify + if platform.system() == "Windows": + from . import windows + notify = windows.notification() + elif platform.system() == "Linux": + from . import linux + notify = linux.notification() + +def send(title, text): + global notify + if not notify or notify is None: + setup() notify.notify(title, text) \ No newline at end of file diff --git a/src/platform_utils/autostart/windows.py b/src/platform_utils/autostart/windows.py index 9447540f..f4ada511 100644 --- a/src/platform_utils/autostart/windows.py +++ b/src/platform_utils/autostart/windows.py @@ -1,41 +1,42 @@ -import _winreg -import os -import sys -from platform_utils import paths - -RUN_REGKEY = ur"SOFTWARE\Microsoft\Windows\CurrentVersion\Run" - -def is_installed(app_subkey): - """Checks if the currently running copy is installed or portable variant. Requires the name of the application subkey found under the uninstall section in Windows registry.""" - - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s" % app_subkey) - inst_dir = _winreg.QueryValueEx(key,"InstallLocation")[0] - except WindowsError: - return False - _winreg.CloseKey(key) - try: - return os.stat(inst_dir) == os.stat(paths.app_path()) - except WindowsError: - return False - -def getAutoStart(app_name): - """Queries if the automatic startup should be set for the application or not, depending on it's current state.""" - - try: - key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, RUN_REGKEY) - val = _winreg.QueryValueEx(key, unicode(app_name))[0] - return os.stat(val) == os.stat(sys.argv[0]) - except (WindowsError, OSError): - return False - -def setAutoStart(app_name, enable=True): - """Configures automatic startup for the application, if the enable argument is set to True. If set to False, deletes the application AutoStart value.""" - print paths.get_executable() - if getAutoStart(app_name) == enable: - return - key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, RUN_REGKEY, 0, _winreg.KEY_WRITE) - if enable: - _winreg.SetValueEx(key, unicode(app_name), None, _winreg.REG_SZ, paths.get_executable()) - else: - _winreg.DeleteValue(key, unicode(app_name)) +from __future__ import print_function +import _winreg +import os +import sys +from platform_utils import paths + +RUN_REGKEY = ur"SOFTWARE\Microsoft\Windows\CurrentVersion\Run" + +def is_installed(app_subkey): + """Checks if the currently running copy is installed or portable variant. Requires the name of the application subkey found under the uninstall section in Windows registry.""" + + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s" % app_subkey) + inst_dir = _winreg.QueryValueEx(key,"InstallLocation")[0] + except WindowsError: + return False + _winreg.CloseKey(key) + try: + return os.stat(inst_dir) == os.stat(paths.app_path()) + except WindowsError: + return False + +def getAutoStart(app_name): + """Queries if the automatic startup should be set for the application or not, depending on it's current state.""" + + try: + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, RUN_REGKEY) + val = _winreg.QueryValueEx(key, unicode(app_name))[0] + return os.stat(val) == os.stat(sys.argv[0]) + except (WindowsError, OSError): + return False + +def setAutoStart(app_name, enable=True): + """Configures automatic startup for the application, if the enable argument is set to True. If set to False, deletes the application AutoStart value.""" + print(paths.get_executable()) + if getAutoStart(app_name) == enable: + return + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, RUN_REGKEY, 0, _winreg.KEY_WRITE) + if enable: + _winreg.SetValueEx(key, unicode(app_name), None, _winreg.REG_SZ, paths.get_executable()) + else: + _winreg.DeleteValue(key, unicode(app_name)) diff --git a/src/sessionmanager/manager.py b/src/sessionmanager/manager.py index 0fd9b5d8..58d54d06 100644 --- a/src/sessionmanager/manager.py +++ b/src/sessionmanager/manager.py @@ -1,49 +1,50 @@ -# -*- coding: cp1252 -*- -#from config_utils import Configuration, ConfigurationResetException -import config -import paths -import os -import logging -log = logging.getLogger("sessionmanager.manager") -import session_exceptions - -manager = None -def setup(): - global manager - if not manager: - manager = sessionManager() - -class sessionManager(object): -# def __init__(self): -# FILE = "sessions.conf" -# SPEC = "app-configuration.defaults" -# try: -# self.main = Configuration(paths.config_path(FILE), paths.app_path(SPEC)) -# except ConfigurationResetException: -# pass - - def get_current_session(self): - if self.is_valid(config.app["sessions"]["current_session"]): - return config.app["sessions"]["current_session"] - else: - return False - - def add_session(self, id): - log.debug("Adding a new session: %s" % (id,)) - path = paths.config_path(id) - if not os.path.exists(path): - log.debug("Creating %s path" % (paths.config_path(path),)) - os.mkdir(path) - config.app["sessions"]["sessions"].append(id) - - def set_current_session(self, sessionID): - config.app["sessions"]["current_session"] = sessionID - config.app.write() - - def is_valid(self, id): - if not os.path.exists(paths.config_path(id)): - raise session_exceptions.NonExistentSessionError("That session does not exist.") - config.app["sessions"]["current_session"] = "" - return False - else: +# -*- coding: cp1252 -*- +#from config_utils import Configuration, ConfigurationResetException +from __future__ import absolute_import +import config +import paths +import os +import logging +log = logging.getLogger("sessionmanager.manager") +from . import session_exceptions + +manager = None +def setup(): + global manager + if not manager: + manager = sessionManager() + +class sessionManager(object): +# def __init__(self): +# FILE = "sessions.conf" +# SPEC = "app-configuration.defaults" +# try: +# self.main = Configuration(paths.config_path(FILE), paths.app_path(SPEC)) +# except ConfigurationResetException: +# pass + + def get_current_session(self): + if self.is_valid(config.app["sessions"]["current_session"]): + return config.app["sessions"]["current_session"] + else: + return False + + def add_session(self, id): + log.debug("Adding a new session: %s" % (id,)) + path = paths.config_path(id) + if not os.path.exists(path): + log.debug("Creating %s path" % (paths.config_path(path),)) + os.mkdir(path) + config.app["sessions"]["sessions"].append(id) + + def set_current_session(self, sessionID): + config.app["sessions"]["current_session"] = sessionID + config.app.write() + + def is_valid(self, id): + if not os.path.exists(paths.config_path(id)): + raise session_exceptions.NonExistentSessionError("That session does not exist.") + config.app["sessions"]["current_session"] = "" + return False + else: return True \ No newline at end of file diff --git a/src/sessionmanager/session.py b/src/sessionmanager/session.py index f0732a45..5b376800 100644 --- a/src/sessionmanager/session.py +++ b/src/sessionmanager/session.py @@ -1,482 +1,483 @@ -# -*- coding: utf-8 -*- -""" The main session object. Here are the twitter functions to interact with the "model" of TWBlue.""" -import urllib2 -import config -import twitter -from keys import keyring -import session_exceptions as Exceptions -import paths -import output -import time -import sound -import logging -from twitter import utils, compose -from twython import TwythonError, TwythonRateLimitError, TwythonAuthError -import config_utils -import shelve -import application -import os -from mysc.thread_utils import stream_threaded -from pubsub import pub -log = logging.getLogger("sessionmanager.session") -from long_tweets import tweets, twishort - -sessions = {} - -class Session(object): - """ A session object where we will save configuration, the twitter object and a local storage for saving the items retrieved through the Twitter API methods""" - - # Decorators. - - def _require_login(fn): - - """ Decorator for checking if the user is logged in(a twitter object has credentials) on twitter. - Some functions may need this to avoid making unneeded twitter API calls.""" - - def f(self, *args, **kwargs): - if self.logged == True: - fn(self, *args, **kwargs) - else: - raise Exceptions.NotLoggedSessionError("You are not logged in yet.") - return f - - def _require_configuration(fn): - - """ Check if the user has a configured session.""" - - def f(self, *args, **kwargs): - if self.settings != None: - fn(self, *args, **kwargs) - else: - raise Exceptions.NotConfiguredSessionError("Not configured.") - return f - - def order_buffer(self, name, data, ignore_older=True): - - """ Put the new items in the local database. - name str: The name for the buffer stored in the dictionary. - data list: A list with tweets. - returns the number of items that have been added in this execution""" - - num = 0 - last_id = None - if self.db.has_key(name) == False: - self.db[name] = [] - if ignore_older and len(self.db[name]) > 0: - if self.settings["general"]["reverse_timelines"] == False: - last_id = self.db[name][0]["id"] - else: - 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"])) - continue - if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings["twitter"]["ignored_clients"]) == True: - try: i = self.check_quoted_status(i) - except: pass - 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 - return num - - def order_cursored_buffer(self, name, data): - - """ Put the 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""" - - num = 0 - if self.db.has_key(name) == False: - self.db[name] = {} - self.db[name]["items"] = [] -# if len(self.db[name]["items"]) > 0: - 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) - num = num+1 - return num - - def __init__(self, session_id): - - """ session_id (str): The name of the folder inside the config directory where the session is located.""" - - super(Session, self).__init__() - self.session_id = session_id - self.logged = False - self.settings = None - self.twitter = twitter.twitter.twitter() - self.db={} - self.reconnection_function_active = False - self.counter = 0 - self.lists = [] - pub.subscribe(self.add_friends, "friends-receibed") - - @property - def is_logged(self): - return self.logged - - def get_configuration(self): - - """ Gets settings for a session.""" - - file_ = "%s/session.conf" % (self.session_id,) -# try: - log.debug("Creating config file %s" % (file_,)) - self.settings = config_utils.load_config(paths.config_path(file_), paths.app_path("Conf.defaults")) - self.init_sound() - self.deshelve() -# except: -# log.exception("The session configuration has failed.") -# self.settings = None - - def init_sound(self): - try: self.sound = sound.soundSystem(self.settings["sound"]) - except: log.exception("Exception thrown during sound system initialization") - - @_require_configuration - def login(self, verify_credentials=True): - - """ Log into twitter using credentials from settings. - if the user account isn't authorised, it needs to call self.authorise() before login.""" - - if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None: - try: - log.debug("Logging in to twitter...") - self.twitter.login(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], verify_credentials) - self.logged = True - log.debug("Logged.") - self.counter = 0 - except: - log.error("The login attempt failed.") - self.logged = False - else: - self.logged = False - raise Exceptions.RequireCredentialsSessionError - - @_require_configuration - def authorise(self): - - """ Authorises a Twitter account. This function needs to be called for each new session, after self.get_configuration() and before self.login()""" - - if self.logged == True: - raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.") - else: - self.twitter.authorise(self.settings) - - def get_more_items(self, update_function, users=False, name=None, *args, **kwargs): - results = [] - data = getattr(self.twitter.twitter, update_function)(*args, **kwargs) - if users == True: - if type(data) == dict and data.has_key("cursor"): - self.db[name]["cursor"] = data["next_cursor"] - for i in data["users"]: results.append(i) - elif type(data) == list: - results.extend(data[1:]) - else: - results.extend(data[1:]) - return results - - def api_call(self, call_name, action="", _sound=None, report_success=False, report_failure=True, preexec_message="", *args, **kwargs): - - """ Make a call to the Twitter API. If there is a connectionError or another exception not related to Twitter, It will call the method again at least 25 times, waiting a while between calls. Useful for post methods. - If twitter returns an error, it will not call the method anymore. - call_name str: The method to call - action str: What you are doing on twitter, it will be reported to the user if report_success is set to True. - for example "following @tw_blue2" will be reported as "following @tw_blue2 succeeded". - _sound str: a sound to play if the call is executed properly. - report_success and report_failure bool: These are self explanatory. True or False. - preexec_message str: A message to speak to the user while the method is running, example: "trying to follow x user".""" - - finished = False - tries = 0 - if preexec_message: - output.speak(preexec_message, True) - while finished==False and tries < 25: - try: - val = getattr(self.twitter.twitter, call_name)(*args, **kwargs) - finished = True - except TwythonError as e: - output.speak(e.message) - 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.message)) - finished = True -# except: -# tries = tries + 1 -# time.sleep(5) - if report_success: - output.speak(_("%s succeeded.") % action) - if _sound != None: self.sound.play(_sound) - return val - - def search(self, name, *args, **kwargs): - tl = self.twitter.twitter.search(*args, **kwargs) - tl["statuses"].reverse() - return tl["statuses"] - - @_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.""" - - tl = self.call_paged(self.twitter.twitter.get_favorites, *args, **kwargs) - return self.order_buffer(name, tl) - - def call_paged(self, update_function, *args, **kwargs): - - """ Makes a call to the Twitter API methods several times. Useful for get methods. - this function is needed for retrieving more than 200 items. - update_function str: The function to call. This function must be child of self.twitter.twitter - returns a list with all items retrieved.""" - - max = int(self.settings["general"]["max_api_calls"])-1 - results = [] - data = getattr(self.twitter.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"] - data = getattr(self.twitter.twitter, update_function)(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) - results.extend(data) - results.reverse() - return results - - @_require_login - def get_user_info(self): - - """ Retrieves some information required by TWBlue for setup.""" - f = self.twitter.twitter.get_account_settings() - sn = f["screen_name"] - self.settings["twitter"]["user_name"] = sn - self.db["user_name"] = sn - self.db["user_id"] = self.twitter.twitter.show_user(screen_name=sn)["id_str"] - try: - self.db["utc_offset"] = f["time_zone"]["utc_offset"] - except KeyError: - self.db["utc_offset"] = -time.timezone - self.get_lists() - self.get_muted_users() - self.settings.write() - - @_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.twitter.show_lists(reverse=True) - - @_require_login - def get_muted_users(self): - - """ Gets muted users (oh really?).""" - - self.db["muted_users"] = self.twitter.twitter.list_mute_ids()["ids"] - - @_require_login - def get_stream(self, name, function, *args, **kwargs): - - """ Retrieves the items for a regular stream. - name str: Name to save items to the database. - function str: A function to get the items.""" - - last_id = -1 - if self.db.has_key(name): - try: - if self.db[name][0]["id"] > self.db[name][-1]["id"]: - last_id = self.db[name][0]["id"] - else: - last_id = self.db[name][-1]["id"] - except IndexError: - pass - tl = self.call_paged(function, sinze_id=last_id, *args, **kwargs) - self.order_buffer(name, tl) - - def get_cursored_stream(self, name, function, items="users", get_previous=False, *args, **kwargs): - - """ Gets items for API calls that require using cursors to paginate the results. - name str: Name to save it in the database. - function str: Function that provides the items. - items: When the function returns the list with results, items will tell how the order function should be look. - for example get_followers_list returns a list and users are under list["users"], here the items should point to "users".""" - - items_ = [] - try: - if self.db[name].has_key("cursor") and get_previous: - cursor = self.db[name]["cursor"] - else: - cursor = -1 - except KeyError: - cursor = -1 - tl = getattr(self.twitter.twitter, function)(cursor=cursor, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) - tl[items].reverse() - num = self.order_cursored_buffer(name, tl[items]) - self.db[name]["cursor"] = tl["next_cursor"] - return num - - def start_streaming(self): - - """ Start the streaming for sending tweets in realtime.""" - if not hasattr(self, "main_stream"): - self.get_timelines() - if not hasattr(self, "timelinesStream"): - self.get_main_stream() - - def get_main_stream(self): - log.debug("Starting the main stream...") - self.main_stream = twitter.buffers.stream.streamer(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], self) - stream_threaded(self.main_stream.user, self.session_id) - - def get_timelines(self): - log.debug("Starting the timelines stream...") - self.timelinesStream = twitter.buffers.indibidual.timelinesStreamer(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], session=self) - ids = "" - for i in self.settings["other_buffers"]["timelines"]: - ids = ids + "%s, " % (self.db[i+"-timeline"][0]["user"]["id_str"]) - for i in self.lists: - for z in i.users: - ids += str(z) + ", " - if ids != "": -# print ids - stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids) - - def add_friends(self): - try: -# print "setting friends" - self.timelinesStream.set_friends(self.main_stream.friends) - except AttributeError: - pass - - def listen_stream_error(self): - if hasattr(self, "main_stream"): - log.debug("Disconnecting the main stream...") - self.main_stream.disconnect() - del self.main_stream - if hasattr(self, "timelinesStream"): - log.debug("disconnecting the timelines stream...") - self.timelinesStream.disconnect() - del self.timelinesStream - - def check_connection(self): - instan = 0 - self.counter += 1 - if self.counter >= 4: - del self.twitter - self.logged = False - self.twitter = twitter.twitter.twitter() - self.login(False) - pub.sendMessage("restart_streams", session=self.session_id) - if self.reconnection_function_active == True: return - self.reconnection_function_active = True - if not hasattr(self, "main_stream"): - self.get_main_stream() - if not hasattr(self, "timelinesStream"): - self.get_timelines() - self.reconnection_function_active = False - if hasattr(self, "timelinesStream") and not hasattr(self.timelinesStream, "friends"): - self.add_friends() -# try: -# urllib2.urlopen("http://74.125.228.231", timeout=5) -# except urllib2.URLError: -# pub.sendMessage("stream-error", session=self.session_id) - - def remove_stream(self, stream): - if stream == "timelinesStream": - if hasattr(self, "timelinesStream"): - self.timelinesStream.disconnect() - del self.timelinesStream - else: - self.main_stream.disconnect() - del self.main_stream - - def shelve(self): - "Shelve the database to allow for persistance." - shelfname=paths.config_path(str(self.session_id)+"/cache.db") - if self.settings["general"]["persist_size"] == 0: - if os.path.exists(shelfname): - os.remove(shelfname) - return - try: - if not os.path.exists(shelfname): - output.speak("Generating database, this might take a while.",True) - shelf=shelve.open(paths.config_path(shelfname),'c') - for key,value in self.db.items(): - if type(key) != str and type(key) != unicode: - output.speak("Uh oh, while shelving the database, a key of type " + str(type(key)) + " has been found. It will be converted to type str, but this will cause all sorts of problems on deshelve. Please bring this to the attention of the " + application.name + " developers immediately. More information about the error will be written to the error log.",True) - log.error("Uh oh, " + str(key) + " is of type " + str(type(key)) + "!") - # Convert unicode objects to UTF-8 strings before shelve these objects. - if type(value) == list and self.settings["general"]["persist_size"] != -1 and len(value) > self.settings["general"]["persist_size"]: - shelf[str(key.encode("utf-8"))]=value[self.settings["general"]["persist_size"]:] - else: - shelf[str(key.encode("utf-8"))]=value - shelf.close() - except: - output.speak("An exception occurred while shelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True) - log.exception("Exception while shelving" + shelfname) - os.remove(shelfname) - - def deshelve(self): - "Import a shelved database." - shelfname=paths.config_path(str(self.session_id)+"/cache.db") - if self.settings["general"]["persist_size"] == 0: - if os.path.exists(shelfname): - os.remove(shelfname) - return - try: - shelf=shelve.open(paths.config_path(shelfname),'c') - for key,value in shelf.items(): - self.db[key]=value - shelf.close() - except: - output.speak("An exception occurred while deshelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True) - log.exception("Exception while deshelving" + shelfname) - try: - os.remove(shelfname) - except: - pass - - def check_quoted_status(self, tweet): - status = tweets.is_long(tweet) - if status != False and config.app["app-settings"]["handle_longtweets"]: - tweet = self.get_quoted_tweet(tweet) - return tweet - - def get_quoted_tweet(self, tweet): - quoted_tweet = tweet - if tweet.has_key("full_text"): - value = "full_text" - else: - value = "text" - urls = utils.find_urls_in_text(quoted_tweet[value]) - for url in range(0, len(urls)): - try: quoted_tweet[value] = quoted_tweet[value].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass - id = tweets.is_long(quoted_tweet) - try: original_tweet = self.twitter.twitter.show_status(id=id, tweet_mode="extended") - except: return quoted_tweet - original_tweet = self.check_long_tweet(original_tweet) - urls = utils.find_urls_in_text(original_tweet["full_text"]) - for url in range(0, len(urls)): - try: original_tweet["full_text"] = original_tweet["full_text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass - return compose.compose_quoted_tweet(quoted_tweet, original_tweet) - - def check_long_tweet(self, tweet): - long = twishort.is_long(tweet) - if long != False and config.app["app-settings"]["handle_longtweets"]: - tweet["message"] = twishort.get_full_text(long) - 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 tweet.has_key("retweeted_status") and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]: - continue - tweet["message"] = u"@%s %s" % (i["screen_name"], tweet["message"]) +# -*- coding: utf-8 -*- +""" The main session object. Here are the twitter functions to interact with the "model" of TWBlue.""" +from __future__ import absolute_import +import urllib2 +import config +import twitter +from keys import keyring +from . import session_exceptions as Exceptions +import paths +import output +import time +import sound +import logging +from twitter import utils, compose +from twython import TwythonError, TwythonRateLimitError, TwythonAuthError +import config_utils +import shelve +import application +import os +from mysc.thread_utils import stream_threaded +from pubsub import pub +log = logging.getLogger("sessionmanager.session") +from long_tweets import tweets, twishort + +sessions = {} + +class Session(object): + """ A session object where we will save configuration, the twitter object and a local storage for saving the items retrieved through the Twitter API methods""" + + # Decorators. + + def _require_login(fn): + + """ Decorator for checking if the user is logged in(a twitter object has credentials) on twitter. + Some functions may need this to avoid making unneeded twitter API calls.""" + + def f(self, *args, **kwargs): + if self.logged == True: + fn(self, *args, **kwargs) + else: + raise Exceptions.NotLoggedSessionError("You are not logged in yet.") + return f + + def _require_configuration(fn): + + """ Check if the user has a configured session.""" + + def f(self, *args, **kwargs): + if self.settings != None: + fn(self, *args, **kwargs) + else: + raise Exceptions.NotConfiguredSessionError("Not configured.") + return f + + def order_buffer(self, name, data, ignore_older=True): + + """ Put the new items in the local database. + name str: The name for the buffer stored in the dictionary. + data list: A list with tweets. + returns the number of items that have been added in this execution""" + + num = 0 + last_id = None + if (name in self.db) == False: + self.db[name] = [] + if ignore_older and len(self.db[name]) > 0: + if self.settings["general"]["reverse_timelines"] == False: + last_id = self.db[name][0]["id"] + else: + 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"])) + continue + if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings["twitter"]["ignored_clients"]) == True: + try: i = self.check_quoted_status(i) + except: pass + 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 + return num + + def order_cursored_buffer(self, name, data): + + """ Put the 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""" + + num = 0 + if (name in self.db) == False: + self.db[name] = {} + self.db[name]["items"] = [] +# if len(self.db[name]["items"]) > 0: + 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) + num = num+1 + return num + + def __init__(self, session_id): + + """ session_id (str): The name of the folder inside the config directory where the session is located.""" + + super(Session, self).__init__() + self.session_id = session_id + self.logged = False + self.settings = None + self.twitter = twitter.twitter.twitter() + self.db={} + self.reconnection_function_active = False + self.counter = 0 + self.lists = [] + pub.subscribe(self.add_friends, "friends-receibed") + + @property + def is_logged(self): + return self.logged + + def get_configuration(self): + + """ Gets settings for a session.""" + + file_ = "%s/session.conf" % (self.session_id,) +# try: + log.debug("Creating config file %s" % (file_,)) + self.settings = config_utils.load_config(paths.config_path(file_), paths.app_path("Conf.defaults")) + self.init_sound() + self.deshelve() +# except: +# log.exception("The session configuration has failed.") +# self.settings = None + + def init_sound(self): + try: self.sound = sound.soundSystem(self.settings["sound"]) + except: log.exception("Exception thrown during sound system initialization") + + @_require_configuration + def login(self, verify_credentials=True): + + """ Log into twitter using credentials from settings. + if the user account isn't authorised, it needs to call self.authorise() before login.""" + + if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None: + try: + log.debug("Logging in to twitter...") + self.twitter.login(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], verify_credentials) + self.logged = True + log.debug("Logged.") + self.counter = 0 + except: + log.error("The login attempt failed.") + self.logged = False + else: + self.logged = False + raise Exceptions.RequireCredentialsSessionError + + @_require_configuration + def authorise(self): + + """ Authorises a Twitter account. This function needs to be called for each new session, after self.get_configuration() and before self.login()""" + + if self.logged == True: + raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.") + else: + self.twitter.authorise(self.settings) + + def get_more_items(self, update_function, users=False, name=None, *args, **kwargs): + results = [] + data = getattr(self.twitter.twitter, update_function)(*args, **kwargs) + if users == True: + if type(data) == dict and "cursor" in data: + self.db[name]["cursor"] = data["next_cursor"] + for i in data["users"]: results.append(i) + elif type(data) == list: + results.extend(data[1:]) + else: + results.extend(data[1:]) + return results + + def api_call(self, call_name, action="", _sound=None, report_success=False, report_failure=True, preexec_message="", *args, **kwargs): + + """ Make a call to the Twitter API. If there is a connectionError or another exception not related to Twitter, It will call the method again at least 25 times, waiting a while between calls. Useful for post methods. + If twitter returns an error, it will not call the method anymore. + call_name str: The method to call + action str: What you are doing on twitter, it will be reported to the user if report_success is set to True. + for example "following @tw_blue2" will be reported as "following @tw_blue2 succeeded". + _sound str: a sound to play if the call is executed properly. + report_success and report_failure bool: These are self explanatory. True or False. + preexec_message str: A message to speak to the user while the method is running, example: "trying to follow x user".""" + + finished = False + tries = 0 + if preexec_message: + output.speak(preexec_message, True) + while finished==False and tries < 25: + try: + val = getattr(self.twitter.twitter, call_name)(*args, **kwargs) + finished = True + except TwythonError as e: + output.speak(e.message) + 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.message)) + finished = True +# except: +# tries = tries + 1 +# time.sleep(5) + if report_success: + output.speak(_("%s succeeded.") % action) + if _sound != None: self.sound.play(_sound) + return val + + def search(self, name, *args, **kwargs): + tl = self.twitter.twitter.search(*args, **kwargs) + tl["statuses"].reverse() + return tl["statuses"] + + @_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.""" + + tl = self.call_paged(self.twitter.twitter.get_favorites, *args, **kwargs) + return self.order_buffer(name, tl) + + def call_paged(self, update_function, *args, **kwargs): + + """ Makes a call to the Twitter API methods several times. Useful for get methods. + this function is needed for retrieving more than 200 items. + update_function str: The function to call. This function must be child of self.twitter.twitter + returns a list with all items retrieved.""" + + max = int(self.settings["general"]["max_api_calls"])-1 + results = [] + data = getattr(self.twitter.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"] + data = getattr(self.twitter.twitter, update_function)(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) + results.extend(data) + results.reverse() + return results + + @_require_login + def get_user_info(self): + + """ Retrieves some information required by TWBlue for setup.""" + f = self.twitter.twitter.get_account_settings() + sn = f["screen_name"] + self.settings["twitter"]["user_name"] = sn + self.db["user_name"] = sn + self.db["user_id"] = self.twitter.twitter.show_user(screen_name=sn)["id_str"] + try: + self.db["utc_offset"] = f["time_zone"]["utc_offset"] + except KeyError: + self.db["utc_offset"] = -time.timezone + self.get_lists() + self.get_muted_users() + self.settings.write() + + @_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.twitter.show_lists(reverse=True) + + @_require_login + def get_muted_users(self): + + """ Gets muted users (oh really?).""" + + self.db["muted_users"] = self.twitter.twitter.list_mute_ids()["ids"] + + @_require_login + def get_stream(self, name, function, *args, **kwargs): + + """ Retrieves the items for a regular stream. + name str: Name to save items to the database. + function str: A function to get the items.""" + + last_id = -1 + if name in self.db: + try: + if self.db[name][0]["id"] > self.db[name][-1]["id"]: + last_id = self.db[name][0]["id"] + else: + last_id = self.db[name][-1]["id"] + except IndexError: + pass + tl = self.call_paged(function, sinze_id=last_id, *args, **kwargs) + self.order_buffer(name, tl) + + def get_cursored_stream(self, name, function, items="users", get_previous=False, *args, **kwargs): + + """ Gets items for API calls that require using cursors to paginate the results. + name str: Name to save it in the database. + function str: Function that provides the items. + items: When the function returns the list with results, items will tell how the order function should be look. + for example get_followers_list returns a list and users are under list["users"], here the items should point to "users".""" + + items_ = [] + try: + if "cursor" in self.db[name] and get_previous: + cursor = self.db[name]["cursor"] + else: + cursor = -1 + except KeyError: + cursor = -1 + tl = getattr(self.twitter.twitter, function)(cursor=cursor, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) + tl[items].reverse() + num = self.order_cursored_buffer(name, tl[items]) + self.db[name]["cursor"] = tl["next_cursor"] + return num + + def start_streaming(self): + + """ Start the streaming for sending tweets in realtime.""" + if not hasattr(self, "main_stream"): + self.get_timelines() + if not hasattr(self, "timelinesStream"): + self.get_main_stream() + + def get_main_stream(self): + log.debug("Starting the main stream...") + self.main_stream = twitter.buffers.stream.streamer(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], self) + stream_threaded(self.main_stream.user, self.session_id) + + def get_timelines(self): + log.debug("Starting the timelines stream...") + self.timelinesStream = twitter.buffers.indibidual.timelinesStreamer(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], session=self) + ids = "" + for i in self.settings["other_buffers"]["timelines"]: + ids = ids + "%s, " % (self.db[i+"-timeline"][0]["user"]["id_str"]) + for i in self.lists: + for z in i.users: + ids += str(z) + ", " + if ids != "": +# print ids + stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids) + + def add_friends(self): + try: +# print "setting friends" + self.timelinesStream.set_friends(self.main_stream.friends) + except AttributeError: + pass + + def listen_stream_error(self): + if hasattr(self, "main_stream"): + log.debug("Disconnecting the main stream...") + self.main_stream.disconnect() + del self.main_stream + if hasattr(self, "timelinesStream"): + log.debug("disconnecting the timelines stream...") + self.timelinesStream.disconnect() + del self.timelinesStream + + def check_connection(self): + instan = 0 + self.counter += 1 + if self.counter >= 4: + del self.twitter + self.logged = False + self.twitter = twitter.twitter.twitter() + self.login(False) + pub.sendMessage("restart_streams", session=self.session_id) + if self.reconnection_function_active == True: return + self.reconnection_function_active = True + if not hasattr(self, "main_stream"): + self.get_main_stream() + if not hasattr(self, "timelinesStream"): + self.get_timelines() + self.reconnection_function_active = False + if hasattr(self, "timelinesStream") and not hasattr(self.timelinesStream, "friends"): + self.add_friends() +# try: +# urllib2.urlopen("http://74.125.228.231", timeout=5) +# except urllib2.URLError: +# pub.sendMessage("stream-error", session=self.session_id) + + def remove_stream(self, stream): + if stream == "timelinesStream": + if hasattr(self, "timelinesStream"): + self.timelinesStream.disconnect() + del self.timelinesStream + else: + self.main_stream.disconnect() + del self.main_stream + + def shelve(self): + "Shelve the database to allow for persistance." + shelfname=paths.config_path(str(self.session_id)+"/cache.db") + if self.settings["general"]["persist_size"] == 0: + if os.path.exists(shelfname): + os.remove(shelfname) + return + try: + if not os.path.exists(shelfname): + output.speak("Generating database, this might take a while.",True) + shelf=shelve.open(paths.config_path(shelfname),'c') + for key,value in self.db.items(): + if type(key) != str and type(key) != unicode: + output.speak("Uh oh, while shelving the database, a key of type " + str(type(key)) + " has been found. It will be converted to type str, but this will cause all sorts of problems on deshelve. Please bring this to the attention of the " + application.name + " developers immediately. More information about the error will be written to the error log.",True) + log.error("Uh oh, " + str(key) + " is of type " + str(type(key)) + "!") + # Convert unicode objects to UTF-8 strings before shelve these objects. + if type(value) == list and self.settings["general"]["persist_size"] != -1 and len(value) > self.settings["general"]["persist_size"]: + shelf[str(key.encode("utf-8"))]=value[self.settings["general"]["persist_size"]:] + else: + shelf[str(key.encode("utf-8"))]=value + shelf.close() + except: + output.speak("An exception occurred while shelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True) + log.exception("Exception while shelving" + shelfname) + os.remove(shelfname) + + def deshelve(self): + "Import a shelved database." + shelfname=paths.config_path(str(self.session_id)+"/cache.db") + if self.settings["general"]["persist_size"] == 0: + if os.path.exists(shelfname): + os.remove(shelfname) + return + try: + shelf=shelve.open(paths.config_path(shelfname),'c') + for key,value in shelf.items(): + self.db[key]=value + shelf.close() + except: + output.speak("An exception occurred while deshelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True) + log.exception("Exception while deshelving" + shelfname) + try: + os.remove(shelfname) + except: + pass + + def check_quoted_status(self, tweet): + status = tweets.is_long(tweet) + if status != False and config.app["app-settings"]["handle_longtweets"]: + tweet = self.get_quoted_tweet(tweet) + return tweet + + def get_quoted_tweet(self, tweet): + quoted_tweet = tweet + if "full_text" in tweet: + value = "full_text" + else: + value = "text" + urls = utils.find_urls_in_text(quoted_tweet[value]) + for url in range(0, len(urls)): + try: quoted_tweet[value] = quoted_tweet[value].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass + id = tweets.is_long(quoted_tweet) + try: original_tweet = self.twitter.twitter.show_status(id=id, tweet_mode="extended") + except: return quoted_tweet + original_tweet = self.check_long_tweet(original_tweet) + urls = utils.find_urls_in_text(original_tweet["full_text"]) + for url in range(0, len(urls)): + try: original_tweet["full_text"] = original_tweet["full_text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass + return compose.compose_quoted_tweet(quoted_tweet, original_tweet) + + def check_long_tweet(self, tweet): + long = twishort.is_long(tweet) + if long != False and config.app["app-settings"]["handle_longtweets"]: + tweet["message"] = twishort.get_full_text(long) + 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"]: + continue + tweet["message"] = u"@%s %s" % (i["screen_name"], tweet["message"]) return tweet \ No newline at end of file diff --git a/src/sessionmanager/sessionManager.py b/src/sessionmanager/sessionManager.py index c567e077..f2830fbc 100644 --- a/src/sessionmanager/sessionManager.py +++ b/src/sessionmanager/sessionManager.py @@ -1,117 +1,118 @@ -# -*- coding: utf-8 -*- -import shutil -import widgetUtils -import platform -import output -if platform.system() == "Windows": - import wxUI as view - from controller import settings -elif platform.system() == "Linux": - import gtkUI as view -import paths -import time -import os -import logging -import session -import manager -import config_utils -import config - -log = logging.getLogger("sessionmanager.sessionManager") - -class sessionManagerController(object): - def __init__(self, started=False): - super(sessionManagerController, self).__init__() - log.debug("Setting up the session manager.") - self.started = started - manager.setup() - self.view = view.sessionManagerWindow() - widgetUtils.connect_event(self.view.new, widgetUtils.BUTTON_PRESSED, self.manage_new_account) - widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.remove) - if self.started == False: - widgetUtils.connect_event(self.view.configuration, widgetUtils.BUTTON_PRESSED, self.configuration) - else: - self.view.hide_configuration() - self.new_sessions = {} - self.removed_sessions = [] - - def fill_list(self): - sessionsList = [] - log.debug("Filling the sessions list.") - self.sessions = [] - for i in os.listdir(paths.config_path()): - if os.path.isdir(paths.config_path(i)): - log.debug("Adding session %s" % (i,)) - strconfig = "%s/session.conf" % (paths.config_path(i)) - config_test = config_utils.load_config(strconfig) - if len(config_test) == 0: - try: - log.debug("Deleting session %s" % (i,)) - shutil.rmtree(paths.config_path(i)) - continue - except: - output.speak("An exception was raised while attempting to clean malformed session data. See the error log for details. If this message persists, contact the developers.",True) - os.exception("Exception thrown while removing malformed session") - continue - name = config_test["twitter"]["user_name"] - if config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "": - sessionsList.append(name) - self.sessions.append(i) - else: - try: - log.debug("Deleting session %s" % (i,)) - shutil.rmtree(paths.config_path(i)) - except: - output.speak("An exception was raised while attempting to clean malformed session data. See the error log for details. If this message persists, contact the developers.",True) - os.exception("Exception thrown while removing malformed session") - self.view.fill_list(sessionsList) - - def show(self): - if self.view.get_response() == widgetUtils.OK: - self.do_ok() -# else: - self.view.destroy() - - def do_ok(self): - log.debug("Starting sessions...") - for i in self.sessions: - if session.sessions.has_key(i) == True: continue - s = session.Session(i) - s.get_configuration() - if i not in config.app["sessions"]["ignored_sessions"]: - s.login() - session.sessions[i] = s - self.new_sessions[i] = s -# self.view.destroy() - - def manage_new_account(self, *args, **kwargs): - if self.view.new_account_dialog() == widgetUtils.YES: - location = (str(time.time())[-6:]) - log.debug("Creating session in the %s path" % (location,)) - s = session.Session(location) - manager.manager.add_session(location) - s.get_configuration() -# try: - s.authorise() - self.sessions.append(location) - self.view.add_new_session_to_list() - s.settings.write() -# except: -# log.exception("Error authorising the session") -# self.view.show_unauthorised_error() -# return - - def remove(self, *args, **kwargs): - if self.view.remove_account_dialog() == widgetUtils.YES: - selected_account = self.sessions[self.view.get_selected()] - self.view.remove_session(self.view.get_selected()) - self.removed_sessions.append(selected_account) - self.sessions.remove(selected_account) - shutil.rmtree(path=paths.config_path(selected_account), ignore_errors=True) - - - def configuration(self, *args, **kwargs): - """ Opens the global settings dialogue.""" - d = settings.globalSettingsController() - if d.response == widgetUtils.OK: - d.save_configuration() +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import shutil +import widgetUtils +import platform +import output +if platform.system() == "Windows": + from . import wxUI as view + from controller import settings +elif platform.system() == "Linux": + from . import gtkUI as view +import paths +import time +import os +import logging +from . import session +from . import manager +import config_utils +import config + +log = logging.getLogger("sessionmanager.sessionManager") + +class sessionManagerController(object): + def __init__(self, started=False): + super(sessionManagerController, self).__init__() + log.debug("Setting up the session manager.") + self.started = started + manager.setup() + self.view = view.sessionManagerWindow() + widgetUtils.connect_event(self.view.new, widgetUtils.BUTTON_PRESSED, self.manage_new_account) + widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.remove) + if self.started == False: + widgetUtils.connect_event(self.view.configuration, widgetUtils.BUTTON_PRESSED, self.configuration) + else: + self.view.hide_configuration() + self.new_sessions = {} + self.removed_sessions = [] + + def fill_list(self): + sessionsList = [] + log.debug("Filling the sessions list.") + self.sessions = [] + for i in os.listdir(paths.config_path()): + if os.path.isdir(paths.config_path(i)): + log.debug("Adding session %s" % (i,)) + strconfig = "%s/session.conf" % (paths.config_path(i)) + config_test = config_utils.load_config(strconfig) + if len(config_test) == 0: + try: + log.debug("Deleting session %s" % (i,)) + shutil.rmtree(paths.config_path(i)) + continue + except: + output.speak("An exception was raised while attempting to clean malformed session data. See the error log for details. If this message persists, contact the developers.",True) + os.exception("Exception thrown while removing malformed session") + continue + name = config_test["twitter"]["user_name"] + if config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "": + sessionsList.append(name) + self.sessions.append(i) + else: + try: + log.debug("Deleting session %s" % (i,)) + shutil.rmtree(paths.config_path(i)) + except: + output.speak("An exception was raised while attempting to clean malformed session data. See the error log for details. If this message persists, contact the developers.",True) + os.exception("Exception thrown while removing malformed session") + self.view.fill_list(sessionsList) + + def show(self): + if self.view.get_response() == widgetUtils.OK: + self.do_ok() +# else: + self.view.destroy() + + def do_ok(self): + log.debug("Starting sessions...") + for i in self.sessions: + if (i in session.sessions) == True: continue + s = session.Session(i) + s.get_configuration() + if i not in config.app["sessions"]["ignored_sessions"]: + s.login() + session.sessions[i] = s + self.new_sessions[i] = s +# self.view.destroy() + + def manage_new_account(self, *args, **kwargs): + if self.view.new_account_dialog() == widgetUtils.YES: + location = (str(time.time())[-6:]) + log.debug("Creating session in the %s path" % (location,)) + s = session.Session(location) + manager.manager.add_session(location) + s.get_configuration() +# try: + s.authorise() + self.sessions.append(location) + self.view.add_new_session_to_list() + s.settings.write() +# except: +# log.exception("Error authorising the session") +# self.view.show_unauthorised_error() +# return + + def remove(self, *args, **kwargs): + if self.view.remove_account_dialog() == widgetUtils.YES: + selected_account = self.sessions[self.view.get_selected()] + self.view.remove_session(self.view.get_selected()) + self.removed_sessions.append(selected_account) + self.sessions.remove(selected_account) + shutil.rmtree(path=paths.config_path(selected_account), ignore_errors=True) + + + def configuration(self, *args, **kwargs): + """ Opens the global settings dialogue.""" + d = settings.globalSettingsController() + if d.response == widgetUtils.OK: + d.save_configuration() diff --git a/src/twitter/__init__.py b/src/twitter/__init__.py index 57752919..06e9015c 100644 --- a/src/twitter/__init__.py +++ b/src/twitter/__init__.py @@ -1 +1,2 @@ -import buffers, utils, compose, twitter +from __future__ import absolute_import +from . import buffers, utils, compose, twitter diff --git a/src/twitter/buffers/__init__.py b/src/twitter/buffers/__init__.py index 891157f7..6bdd7a95 100644 --- a/src/twitter/buffers/__init__.py +++ b/src/twitter/buffers/__init__.py @@ -1 +1,2 @@ -import stream, indibidual \ No newline at end of file +from __future__ import absolute_import +from . import stream, indibidual \ No newline at end of file diff --git a/src/twitter/buffers/indibidual.py b/src/twitter/buffers/indibidual.py index 66c7d74d..90be5845 100644 --- a/src/twitter/buffers/indibidual.py +++ b/src/twitter/buffers/indibidual.py @@ -1,71 +1,71 @@ -# -*- coding: utf-8 -*- -import config -from requests.auth import HTTPProxyAuth -from twitter import compose, utils -from twython import TwythonStreamer -from pubsub import pub -import logging as original_logger -log = original_logger.getLogger("TimelinesStream") - -class timelinesStreamer(TwythonStreamer): - def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=300, retry_count=None, retry_in=10, client_args=None, handlers=None, chunk_size=1, session=None): - self.session = session - super(timelinesStreamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, timeout=60, retry_count=None, retry_in=180, handlers=None, chunk_size=1) - self.lists = self.session.lists - - def on_error(self, status_code, data): - log.error("error in stream: %s: %s" % (status_code, data)) -# pub.sendMessage("stream-error", session=self.session.session_id) - - def on_timeout(self, *args, **kwargs): - log.error("Twitter timeout Error") -# pub.sendMessage("stream-error", session=self.session.session_id) - - def check_tls(self, data): - for i in self.session.settings["other_buffers"]["timelines"]: - if data["user"]["id_str"] == i: - if utils.find_item(data["id"], self.session.db["%s-timeline" % (i,)]) != None: - log.error("duplicated tweet. Ignoring it...") - return -# try: - data_ = self.session.check_quoted_status(data) - data_ = self.session.check_long_tweet(data_) - data = data_ -# except ValueError: -# pass - if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s-timeline" % (i,)].append(data) - else: self.session.db["%s-timeline" % (i,)].insert(0, data) - pub.sendMessage("item-in-timeline", data= data, user= self.session.db["user_name"], who= i) - return - for i in self.session.lists: - try: - i.users.index(data["user"]["id"]) - usr = data["in_reply_to_user_id"] - if (usr != None and usr in self.friends) or data.has_key("retweeted_status"): - data = self.session.check_quoted_status(data) - data = self.session.check_long_tweet(data) - if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data) - else: self.session.db["%s" % (i.name,)].insert(0, data) - pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name) - elif usr == None: - data = self.session.check_quoted_status(data) - data = self.session.check_long_tweet(data) - if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data) - else: self.session.db["%s" % (i.name,)].insert(0, data) - pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name) - except ValueError: - pass - - def set_friends(self, friends): - self.friends = friends - - def on_success(self, data): -# try: - if "text" in data and utils.is_allowed(data, self.session.settings["twitter"]["ignored_clients"]) == True: - if data.has_key("extended_tweet"): - data["full_text"] = data["extended_tweet"]["full_text"] -# data["entities"] = data["extended_tweet"]["entities"] -# log.error(data["extended_entities"]) - self.check_tls(data) -# except: -# pass +# -*- coding: utf-8 -*- +import config +from requests.auth import HTTPProxyAuth +from twitter import compose, utils +from twython import TwythonStreamer +from pubsub import pub +import logging as original_logger +log = original_logger.getLogger("TimelinesStream") + +class timelinesStreamer(TwythonStreamer): + def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=300, retry_count=None, retry_in=10, client_args=None, handlers=None, chunk_size=1, session=None): + self.session = session + super(timelinesStreamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, timeout=60, retry_count=None, retry_in=180, handlers=None, chunk_size=1) + self.lists = self.session.lists + + def on_error(self, status_code, data): + log.error("error in stream: %s: %s" % (status_code, data)) +# pub.sendMessage("stream-error", session=self.session.session_id) + + def on_timeout(self, *args, **kwargs): + log.error("Twitter timeout Error") +# pub.sendMessage("stream-error", session=self.session.session_id) + + def check_tls(self, data): + for i in self.session.settings["other_buffers"]["timelines"]: + if data["user"]["id_str"] == i: + if utils.find_item(data["id"], self.session.db["%s-timeline" % (i,)]) != None: + log.error("duplicated tweet. Ignoring it...") + return +# try: + data_ = self.session.check_quoted_status(data) + data_ = self.session.check_long_tweet(data_) + data = data_ +# except ValueError: +# pass + if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s-timeline" % (i,)].append(data) + else: self.session.db["%s-timeline" % (i,)].insert(0, data) + pub.sendMessage("item-in-timeline", data= data, user= self.session.db["user_name"], who= i) + return + for i in self.session.lists: + try: + i.users.index(data["user"]["id"]) + usr = data["in_reply_to_user_id"] + if (usr != None and usr in self.friends) or "retweeted_status" in data: + data = self.session.check_quoted_status(data) + data = self.session.check_long_tweet(data) + if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data) + else: self.session.db["%s" % (i.name,)].insert(0, data) + pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name) + elif usr == None: + data = self.session.check_quoted_status(data) + data = self.session.check_long_tweet(data) + if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data) + else: self.session.db["%s" % (i.name,)].insert(0, data) + pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name) + except ValueError: + pass + + def set_friends(self, friends): + self.friends = friends + + def on_success(self, data): +# try: + if "text" in data and utils.is_allowed(data, self.session.settings["twitter"]["ignored_clients"]) == True: + if "extended_tweet" in data: + data["full_text"] = data["extended_tweet"]["full_text"] +# data["entities"] = data["extended_tweet"]["entities"] +# log.error(data["extended_entities"]) + self.check_tls(data) +# except: +# pass diff --git a/src/twitter/buffers/stream.py b/src/twitter/buffers/stream.py index 77929082..e7b37ba1 100644 --- a/src/twitter/buffers/stream.py +++ b/src/twitter/buffers/stream.py @@ -1,182 +1,182 @@ -# -*- coding: utf-8 -*- -import config -from requests.auth import HTTPProxyAuth -from twitter import utils -from twython import TwythonStreamer -from pubsub import pub -import logging as original_logger -log = original_logger.getLogger("MainStream") - -class streamer(TwythonStreamer): - def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, sessionObject, *a, **kw): - super(streamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, *a, **kw) - self.session = sessionObject - self.muted_users = self.session.db["muted_users"] -# self.blocked_users = [] - - def on_timeout(self, *args, **kwargs): - log.error("Twitter timeout Error") -# pub.sendMessage("stream-error", session=self.session.session_id) - - def on_error(self, status_code, data): - log.error("Error %s: %s" % (status_code, data)) -# pub.sendMessage("stream-error", session=self.session.session_id) - - def get_user(self): - return self.session.db["user_name"] - - def put_data(self, place, data): - if self.session.db.has_key(place): - if utils.find_item(data["id"], self.session.db[place]) != None: - log.error("duplicated tweet. Ignoring it...") - return False -# try: - data_ = self.session.check_quoted_status(data) - data_ = self.session.check_long_tweet(data_) - data = data_ -# except: -# pass - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db[place].append(data) - else: - self.session.db[place].insert(0, data) - utils.is_audio(data) - return True - - def block_user(self, data): - id = data["target"]["id"] - if id in self.friends: - self.friends.remove(id) - if "blocks" in self.session.settings["general"]["buffer_order"]: - self.session.db["blocked"]["items"].append(data["target"]) - pub.sendMessage("blocked-user", data=data["target"], user=self.get_user()) - - def unblock(self, data): - if "blocks" in self.session.settings["general"]["buffer_order"] == True: - item = utils.find_item(data["target"]["id"], self.session.db["blocked"]["items"]) - self.session.db["blocked"]["items"].pop(item) - pub.sendMessage("unblocked-user", item=item, user=self.get_user()) - - def check_send(self, data): - if self.session.db["user_name"] == data["user"]["screen_name"]: - d = self.put_data("sent_tweets", data) - if d != False: - pub.sendMessage("sent-tweet", data=data, user=self.get_user()) - - def check_favs(self, data): - if data["source"]["screen_name"] == self.session.db["user_name"]: - d = self.put_data("favourites", data["target_object"]) - if d != False: - pub.sendMessage("favourite", data=data["target_object"], user=self.get_user()) - - def check_mentions(self, data): - if "@%s" % (self.session.db["user_name"]) in data["text"]: - d = self.put_data("mentions", data) - if d != False: - pub.sendMessage("mention", data=data, user=self.get_user()) - - def set_quoted_tweet(self, data): - if data["source"]["screen_name"] != self.session.db["user_name"]: - d = self.put_data("mentions", data["target_object"]) - if d != False: - pub.sendMessage("mention", data=data["target_object"], user=self.get_user()) - - def process_dm(self, data): - if self.session.db["user_name"] != data["direct_message"]["sender"]["screen_name"]: -# d = self.put_data("sent_direct_messages", data["direct_message"]) -# if d != False: -# pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user()) -# else: - d = self.put_data("direct_messages", data["direct_message"]) - if d != False: - pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user()) - - def check_follower(self, data): - if data["target"]["screen_name"] == self.session.db["user_name"]: - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db["followers"]["items"].append(data["source"]) - else: - self.session.db["followers"]["items"].insert(0, data["source"]) - pub.sendMessage("follower", data=data["source"], user = self.get_user()) - else: - if self.session.settings["general"]["reverse_timelines"] == False: - self.session.db["friends"]["items"].append(data["target"]) - else: - self.session.db["friends"]["items"].insert(0, data["target"]) - pub.sendMessage("friend", data=data["target"], user=self.get_user()) - -### - def remove_fav(self, data): - if self.session.db["user_name"] == data["source"]["screen_name"]: - item = utils.find_item(data["target_object"]["id"], self.session.db["favourites"]) - self.session.db["favourites"].pop(item) - pub.sendMessage("unfavourite", item=item, user=self.get_user()) - - def remove_friend(self, data): - if "friends" in self.session.settings["general"]["buffer_order"]: - item = utils.find_item(data["target"]["id"], self.session.db["friends"]["items"]) - if item > 0: - self.friends.pop(item) - pub.sendMessage("unfollowing", item=item, user=self.get_user()) - - def on_success(self, data): - try: -# if "delete" in data: -# pub.sendMessage("tweet-deleted", data=data) - if "direct_message" in data: - self.process_dm(data) - elif "friends" in data: - self.friends = data["friends"] - pub.sendMessage("friends-receibed") - elif "text" in data and utils.is_allowed(data, self.session.settings["twitter"]["ignored_clients"]) == True: - if data.has_key("extended_tweet"): - data["full_text"] = data["extended_tweet"]["full_text"] - data["entities"] = data["extended_tweet"]["entities"] -# log.error(data["extended_tweet"]) -# log.error("Extended tweet") - if data["user"]["id"] in self.muted_users: return - self.check_mentions(data) - self.check_send(data) - if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]: - d = self.put_data("home_timeline", data) - if d != False: - pub.sendMessage("item-in-home", data=data, user=self.get_user()) - elif data.has_key("event"): - if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]: - self.check_favs(data) - elif "unfavorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]: - self.remove_fav(data) - elif "follow" == data["event"] and "followers" in self.session.settings["general"]["buffer_order"]: - self.check_follower(data) - elif "unfollow" == data["event"] and "friends" in self.session.settings["general"]["buffer_order"]: - self.remove_friend(data) - elif "block" == data["event"]: - self.block_user(data) - elif "unblock" == data["event"]: - self.unblock(data) - elif "list_created" == data["event"]: - item = utils.find_item(data["target_object"]["id"], self.session.db["lists"]) - if item != None: self.session.db["lists"].append(data["target_object"]) - elif "list_destroyed" == data["event"]: - item = utils.find_item(data["target_object"]["id"], self.session.db["lists"]) - if item != None: self.session.db["lists"].pop(item) - self.parent.remove_list(data["target_object"]["id"]) - elif "list_member_added" == data["event"] and data["source"]["screen_name"] == self.get_user(): - pub.sendMessage("new-list-member-added", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()}) - elif "list_member_added" == data["event"] and data["target"]["screen_name"] == self.get_user(): - self.session.db["lists"].append(data["target_object"]) - elif "list_member_removed" == data["event"] and data["source"]["screen_name"] == self.get_user(): - pub.sendMessage("list-member-deleted", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()}) - elif "list_member_removed" == data["event"] and data["target"] == self.get_user(): - id = data["target_object"]["id"] - list = utils.find_item(id, self.session.db["lists"]) - if list != None: self.session.db["lists"].pop(list) - pub.sendMessage("list-deleted", **{"item":list, "user":self.get_user()}) - elif "quoted_tweet" == data["event"]: - self.set_quoted_tweet(data) - - if "events" in self.session.settings["general"]["buffer_order"]: - pub.sendMessage("event", data= data, user= self.get_user()) -# self.sound.play("new_event.ogg") - except KeyboardInterrupt: - pass +# -*- coding: utf-8 -*- +import config +from requests.auth import HTTPProxyAuth +from twitter import utils +from twython import TwythonStreamer +from pubsub import pub +import logging as original_logger +log = original_logger.getLogger("MainStream") + +class streamer(TwythonStreamer): + def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, sessionObject, *a, **kw): + super(streamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, *a, **kw) + self.session = sessionObject + self.muted_users = self.session.db["muted_users"] +# self.blocked_users = [] + + def on_timeout(self, *args, **kwargs): + log.error("Twitter timeout Error") +# pub.sendMessage("stream-error", session=self.session.session_id) + + def on_error(self, status_code, data): + log.error("Error %s: %s" % (status_code, data)) +# pub.sendMessage("stream-error", session=self.session.session_id) + + def get_user(self): + return self.session.db["user_name"] + + def put_data(self, place, data): + if place in self.session.db: + if utils.find_item(data["id"], self.session.db[place]) != None: + log.error("duplicated tweet. Ignoring it...") + return False +# try: + data_ = self.session.check_quoted_status(data) + data_ = self.session.check_long_tweet(data_) + data = data_ +# except: +# pass + if self.session.settings["general"]["reverse_timelines"] == False: + self.session.db[place].append(data) + else: + self.session.db[place].insert(0, data) + utils.is_audio(data) + return True + + def block_user(self, data): + id = data["target"]["id"] + if id in self.friends: + self.friends.remove(id) + if "blocks" in self.session.settings["general"]["buffer_order"]: + self.session.db["blocked"]["items"].append(data["target"]) + pub.sendMessage("blocked-user", data=data["target"], user=self.get_user()) + + def unblock(self, data): + if "blocks" in self.session.settings["general"]["buffer_order"] == True: + item = utils.find_item(data["target"]["id"], self.session.db["blocked"]["items"]) + self.session.db["blocked"]["items"].pop(item) + pub.sendMessage("unblocked-user", item=item, user=self.get_user()) + + def check_send(self, data): + if self.session.db["user_name"] == data["user"]["screen_name"]: + d = self.put_data("sent_tweets", data) + if d != False: + pub.sendMessage("sent-tweet", data=data, user=self.get_user()) + + def check_favs(self, data): + if data["source"]["screen_name"] == self.session.db["user_name"]: + d = self.put_data("favourites", data["target_object"]) + if d != False: + pub.sendMessage("favourite", data=data["target_object"], user=self.get_user()) + + def check_mentions(self, data): + if "@%s" % (self.session.db["user_name"]) in data["text"]: + d = self.put_data("mentions", data) + if d != False: + pub.sendMessage("mention", data=data, user=self.get_user()) + + def set_quoted_tweet(self, data): + if data["source"]["screen_name"] != self.session.db["user_name"]: + d = self.put_data("mentions", data["target_object"]) + if d != False: + pub.sendMessage("mention", data=data["target_object"], user=self.get_user()) + + def process_dm(self, data): + if self.session.db["user_name"] != data["direct_message"]["sender"]["screen_name"]: +# d = self.put_data("sent_direct_messages", data["direct_message"]) +# if d != False: +# pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user()) +# else: + d = self.put_data("direct_messages", data["direct_message"]) + if d != False: + pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user()) + + def check_follower(self, data): + if data["target"]["screen_name"] == self.session.db["user_name"]: + if self.session.settings["general"]["reverse_timelines"] == False: + self.session.db["followers"]["items"].append(data["source"]) + else: + self.session.db["followers"]["items"].insert(0, data["source"]) + pub.sendMessage("follower", data=data["source"], user = self.get_user()) + else: + if self.session.settings["general"]["reverse_timelines"] == False: + self.session.db["friends"]["items"].append(data["target"]) + else: + self.session.db["friends"]["items"].insert(0, data["target"]) + pub.sendMessage("friend", data=data["target"], user=self.get_user()) + +### + def remove_fav(self, data): + if self.session.db["user_name"] == data["source"]["screen_name"]: + item = utils.find_item(data["target_object"]["id"], self.session.db["favourites"]) + self.session.db["favourites"].pop(item) + pub.sendMessage("unfavourite", item=item, user=self.get_user()) + + def remove_friend(self, data): + if "friends" in self.session.settings["general"]["buffer_order"]: + item = utils.find_item(data["target"]["id"], self.session.db["friends"]["items"]) + if item > 0: + self.friends.pop(item) + pub.sendMessage("unfollowing", item=item, user=self.get_user()) + + def on_success(self, data): + try: +# if "delete" in data: +# pub.sendMessage("tweet-deleted", data=data) + if "direct_message" in data: + self.process_dm(data) + elif "friends" in data: + self.friends = data["friends"] + pub.sendMessage("friends-receibed") + elif "text" in data and utils.is_allowed(data, self.session.settings["twitter"]["ignored_clients"]) == True: + if "extended_tweet" in data: + data["full_text"] = data["extended_tweet"]["full_text"] + data["entities"] = data["extended_tweet"]["entities"] +# log.error(data["extended_tweet"]) +# log.error("Extended tweet") + if data["user"]["id"] in self.muted_users: return + self.check_mentions(data) + self.check_send(data) + if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]: + d = self.put_data("home_timeline", data) + if d != False: + pub.sendMessage("item-in-home", data=data, user=self.get_user()) + elif "event" in data: + if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]: + self.check_favs(data) + elif "unfavorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]: + self.remove_fav(data) + elif "follow" == data["event"] and "followers" in self.session.settings["general"]["buffer_order"]: + self.check_follower(data) + elif "unfollow" == data["event"] and "friends" in self.session.settings["general"]["buffer_order"]: + self.remove_friend(data) + elif "block" == data["event"]: + self.block_user(data) + elif "unblock" == data["event"]: + self.unblock(data) + elif "list_created" == data["event"]: + item = utils.find_item(data["target_object"]["id"], self.session.db["lists"]) + if item != None: self.session.db["lists"].append(data["target_object"]) + elif "list_destroyed" == data["event"]: + item = utils.find_item(data["target_object"]["id"], self.session.db["lists"]) + if item != None: self.session.db["lists"].pop(item) + self.parent.remove_list(data["target_object"]["id"]) + elif "list_member_added" == data["event"] and data["source"]["screen_name"] == self.get_user(): + pub.sendMessage("new-list-member-added", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()}) + elif "list_member_added" == data["event"] and data["target"]["screen_name"] == self.get_user(): + self.session.db["lists"].append(data["target_object"]) + elif "list_member_removed" == data["event"] and data["source"]["screen_name"] == self.get_user(): + pub.sendMessage("list-member-deleted", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()}) + elif "list_member_removed" == data["event"] and data["target"] == self.get_user(): + id = data["target_object"]["id"] + list = utils.find_item(id, self.session.db["lists"]) + if list != None: self.session.db["lists"].pop(list) + pub.sendMessage("list-deleted", **{"item":list, "user":self.get_user()}) + elif "quoted_tweet" == data["event"]: + self.set_quoted_tweet(data) + + if "events" in self.session.settings["general"]["buffer_order"]: + pub.sendMessage("event", data= data, user= self.get_user()) +# self.sound.play("new_event.ogg") + except KeyboardInterrupt: + pass diff --git a/src/twitter/compose.py b/src/twitter/compose.py index 57d521cf..91da76ab 100644 --- a/src/twitter/compose.py +++ b/src/twitter/compose.py @@ -1,209 +1,210 @@ -# -*- coding: utf-8 -*- -import platform -system = platform.system() -import utils -import re -import htmlentitydefs -import time -import output -import languageHandler -import arrow -import logging -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+);") - def matchFunc(match): - """Nested function to handle a match object. - If we match &blah; and it's not found, &blah; will be returned. - if we match #\d+, unichr(digits) will be returned. - Else, a unicode string will be returned.""" - if match.group(1).startswith('#'): return unichr(int(match.group(1)[1:])) - replacement = htmlentitydefs.entitydefs.get(match.group(1), "&%s;" % match.group(1)) - return replacement.decode('iso-8859-1') - return unicode(entity_re.sub(matchFunc, s)) - -chars = "abcdefghijklmnopqrstuvwxyz" - -def compose_tweet(tweet, db, relative_times, show_screen_names=False): - """ 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") - if relative_times == True: - ts = original_date.humanize(locale=languageHandler.getLanguage()) - else: - ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) - else: - ts = tweet["created_at"] - if tweet.has_key("message"): - value = "message" - elif tweet.has_key("full_text"): - value = "full_text" - else: - value = "text" -# log.exception(tweet.keys()) - text = StripChars(tweet[value]) - if show_screen_names: - user = tweet["user"]["screen_name"] - else: - user = tweet["user"]["name"] - source = re.sub(r"(?s)<.*?>", "", tweet["source"]) - if tweet.has_key("retweeted_status"): - if tweet.has_key("message") == False and tweet["retweeted_status"]["is_quote_status"] == False: - text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(tweet["retweeted_status"][value])) - elif tweet["retweeted_status"]["is_quote_status"]: - text = "%s" % (StripChars(tweet[value])) - else: - text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(tweet[value])) -# if text[-1] in chars: text=text+"." - if tweet.has_key("message") == False: - urls = utils.find_urls_in_text(text) - for url in range(0, len(urls)): - try: - text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) - except: pass - if config.app['app-settings']['handle_longtweets']: pass -# return [user+", ", text, ts+", ", source] - return [user+", ", text, ts+", ", source] - -def compose_dm(tweet, db, relative_times, show_screen_names=False): - """ 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") - if relative_times == True: - ts = original_date.humanize(locale=languageHandler.getLanguage()) - else: - ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) - else: - ts = tweet["created_at"] - text = StripChars(tweet["text"]) - source = "DM" - if db["user_name"] == tweet["sender"]["screen_name"]: - if show_screen_names: - user = _(u"Dm to %s ") % (tweet["recipient"]["screen_name"],) - else: - user = _(u"Dm to %s ") % (tweet["recipient"]["name"],) - else: - if show_screen_names: - user = tweet["sender"]["screen_name"] - else: - user = tweet["sender"]["name"] - if text[-1] in chars: text=text+"." - urls = utils.find_urls_in_text(text) - for url in range(0, len(urls)): - try: text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) - except IndexError: pass - return [user+", ", text, ts+", ", source] - -def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False): - """ 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 quoted_tweet.has_key("full_text"): - value = "full_text" - else: - value = "text" - text = StripChars(quoted_tweet[value]) - if show_screen_names: - quoting_user = quoted_tweet["user"]["screen_name"] - else: - quoting_user = quoted_tweet["user"]["name"] - source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"]) - try: text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], StripChars(quoted_tweet["retweeted_status"][value])) - except KeyError: text = "%s" % (StripChars(quoted_tweet[value])) - if text[-1] in chars: text=text+"." - original_user = original_tweet["user"]["screen_name"] - if original_tweet.has_key("message"): - original_text = StripChars(original_tweet["message"]) - elif original_tweet.has_key("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( quoted_tweet[value], original_user, original_text) - quoted_tweet = tweets.clear_url(quoted_tweet) - return quoted_tweet - -def compose_followers_list(tweet, db, relative_times=True, show_screen_names=False): - if system == "Windows": - 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.getLanguage()) - else: - ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) - else: - ts = tweet["created_at"] - if tweet.has_key("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.getLanguage()) - else: - ts2 = original_date2.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) - else: - 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)] - -def compose_event(data, username, show_screen_names=False): - if show_screen_names: - value = "screen_name" - else: - value = "name" - if data["event"] == "block": - event = _("You've blocked %s") % (data["target"][value]) - elif data["event"] == "unblock": - event = _(u"You've unblocked %s") % (data["target"][value]) - elif data["event"] == "follow": - if data["target"]["screen_name"] == username: - event = _(u"%s(@%s) has followed you") % (data["source"]["name"], data["source"]["screen_name"]) - elif data["source"]["screen_name"] == username: - event = _(u"You've followed %s(@%s)") % (data["target"]["name"], data["target"]["screen_name"]) - elif data["event"] == "unfollow": - event = _(u"You've unfollowed %s (@%s)") % (data["target"]["name"], data["target"]["screen_name"]) - elif data["event"] == "favorite": - if data["source"]["screen_name"] == username: - event = _(u"You've liked: %s, %s") % (data["target"][value], data["target_object"]["text"]) - else: - event = _(u"%s(@%s) has liked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"]) - elif data["event"] == "unfavorite": - if data["source"]["screen_name"] == username: event = _(u"You've unliked: %s, %s") % (data["target"][value], data["target_object"]["text"]) - else: event = _(u"%s(@%s) has unliked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"]) - elif data["event"] == "list_created": - event = _(u"You've created the list %s") % (data["target_object"]["name"]) - elif data["event"] == "list_destroyed": - event = _("You've deleted the list %s") % (data["target_object"]["name"]) - elif data["event"] == "list_updated": - event = _("You've updated the list %s") % (data["target_object"]["name"]) - elif data["event"] == "list_member_added": - if data["source"]["screen_name"] == username: event = _(u"You've added %s(@%s) to the list %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["name"]) - else: event = _(u"%s(@%s) has added you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"]) - elif data["event"] == "list_member_removed": - if data["source"]["screen_name"] == username: event = _(u"You'be removed %s(@%s) from the list %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["name"]) - else: event = _(u"%s(@%s) has removed you from the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"]) - elif data["event"] == "list_user_subscribed": - if data["source"]["screen_name"] == username: event = _(u"You've subscribed to the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"]) - else: event = _(u"%s(@%s) has suscribed you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"]) - elif data["event"] == "list_user_unsubscribed": - if data["source"]["screen_name"] == username: event = _(u"You've unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"]) - else: event = _("You've been unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["source"]["name"], data["source"]["screen_name"]) - elif data["event"] == "retweeted_retweet": - if data["source"]["screen_name"] == username: event = _(u"You have retweeted a retweet from %s(@%s): %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["retweeted_status"]["text"]) - else: event = _(u"%s(@%s) has retweeted your retweet: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["retweeted_status"]["text"]) - elif data["event"] == "quoted_tweet": - event = _(u"@{0} quoted your tweet: {1}").format(data["source"]["screen_name"], data["target_object"]["text"]) - else: - event = _("Unknown") - log.error("event: %s\n target: %s\n source: %s\n target_object: %s" % (data["event"], data["target"], data["source"], data["target_object"])) - return [time.strftime("%I:%M %p"), event] - -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") - else: status = _(u"public") - return [name, description, user, members, status] +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import platform +system = platform.system() +from . import utils +import re +import htmlentitydefs +import time +import output +import languageHandler +import arrow +import logging +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+);") + def matchFunc(match): + """Nested function to handle a match object. + If we match &blah; and it's not found, &blah; will be returned. + if we match #\d+, unichr(digits) will be returned. + Else, a unicode string will be returned.""" + if match.group(1).startswith('#'): return unichr(int(match.group(1)[1:])) + replacement = htmlentitydefs.entitydefs.get(match.group(1), "&%s;" % match.group(1)) + return replacement.decode('iso-8859-1') + return unicode(entity_re.sub(matchFunc, s)) + +chars = "abcdefghijklmnopqrstuvwxyz" + +def compose_tweet(tweet, db, relative_times, show_screen_names=False): + """ 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") + if relative_times == True: + ts = original_date.humanize(locale=languageHandler.getLanguage()) + else: + ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) + else: + ts = tweet["created_at"] + if "message" in tweet: + value = "message" + elif "full_text" in tweet: + value = "full_text" + else: + value = "text" +# log.exception(tweet.keys()) + text = StripChars(tweet[value]) + if show_screen_names: + 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"], StripChars(tweet["retweeted_status"][value])) + elif tweet["retweeted_status"]["is_quote_status"]: + text = "%s" % (StripChars(tweet[value])) + else: + text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(tweet[value])) +# if text[-1] in chars: text=text+"." + if ("message" in tweet) == False: + urls = utils.find_urls_in_text(text) + for url in range(0, len(urls)): + try: + text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) + except: pass + if config.app['app-settings']['handle_longtweets']: pass +# return [user+", ", text, ts+", ", source] + return [user+", ", text, ts+", ", source] + +def compose_dm(tweet, db, relative_times, show_screen_names=False): + """ 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") + if relative_times == True: + ts = original_date.humanize(locale=languageHandler.getLanguage()) + else: + ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) + else: + ts = tweet["created_at"] + text = StripChars(tweet["text"]) + source = "DM" + if db["user_name"] == tweet["sender"]["screen_name"]: + if show_screen_names: + user = _(u"Dm to %s ") % (tweet["recipient"]["screen_name"],) + else: + user = _(u"Dm to %s ") % (tweet["recipient"]["name"],) + else: + if show_screen_names: + user = tweet["sender"]["screen_name"] + else: + user = tweet["sender"]["name"] + if text[-1] in chars: text=text+"." + urls = utils.find_urls_in_text(text) + for url in range(0, len(urls)): + try: text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"]) + except IndexError: pass + return [user+", ", text, ts+", ", source] + +def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False): + """ 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 "full_text" in quoted_tweet: + value = "full_text" + else: + value = "text" + text = StripChars(quoted_tweet[value]) + if show_screen_names: + quoting_user = quoted_tweet["user"]["screen_name"] + else: + quoting_user = quoted_tweet["user"]["name"] + source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"]) + try: text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], StripChars(quoted_tweet["retweeted_status"][value])) + except KeyError: text = "%s" % (StripChars(quoted_tweet[value])) + if text[-1] in chars: text=text+"." + original_user = original_tweet["user"]["screen_name"] + if "message" in original_tweet: + original_text = StripChars(original_tweet["message"]) + elif "full_text" in original_tweet: + 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( quoted_tweet[value], original_user, original_text) + quoted_tweet = tweets.clear_url(quoted_tweet) + return quoted_tweet + +def compose_followers_list(tweet, db, relative_times=True, show_screen_names=False): + if system == "Windows": + 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.getLanguage()) + else: + ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) + 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") + if relative_times: + ts2 = original_date2.humanize(locale=languageHandler.getLanguage()) + else: + ts2 = original_date2.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage()) + else: + 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)] + +def compose_event(data, username, show_screen_names=False): + if show_screen_names: + value = "screen_name" + else: + value = "name" + if data["event"] == "block": + event = _("You've blocked %s") % (data["target"][value]) + elif data["event"] == "unblock": + event = _(u"You've unblocked %s") % (data["target"][value]) + elif data["event"] == "follow": + if data["target"]["screen_name"] == username: + event = _(u"%s(@%s) has followed you") % (data["source"]["name"], data["source"]["screen_name"]) + elif data["source"]["screen_name"] == username: + event = _(u"You've followed %s(@%s)") % (data["target"]["name"], data["target"]["screen_name"]) + elif data["event"] == "unfollow": + event = _(u"You've unfollowed %s (@%s)") % (data["target"]["name"], data["target"]["screen_name"]) + elif data["event"] == "favorite": + if data["source"]["screen_name"] == username: + event = _(u"You've liked: %s, %s") % (data["target"][value], data["target_object"]["text"]) + else: + event = _(u"%s(@%s) has liked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"]) + elif data["event"] == "unfavorite": + if data["source"]["screen_name"] == username: event = _(u"You've unliked: %s, %s") % (data["target"][value], data["target_object"]["text"]) + else: event = _(u"%s(@%s) has unliked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"]) + elif data["event"] == "list_created": + event = _(u"You've created the list %s") % (data["target_object"]["name"]) + elif data["event"] == "list_destroyed": + event = _("You've deleted the list %s") % (data["target_object"]["name"]) + elif data["event"] == "list_updated": + event = _("You've updated the list %s") % (data["target_object"]["name"]) + elif data["event"] == "list_member_added": + if data["source"]["screen_name"] == username: event = _(u"You've added %s(@%s) to the list %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["name"]) + else: event = _(u"%s(@%s) has added you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"]) + elif data["event"] == "list_member_removed": + if data["source"]["screen_name"] == username: event = _(u"You'be removed %s(@%s) from the list %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["name"]) + else: event = _(u"%s(@%s) has removed you from the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"]) + elif data["event"] == "list_user_subscribed": + if data["source"]["screen_name"] == username: event = _(u"You've subscribed to the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"]) + else: event = _(u"%s(@%s) has suscribed you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"]) + elif data["event"] == "list_user_unsubscribed": + if data["source"]["screen_name"] == username: event = _(u"You've unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"]) + else: event = _("You've been unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["source"]["name"], data["source"]["screen_name"]) + elif data["event"] == "retweeted_retweet": + if data["source"]["screen_name"] == username: event = _(u"You have retweeted a retweet from %s(@%s): %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["retweeted_status"]["text"]) + else: event = _(u"%s(@%s) has retweeted your retweet: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["retweeted_status"]["text"]) + elif data["event"] == "quoted_tweet": + event = _(u"@{0} quoted your tweet: {1}").format(data["source"]["screen_name"], data["target_object"]["text"]) + else: + event = _("Unknown") + log.error("event: %s\n target: %s\n source: %s\n target_object: %s" % (data["event"], data["target"], data["source"], data["target_object"])) + return [time.strftime("%I:%M %p"), event] + +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") + else: status = _(u"public") + return [name, description, user, members, status] diff --git a/src/twitter/twitter.py b/src/twitter/twitter.py index eae3aa64..94c7d053 100644 --- a/src/twitter/twitter.py +++ b/src/twitter/twitter.py @@ -1,38 +1,39 @@ -# -*- coding: utf-8 -*- -import config -import random -import BaseHTTPServer -import webbrowser -from twython import Twython, TwythonError -from keys import keyring -import authorisationHandler -from requests import certs -import logging -log = logging.getLogger("sessionTwitter") - -class twitter(object): - - def login(self, user_key, user_secret, verify_credentials): - self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), user_key, user_secret) - if verify_credentials == True: - self.credentials = self.twitter.verify_credentials() - - def authorise(self, settings): - authorisationHandler.logged = False - port = random.randint(30000, 65535) - httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', port), authorisationHandler.handler) - twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), auth_endpoint='authorize') - auth = twitter.get_authentication_tokens("http://127.0.0.1:{0}".format(port,)) - webbrowser.open_new_tab(auth['auth_url']) - while authorisationHandler.logged == False: - httpd.handle_request() - self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), auth['oauth_token'], auth['oauth_token_secret']) - final = self.twitter.get_authorized_tokens(authorisationHandler.verifier) - self.save_configuration(settings, final["oauth_token"], final["oauth_token_secret"]) - httpd.server_close() - - def save_configuration(self, settings, user_key, user_secret): - settings["twitter"]["user_key"] = user_key - settings["twitter"]["user_secret"] = user_secret - settings.write() - +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import config +import random +import BaseHTTPServer +import webbrowser +from twython import Twython, TwythonError +from keys import keyring +from . import authorisationHandler +from requests import certs +import logging +log = logging.getLogger("sessionTwitter") + +class twitter(object): + + def login(self, user_key, user_secret, verify_credentials): + self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), user_key, user_secret) + if verify_credentials == True: + self.credentials = self.twitter.verify_credentials() + + def authorise(self, settings): + authorisationHandler.logged = False + port = random.randint(30000, 65535) + httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', port), authorisationHandler.handler) + twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), auth_endpoint='authorize') + auth = twitter.get_authentication_tokens("http://127.0.0.1:{0}".format(port,)) + webbrowser.open_new_tab(auth['auth_url']) + while authorisationHandler.logged == False: + httpd.handle_request() + self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), auth['oauth_token'], auth['oauth_token_secret']) + final = self.twitter.get_authorized_tokens(authorisationHandler.verifier) + self.save_configuration(settings, final["oauth_token"], final["oauth_token_secret"]) + httpd.server_close() + + def save_configuration(self, settings, user_key, user_secret): + settings["twitter"]["user_key"] = user_key + settings["twitter"]["user_secret"] = user_secret + settings.write() + diff --git a/src/twitter/utils.py b/src/twitter/utils.py index 5ed717cf..9299e96e 100644 --- a/src/twitter/utils.py +++ b/src/twitter/utils.py @@ -1,144 +1,145 @@ -# -*- coding: utf-8 -*- -import url_shortener, re -import output -from twython import TwythonError -import config -import logging -import requests -import time -import sound -log = logging.getLogger("twitter.utils") -""" Some utilities for the twitter interface.""" - -__version__ = 0.1 -__doc__ = "Find urls in tweets and #audio hashtag." - -url_re = re.compile(r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))") - -url_re2 = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*") -bad_chars = '\'\\.,[](){}:;"' - -def find_urls_in_text(text): - return [s.strip(bad_chars) for s in url_re2.findall(text)] - -def find_urls (tweet): - urls = [] - if tweet.has_key("message"): - i = "message" - elif tweet.has_key("full_text"): - i = "full_text" - else: - i = "text" - return [s[0] for s in url_re.findall(tweet[i])] - -def find_item(id, listItem): - for i in range(0, len(listItem)): - 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"] - -def find_previous_reply(id, listItem): - for i in range(0, len(listItem)): - if listItem[i]["id_str"] == str(id): return i - return None - -def find_next_reply(id, listItem): - for i in range(0, len(listItem)): - if listItem[i]["in_reply_to_status_id_str"] == str(id): return i - return None - -def is_audio(tweet): - try: - if len(find_urls(tweet)) < 1: - return False - if len(tweet["entities"]["hashtags"]) > 0: - for i in tweet["entities"]["hashtags"]: - if i["text"] == "audio": - return True - except: - print tweet["entities"]["hashtags"] - log.exception("Exception while executing is_audio hashtag algorithm") - -def is_geocoded(tweet): - if tweet.has_key("coordinates") and tweet["coordinates"] != None: - return True - -def is_media(tweet): - if tweet["entities"].has_key("media") == False: - return False - for i in tweet["entities"]["media"]: - if i.has_key("type") and i["type"] == "photo": - return True - return False - -def get_all_mentioned(tweet, conf, field="screen_name"): - """ Gets all users that has 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]) - return results - -def get_all_users(tweet, conf): - string = [] - if tweet.has_key("retweeted_status"): - string.append(tweet["user"]["screen_name"]) - tweet = tweet["retweeted_status"] - if tweet.has_key("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 len(string) == 0: - string.append(tweet["user"]["screen_name"]) - return string - -def if_user_exists(twitter, user): - try: - data = twitter.show_user(screen_name=user) - return data - except TwythonError as err: - if err.error_code == 404: - return None - else: - return user - -def api_call(parent=None, call_name=None, preexec_message="", success="", success_snd="", *args, **kwargs): - if preexec_message: - output.speak(preexec_message, True) - try: - val = getattr(parent.twitter.twitter, call_name)(*args, **kwargs) - output.speak(success) - parent.parent.sound.play(success_snd) - except TwythonError as e: - output.speak("Error %s: %s" % (e.error_code, e.msg), True) - parent.parent.sound.play("error.ogg") - return val - -def is_allowed(tweet, clients): - if tweet.has_key("sender"): return True - allowed = True - if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"] - source = re.sub(r"(?s)<.*?>", "", tweet["source"]) - for i in clients: - if i.lower() == source.lower(): - allowed = False -# log.exception("Tuit not allowed: %r" % (tweet,)) - return allowed - -def twitter_error(error): - if error.error_code == 403: - msg = _(u"Sorry, you are not authorised to see this status.") - elif error.error_code == 404: - msg = _(u"No status found with that ID") - else: - msg = _(u"Error code {0}").format(error.error_code,) +# -*- coding: utf-8 -*- +from __future__ import print_function +import url_shortener, re +import output +from twython import TwythonError +import config +import logging +import requests +import time +import sound +log = logging.getLogger("twitter.utils") +""" Some utilities for the twitter interface.""" + +__version__ = 0.1 +__doc__ = "Find urls in tweets and #audio hashtag." + +url_re = re.compile(r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))") + +url_re2 = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*") +bad_chars = '\'\\.,[](){}:;"' + +def find_urls_in_text(text): + return [s.strip(bad_chars) for s in url_re2.findall(text)] + +def find_urls (tweet): + urls = [] + if "message" in tweet: + i = "message" + elif "full_text" in tweet: + i = "full_text" + else: + i = "text" + return [s[0] for s in url_re.findall(tweet[i])] + +def find_item(id, listItem): + for i in range(0, len(listItem)): + 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"] + +def find_previous_reply(id, listItem): + for i in range(0, len(listItem)): + if listItem[i]["id_str"] == str(id): return i + return None + +def find_next_reply(id, listItem): + for i in range(0, len(listItem)): + if listItem[i]["in_reply_to_status_id_str"] == str(id): return i + return None + +def is_audio(tweet): + try: + if len(find_urls(tweet)) < 1: + return False + if len(tweet["entities"]["hashtags"]) > 0: + for i in tweet["entities"]["hashtags"]: + if i["text"] == "audio": + return True + except: + 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: + return True + +def is_media(tweet): + if ("media" in tweet["entities"]) == False: + return False + for i in tweet["entities"]["media"]: + if "type" in i and i["type"] == "photo": + return True + return False + +def get_all_mentioned(tweet, conf, field="screen_name"): + """ Gets all users that has 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]) + 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"]) + 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 len(string) == 0: + string.append(tweet["user"]["screen_name"]) + return string + +def if_user_exists(twitter, user): + try: + data = twitter.show_user(screen_name=user) + return data + except TwythonError as err: + if err.error_code == 404: + return None + else: + return user + +def api_call(parent=None, call_name=None, preexec_message="", success="", success_snd="", *args, **kwargs): + if preexec_message: + output.speak(preexec_message, True) + try: + val = getattr(parent.twitter.twitter, call_name)(*args, **kwargs) + output.speak(success) + parent.parent.sound.play(success_snd) + except TwythonError as e: + output.speak("Error %s: %s" % (e.error_code, e.msg), True) + parent.parent.sound.play("error.ogg") + return val + +def is_allowed(tweet, clients): + if "sender" in tweet: return True + allowed = True + if "retweeted_status" in tweet: tweet = tweet["retweeted_status"] + source = re.sub(r"(?s)<.*?>", "", tweet["source"]) + for i in clients: + if i.lower() == source.lower(): + allowed = False +# log.exception("Tuit not allowed: %r" % (tweet,)) + return allowed + +def twitter_error(error): + if error.error_code == 403: + msg = _(u"Sorry, you are not authorised to see this status.") + elif error.error_code == 404: + msg = _(u"No status found with that ID") + else: + msg = _(u"Error code {0}").format(error.error_code,) output.speak(msg) \ No newline at end of file diff --git a/src/update/updater.py b/src/update/updater.py index c0375d84..6d6d2c7b 100644 --- a/src/update/updater.py +++ b/src/update/updater.py @@ -1,20 +1,21 @@ -# -*- coding: utf-8 -*- -import application -import update -import platform -import logging -import output -from requests.exceptions import ConnectionError -from wxUpdater import * -logger = logging.getLogger("updater") - -def do_update(endpoint=application.update_url): - try: - update.perform_update(endpoint=endpoint, current_version=application.version, app_name=application.name, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished) - except: - if endpoint == application.update_url: - logger.error("Update failed! Using mirror URL...") - return do_update(endpoint=application.mirror_update_url) - else: - logger.exception("Update failed.") +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import application +from . import update +import platform +import logging +import output +from requests.exceptions import ConnectionError +from .wxUpdater import * +logger = logging.getLogger("updater") + +def do_update(endpoint=application.update_url): + try: + update.perform_update(endpoint=endpoint, current_version=application.version, app_name=application.name, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished) + except: + if endpoint == application.update_url: + logger.error("Update failed! Using mirror URL...") + return do_update(endpoint=application.mirror_update_url) + else: + logger.exception("Update failed.") output.speak("An exception occurred while attempting to update " + application.name + ". If this message persists, contact the " + application.name + " developers. More information about the exception has been written to the error log.",True) \ No newline at end of file diff --git a/src/update/wxUpdater.py b/src/update/wxUpdater.py index 761d620a..c9e05c58 100644 --- a/src/update/wxUpdater.py +++ b/src/update/wxUpdater.py @@ -1,30 +1,31 @@ -# -*- coding: utf-8 -*- -import wx -import application -import utils - -progress_dialog = None - -def available_update_dialog(version, description, date): - dialog = wx.MessageDialog(None, _(u"There's a new %s version available, released on %s. Would you like to download it now?\n\n %s version: %s\n\nChanges:\n%s") % (application.name, date, application.name, version, description), _(u"New version for %s") % application.name, style=wx.YES|wx.NO|wx.ICON_WARNING) - if dialog.ShowModal() == wx.ID_YES: - return True - else: - return False - - -def create_progress_dialog(): - return wx.ProgressDialog(_(u"Download in Progress"), _(u"Downloading the new version..."), parent=None, maximum=100) - -def progress_callback(total_downloaded, total_size): - global progress_dialog - if progress_dialog == None: - progress_dialog = create_progress_dialog() - progress_dialog.Show() - if total_downloaded == total_size: - progress_dialog.Destroy() - else: - progress_dialog.Update((total_downloaded*100)/total_size, _(u"Updating... %s of %s") % (str(utils.convert_bytes(total_downloaded)), str(utils.convert_bytes(total_size)))) - -def update_finished(): +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +import application +from . import utils + +progress_dialog = None + +def available_update_dialog(version, description, date): + dialog = wx.MessageDialog(None, _(u"There's a new %s version available, released on %s. Would you like to download it now?\n\n %s version: %s\n\nChanges:\n%s") % (application.name, date, application.name, version, description), _(u"New version for %s") % application.name, style=wx.YES|wx.NO|wx.ICON_WARNING) + if dialog.ShowModal() == wx.ID_YES: + return True + else: + return False + + +def create_progress_dialog(): + return wx.ProgressDialog(_(u"Download in Progress"), _(u"Downloading the new version..."), parent=None, maximum=100) + +def progress_callback(total_downloaded, total_size): + global progress_dialog + if progress_dialog == None: + progress_dialog = create_progress_dialog() + progress_dialog.Show() + if total_downloaded == total_size: + progress_dialog.Destroy() + else: + progress_dialog.Update((total_downloaded*100)/total_size, _(u"Updating... %s of %s") % (str(utils.convert_bytes(total_downloaded)), str(utils.convert_bytes(total_size)))) + +def update_finished(): ms = wx.MessageDialog(None, _(u"The update has been downloaded and installed successfully. Press OK to continue."), _(u"Done!")).ShowModal() \ No newline at end of file diff --git a/src/url_shortener/__init__.py b/src/url_shortener/__init__.py index d1819cbc..d9556030 100644 --- a/src/url_shortener/__init__.py +++ b/src/url_shortener/__init__.py @@ -1,2 +1,3 @@ -import shorteners -from __main__ import * +from __future__ import absolute_import +from . import shorteners +from .__main__ import * diff --git a/src/url_shortener/__main__.py b/src/url_shortener/__main__.py index 56080ce7..2f5b28b8 100644 --- a/src/url_shortener/__main__.py +++ b/src/url_shortener/__main__.py @@ -1,45 +1,46 @@ -from functools import wraps -import shorteners - - -def service_selecter (func): - @wraps(func) - def wrapper (*args, **kwargs): - tmp = dict(kwargs) - if 'service' in tmp: - del(tmp['service']) - kwargs['service'] = find_service(kwargs['service'], **tmp) or default_service() - else: - kwargs['service'] = default_service() - return func(*args, **kwargs) - return wrapper - -@service_selecter -def shorten (url, service=None, **kwargs): - return service(**kwargs).shorten(url) - - -@service_selecter -def unshorten (url, service=None, **kwargs): - return service(**kwargs).unshorten(url) - - -def default_service (): - return shorteners.TinyurlShortener - -def find_service (service, **kwargs): - for i in shorteners.__all__: - obj = getattr(shorteners, i)(**kwargs) - if obj.name.lower() == service.lower(): - return getattr(shorteners, i) - -def list_services (): - return [getattr(shorteners, i)().name for i in shorteners.__all__] - -def unshorten_any (url): - """Unshortens an URL using any available unshortener. Check to see if unshortened URL was created by a shortener (nested) and unshorten if so.""" - unshortened_url = shorteners.URLShortener().unshorten(url) - # None is returned if URL not unshortened - if unshortened_url: - return unshorten_any(unshortened_url) - return url +from __future__ import absolute_import +from functools import wraps +from . import shorteners + + +def service_selecter (func): + @wraps(func) + def wrapper (*args, **kwargs): + tmp = dict(kwargs) + if 'service' in tmp: + del(tmp['service']) + kwargs['service'] = find_service(kwargs['service'], **tmp) or default_service() + else: + kwargs['service'] = default_service() + return func(*args, **kwargs) + return wrapper + +@service_selecter +def shorten (url, service=None, **kwargs): + return service(**kwargs).shorten(url) + + +@service_selecter +def unshorten (url, service=None, **kwargs): + return service(**kwargs).unshorten(url) + + +def default_service (): + return shorteners.TinyurlShortener + +def find_service (service, **kwargs): + for i in shorteners.__all__: + obj = getattr(shorteners, i)(**kwargs) + if obj.name.lower() == service.lower(): + return getattr(shorteners, i) + +def list_services (): + return [getattr(shorteners, i)().name for i in shorteners.__all__] + +def unshorten_any (url): + """Unshortens an URL using any available unshortener. Check to see if unshortened URL was created by a shortener (nested) and unshorten if so.""" + unshortened_url = shorteners.URLShortener().unshorten(url) + # None is returned if URL not unshortened + if unshortened_url: + return unshorten_any(unshortened_url) + return url diff --git a/src/url_shortener/shorteners/__init__.py b/src/url_shortener/shorteners/__init__.py index 53dce662..ba9dafc5 100644 --- a/src/url_shortener/shorteners/__init__.py +++ b/src/url_shortener/shorteners/__init__.py @@ -1,9 +1,10 @@ -from url_shortener import URLShortener -from hkcim import HKCShortener -from isgd import IsgdShortener -from onjme import OnjmeShortener -from tinyarrows import TinyArrowsShortener -from tinyurl import TinyurlShortener -from xedcc import XedccShortener -from clckru import ClckruShortener -__all__ = ["HKCShortener", "IsgdShortener", "OnjmeShortener", "TinyArrowsShortener", "TinyurlShortener", "XedccShortener", "ClckruShortener"] +from __future__ import absolute_import +from .url_shortener import URLShortener +from .hkcim import HKCShortener +from .isgd import IsgdShortener +from .onjme import OnjmeShortener +from .tinyarrows import TinyArrowsShortener +from .tinyurl import TinyurlShortener +from .xedcc import XedccShortener +from .clckru import ClckruShortener +__all__ = ["HKCShortener", "IsgdShortener", "OnjmeShortener", "TinyArrowsShortener", "TinyurlShortener", "XedccShortener", "ClckruShortener"] diff --git a/src/url_shortener/shorteners/clckru.py b/src/url_shortener/shorteners/clckru.py index f72f9281..efc18023 100644 --- a/src/url_shortener/shorteners/clckru.py +++ b/src/url_shortener/shorteners/clckru.py @@ -1,20 +1,21 @@ -import urllib - -from url_shortener import URLShortener - - -class ClckruShortener (URLShortener): - def __init__ (self, *args, **kwargs): - self.name = "clck.ru" - return super(ClckruShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - answer = url - api = urllib.urlopen ("http://clck.ru/--?url=" + urllib.quote(url)) - if api.getcode() == 200: - answer = api.read() - api.close() - return answer - - def created_url (self, url): - return 'clck.ru' in url +from __future__ import absolute_import +import urllib + +from .url_shortener import URLShortener + + +class ClckruShortener (URLShortener): + def __init__ (self, *args, **kwargs): + self.name = "clck.ru" + return super(ClckruShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + answer = url + api = urllib.urlopen ("http://clck.ru/--?url=" + urllib.quote(url)) + if api.getcode() == 200: + answer = api.read() + api.close() + return answer + + def created_url (self, url): + return 'clck.ru' in url diff --git a/src/url_shortener/shorteners/hkcim.py b/src/url_shortener/shorteners/hkcim.py index 3a47e16f..2b45dc18 100644 --- a/src/url_shortener/shorteners/hkcim.py +++ b/src/url_shortener/shorteners/hkcim.py @@ -1,19 +1,20 @@ -import urllib - -from url_shortener import URLShortener - -class HKCShortener (URLShortener): - def __init__ (self, *args, **kwargs): - self.name = "HKC.im" - super(HKCShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - answer = url - api = urllib.urlopen ("http://hkc.im/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url)) - if api.getcode() == 200: - answer = api.read() - api.close() - return answer - - def created_url (self, url): - return 'hkc.im' in url.lower() +from __future__ import absolute_import +import urllib + +from .url_shortener import URLShortener + +class HKCShortener (URLShortener): + def __init__ (self, *args, **kwargs): + self.name = "HKC.im" + super(HKCShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + answer = url + api = urllib.urlopen ("http://hkc.im/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url)) + if api.getcode() == 200: + answer = api.read() + api.close() + return answer + + def created_url (self, url): + return 'hkc.im' in url.lower() diff --git a/src/url_shortener/shorteners/isgd.py b/src/url_shortener/shorteners/isgd.py index d2d25b33..a624cf85 100644 --- a/src/url_shortener/shorteners/isgd.py +++ b/src/url_shortener/shorteners/isgd.py @@ -1,20 +1,21 @@ -import urllib - -from url_shortener import URLShortener - - -class IsgdShortener (URLShortener): - def __init__ (self, *args, **kwargs): - self.name = "Is.gd" - return super(IsgdShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - answer = url - api = urllib.urlopen ("http://is.gd/api.php?longurl=" + urllib.quote(url)) - if api.getcode() == 200: - answer = api.read() - api.close() - return answer - - def created_url (self, url): - return 'is.gd' in url +from __future__ import absolute_import +import urllib + +from .url_shortener import URLShortener + + +class IsgdShortener (URLShortener): + def __init__ (self, *args, **kwargs): + self.name = "Is.gd" + return super(IsgdShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + answer = url + api = urllib.urlopen ("http://is.gd/api.php?longurl=" + urllib.quote(url)) + if api.getcode() == 200: + answer = api.read() + api.close() + return answer + + def created_url (self, url): + return 'is.gd' in url diff --git a/src/url_shortener/shorteners/onjme.py b/src/url_shortener/shorteners/onjme.py index 0b0fd5a2..ecb2bc91 100644 --- a/src/url_shortener/shorteners/onjme.py +++ b/src/url_shortener/shorteners/onjme.py @@ -1,19 +1,20 @@ -import urllib - -from url_shortener import URLShortener - -class OnjmeShortener (URLShortener): - def __init__ (self, *args, **kwargs): - self.name = "Onj.me" - super(OnjmeShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - answer = url - api = urllib.urlopen ("http://onj.me/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url)) - if api.getcode() == 200: - answer = api.read() - api.close() - return answer - - def created_url (self, url): - return 'onj.me' in url.lower() +from __future__ import absolute_import +import urllib + +from .url_shortener import URLShortener + +class OnjmeShortener (URLShortener): + def __init__ (self, *args, **kwargs): + self.name = "Onj.me" + super(OnjmeShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + answer = url + api = urllib.urlopen ("http://onj.me/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url)) + if api.getcode() == 200: + answer = api.read() + api.close() + return answer + + def created_url (self, url): + return 'onj.me' in url.lower() diff --git a/src/url_shortener/shorteners/tinyarrows.py b/src/url_shortener/shorteners/tinyarrows.py index d9392fb7..7a6d020f 100644 --- a/src/url_shortener/shorteners/tinyarrows.py +++ b/src/url_shortener/shorteners/tinyarrows.py @@ -1,16 +1,17 @@ -import urllib - -from url_shortener import URLShortener - -class TinyArrowsShortener (URLShortener): - def __init__ (self, *args, **kwargs): - self.name = "TinyArro.ws" - super(TinyArrowsShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - answer = url - answer = urllib.urlopen("http://tinyarro.ws/api-create.php?utfpure=1&url=%s" % urllib.quote(url)).read() - return answer.decode('UTF-8') - - def created_url(self, url): - return False +from __future__ import absolute_import +import urllib + +from .url_shortener import URLShortener + +class TinyArrowsShortener (URLShortener): + def __init__ (self, *args, **kwargs): + self.name = "TinyArro.ws" + super(TinyArrowsShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + answer = url + answer = urllib.urlopen("http://tinyarro.ws/api-create.php?utfpure=1&url=%s" % urllib.quote(url)).read() + return answer.decode('UTF-8') + + def created_url(self, url): + return False diff --git a/src/url_shortener/shorteners/tinyurl.py b/src/url_shortener/shorteners/tinyurl.py index 6f1b316e..d8057498 100644 --- a/src/url_shortener/shorteners/tinyurl.py +++ b/src/url_shortener/shorteners/tinyurl.py @@ -1,18 +1,19 @@ -from url_shortener import URLShortener -import urllib -class TinyurlShortener (URLShortener): - def __init__(self, *args, **kwargs): - self.name = "TinyURL.com" - super(TinyurlShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - - answer = url - api = urllib.urlopen ("http://tinyurl.com/api-create.php?url=" + urllib.quote(url)) - if api.getcode() == 200: - answer = api.read() - api.close() - return answer - - def created_url (self, url): - return 'tinyurl.com' in url +from __future__ import absolute_import +from .url_shortener import URLShortener +import urllib +class TinyurlShortener (URLShortener): + def __init__(self, *args, **kwargs): + self.name = "TinyURL.com" + super(TinyurlShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + + answer = url + api = urllib.urlopen ("http://tinyurl.com/api-create.php?url=" + urllib.quote(url)) + if api.getcode() == 200: + answer = api.read() + api.close() + return answer + + def created_url (self, url): + return 'tinyurl.com' in url diff --git a/src/url_shortener/shorteners/url_shortener.py b/src/url_shortener/shorteners/url_shortener.py index e0b25561..2bab88ab 100644 --- a/src/url_shortener/shorteners/url_shortener.py +++ b/src/url_shortener/shorteners/url_shortener.py @@ -1,33 +1,33 @@ -from httplib import HTTPConnection -from urlparse import urlparse - - -class URLShortener (object): - - def __init__ (self, *args, **kwargs): - #Stub out arguments, silly object. :( - return super(URLShortener, self).__init__() - - def shorten (self, url): - if self.created_url(url): - return url - else: - return self._shorten(url) - - def _shorten (self, url): - raise NotImplementedError - - def created_url (self, url): - """Returns a boolean indicating whether or not this shortener created a provided url""" - raise NotImplementedError - - def unshorten(self, url): - working = urlparse(url) - if not working.netloc: - raise TypeError, "Unable to parse URL." - con = HTTPConnection(working.netloc) - con.connect() - con.request('GET', working.path) - resp = con.getresponse() - con.close() - return resp.getheader('location') +from httplib import HTTPConnection +from urlparse import urlparse + + +class URLShortener (object): + + def __init__ (self, *args, **kwargs): + #Stub out arguments, silly object. :( + return super(URLShortener, self).__init__() + + def shorten (self, url): + if self.created_url(url): + return url + else: + return self._shorten(url) + + def _shorten (self, url): + raise NotImplementedError + + def created_url (self, url): + """Returns a boolean indicating whether or not this shortener created a provided url""" + raise NotImplementedError + + def unshorten(self, url): + working = urlparse(url) + if not working.netloc: + raise TypeError("Unable to parse URL.") + con = HTTPConnection(working.netloc) + con.connect() + con.request('GET', working.path) + resp = con.getresponse() + con.close() + return resp.getheader('location') diff --git a/src/url_shortener/shorteners/xedcc.py b/src/url_shortener/shorteners/xedcc.py index 8d466306..c12e55be 100644 --- a/src/url_shortener/shorteners/xedcc.py +++ b/src/url_shortener/shorteners/xedcc.py @@ -1,19 +1,20 @@ -import urllib - -from url_shortener import URLShortener - -class XedccShortener (URLShortener): - def __init__ (self, *args, **kwargs): - self.name = "Xed.cc" - super(XedccShortener, self).__init__(*args, **kwargs) - - def _shorten (self, url): - answer = url - api = urllib.urlopen ("http://xed.cc/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url)) - if api.getcode() == 200: - answer = api.read() - api.close() - return answer - - def created_url (self, url): - return 'xed.cc' in url.lower() +from __future__ import absolute_import +import urllib + +from .url_shortener import URLShortener + +class XedccShortener (URLShortener): + def __init__ (self, *args, **kwargs): + self.name = "Xed.cc" + super(XedccShortener, self).__init__(*args, **kwargs) + + def _shorten (self, url): + answer = url + api = urllib.urlopen ("http://xed.cc/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url)) + if api.getcode() == 200: + answer = api.read() + api.close() + return answer + + def created_url (self, url): + return 'xed.cc' in url.lower() diff --git a/src/widgetUtils/__init__.py b/src/widgetUtils/__init__.py index 30509ef6..673ab67c 100644 --- a/src/widgetUtils/__init__.py +++ b/src/widgetUtils/__init__.py @@ -1,5 +1,6 @@ -import platform -if platform.system() == "Windows": - from wxUtils import * -#elif platform.system() == "Linux": -# from gtkUtils import * +from __future__ import absolute_import +import platform +if platform.system() == "Windows": + from .wxUtils import * +#elif platform.system() == "Linux": +# from gtkUtils import * diff --git a/src/wxUI/buffers/__init__.py b/src/wxUI/buffers/__init__.py index 2380f3a9..adf383df 100644 --- a/src/wxUI/buffers/__init__.py +++ b/src/wxUI/buffers/__init__.py @@ -1,11 +1,12 @@ -# -*- coding: utf-8 -*- -from base import basePanel -from dm import dmPanel -from events import eventsPanel -from favourites import favsPanel -from lists import listPanel -from panels import accountPanel, emptyPanel -from people import peoplePanel -from trends import trendsPanel -from tweet_searches import searchPanel -from user_searches import searchUsersPanel \ No newline at end of file +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from .base import basePanel +from .dm import dmPanel +from .events import eventsPanel +from .favourites import favsPanel +from .lists import listPanel +from .panels import accountPanel, emptyPanel +from .people import peoplePanel +from .trends import trendsPanel +from .tweet_searches import searchPanel +from .user_searches import searchUsersPanel \ No newline at end of file diff --git a/src/wxUI/buffers/dm.py b/src/wxUI/buffers/dm.py index db95aae0..26bddc31 100644 --- a/src/wxUI/buffers/dm.py +++ b/src/wxUI/buffers/dm.py @@ -1,11 +1,12 @@ -# -*- coding: utf-8 -*- -import wx -from base import basePanel - -class dmPanel(basePanel): - def __init__(self, parent, name): - """ Class to DM'S. Reply and retweet buttons are not showed and they have your delete method for dm's.""" - super(dmPanel, self).__init__(parent, name) - self.retweet.Disable() - self.reply.Disable() +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from .base import basePanel + +class dmPanel(basePanel): + def __init__(self, parent, name): + """ Class to DM'S. Reply and retweet buttons are not showed and they have your delete method for dm's.""" + super(dmPanel, self).__init__(parent, name) + self.retweet.Disable() + self.reply.Disable() self.type = "dm" \ No newline at end of file diff --git a/src/wxUI/buffers/favourites.py b/src/wxUI/buffers/favourites.py index 4837dd6f..c665bed4 100644 --- a/src/wxUI/buffers/favourites.py +++ b/src/wxUI/buffers/favourites.py @@ -1,8 +1,9 @@ -# -*- coding: utf-8 -*- -import wx -from base import basePanel - -class favsPanel(basePanel): - def __init__(self, parent, name): - super(favsPanel, self).__init__(parent, name) +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from .base import basePanel + +class favsPanel(basePanel): + def __init__(self, parent, name): + super(favsPanel, self).__init__(parent, name) self.type = "favourites_timeline" \ No newline at end of file diff --git a/src/wxUI/buffers/lists.py b/src/wxUI/buffers/lists.py index 82ca73bc..c2e02fbc 100644 --- a/src/wxUI/buffers/lists.py +++ b/src/wxUI/buffers/lists.py @@ -1,8 +1,9 @@ -# -*- coding: utf-8 -*- -import wx -from base import basePanel - -class listPanel(basePanel): - def __init__(self, parent, name): - super(listPanel, self).__init__(parent, name) - self.type = "list" +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from .base import basePanel + +class listPanel(basePanel): + def __init__(self, parent, name): + super(listPanel, self).__init__(parent, name) + self.type = "list" diff --git a/src/wxUI/buffers/people.py b/src/wxUI/buffers/people.py index f887ba4d..e1b4e566 100644 --- a/src/wxUI/buffers/people.py +++ b/src/wxUI/buffers/people.py @@ -1,16 +1,17 @@ -# -*- coding: utf-8 -*- -import wx -from multiplatform_widgets import widgets -from base import basePanel - -class peoplePanel(basePanel): - """ Buffer used to show people.""" - - def create_list(self): - self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800)) - - def __init__(self, parent, name): - super(peoplePanel, self).__init__(parent, name) - self.type = "people" - self.reply.SetLabel(_(u"Mention")) - self.retweet.Disable() +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from multiplatform_widgets import widgets +from .base import basePanel + +class peoplePanel(basePanel): + """ Buffer used to show people.""" + + def create_list(self): + self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800)) + + def __init__(self, parent, name): + super(peoplePanel, self).__init__(parent, name) + self.type = "people" + self.reply.SetLabel(_(u"Mention")) + self.retweet.Disable() diff --git a/src/wxUI/buffers/tweet_searches.py b/src/wxUI/buffers/tweet_searches.py index 28cf974e..cb6b797c 100644 --- a/src/wxUI/buffers/tweet_searches.py +++ b/src/wxUI/buffers/tweet_searches.py @@ -1,8 +1,9 @@ -# -*- coding: utf-8 -*- -import wx -from base import basePanel - -class searchPanel(basePanel): - def __init__(self, parent, name): - super(searchPanel, self).__init__(parent, name) - self.type = "search" +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from .base import basePanel + +class searchPanel(basePanel): + def __init__(self, parent, name): + super(searchPanel, self).__init__(parent, name) + self.type = "search" diff --git a/src/wxUI/buffers/user_searches.py b/src/wxUI/buffers/user_searches.py index b3b1415c..e68fec2f 100644 --- a/src/wxUI/buffers/user_searches.py +++ b/src/wxUI/buffers/user_searches.py @@ -1,14 +1,15 @@ -# -*- coding: utf-8 -*- -import wx -from tweet_searches import searchPanel -from multiplatform_widgets import widgets - -class searchUsersPanel(searchPanel): - def create_list(self): - """ Returns the list for put the tweets here.""" - self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800)) - - def __init__(self, parent, name): - super(searchUsersPanel, self).__init__(parent, name) - self.create_list() +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from .tweet_searches import searchPanel +from multiplatform_widgets import widgets + +class searchUsersPanel(searchPanel): + def create_list(self): + """ Returns the list for put the tweets here.""" + self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800)) + + def __init__(self, parent, name): + super(searchUsersPanel, self).__init__(parent, name) + self.create_list() self.type = "user_searches" \ No newline at end of file diff --git a/src/wxUI/dialogs/__init__.py b/src/wxUI/dialogs/__init__.py index cbf0d2da..0e267e1f 100644 --- a/src/wxUI/dialogs/__init__.py +++ b/src/wxUI/dialogs/__init__.py @@ -1 +1,2 @@ -import baseDialog, trends, configuration, lists, message, search, find, show_user, update_profile, urlList, userSelection, utils +from __future__ import absolute_import +from . import baseDialog, trends, configuration, lists, message, search, find, show_user, update_profile, urlList, userSelection, utils diff --git a/src/wxUI/dialogs/configuration.py b/src/wxUI/dialogs/configuration.py index f45ff40c..94158d96 100644 --- a/src/wxUI/dialogs/configuration.py +++ b/src/wxUI/dialogs/configuration.py @@ -1,377 +1,379 @@ -# -*- coding: utf-8 -*- -import baseDialog -import wx -import logging as original_logger -import application -from multiplatform_widgets import widgets -import output -import config - -class general(wx.Panel, baseDialog.BaseWXDialog): - def __init__(self, parent, languages,keymaps): - super(general, self).__init__(parent) - sizer = wx.BoxSizer(wx.VERTICAL) - language = wx.StaticText(self, -1, _(u"Language")) - self.language = wx.ListBox(self, -1, choices=languages) - self.language.SetSize(self.language.GetBestSize()) - langBox = wx.BoxSizer(wx.HORIZONTAL) - langBox.Add(language, 0, wx.ALL, 5) - langBox.Add(self.language, 0, wx.ALL, 5) - sizer.Add(langBox, 0, wx.ALL, 5) - self.autostart = wx.CheckBox(self, -1, _(u"Run {0} at Windows startup").format(application.name,)) - self.ask_at_exit = wx.CheckBox(self, -1, _(U"ask before exiting {0}").format(application.name,)) - sizer.Add(self.autostart, 0, wx.ALL, 5) - sizer.Add(self.ask_at_exit, 0, wx.ALL, 5) - self.play_ready_sound = wx.CheckBox(self, -1, _(U"Play a sound when {0} launches").format(application.name,)) - sizer.Add(self.play_ready_sound, 0, wx.ALL, 5) - self.speak_ready_msg = wx.CheckBox(self, -1, _(U"Speak a message when {0} launches").format(application.name,)) - sizer.Add(self.speak_ready_msg, 0, wx.ALL, 5) - self.use_invisible_shorcuts = wx.CheckBox(self, -1, _(u"Use invisible interface's keyboard shortcuts while GUI is visible")) - sizer.Add(self.use_invisible_shorcuts, 0, wx.ALL, 5) - self.disable_sapi5 = wx.CheckBox(self, -1, _(u"Activate Sapi5 when any other screen reader is not being run")) - sizer.Add(self.disable_sapi5, 0, wx.ALL, 5) - self.hide_gui = wx.CheckBox(self, -1, _(u"Hide GUI on launch")) - sizer.Add(self.hide_gui, 0, wx.ALL, 5) - self.handle_longtweets = wx.CheckBox(self, wx.NewId(), _(u"Use Codeofdusk's longtweet handlers (may decrease client performance)")) - sizer.Add(self.handle_longtweets, 0, wx.ALL, 5) - kmbox = wx.BoxSizer(wx.VERTICAL) - km_label = wx.StaticText(self, -1, _(u"Keymap")) - self.km = wx.ComboBox(self, -1, choices=keymaps, style=wx.CB_READONLY) - self.km.SetSize(self.km.GetBestSize()) - kmbox.Add(km_label, 0, wx.ALL, 5) - kmbox.Add(self.km, 0, wx.ALL, 5) - self.check_for_updates = wx.CheckBox(self, -1, _(U"Check for updates when {0} launches").format(application.name,)) - sizer.Add(self.check_for_updates, 0, wx.ALL, 5) - sizer.Add(kmbox, 0, wx.ALL, 5) - self.SetSizer(sizer) - -class proxy(wx.Panel, baseDialog.BaseWXDialog): - - def __init__(self, parent, proxyTypes): - super(proxy, self).__init__(parent) - sizer = wx.BoxSizer(wx.VERTICAL) - type=wx.StaticText(self, wx.NewId(), _(u"Proxy type: ")) - self.type=wx.ComboBox(self, -1, choices=proxyTypes, style=wx.CB_READONLY) - self.type.SetSize(self.type.GetBestSize()) - typeBox = wx.BoxSizer(wx.HORIZONTAL) - typeBox.Add(type, 0, wx.ALL, 5) - typeBox.Add(self.type, 0, wx.ALL, 5) - sizer.Add(typeBox, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _(u"Proxy server: ")) - self.server = wx.TextCtrl(self, -1) - serverBox = wx.BoxSizer(wx.HORIZONTAL) - serverBox.Add(lbl, 0, wx.ALL, 5) - serverBox.Add(self.server, 0, wx.ALL, 5) - sizer.Add(serverBox, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _(u"Port: ")) - self.port = wx.TextCtrl(self, wx.NewId()) - portBox = wx.BoxSizer(wx.HORIZONTAL) - portBox.Add(lbl, 0, wx.ALL, 5) - portBox.Add(self.port, 0, wx.ALL, 5) - sizer.Add(portBox, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _(u"User: ")) - self.user = wx.TextCtrl(self, wx.NewId()) - userBox = wx.BoxSizer(wx.HORIZONTAL) - userBox.Add(lbl, 0, wx.ALL, 5) - userBox.Add(self.user, 0, wx.ALL, 5) - sizer.Add(userBox, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _(u"Password: ")) - self.password = wx.TextCtrl(self, wx.NewId(), style=wx.TE_PASSWORD) - passwordBox = wx.BoxSizer(wx.HORIZONTAL) - passwordBox.Add(lbl, 0, wx.ALL, 5) - passwordBox.Add(self.password, 0, wx.ALL, 5) - sizer.Add(serverBox, 0, wx.ALL, 5) - self.SetSizer(sizer) - -class generalAccount(wx.Panel, baseDialog.BaseWXDialog): - def __init__(self, parent): - super(generalAccount, self).__init__(parent) - sizer = wx.BoxSizer(wx.VERTICAL) - self.au = wx.Button(self, wx.NewId(), _(u"Autocompletion settings...")) - sizer.Add(self.au, 0, wx.ALL, 5) - self.relative_time = wx.CheckBox(self, wx.NewId(), _(U"Relative timestamps")) - sizer.Add(self.relative_time, 0, wx.ALL, 5) - apiCallsBox = wx.BoxSizer(wx.HORIZONTAL) - apiCallsBox.Add(wx.StaticText(self, -1, _(u"API calls (One API call = 200 tweets, two API calls = 400 tweets, etc):")), 0, wx.ALL, 5) - self.apiCalls = wx.SpinCtrl(self, wx.NewId()) - self.apiCalls.SetRange(1, 10) - self.apiCalls.SetSize(self.apiCalls.GetBestSize()) - apiCallsBox.Add(self.apiCalls, 0, wx.ALL, 5) - sizer.Add(apiCallsBox, 0, wx.ALL, 5) - tweetsPerCallBox = wx.BoxSizer(wx.HORIZONTAL) - tweetsPerCallBox.Add(wx.StaticText(self, -1, _(u"Items on each API call")), 0, wx.ALL, 5) - self.itemsPerApiCall = wx.SpinCtrl(self, wx.NewId()) - self.itemsPerApiCall.SetRange(0, 200) - self.itemsPerApiCall.SetSize(self.itemsPerApiCall.GetBestSize()) - tweetsPerCallBox.Add(self.itemsPerApiCall, 0, wx.ALL, 5) - sizer.Add(tweetsPerCallBox, 0, wx.ALL, 5) - self.reverse_timelines = wx.CheckBox(self, wx.NewId(), _(u"Inverted buffers: The newest tweets will be shown at the beginning while the oldest at the end")) - sizer.Add(self.reverse_timelines, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _(u"Retweet mode")) - self.retweet_mode = wx.ComboBox(self, wx.NewId(), choices=[_(u"Ask"), _(u"Retweet without comments"), _(u"Retweet with comments")], style=wx.CB_READONLY) - rMode = wx.BoxSizer(wx.HORIZONTAL) - rMode.Add(lbl, 0, wx.ALL, 5) - rMode.Add(self.retweet_mode, 0, wx.ALL, 5) - sizer.Add(rMode, 0, wx.ALL, 5) - self.show_screen_names = wx.CheckBox(self, wx.NewId(), _(U"Show screen names instead of full names")) - sizer.Add(self.show_screen_names, 0, wx.ALL, 5) - PersistSizeLabel = wx.StaticText(self, -1, _(u"Number of items per buffer to cache in database (0 to disable caching, blank for unlimited)")) - self.persist_size = wx.TextCtrl(self, -1) - sizer.Add(PersistSizeLabel, 0, wx.ALL, 5) - sizer.Add(self.persist_size, 0, wx.ALL, 5) - self.SetSizer(sizer) - -class other_buffers(wx.Panel): - def __init__(self, parent): - super(other_buffers, self).__init__(parent) - sizer = wx.BoxSizer(wx.VERTICAL) - self.buffers = widgets.list(self, _(u"Buffer"), _(u"Name"), _(u"Status"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT) - sizer.Add(self.buffers.list, 0, wx.ALL, 5) - btnSizer = wx.BoxSizer(wx.HORIZONTAL) - self.toggle_state = wx.Button(self, -1, _(u"Show/hide")) - self.up = wx.Button(self, -1, _(u"Move up")) - self.down = wx.Button(self, -1, _(u"Move down")) - btnSizer.Add(self.toggle_state, 0, wx.ALL, 5) - btnSizer.Add(self.up, 0, wx.ALL, 5) - btnSizer.Add(self.down, 0, wx.ALL, 5) - sizer.Add(btnSizer, 0, wx.ALL, 5) - self.SetSizer(sizer) - - def insert_buffers(self, buffers): - for i in buffers: - if i[2] == True: - self.buffers.insert_item(False, *[i[0], i[1], _(u"Show")]) - else: - self.buffers.insert_item(False, *[i[0], i[1], _(u"Hide")]) - - def connect_hook_func(self, func): - self.buffers.list.Bind(wx.EVT_CHAR_HOOK, func) - - def move_up(self, *args, **kwargs): - current = self.buffers.get_selected() - if current == -1: - output.speak(_(u"Select a buffer first."), True) - return False - if self.buffers.get_text_column(current, 2) == _(u"Hide"): - output.speak(_(u"The buffer is hidden, show it first."), True) - return False - if current <= 0: - output.speak(_(u"The buffer is already at the top of the list."), True) - return False - current_text = self.buffers.get_text_column(self.buffers.get_selected(), 0) - current_name = self.buffers.get_text_column(self.buffers.get_selected(), 1) - current_text_state = self.buffers.get_text_column(self.buffers.get_selected(), 2) - text_above = self.buffers.get_text_column(self.buffers.get_selected()-1, 0) - name_above = self.buffers.get_text_column(self.buffers.get_selected()-1, 1) - text_above_state = self.buffers.get_text_column(self.buffers.get_selected()-1, 2) - self.buffers.set_text_column(self.buffers.get_selected()-1, 0, current_text) - self.buffers.set_text_column(self.buffers.get_selected()-1, 1, current_name) - self.buffers.set_text_column(self.buffers.get_selected()-1, 2, current_text_state) - self.buffers.set_text_column(self.buffers.get_selected(), 0, text_above) - self.buffers.set_text_column(self.buffers.get_selected(), 1, name_above) - self.buffers.set_text_column(self.buffers.get_selected(), 2, text_above_state) - - def move_down(self, *args, **kwargs): - current = self.buffers.get_selected() - if current == -1: - output.speak(_(u"Select a buffer first."), True) - return False - if self.buffers.get_text_column(current, 2) == _(u"Hide"): - output.speak(_(u"The buffer is hidden, show it first."), True) - return False - if current+1 >= self.buffers.get_count(): - output.speak(_(u"The buffer is already at the bottom of the list."), True) - return False - current_text = self.buffers.get_text_column(self.buffers.get_selected(), 0) - current_name = self.buffers.get_text_column(self.buffers.get_selected(), 1) - current_text_state = self.buffers.get_text_column(self.buffers.get_selected(), 2) - text_below = self.buffers.get_text_column(self.buffers.get_selected()+1, 0) - name_below = self.buffers.get_text_column(self.buffers.get_selected()+1, 1) - text_below_state = self.buffers.get_text_column(self.buffers.get_selected()+1, 2) - self.buffers.set_text_column(self.buffers.get_selected()+1, 0, current_text) - self.buffers.set_text_column(self.buffers.get_selected()+1, 1, current_name) - self.buffers.set_text_column(self.buffers.get_selected()+1, 2, current_text_state) - self.buffers.set_text_column(self.buffers.get_selected(), 0, text_below) - self.buffers.set_text_column(self.buffers.get_selected(), 1, name_below) - self.buffers.set_text_column(self.buffers.get_selected(), 2, text_below_state) - - def get_event(self, ev): - if ev.GetKeyCode() == wx.WXK_SPACE: - return True - else: - ev.Skip() - return False - - def change_selected_item(self): - current = self.buffers.get_selected() - text = self.buffers.get_text_column(current, 2) - if text == _(u"Show"): - self.buffers.set_text_column(current, 2, _(u"Hide")) - else: - self.buffers.set_text_column(current, 2, _(u"Show")) - output.speak(self.buffers.get_text_column(current, 2),True) - def get_list(self): - buffers_list = [] - for i in xrange(0, self.buffers.get_count()): - if self.buffers.get_text_column(i, 2) == _(u"Show"): - buffers_list.append(self.buffers.get_text_column(i, 0)) - return buffers_list - -class ignoredClients(wx.Panel): - def __init__(self, parent, choices): - super(ignoredClients, self).__init__(parent=parent) - sizer = wx.BoxSizer(wx.VERTICAL) - label = wx.StaticText(self, -1, _(u"Ignored clients")) - self.clients = wx.ListBox(self, -1, choices=choices) - self.clients.SetSize(self.clients.GetBestSize()) - clientsBox = wx.BoxSizer(wx.HORIZONTAL) - clientsBox.Add(label, 0, wx.ALL, 5) - clientsBox.Add(self.clients, 0, wx.ALL, 5) - self.add = wx.Button(self, -1, _(u"Add client")) - self.remove = wx.Button(self, -1, _(u"Remove client")) - btnBox = wx.BoxSizer(wx.HORIZONTAL) - btnBox.Add(self.add, 0, wx.ALL, 5) - btnBox.Add(self.remove, 0, wx.ALL, 5) - sizer.Add(clientsBox, 0, wx.ALL, 5) - sizer.Add(btnBox, 0, wx.ALL, 5) - self.SetSizer(sizer) - - def append(self, client): - self.clients.Append(client) - - def get_clients(self): - return self.clients.GetCount() - - def get_client_id(self): - return self.clients.GetSelection() - - def remove_(self, id): - self.clients.Delete(id) - -class sound(wx.Panel): - def __init__(self, parent, input_devices, output_devices, soundpacks): - wx.Panel.__init__(self, parent) - sizer = wx.BoxSizer(wx.VERTICAL) - volume = wx.StaticText(self, -1, _(u"Volume")) - self.volumeCtrl = wx.Slider(self) - self.volumeCtrl.SetRange(0, 100) - self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize()) - volumeBox = wx.BoxSizer(wx.HORIZONTAL) - volumeBox.Add(volume, 0, wx.ALL, 5) - volumeBox.Add(self.volumeCtrl, 0, wx.ALL, 5) - sizer.Add(volumeBox, 0, wx.ALL, 5) - self.session_mute = wx.CheckBox(self, -1, _(u"Session mute")) - sizer.Add(self.session_mute, 0, wx.ALL, 5) - output_label = wx.StaticText(self, -1, _(u"Output device")) - self.output = wx.ComboBox(self, -1, choices=output_devices, style=wx.CB_READONLY) - self.output.SetSize(self.output.GetBestSize()) - outputBox = wx.BoxSizer(wx.HORIZONTAL) - outputBox.Add(output_label, 0, wx.ALL, 5) - outputBox.Add(self.output, 0, wx.ALL, 5) - sizer.Add(outputBox, 0, wx.ALL, 5) - input_label = wx.StaticText(self, -1, _(u"Input device")) - self.input = wx.ComboBox(self, -1, choices=input_devices, style=wx.CB_READONLY) - self.input.SetSize(self.input.GetBestSize()) - inputBox = wx.BoxSizer(wx.HORIZONTAL) - inputBox.Add(input_label, 0, wx.ALL, 5) - inputBox.Add(self.input, 0, wx.ALL, 5) - sizer.Add(inputBox, 0, wx.ALL, 5) - soundBox = wx.BoxSizer(wx.VERTICAL) - soundpack_label = wx.StaticText(self, -1, _(u"Sound pack")) - self.soundpack = wx.ComboBox(self, -1, choices=soundpacks, style=wx.CB_READONLY) - self.soundpack.SetSize(self.soundpack.GetBestSize()) - soundBox.Add(soundpack_label, 0, wx.ALL, 5) - soundBox.Add(self.soundpack, 0, wx.ALL, 5) - sizer.Add(soundBox, 0, wx.ALL, 5) - self.indicate_audio = wx.CheckBox(self, -1, _(u"Indicate audio tweets with sound")) - sizer.Add(self.indicate_audio, 0, wx.ALL, 5) - self.indicate_geo = wx.CheckBox(self, -1, _(u"Indicate geotweets with sound")) - sizer.Add(self.indicate_geo, 0, wx.ALL, 5) - self.indicate_img = wx.CheckBox(self, -1, _(u"Indicate tweets containing images with sound")) - sizer.Add(self.indicate_img, 0, wx.ALL, 5) - self.SetSizer(sizer) - - def get(self, control): - return getattr(self, control).GetStringSelection() - -class extrasPanel(wx.Panel): - def __init__(self, parent, ocr_languages=[], translation_languages=[]): - super(extrasPanel, self).__init__(parent) - mainSizer = wx.BoxSizer(wx.VERTICAL) - OCRBox = wx.StaticBox(self, label=_(u"Language for OCR")) - self.ocr_lang = wx.ListBox(self, -1, choices=ocr_languages) - self.ocr_lang.SetSize(self.ocr_lang.GetBestSize()) - ocrLanguageSizer = wx.StaticBoxSizer(OCRBox, wx.HORIZONTAL) - ocrLanguageSizer.Add(self.ocr_lang, 0, wx.ALL, 5) - mainSizer.Add(ocrLanguageSizer, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _(u"API Key for SndUp")) - self.sndup_apiKey = wx.TextCtrl(self, -1) - sndupBox = wx.BoxSizer(wx.HORIZONTAL) - sndupBox.Add(lbl, 0, wx.ALL, 5) - sndupBox.Add(self.sndup_apiKey, 0, wx.ALL, 5) - mainSizer.Add(sndupBox, 0, wx.ALL, 5) - self.SetSizer(mainSizer) - -class configurationDialog(baseDialog.BaseWXDialog): - def set_title(self, title): - self.SetTitle(title) - - def __init__(self): - super(configurationDialog, self).__init__(None, -1) - self.panel = wx.Panel(self) - self.SetTitle(_(u"{0} preferences").format(application.name,)) - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.notebook = wx.Notebook(self.panel) - - def create_general(self, languageList,keymaps): - self.general = general(self.notebook, languageList,keymaps) - self.notebook.AddPage(self.general, _(u"General")) - self.general.SetFocus() - - def create_proxy(self, proxyTypes): - self.proxy = proxy(self.notebook, proxyTypes) - self.notebook.AddPage(self.proxy, _(u"Proxy")) - - def create_general_account(self): - self.general = generalAccount(self.notebook) - self.notebook.AddPage(self.general, _(u"General")) - self.general.SetFocus() - - def create_other_buffers(self): - self.buffers = other_buffers(self.notebook) - self.notebook.AddPage(self.buffers, _(u"Buffers")) - - def create_ignored_clients(self, ignored_clients_list): - self.ignored_clients = ignoredClients(self.notebook, ignored_clients_list) - self.notebook.AddPage(self.ignored_clients, _(u"Ignored clients")) - - def create_sound(self, output_devices, input_devices, soundpacks): - self.sound = sound(self.notebook, output_devices, input_devices, soundpacks) - self.notebook.AddPage(self.sound, _(u"Sound")) - - def create_extras(self, ocr_languages=[], translator_languages=[]): - self.extras = extrasPanel(self.notebook, ocr_languages, translator_languages) - self.notebook.AddPage(self.extras, _(u"Extras")) - - def realize(self): - self.sizer.Add(self.notebook, 0, wx.ALL, 5) - ok_cancel_box = wx.BoxSizer(wx.HORIZONTAL) - ok = wx.Button(self.panel, wx.ID_OK, _(u"Save")) - ok.SetDefault() - cancel = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close")) - self.SetEscapeId(cancel.GetId()) - ok_cancel_box.Add(ok, 0, wx.ALL, 5) - ok_cancel_box.Add(cancel, 0, wx.ALL, 5) - self.sizer.Add(ok_cancel_box, 0, wx.ALL, 5) - self.panel.SetSizer(self.sizer) - self.SetClientSize(self.sizer.CalcMin()) - - def get_value(self, panel, key): - p = getattr(self, panel) - return getattr(p, key).GetValue() - - def set_value(self, panel, key, value): - p = getattr(self, panel) - control = getattr(p, key) - getattr(control, "SetValue")(value) - +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import baseDialog +import wx +import logging as original_logger +import application +from multiplatform_widgets import widgets +import output +import config + +class general(wx.Panel, baseDialog.BaseWXDialog): + def __init__(self, parent, languages,keymaps): + super(general, self).__init__(parent) + sizer = wx.BoxSizer(wx.VERTICAL) + language = wx.StaticText(self, -1, _(u"Language")) + self.language = wx.ListBox(self, -1, choices=languages) + self.language.SetSize(self.language.GetBestSize()) + langBox = wx.BoxSizer(wx.HORIZONTAL) + langBox.Add(language, 0, wx.ALL, 5) + langBox.Add(self.language, 0, wx.ALL, 5) + sizer.Add(langBox, 0, wx.ALL, 5) + self.autostart = wx.CheckBox(self, -1, _(u"Run {0} at Windows startup").format(application.name,)) + self.ask_at_exit = wx.CheckBox(self, -1, _(U"ask before exiting {0}").format(application.name,)) + sizer.Add(self.autostart, 0, wx.ALL, 5) + sizer.Add(self.ask_at_exit, 0, wx.ALL, 5) + self.play_ready_sound = wx.CheckBox(self, -1, _(U"Play a sound when {0} launches").format(application.name,)) + sizer.Add(self.play_ready_sound, 0, wx.ALL, 5) + self.speak_ready_msg = wx.CheckBox(self, -1, _(U"Speak a message when {0} launches").format(application.name,)) + sizer.Add(self.speak_ready_msg, 0, wx.ALL, 5) + self.use_invisible_shorcuts = wx.CheckBox(self, -1, _(u"Use invisible interface's keyboard shortcuts while GUI is visible")) + sizer.Add(self.use_invisible_shorcuts, 0, wx.ALL, 5) + self.disable_sapi5 = wx.CheckBox(self, -1, _(u"Activate Sapi5 when any other screen reader is not being run")) + sizer.Add(self.disable_sapi5, 0, wx.ALL, 5) + self.hide_gui = wx.CheckBox(self, -1, _(u"Hide GUI on launch")) + sizer.Add(self.hide_gui, 0, wx.ALL, 5) + self.handle_longtweets = wx.CheckBox(self, wx.NewId(), _(u"Use Codeofdusk's longtweet handlers (may decrease client performance)")) + sizer.Add(self.handle_longtweets, 0, wx.ALL, 5) + kmbox = wx.BoxSizer(wx.VERTICAL) + km_label = wx.StaticText(self, -1, _(u"Keymap")) + self.km = wx.ComboBox(self, -1, choices=keymaps, style=wx.CB_READONLY) + self.km.SetSize(self.km.GetBestSize()) + kmbox.Add(km_label, 0, wx.ALL, 5) + kmbox.Add(self.km, 0, wx.ALL, 5) + self.check_for_updates = wx.CheckBox(self, -1, _(U"Check for updates when {0} launches").format(application.name,)) + sizer.Add(self.check_for_updates, 0, wx.ALL, 5) + sizer.Add(kmbox, 0, wx.ALL, 5) + self.SetSizer(sizer) + +class proxy(wx.Panel, baseDialog.BaseWXDialog): + + def __init__(self, parent, proxyTypes): + super(proxy, self).__init__(parent) + sizer = wx.BoxSizer(wx.VERTICAL) + type=wx.StaticText(self, wx.NewId(), _(u"Proxy type: ")) + self.type=wx.ComboBox(self, -1, choices=proxyTypes, style=wx.CB_READONLY) + self.type.SetSize(self.type.GetBestSize()) + typeBox = wx.BoxSizer(wx.HORIZONTAL) + typeBox.Add(type, 0, wx.ALL, 5) + typeBox.Add(self.type, 0, wx.ALL, 5) + sizer.Add(typeBox, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _(u"Proxy server: ")) + self.server = wx.TextCtrl(self, -1) + serverBox = wx.BoxSizer(wx.HORIZONTAL) + serverBox.Add(lbl, 0, wx.ALL, 5) + serverBox.Add(self.server, 0, wx.ALL, 5) + sizer.Add(serverBox, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _(u"Port: ")) + self.port = wx.TextCtrl(self, wx.NewId()) + portBox = wx.BoxSizer(wx.HORIZONTAL) + portBox.Add(lbl, 0, wx.ALL, 5) + portBox.Add(self.port, 0, wx.ALL, 5) + sizer.Add(portBox, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _(u"User: ")) + self.user = wx.TextCtrl(self, wx.NewId()) + userBox = wx.BoxSizer(wx.HORIZONTAL) + userBox.Add(lbl, 0, wx.ALL, 5) + userBox.Add(self.user, 0, wx.ALL, 5) + sizer.Add(userBox, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _(u"Password: ")) + self.password = wx.TextCtrl(self, wx.NewId(), style=wx.TE_PASSWORD) + passwordBox = wx.BoxSizer(wx.HORIZONTAL) + passwordBox.Add(lbl, 0, wx.ALL, 5) + passwordBox.Add(self.password, 0, wx.ALL, 5) + sizer.Add(serverBox, 0, wx.ALL, 5) + self.SetSizer(sizer) + +class generalAccount(wx.Panel, baseDialog.BaseWXDialog): + def __init__(self, parent): + super(generalAccount, self).__init__(parent) + sizer = wx.BoxSizer(wx.VERTICAL) + self.au = wx.Button(self, wx.NewId(), _(u"Autocompletion settings...")) + sizer.Add(self.au, 0, wx.ALL, 5) + self.relative_time = wx.CheckBox(self, wx.NewId(), _(U"Relative timestamps")) + sizer.Add(self.relative_time, 0, wx.ALL, 5) + apiCallsBox = wx.BoxSizer(wx.HORIZONTAL) + apiCallsBox.Add(wx.StaticText(self, -1, _(u"API calls (One API call = 200 tweets, two API calls = 400 tweets, etc):")), 0, wx.ALL, 5) + self.apiCalls = wx.SpinCtrl(self, wx.NewId()) + self.apiCalls.SetRange(1, 10) + self.apiCalls.SetSize(self.apiCalls.GetBestSize()) + apiCallsBox.Add(self.apiCalls, 0, wx.ALL, 5) + sizer.Add(apiCallsBox, 0, wx.ALL, 5) + tweetsPerCallBox = wx.BoxSizer(wx.HORIZONTAL) + tweetsPerCallBox.Add(wx.StaticText(self, -1, _(u"Items on each API call")), 0, wx.ALL, 5) + self.itemsPerApiCall = wx.SpinCtrl(self, wx.NewId()) + self.itemsPerApiCall.SetRange(0, 200) + self.itemsPerApiCall.SetSize(self.itemsPerApiCall.GetBestSize()) + tweetsPerCallBox.Add(self.itemsPerApiCall, 0, wx.ALL, 5) + sizer.Add(tweetsPerCallBox, 0, wx.ALL, 5) + self.reverse_timelines = wx.CheckBox(self, wx.NewId(), _(u"Inverted buffers: The newest tweets will be shown at the beginning while the oldest at the end")) + sizer.Add(self.reverse_timelines, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _(u"Retweet mode")) + self.retweet_mode = wx.ComboBox(self, wx.NewId(), choices=[_(u"Ask"), _(u"Retweet without comments"), _(u"Retweet with comments")], style=wx.CB_READONLY) + rMode = wx.BoxSizer(wx.HORIZONTAL) + rMode.Add(lbl, 0, wx.ALL, 5) + rMode.Add(self.retweet_mode, 0, wx.ALL, 5) + sizer.Add(rMode, 0, wx.ALL, 5) + self.show_screen_names = wx.CheckBox(self, wx.NewId(), _(U"Show screen names instead of full names")) + sizer.Add(self.show_screen_names, 0, wx.ALL, 5) + PersistSizeLabel = wx.StaticText(self, -1, _(u"Number of items per buffer to cache in database (0 to disable caching, blank for unlimited)")) + self.persist_size = wx.TextCtrl(self, -1) + sizer.Add(PersistSizeLabel, 0, wx.ALL, 5) + sizer.Add(self.persist_size, 0, wx.ALL, 5) + self.SetSizer(sizer) + +class other_buffers(wx.Panel): + def __init__(self, parent): + super(other_buffers, self).__init__(parent) + sizer = wx.BoxSizer(wx.VERTICAL) + self.buffers = widgets.list(self, _(u"Buffer"), _(u"Name"), _(u"Status"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT) + sizer.Add(self.buffers.list, 0, wx.ALL, 5) + btnSizer = wx.BoxSizer(wx.HORIZONTAL) + self.toggle_state = wx.Button(self, -1, _(u"Show/hide")) + self.up = wx.Button(self, -1, _(u"Move up")) + self.down = wx.Button(self, -1, _(u"Move down")) + btnSizer.Add(self.toggle_state, 0, wx.ALL, 5) + btnSizer.Add(self.up, 0, wx.ALL, 5) + btnSizer.Add(self.down, 0, wx.ALL, 5) + sizer.Add(btnSizer, 0, wx.ALL, 5) + self.SetSizer(sizer) + + def insert_buffers(self, buffers): + for i in buffers: + if i[2] == True: + self.buffers.insert_item(False, *[i[0], i[1], _(u"Show")]) + else: + self.buffers.insert_item(False, *[i[0], i[1], _(u"Hide")]) + + def connect_hook_func(self, func): + self.buffers.list.Bind(wx.EVT_CHAR_HOOK, func) + + def move_up(self, *args, **kwargs): + current = self.buffers.get_selected() + if current == -1: + output.speak(_(u"Select a buffer first."), True) + return False + if self.buffers.get_text_column(current, 2) == _(u"Hide"): + output.speak(_(u"The buffer is hidden, show it first."), True) + return False + if current <= 0: + output.speak(_(u"The buffer is already at the top of the list."), True) + return False + current_text = self.buffers.get_text_column(self.buffers.get_selected(), 0) + current_name = self.buffers.get_text_column(self.buffers.get_selected(), 1) + current_text_state = self.buffers.get_text_column(self.buffers.get_selected(), 2) + text_above = self.buffers.get_text_column(self.buffers.get_selected()-1, 0) + name_above = self.buffers.get_text_column(self.buffers.get_selected()-1, 1) + text_above_state = self.buffers.get_text_column(self.buffers.get_selected()-1, 2) + self.buffers.set_text_column(self.buffers.get_selected()-1, 0, current_text) + self.buffers.set_text_column(self.buffers.get_selected()-1, 1, current_name) + self.buffers.set_text_column(self.buffers.get_selected()-1, 2, current_text_state) + self.buffers.set_text_column(self.buffers.get_selected(), 0, text_above) + self.buffers.set_text_column(self.buffers.get_selected(), 1, name_above) + self.buffers.set_text_column(self.buffers.get_selected(), 2, text_above_state) + + def move_down(self, *args, **kwargs): + current = self.buffers.get_selected() + if current == -1: + output.speak(_(u"Select a buffer first."), True) + return False + if self.buffers.get_text_column(current, 2) == _(u"Hide"): + output.speak(_(u"The buffer is hidden, show it first."), True) + return False + if current+1 >= self.buffers.get_count(): + output.speak(_(u"The buffer is already at the bottom of the list."), True) + return False + current_text = self.buffers.get_text_column(self.buffers.get_selected(), 0) + current_name = self.buffers.get_text_column(self.buffers.get_selected(), 1) + current_text_state = self.buffers.get_text_column(self.buffers.get_selected(), 2) + text_below = self.buffers.get_text_column(self.buffers.get_selected()+1, 0) + name_below = self.buffers.get_text_column(self.buffers.get_selected()+1, 1) + text_below_state = self.buffers.get_text_column(self.buffers.get_selected()+1, 2) + self.buffers.set_text_column(self.buffers.get_selected()+1, 0, current_text) + self.buffers.set_text_column(self.buffers.get_selected()+1, 1, current_name) + self.buffers.set_text_column(self.buffers.get_selected()+1, 2, current_text_state) + self.buffers.set_text_column(self.buffers.get_selected(), 0, text_below) + self.buffers.set_text_column(self.buffers.get_selected(), 1, name_below) + self.buffers.set_text_column(self.buffers.get_selected(), 2, text_below_state) + + def get_event(self, ev): + if ev.GetKeyCode() == wx.WXK_SPACE: + return True + else: + ev.Skip() + return False + + def change_selected_item(self): + current = self.buffers.get_selected() + text = self.buffers.get_text_column(current, 2) + if text == _(u"Show"): + self.buffers.set_text_column(current, 2, _(u"Hide")) + else: + self.buffers.set_text_column(current, 2, _(u"Show")) + output.speak(self.buffers.get_text_column(current, 2),True) + def get_list(self): + buffers_list = [] + for i in xrange(0, self.buffers.get_count()): + if self.buffers.get_text_column(i, 2) == _(u"Show"): + buffers_list.append(self.buffers.get_text_column(i, 0)) + return buffers_list + +class ignoredClients(wx.Panel): + def __init__(self, parent, choices): + super(ignoredClients, self).__init__(parent=parent) + sizer = wx.BoxSizer(wx.VERTICAL) + label = wx.StaticText(self, -1, _(u"Ignored clients")) + self.clients = wx.ListBox(self, -1, choices=choices) + self.clients.SetSize(self.clients.GetBestSize()) + clientsBox = wx.BoxSizer(wx.HORIZONTAL) + clientsBox.Add(label, 0, wx.ALL, 5) + clientsBox.Add(self.clients, 0, wx.ALL, 5) + self.add = wx.Button(self, -1, _(u"Add client")) + self.remove = wx.Button(self, -1, _(u"Remove client")) + btnBox = wx.BoxSizer(wx.HORIZONTAL) + btnBox.Add(self.add, 0, wx.ALL, 5) + btnBox.Add(self.remove, 0, wx.ALL, 5) + sizer.Add(clientsBox, 0, wx.ALL, 5) + sizer.Add(btnBox, 0, wx.ALL, 5) + self.SetSizer(sizer) + + def append(self, client): + self.clients.Append(client) + + def get_clients(self): + return self.clients.GetCount() + + def get_client_id(self): + return self.clients.GetSelection() + + def remove_(self, id): + self.clients.Delete(id) + +class sound(wx.Panel): + def __init__(self, parent, input_devices, output_devices, soundpacks): + wx.Panel.__init__(self, parent) + sizer = wx.BoxSizer(wx.VERTICAL) + volume = wx.StaticText(self, -1, _(u"Volume")) + self.volumeCtrl = wx.Slider(self) + self.volumeCtrl.SetRange(0, 100) + self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize()) + volumeBox = wx.BoxSizer(wx.HORIZONTAL) + volumeBox.Add(volume, 0, wx.ALL, 5) + volumeBox.Add(self.volumeCtrl, 0, wx.ALL, 5) + sizer.Add(volumeBox, 0, wx.ALL, 5) + self.session_mute = wx.CheckBox(self, -1, _(u"Session mute")) + sizer.Add(self.session_mute, 0, wx.ALL, 5) + output_label = wx.StaticText(self, -1, _(u"Output device")) + self.output = wx.ComboBox(self, -1, choices=output_devices, style=wx.CB_READONLY) + self.output.SetSize(self.output.GetBestSize()) + outputBox = wx.BoxSizer(wx.HORIZONTAL) + outputBox.Add(output_label, 0, wx.ALL, 5) + outputBox.Add(self.output, 0, wx.ALL, 5) + sizer.Add(outputBox, 0, wx.ALL, 5) + input_label = wx.StaticText(self, -1, _(u"Input device")) + self.input = wx.ComboBox(self, -1, choices=input_devices, style=wx.CB_READONLY) + self.input.SetSize(self.input.GetBestSize()) + inputBox = wx.BoxSizer(wx.HORIZONTAL) + inputBox.Add(input_label, 0, wx.ALL, 5) + inputBox.Add(self.input, 0, wx.ALL, 5) + sizer.Add(inputBox, 0, wx.ALL, 5) + soundBox = wx.BoxSizer(wx.VERTICAL) + soundpack_label = wx.StaticText(self, -1, _(u"Sound pack")) + self.soundpack = wx.ComboBox(self, -1, choices=soundpacks, style=wx.CB_READONLY) + self.soundpack.SetSize(self.soundpack.GetBestSize()) + soundBox.Add(soundpack_label, 0, wx.ALL, 5) + soundBox.Add(self.soundpack, 0, wx.ALL, 5) + sizer.Add(soundBox, 0, wx.ALL, 5) + self.indicate_audio = wx.CheckBox(self, -1, _(u"Indicate audio tweets with sound")) + sizer.Add(self.indicate_audio, 0, wx.ALL, 5) + self.indicate_geo = wx.CheckBox(self, -1, _(u"Indicate geotweets with sound")) + sizer.Add(self.indicate_geo, 0, wx.ALL, 5) + self.indicate_img = wx.CheckBox(self, -1, _(u"Indicate tweets containing images with sound")) + sizer.Add(self.indicate_img, 0, wx.ALL, 5) + self.SetSizer(sizer) + + def get(self, control): + return getattr(self, control).GetStringSelection() + +class extrasPanel(wx.Panel): + def __init__(self, parent, ocr_languages=[], translation_languages=[]): + super(extrasPanel, self).__init__(parent) + mainSizer = wx.BoxSizer(wx.VERTICAL) + OCRBox = wx.StaticBox(self, label=_(u"Language for OCR")) + self.ocr_lang = wx.ListBox(self, -1, choices=ocr_languages) + self.ocr_lang.SetSize(self.ocr_lang.GetBestSize()) + ocrLanguageSizer = wx.StaticBoxSizer(OCRBox, wx.HORIZONTAL) + ocrLanguageSizer.Add(self.ocr_lang, 0, wx.ALL, 5) + mainSizer.Add(ocrLanguageSizer, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _(u"API Key for SndUp")) + self.sndup_apiKey = wx.TextCtrl(self, -1) + sndupBox = wx.BoxSizer(wx.HORIZONTAL) + sndupBox.Add(lbl, 0, wx.ALL, 5) + sndupBox.Add(self.sndup_apiKey, 0, wx.ALL, 5) + mainSizer.Add(sndupBox, 0, wx.ALL, 5) + self.SetSizer(mainSizer) + +class configurationDialog(baseDialog.BaseWXDialog): + def set_title(self, title): + self.SetTitle(title) + + def __init__(self): + super(configurationDialog, self).__init__(None, -1) + self.panel = wx.Panel(self) + self.SetTitle(_(u"{0} preferences").format(application.name,)) + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.notebook = wx.Notebook(self.panel) + + def create_general(self, languageList,keymaps): + self.general = general(self.notebook, languageList,keymaps) + self.notebook.AddPage(self.general, _(u"General")) + self.general.SetFocus() + + def create_proxy(self, proxyTypes): + self.proxy = proxy(self.notebook, proxyTypes) + self.notebook.AddPage(self.proxy, _(u"Proxy")) + + def create_general_account(self): + self.general = generalAccount(self.notebook) + self.notebook.AddPage(self.general, _(u"General")) + self.general.SetFocus() + + def create_other_buffers(self): + self.buffers = other_buffers(self.notebook) + self.notebook.AddPage(self.buffers, _(u"Buffers")) + + def create_ignored_clients(self, ignored_clients_list): + self.ignored_clients = ignoredClients(self.notebook, ignored_clients_list) + self.notebook.AddPage(self.ignored_clients, _(u"Ignored clients")) + + def create_sound(self, output_devices, input_devices, soundpacks): + self.sound = sound(self.notebook, output_devices, input_devices, soundpacks) + self.notebook.AddPage(self.sound, _(u"Sound")) + + def create_extras(self, ocr_languages=[], translator_languages=[]): + self.extras = extrasPanel(self.notebook, ocr_languages, translator_languages) + self.notebook.AddPage(self.extras, _(u"Extras")) + + def realize(self): + self.sizer.Add(self.notebook, 0, wx.ALL, 5) + ok_cancel_box = wx.BoxSizer(wx.HORIZONTAL) + ok = wx.Button(self.panel, wx.ID_OK, _(u"Save")) + ok.SetDefault() + cancel = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close")) + self.SetEscapeId(cancel.GetId()) + ok_cancel_box.Add(ok, 0, wx.ALL, 5) + ok_cancel_box.Add(cancel, 0, wx.ALL, 5) + self.sizer.Add(ok_cancel_box, 0, wx.ALL, 5) + self.panel.SetSizer(self.sizer) + self.SetClientSize(self.sizer.CalcMin()) + + def get_value(self, panel, key): + p = getattr(self, panel) + return getattr(p, key).GetValue() + + def set_value(self, panel, key, value): + p = getattr(self, panel) + control = getattr(p, key) + getattr(control, "SetValue")(value) + diff --git a/src/wxUI/dialogs/find.py b/src/wxUI/dialogs/find.py index 48396295..a88b91f3 100644 --- a/src/wxUI/dialogs/find.py +++ b/src/wxUI/dialogs/find.py @@ -1,26 +1,28 @@ -# -*- coding: utf-8 -*- -import baseDialog -import wx - -class findDialog(baseDialog.BaseWXDialog): - def __init__(self, value=""): - super(findDialog, self).__init__(None, -1) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetTitle(_(u"Find in current buffer")) - label = wx.StaticText(panel, -1, _(u"String")) - self.string = wx.TextCtrl(panel, -1, value) - dc = wx.WindowDC(self.string) - dc.SetFont(self.string.GetFont()) - self.string.SetSize(dc.GetTextExtent("0"*40)) - sizer.Add(label, 0, wx.ALL, 5) - sizer.Add(self.string, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _(u"OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel")) - btnsizer = wx.BoxSizer() - btnsizer.Add(ok, 0, wx.ALL, 5) - btnsizer.Add(cancel, 0, wx.ALL, 5) - sizer.Add(btnsizer, 0, wx.ALL, 5) - panel.SetSizer(sizer) +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import baseDialog +import wx + +class findDialog(baseDialog.BaseWXDialog): + def __init__(self, value=""): + super(findDialog, self).__init__(None, -1) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.SetTitle(_(u"Find in current buffer")) + label = wx.StaticText(panel, -1, _(u"String")) + self.string = wx.TextCtrl(panel, -1, value) + dc = wx.WindowDC(self.string) + dc.SetFont(self.string.GetFont()) + self.string.SetSize(dc.GetTextExtent("0"*40)) + sizer.Add(label, 0, wx.ALL, 5) + sizer.Add(self.string, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _(u"OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel")) + btnsizer = wx.BoxSizer() + btnsizer.Add(ok, 0, wx.ALL, 5) + btnsizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(btnsizer, 0, wx.ALL, 5) + panel.SetSizer(sizer) self.SetClientSize(sizer.CalcMin()) \ No newline at end of file diff --git a/src/wxUI/dialogs/search.py b/src/wxUI/dialogs/search.py index e04f07c6..a3f9eacf 100644 --- a/src/wxUI/dialogs/search.py +++ b/src/wxUI/dialogs/search.py @@ -1,68 +1,69 @@ -# -*- coding: utf-8 -*- -import widgetUtils -import baseDialog -import wx -from extra import translator - -class searchDialog(baseDialog.BaseWXDialog): - def __init__(self, value=""): - super(searchDialog, self).__init__(None, -1) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetTitle(_(u"Search on Twitter")) - label = wx.StaticText(panel, -1, _(u"&Search")) - self.term = wx.TextCtrl(panel, -1, value) - dc = wx.WindowDC(self.term) - dc.SetFont(self.term.GetFont()) - self.term.SetSize(dc.GetTextExtent("0"*40)) - sizer.Add(label, 0, wx.ALL, 5) - sizer.Add(self.term, 0, wx.ALL, 5) - self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP) - self.users = wx.RadioButton(panel, -1, _(u"Users")) - widgetUtils.connect_event(self.tweets, widgetUtils.RADIOBUTTON, self.show_advanced_search) - widgetUtils.connect_event(self.users, widgetUtils.RADIOBUTTON, self.hide_advanced_search) - radioSizer = wx.BoxSizer(wx.HORIZONTAL) - radioSizer.Add(self.tweets, 0, wx.ALL, 5) - radioSizer.Add(self.users, 0, wx.ALL, 5) - sizer.Add(radioSizer, 0, wx.ALL, 5) - lang = wx.StaticText(panel, -1, _(u"&Language for results: ")) - langs = [x[1] for x in translator.translator.available_languages()] - langs[:] = langs[1:] - langs.insert(0, _(u"any")) - self.lang = wx.ComboBox(panel, -1, choices=langs, value=langs[0], style = wx.CB_READONLY) - langBox = wx.BoxSizer(wx.HORIZONTAL) - langBox.Add(lang, 0, wx.ALL, 5) - langBox.Add(self.lang, 0, wx.ALL, 5) - sizer.Add(langBox, 0, wx.ALL, 5) - resulttype = wx.StaticText(panel, -1, _(U"Results &type: ")) - self.resultstype = wx.ComboBox(panel, -1, choices=[_(u"Mixed"), _(u"Recent"), _(u"Popular")], value=_(u"Mixed"), style=wx.CB_READONLY) - rBox = wx.BoxSizer(wx.HORIZONTAL) - rBox.Add(resulttype, 0, wx.ALL, 5) - rBox.Add(self.resultstype, 0, wx.ALL, 5) - sizer.Add(rBox, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _(u"&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Close")) - btnsizer = wx.BoxSizer() - btnsizer.Add(ok, 0, wx.ALL, 5) - btnsizer.Add(cancel, 0, wx.ALL, 5) - sizer.Add(btnsizer, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) - - def get_language(self): - return [x[0] for x in translator.translator.available_languages()][self.lang.GetSelection()] - - def get_result_type(self): - r = self.resultstype.GetValue() - if r == _(u"Mixed"): return "mixed" - elif r == _(u"Recent"): return "recent" - elif r == _(u"Popular"): return "popular" - - def hide_advanced_search(self, *args, **kwargs): - self.lang.Hide() - self.resultstype.Hide() - - def show_advanced_search(self, *args, **kwargs): - self.lang.Show() - self.resultstype.Show() +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import widgetUtils +from . import baseDialog +import wx +from extra import translator + +class searchDialog(baseDialog.BaseWXDialog): + def __init__(self, value=""): + super(searchDialog, self).__init__(None, -1) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.SetTitle(_(u"Search on Twitter")) + label = wx.StaticText(panel, -1, _(u"&Search")) + self.term = wx.TextCtrl(panel, -1, value) + dc = wx.WindowDC(self.term) + dc.SetFont(self.term.GetFont()) + self.term.SetSize(dc.GetTextExtent("0"*40)) + sizer.Add(label, 0, wx.ALL, 5) + sizer.Add(self.term, 0, wx.ALL, 5) + self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP) + self.users = wx.RadioButton(panel, -1, _(u"Users")) + widgetUtils.connect_event(self.tweets, widgetUtils.RADIOBUTTON, self.show_advanced_search) + widgetUtils.connect_event(self.users, widgetUtils.RADIOBUTTON, self.hide_advanced_search) + radioSizer = wx.BoxSizer(wx.HORIZONTAL) + radioSizer.Add(self.tweets, 0, wx.ALL, 5) + radioSizer.Add(self.users, 0, wx.ALL, 5) + sizer.Add(radioSizer, 0, wx.ALL, 5) + lang = wx.StaticText(panel, -1, _(u"&Language for results: ")) + langs = [x[1] for x in translator.translator.available_languages()] + langs[:] = langs[1:] + langs.insert(0, _(u"any")) + self.lang = wx.ComboBox(panel, -1, choices=langs, value=langs[0], style = wx.CB_READONLY) + langBox = wx.BoxSizer(wx.HORIZONTAL) + langBox.Add(lang, 0, wx.ALL, 5) + langBox.Add(self.lang, 0, wx.ALL, 5) + sizer.Add(langBox, 0, wx.ALL, 5) + resulttype = wx.StaticText(panel, -1, _(U"Results &type: ")) + self.resultstype = wx.ComboBox(panel, -1, choices=[_(u"Mixed"), _(u"Recent"), _(u"Popular")], value=_(u"Mixed"), style=wx.CB_READONLY) + rBox = wx.BoxSizer(wx.HORIZONTAL) + rBox.Add(resulttype, 0, wx.ALL, 5) + rBox.Add(self.resultstype, 0, wx.ALL, 5) + sizer.Add(rBox, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _(u"&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Close")) + btnsizer = wx.BoxSizer() + btnsizer.Add(ok, 0, wx.ALL, 5) + btnsizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(btnsizer, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def get_language(self): + return [x[0] for x in translator.translator.available_languages()][self.lang.GetSelection()] + + def get_result_type(self): + r = self.resultstype.GetValue() + if r == _(u"Mixed"): return "mixed" + elif r == _(u"Recent"): return "recent" + elif r == _(u"Popular"): return "popular" + + def hide_advanced_search(self, *args, **kwargs): + self.lang.Hide() + self.resultstype.Hide() + + def show_advanced_search(self, *args, **kwargs): + self.lang.Show() + self.resultstype.Show() diff --git a/src/wxUI/dialogs/show_user.py b/src/wxUI/dialogs/show_user.py index a3850a7b..6406e1dc 100644 --- a/src/wxUI/dialogs/show_user.py +++ b/src/wxUI/dialogs/show_user.py @@ -1,26 +1,27 @@ -# -*- coding: utf-8 -*- -import wx -import baseDialog - -class showUserProfile(baseDialog.BaseWXDialog): - def __init__(self): - super(showUserProfile, self).__init__(parent=None, id=wx.NewId()) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - static = wx.StaticText(panel, -1, _(u"Details")) - sizer.Add(static, 0, wx.ALL, 5) - self.text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(350, 250)) - self.text.SetFocus() - sizer.Add(self.text, 0, wx.ALL|wx.EXPAND, 5) - self.url = wx.Button(panel, -1, _(u"&Go to URL"), size=wx.DefaultSize) - self.url.Disable() - close = wx.Button(panel, wx.ID_CANCEL, _(u"&Close")) - btnSizer = wx.BoxSizer(wx.HORIZONTAL) - btnSizer.Add(self.url, 0, wx.ALL, 5) - btnSizer.Add(close, 0, wx.ALL, 5) - sizer.Add(btnSizer, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) - - def enable_url(self, enabled=True): +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from . import baseDialog + +class showUserProfile(baseDialog.BaseWXDialog): + def __init__(self): + super(showUserProfile, self).__init__(parent=None, id=wx.NewId()) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + static = wx.StaticText(panel, -1, _(u"Details")) + sizer.Add(static, 0, wx.ALL, 5) + self.text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(350, 250)) + self.text.SetFocus() + sizer.Add(self.text, 0, wx.ALL|wx.EXPAND, 5) + self.url = wx.Button(panel, -1, _(u"&Go to URL"), size=wx.DefaultSize) + self.url.Disable() + close = wx.Button(panel, wx.ID_CANCEL, _(u"&Close")) + btnSizer = wx.BoxSizer(wx.HORIZONTAL) + btnSizer.Add(self.url, 0, wx.ALL, 5) + btnSizer.Add(close, 0, wx.ALL, 5) + sizer.Add(btnSizer, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def enable_url(self, enabled=True): self.url.Enable(enabled) \ No newline at end of file diff --git a/src/wxUI/dialogs/trends.py b/src/wxUI/dialogs/trends.py index 6cf973f6..20753345 100644 --- a/src/wxUI/dialogs/trends.py +++ b/src/wxUI/dialogs/trends.py @@ -1,46 +1,48 @@ -# -*- coding: utf-8 -*- -import baseDialog -import wx - -class trendingTopicsDialog(baseDialog.BaseWXDialog): - def __init__(self): - super(trendingTopicsDialog, self).__init__(None, -1) - 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) - 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) - radioSizer.Add(label, 0, wx.ALL, 5) - radioSizer.Add(self.country, 0, wx.ALL, 5) - radioSizer.Add(self.city, 0, wx.ALL, 5) - sizer.Add(radioSizer, 0, wx.ALL, 5) - label = wx.StaticText(panel, -1, _(u"&Location")) - self.location = wx.ListBox(panel, -1, choices=[], style=wx.CB_READONLY) - locationBox = wx.BoxSizer(wx.HORIZONTAL) - locationBox.Add(label, 0, wx.ALL, 5) - locationBox.Add(self.location, 0, wx.ALL, 5) - sizer.Add(locationBox, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _(u"&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Close")) - btnsizer = wx.BoxSizer() - btnsizer.Add(ok, 0, wx.ALL, 5) - btnsizer.Add(cancel, 0, wx.ALL, 5) - sizer.Add(btnsizer, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) - - def get_active(self): - if self.country.GetValue() == True: - return "country" - else: - return "city" - - def get_item(self): - return self.location.GetStringSelection() - - def set(self, values): +# -*- coding: utf-8 -*- +from __future__ import absolute_import +# -*- coding: utf-8 -*- +from . import baseDialog +import wx + +class trendingTopicsDialog(baseDialog.BaseWXDialog): + def __init__(self): + super(trendingTopicsDialog, self).__init__(None, -1) + 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) + 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) + radioSizer.Add(label, 0, wx.ALL, 5) + radioSizer.Add(self.country, 0, wx.ALL, 5) + radioSizer.Add(self.city, 0, wx.ALL, 5) + sizer.Add(radioSizer, 0, wx.ALL, 5) + label = wx.StaticText(panel, -1, _(u"&Location")) + self.location = wx.ListBox(panel, -1, choices=[], style=wx.CB_READONLY) + locationBox = wx.BoxSizer(wx.HORIZONTAL) + locationBox.Add(label, 0, wx.ALL, 5) + locationBox.Add(self.location, 0, wx.ALL, 5) + sizer.Add(locationBox, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _(u"&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Close")) + btnsizer = wx.BoxSizer() + btnsizer.Add(ok, 0, wx.ALL, 5) + btnsizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(btnsizer, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def get_active(self): + if self.country.GetValue() == True: + return "country" + else: + return "city" + + def get_item(self): + return self.location.GetStringSelection() + + def set(self, values): self.location.Set(values) \ No newline at end of file diff --git a/src/wxUI/dialogs/update_profile.py b/src/wxUI/dialogs/update_profile.py index 594f7f3b..770cec2c 100644 --- a/src/wxUI/dialogs/update_profile.py +++ b/src/wxUI/dialogs/update_profile.py @@ -1,98 +1,99 @@ -# -*- coding: utf-8 -*- -import wx -import baseDialog - -class updateProfileDialog(baseDialog.BaseWXDialog): - def __init__(self): - super(updateProfileDialog, self).__init__(parent=None, id=-1) - self.SetTitle(_(u"Update your profile")) - panel = wx.Panel(self) - labelName = wx.StaticText(panel, -1, _(u"&Name (20 characters maximum)")) - self.name = wx.TextCtrl(panel, -1) - self.name.SetFocus() - dc = wx.WindowDC(self.name) - dc.SetFont(self.name.GetFont()) - self.name.SetSize(dc.GetTextExtent("0"*20)) - labelLocation = wx.StaticText(panel, -1, _(u"&Location")) - self.location = wx.TextCtrl(panel, -1) - dc = wx.WindowDC(self.location) - dc.SetFont(self.location.GetFont()) - self.location.SetSize(dc.GetTextExtent("0"*35)) - labelUrl = wx.StaticText(panel, -1, _(u"&Website")) - self.url = wx.TextCtrl(panel, -1) - dc = wx.WindowDC(self.url) - dc.SetFont(self.url.GetFont()) - self.url.SetSize(dc.GetTextExtent("0"*22)) - labelDescription = wx.StaticText(panel, -1, _(u"&Bio (160 characters maximum)")) - self.description = wx.TextCtrl(panel, -1, size=(400, 400)) - dc = wx.WindowDC(self.description) - dc.SetFont(self.description.GetFont()) - self.description.SetSize(dc.GetTextExtent("0"*160)) - self.image = None - self.upload_image = wx.Button(panel, -1, _(u"Upload a &picture")) - self.ok = wx.Button(panel, wx.ID_OK, _(u"&Update profile")) - self.ok.SetDefault() - close = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - sizer = wx.BoxSizer(wx.VERTICAL) - nameBox = wx.BoxSizer(wx.HORIZONTAL) - nameBox.Add(labelName, 0, wx.ALL, 5) - nameBox.Add(self.name, 0, wx.ALL, 5) - sizer.Add(nameBox, 0, wx.ALL, 5) - locationBox = wx.BoxSizer(wx.HORIZONTAL) - locationBox.Add(labelLocation, 0, wx.ALL, 5) - locationBox.Add(self.location, 0, wx.ALL, 5) - sizer.Add(locationBox, 0, wx.ALL, 5) - urlBox = wx.BoxSizer(wx.HORIZONTAL) - urlBox.Add(labelUrl, 0, wx.ALL, 5) - urlBox.Add(self.url, 0, wx.ALL, 5) - sizer.Add(urlBox, 0, wx.ALL, 5) - descriptionBox = wx.BoxSizer(wx.HORIZONTAL) - descriptionBox.Add(labelDescription, 0, wx.ALL, 5) - descriptionBox.Add(self.description, 0, wx.ALL, 5) - sizer.Add(descriptionBox, 0, wx.ALL, 5) - sizer.Add(self.upload_image, 5, wx.CENTER, 5) - btnBox = wx.BoxSizer(wx.HORIZONTAL) - btnBox.Add(self.ok, 0, wx.ALL, 5) - btnBox.Add(close, 0, wx.ALL, 5) - sizer.Add(btnBox, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) - - def set_name(self, name): - self.set("name", name) - - def set_description(self, description): - self.set("description", description) - - def set_location(self, location): - self.set("location", location) - - def set_url(self, url): - self.set("url", url) - - def change_upload_button(self, uploaded=False): - if uploaded == False: - self.upload_image.SetLabel(_(u"Upload a picture")) - else: - self.upload_image.SetLabel(_(u"Discard image")) - - def upload_picture(self): - openFileDialog = wx.FileDialog(self, _(u"Select the picture to be uploaded"), "", "", _("Image files (*.png, *.jpg, *.gif)|*.png; *.jpg; *.gif"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - if openFileDialog.ShowModal() == wx.ID_CANCEL: - return None - return openFileDialog.GetPath() - - def hide_upload_button(self, hide): - self.upload_image.Enable(hide) - - def set_readonly(self): - self.name.style = wx.TE_READONLY - self.name.Refresh() - self.description.style = wx.TE_READONLY - self.description.Refresh() - self.location.style = wx.TE_READONLY - self.location.Refresh() - self.url.style = wx.TE_READONLY - self.url.Refresh() - self.hide_upload_button(False) +# -*- coding: utf-8 -*- +from __future__ import absolute_import +import wx +from . import baseDialog + +class updateProfileDialog(baseDialog.BaseWXDialog): + def __init__(self): + super(updateProfileDialog, self).__init__(parent=None, id=-1) + self.SetTitle(_(u"Update your profile")) + panel = wx.Panel(self) + labelName = wx.StaticText(panel, -1, _(u"&Name (20 characters maximum)")) + self.name = wx.TextCtrl(panel, -1) + self.name.SetFocus() + dc = wx.WindowDC(self.name) + dc.SetFont(self.name.GetFont()) + self.name.SetSize(dc.GetTextExtent("0"*20)) + labelLocation = wx.StaticText(panel, -1, _(u"&Location")) + self.location = wx.TextCtrl(panel, -1) + dc = wx.WindowDC(self.location) + dc.SetFont(self.location.GetFont()) + self.location.SetSize(dc.GetTextExtent("0"*35)) + labelUrl = wx.StaticText(panel, -1, _(u"&Website")) + self.url = wx.TextCtrl(panel, -1) + dc = wx.WindowDC(self.url) + dc.SetFont(self.url.GetFont()) + self.url.SetSize(dc.GetTextExtent("0"*22)) + labelDescription = wx.StaticText(panel, -1, _(u"&Bio (160 characters maximum)")) + self.description = wx.TextCtrl(panel, -1, size=(400, 400)) + dc = wx.WindowDC(self.description) + dc.SetFont(self.description.GetFont()) + self.description.SetSize(dc.GetTextExtent("0"*160)) + self.image = None + self.upload_image = wx.Button(panel, -1, _(u"Upload a &picture")) + self.ok = wx.Button(panel, wx.ID_OK, _(u"&Update profile")) + self.ok.SetDefault() + close = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + sizer = wx.BoxSizer(wx.VERTICAL) + nameBox = wx.BoxSizer(wx.HORIZONTAL) + nameBox.Add(labelName, 0, wx.ALL, 5) + nameBox.Add(self.name, 0, wx.ALL, 5) + sizer.Add(nameBox, 0, wx.ALL, 5) + locationBox = wx.BoxSizer(wx.HORIZONTAL) + locationBox.Add(labelLocation, 0, wx.ALL, 5) + locationBox.Add(self.location, 0, wx.ALL, 5) + sizer.Add(locationBox, 0, wx.ALL, 5) + urlBox = wx.BoxSizer(wx.HORIZONTAL) + urlBox.Add(labelUrl, 0, wx.ALL, 5) + urlBox.Add(self.url, 0, wx.ALL, 5) + sizer.Add(urlBox, 0, wx.ALL, 5) + descriptionBox = wx.BoxSizer(wx.HORIZONTAL) + descriptionBox.Add(labelDescription, 0, wx.ALL, 5) + descriptionBox.Add(self.description, 0, wx.ALL, 5) + sizer.Add(descriptionBox, 0, wx.ALL, 5) + sizer.Add(self.upload_image, 5, wx.CENTER, 5) + btnBox = wx.BoxSizer(wx.HORIZONTAL) + btnBox.Add(self.ok, 0, wx.ALL, 5) + btnBox.Add(close, 0, wx.ALL, 5) + sizer.Add(btnBox, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def set_name(self, name): + self.set("name", name) + + def set_description(self, description): + self.set("description", description) + + def set_location(self, location): + self.set("location", location) + + def set_url(self, url): + self.set("url", url) + + def change_upload_button(self, uploaded=False): + if uploaded == False: + self.upload_image.SetLabel(_(u"Upload a picture")) + else: + self.upload_image.SetLabel(_(u"Discard image")) + + def upload_picture(self): + openFileDialog = wx.FileDialog(self, _(u"Select the picture to be uploaded"), "", "", _("Image files (*.png, *.jpg, *.gif)|*.png; *.jpg; *.gif"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if openFileDialog.ShowModal() == wx.ID_CANCEL: + return None + return openFileDialog.GetPath() + + def hide_upload_button(self, hide): + self.upload_image.Enable(hide) + + def set_readonly(self): + self.name.style = wx.TE_READONLY + self.name.Refresh() + self.description.style = wx.TE_READONLY + self.description.Refresh() + self.location.style = wx.TE_READONLY + self.location.Refresh() + self.url.style = wx.TE_READONLY + self.url.Refresh() + self.hide_upload_button(False) self.ok.Enable(False) \ No newline at end of file diff --git a/src/wxUI/dialogs/utils.py b/src/wxUI/dialogs/utils.py index 09da8e4a..334b20f6 100644 --- a/src/wxUI/dialogs/utils.py +++ b/src/wxUI/dialogs/utils.py @@ -1,48 +1,49 @@ -# -*- coding: utf-8 -*- -############################################################ -# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################ -import wx -import baseDialog - -class selectUserDialog(baseDialog.BaseWXDialog): - def __init__(self, title, users): - super(selectUserDialog, self).__init__(parent=None, id=wx.NewId(), title=title) - panel = wx.Panel(self) - userSizer = wx.BoxSizer() - self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize) - self.cb.SetFocus() - self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users")) - userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5) - userSizer.Add(self.cb, 0, wx.ALL, 5) - userSizer.Add(self.autocompletion, 0, wx.ALL, 5) - sizer = wx.BoxSizer(wx.VERTICAL) - ok = wx.Button(panel, wx.ID_OK, _(u"OK")) - ok.SetDefault() -# ok.Bind(wx.EVT_BUTTON, self.onok) - cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close")) - btnsizer = wx.BoxSizer() - btnsizer.Add(ok, 0, wx.ALL, 5) - btnsizer.Add(cancel, 0, wx.ALL, 5) - sizer.Add(userSizer, 0, wx.ALL, 5) - sizer.Add(btnsizer, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) - - def get_user(self): - return self.cb.GetValue() - +# -*- coding: utf-8 -*- +############################################################ +# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################ +from __future__ import absolute_import +import wx +from . import baseDialog + +class selectUserDialog(baseDialog.BaseWXDialog): + def __init__(self, title, users): + super(selectUserDialog, self).__init__(parent=None, id=wx.NewId(), title=title) + panel = wx.Panel(self) + userSizer = wx.BoxSizer() + self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize) + self.cb.SetFocus() + self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users")) + userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5) + userSizer.Add(self.cb, 0, wx.ALL, 5) + userSizer.Add(self.autocompletion, 0, wx.ALL, 5) + sizer = wx.BoxSizer(wx.VERTICAL) + ok = wx.Button(panel, wx.ID_OK, _(u"OK")) + ok.SetDefault() +# ok.Bind(wx.EVT_BUTTON, self.onok) + cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close")) + btnsizer = wx.BoxSizer() + btnsizer.Add(ok, 0, wx.ALL, 5) + btnsizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(userSizer, 0, wx.ALL, 5) + sizer.Add(btnsizer, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def get_user(self): + return self.cb.GetValue() +