diff --git a/TODO b/TODO index 92c7705..c54c8d5 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,14 @@ This is a list of things that still need doing. It includes short-, medium-, and long-term goals. -* Support multiple accounts +features: + * Make all the buttons prettier * Add a graphical options menu * Support some kind of 'conversation' view for in-reply-to chains, instead of the standard single-tweet * Come up with a better bloody name * Status bar icon + + +bugs: + +* Direct Messages have no names... diff --git a/default.glade b/default.glade index 169b2e0..f2b490b 100644 --- a/default.glade +++ b/default.glade @@ -304,9 +304,11 @@ True + null False True True + 0 diff --git a/mytwitter.py b/mytwitter.py index 076e22f..311e589 100755 --- a/mytwitter.py +++ b/mytwitter.py @@ -17,17 +17,14 @@ class MyTwitter(): config = ConfigParser.ConfigParser() config.read(os.path.expanduser(config_file)) - self.accounts = [] + self.accounts = {} for item in config.sections(): if (re.match(r'account-', item)): - account_name = re.sub(r'account-', '', item) - self.accounts.append({'account_name': account_name, - 'username': config.get(item, 'username'), - 'api': twitter.Api(username=config.get(item, 'username'), password=config.get(item, 'password')) - }) + username = config.get(item, 'username') + self.accounts[username] = twitter.Api(username=username, password=config.get(item, 'password')) - self.username = self.accounts[0]['username'] - self.api = self.accounts[0]['api'] + self.username = self.accounts.keys()[0] + self.api = self.accounts[self.username] self.num_entries = int(config.get('global', 'entries')) self.refresh_time = int(config.get('global', 'refreshtime')) @@ -69,10 +66,12 @@ class MyTwitter(): self.context_id = self.status_bar.get_context_id('message') self.tweet_notebook.remove_page(0) # kill the page that glade makes us have + self.account_select.remove_text(0) - # Add entries to the account select box -# for account in self.accounts: -# self.account_select. + # Add entries to the account select box, set the default entry + for username in self.accounts.keys(): + self.account_select.append_text(username) + self.account_select.set_active(0) # When we change tabs, any unread tweets in it become read self.tweet_notebook.connect('switch_page', self.on_tab_change) @@ -81,20 +80,28 @@ class MyTwitter(): for tab in self.db['open_tabs']: self.add_to_notebook(tab) - # Put Home, @user, Direct Messages, and lists in the View menu... - lists = self.api.GetUserLists() - list_names = [] - for l in lists['lists']: - list_names.append(l.name) - list_names.sort() - list_names.insert(0, 'Home') - list_names.insert(1, '@' + self.username) - list_names.insert(2, 'Direct Messages') - for l in list_names: - menu_item = gtk.MenuItem(l) - self.view_menu.append(menu_item) - menu_item.connect('activate', self.on_view_selected, l) - menu_item.show() + # Put Home, @user, Direct Messages, and lists in the View menu for + # each user + for username in self.accounts.keys(): + outer_menu_item = gtk.MenuItem(username) + self.view_menu.append(outer_menu_item) + new_menu = gtk.Menu() + outer_menu_item.set_submenu(new_menu) + + lists = self.accounts[username].GetUserLists() + list_names = [] + for l in lists['lists']: + list_names.append(l.name) + list_names.sort() + list_names.insert(0, 'Home') + list_names.insert(1, '@' + username) + list_names.insert(2, 'Direct Messages') + for l in list_names: + menu_item = gtk.MenuItem(l) + new_menu.append(menu_item) + menu_item.connect('activate', self.on_view_selected, username, l) + menu_item.show() + outer_menu_item.show() # Timer to update periodically gobject.timeout_add(self.refresh_time * 1000, self.update_windows) @@ -105,18 +112,41 @@ class MyTwitter(): pane = self.tweet_notebook.get_nth_page(i) list_name = pane.get_list_name() + # Single tweets should never be updated here if pane.get_single_tweet() is not None: continue - elif list_name is None or list_name == 'Home': - statuses = self.api.GetHomeTimeline(count=self.num_entries) - elif list_name == '@' + self.username: - statuses = self.api.GetMentions(count=self.num_entries) - elif list_name == 'Direct Messages': - statuses = self.dms_to_statuses(self.api.GetDirectMessages()) + + # username/Home entries need to load the appropriate Home feed + elif re.search(r'/Home', list_name): + account = self.accounts[re.sub(r'/Home', r'', list_name)] + statuses = account.GetHomeTimeline(count=self.num_entries) + + # For @username, we need to check if it is one of our usernames, or + # just needs to be searched on + elif re.match('@', list_name): + if self.accounts.has_key(re.sub('@', '', list_name)): + account = self.accounts[re.sub(r'@', r'', list_name)] + statuses = account.GetMentions(count=self.num_entries) + else: + statuses = self.results_to_statuses(self.api.Search(list_name, rpp=self.num_entries)) + + # Direct Messages should match like /Home, above + elif re.search(r'/Direct Messages', list_name): + account = self.accounts[re.sub(r'/Direct Messages', r'', list_name)] + statuses = self.dms_to_statuses(account.GetDirectMessages()) + + # User lookups go straight to the user elif re.match(r'user: ', list_name): statuses = self.api.GetUserTimeline(re.sub(r'^user: ', r'', list_name), count=self.num_entries) + + # Lists load the appropriate list from the appropriate account elif re.match(r'list: ', list_name): - statuses = self.api.GetListStatuses(re.sub(r'^list: ', r'', list_name), per_page=self.num_entries) + username = re.sub(r'list: (.*)/.*', r'\1', list_name) + real_list = re.sub(r'list: .*/(.*)', r'\1', real_list) + account = self.accounts[username] + statuses = account.GetListStatuses(real_list, per_page=self.num_entries) + + # Everything else is a straight search else: statuses = self.results_to_statuses(self.api.Search(list_name, rpp=self.num_entries)) @@ -176,8 +206,10 @@ class MyTwitter(): self.add_to_notebook(data['name'], data['id']) - def on_view_selected(self, event, name): - if name == 'Home' or name == '@' + self.username or name == 'Direct Messages': + def on_view_selected(self, event, username, name): + if name == 'Home' or name == 'Direct Messages': + full_name = username + '/' + name + elif name == '@' + username: full_name = name else: full_name = 'list: ' + name @@ -346,6 +378,13 @@ class MyTwitter(): self.remove_view(current_pane.get_list_name()) + def on_account_changed(self, widget): + new_user = self.account_select.get_active_text() + if self.accounts.has_key(new_user): + self.username = new_user + self.api = self.accounts[self.username] + + # To keep things simple elsewhere and improve code reuse # we'll build a list of home-cooked Status objects out of results. # Why is this even necessary?