Basic multiple account support now functioning
This commit is contained in:
parent
cee3ab8897
commit
7016229885
8
TODO
8
TODO
|
@ -1,8 +1,14 @@
|
||||||
This is a list of things that still need doing. It includes short-, medium-, and long-term goals.
|
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
|
* Make all the buttons prettier
|
||||||
* Add a graphical options menu
|
* Add a graphical options menu
|
||||||
* Support some kind of 'conversation' view for in-reply-to chains, instead of the standard single-tweet
|
* Support some kind of 'conversation' view for in-reply-to chains, instead of the standard single-tweet
|
||||||
* Come up with a better bloody name
|
* Come up with a better bloody name
|
||||||
* Status bar icon
|
* Status bar icon
|
||||||
|
|
||||||
|
|
||||||
|
bugs:
|
||||||
|
|
||||||
|
* Direct Messages have no names...
|
||||||
|
|
|
@ -304,9 +304,11 @@
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkComboBoxEntry" id="account_select">
|
<widget class="GtkComboBoxEntry" id="account_select">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="items" translatable="yes">null</property>
|
||||||
<property name="add_tearoffs">False</property>
|
<property name="add_tearoffs">False</property>
|
||||||
<property name="has_frame">True</property>
|
<property name="has_frame">True</property>
|
||||||
<property name="focus_on_click">True</property>
|
<property name="focus_on_click">True</property>
|
||||||
|
<signal name="changed" handler="on_account_changed" last_modification_time="Tue, 20 Apr 2010 18:28:53 GMT"/>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="padding">0</property>
|
<property name="padding">0</property>
|
||||||
|
|
89
mytwitter.py
89
mytwitter.py
|
@ -17,17 +17,14 @@ class MyTwitter():
|
||||||
config = ConfigParser.ConfigParser()
|
config = ConfigParser.ConfigParser()
|
||||||
config.read(os.path.expanduser(config_file))
|
config.read(os.path.expanduser(config_file))
|
||||||
|
|
||||||
self.accounts = []
|
self.accounts = {}
|
||||||
for item in config.sections():
|
for item in config.sections():
|
||||||
if (re.match(r'account-', item)):
|
if (re.match(r'account-', item)):
|
||||||
account_name = re.sub(r'account-', '', item)
|
username = config.get(item, 'username')
|
||||||
self.accounts.append({'account_name': account_name,
|
self.accounts[username] = twitter.Api(username=username, password=config.get(item, 'password'))
|
||||||
'username': config.get(item, 'username'),
|
|
||||||
'api': twitter.Api(username=config.get(item, 'username'), password=config.get(item, 'password'))
|
|
||||||
})
|
|
||||||
|
|
||||||
self.username = self.accounts[0]['username']
|
self.username = self.accounts.keys()[0]
|
||||||
self.api = self.accounts[0]['api']
|
self.api = self.accounts[self.username]
|
||||||
|
|
||||||
self.num_entries = int(config.get('global', 'entries'))
|
self.num_entries = int(config.get('global', 'entries'))
|
||||||
self.refresh_time = int(config.get('global', 'refreshtime'))
|
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.context_id = self.status_bar.get_context_id('message')
|
||||||
|
|
||||||
self.tweet_notebook.remove_page(0) # kill the page that glade makes us have
|
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
|
# Add entries to the account select box, set the default entry
|
||||||
# for account in self.accounts:
|
for username in self.accounts.keys():
|
||||||
# self.account_select.
|
self.account_select.append_text(username)
|
||||||
|
self.account_select.set_active(0)
|
||||||
|
|
||||||
# When we change tabs, any unread tweets in it become read
|
# When we change tabs, any unread tweets in it become read
|
||||||
self.tweet_notebook.connect('switch_page', self.on_tab_change)
|
self.tweet_notebook.connect('switch_page', self.on_tab_change)
|
||||||
|
@ -81,20 +80,28 @@ class MyTwitter():
|
||||||
for tab in self.db['open_tabs']:
|
for tab in self.db['open_tabs']:
|
||||||
self.add_to_notebook(tab)
|
self.add_to_notebook(tab)
|
||||||
|
|
||||||
# Put Home, @user, Direct Messages, and lists in the View menu...
|
# Put Home, @user, Direct Messages, and lists in the View menu for
|
||||||
lists = self.api.GetUserLists()
|
# 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 = []
|
list_names = []
|
||||||
for l in lists['lists']:
|
for l in lists['lists']:
|
||||||
list_names.append(l.name)
|
list_names.append(l.name)
|
||||||
list_names.sort()
|
list_names.sort()
|
||||||
list_names.insert(0, 'Home')
|
list_names.insert(0, 'Home')
|
||||||
list_names.insert(1, '@' + self.username)
|
list_names.insert(1, '@' + username)
|
||||||
list_names.insert(2, 'Direct Messages')
|
list_names.insert(2, 'Direct Messages')
|
||||||
for l in list_names:
|
for l in list_names:
|
||||||
menu_item = gtk.MenuItem(l)
|
menu_item = gtk.MenuItem(l)
|
||||||
self.view_menu.append(menu_item)
|
new_menu.append(menu_item)
|
||||||
menu_item.connect('activate', self.on_view_selected, l)
|
menu_item.connect('activate', self.on_view_selected, username, l)
|
||||||
menu_item.show()
|
menu_item.show()
|
||||||
|
outer_menu_item.show()
|
||||||
|
|
||||||
# Timer to update periodically
|
# Timer to update periodically
|
||||||
gobject.timeout_add(self.refresh_time * 1000, self.update_windows)
|
gobject.timeout_add(self.refresh_time * 1000, self.update_windows)
|
||||||
|
@ -105,18 +112,41 @@ class MyTwitter():
|
||||||
pane = self.tweet_notebook.get_nth_page(i)
|
pane = self.tweet_notebook.get_nth_page(i)
|
||||||
list_name = pane.get_list_name()
|
list_name = pane.get_list_name()
|
||||||
|
|
||||||
|
# Single tweets should never be updated here
|
||||||
if pane.get_single_tweet() is not None:
|
if pane.get_single_tweet() is not None:
|
||||||
continue
|
continue
|
||||||
elif list_name is None or list_name == 'Home':
|
|
||||||
statuses = self.api.GetHomeTimeline(count=self.num_entries)
|
# username/Home entries need to load the appropriate Home feed
|
||||||
elif list_name == '@' + self.username:
|
elif re.search(r'/Home', list_name):
|
||||||
statuses = self.api.GetMentions(count=self.num_entries)
|
account = self.accounts[re.sub(r'/Home', r'', list_name)]
|
||||||
elif list_name == 'Direct Messages':
|
statuses = account.GetHomeTimeline(count=self.num_entries)
|
||||||
statuses = self.dms_to_statuses(self.api.GetDirectMessages())
|
|
||||||
|
# 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):
|
elif re.match(r'user: ', list_name):
|
||||||
statuses = self.api.GetUserTimeline(re.sub(r'^user: ', r'', list_name), count=self.num_entries)
|
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):
|
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:
|
else:
|
||||||
statuses = self.results_to_statuses(self.api.Search(list_name, rpp=self.num_entries))
|
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'])
|
self.add_to_notebook(data['name'], data['id'])
|
||||||
|
|
||||||
|
|
||||||
def on_view_selected(self, event, name):
|
def on_view_selected(self, event, username, name):
|
||||||
if name == 'Home' or name == '@' + self.username or name == 'Direct Messages':
|
if name == 'Home' or name == 'Direct Messages':
|
||||||
|
full_name = username + '/' + name
|
||||||
|
elif name == '@' + username:
|
||||||
full_name = name
|
full_name = name
|
||||||
else:
|
else:
|
||||||
full_name = 'list: ' + name
|
full_name = 'list: ' + name
|
||||||
|
@ -346,6 +378,13 @@ class MyTwitter():
|
||||||
self.remove_view(current_pane.get_list_name())
|
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
|
# To keep things simple elsewhere and improve code reuse
|
||||||
# we'll build a list of home-cooked Status objects out of results.
|
# we'll build a list of home-cooked Status objects out of results.
|
||||||
# Why is this even necessary?
|
# Why is this even necessary?
|
||||||
|
|
Reference in New Issue
Block a user