Added characters to settings dialog
[mevemon] / package / src / mevemon.py
1 #!/usr/bin/env python
2 #
3 # mEveMon - A character monitor for EVE Online
4 # Copyright (c) 2010  Ryan and Danny Campbell, and the mEveMon Team
5 #
6 # mEveMon is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # mEveMon is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20
21 import hildon
22 import gtk
23 from eveapi import eveapi
24 import fetchimg
25 import apicache
26 import os.path
27
28 # we will store our preferences in gconf
29 import gnome.gconf
30
31 #ugly hack to check maemo version. any better way?
32 if hasattr(hildon, "StackableWindow"):
33     from ui.fremantle import gui
34 else:
35     from ui.diablo import gui
36
37 class mEveMon():
38     """
39     The controller class for mEvemon. The intent is to help
40     abstract the EVE API and settings code from the UI code.
41
42     """
43
44     GCONF_DIR = "/apps/maemo/mevemon"
45
46     def __init__(self):
47         self.program = hildon.Program()
48         self.program.__init__()
49         self.gconf = gnome.gconf.client_get_default()
50         #NOTE: remove this after a few releases
51         self.update_settings()
52         self.cached_api = eveapi.EVEAPIConnection( cacheHandler = \
53                 apicache.cache_handler(debug=False))
54         self.gui = gui.mEveMonUI(self)
55
56     def run(self):
57         gtk.main()
58     
59     def quit(self, *args):
60         gtk.main_quit()
61
62     def update_settings(self):
63         """
64         Update from the old pre 0.3 settings to the new settings layout.
65         We should remove this eventually, once no one is using pre-0.3 mEveMon
66         """
67         uid = self.gconf.get_string("%s/eve_uid" % self.GCONF_DIR)
68         
69         if uid:
70             key = self.gconf.get_string("%s/eve_api_key" % self.GCONF_DIR)
71             self.add_account(uid, key)
72             self.gconf.unset("%s/eve_uid" % self.GCONF_DIR)
73             self.gconf.unset("%s/eve_api_key" % self.GCONF_DIR)
74
75
76     def get_accounts(self):
77         """
78         Returns a dictionary containing uid:api_key pairs gathered from gconf
79         """
80         accounts = {}
81         entries = self.gconf.all_entries("%s/accounts" % self.GCONF_DIR)
82
83         for entry in entries:
84             key = os.path.basename(entry.get_key())
85             value = entry.get_value().to_string()
86             accounts[key] = value
87
88         return accounts
89         
90     def get_api_key(self, uid):
91         """
92         Returns the api key associated with the given uid.
93         """
94         return self.gconf.get_string("%s/accounts/%s" % (self.GCONF_DIR, uid)) or ''
95
96     def remove_account(self, uid):
97         """
98         Removes the provided uid key from gconf
99         """
100         self.gconf.unset("%s/accounts/%s" % (self.GCONF_DIR, uid))
101
102     def add_account(self, uid, api_key):
103         """
104         Adds the provided uid:api_key pair to gconf.
105         """
106         self.gconf.set_string("%s/accounts/%s" % (self.GCONF_DIR, uid), api_key)
107
108     def get_auth(self, uid):
109         """
110         Returns an authentication object to be used for eveapi calls
111         that require authentication.
112         """
113         api_key = self.get_api_key(uid)
114
115         try:
116             auth = self.cached_api.auth(userID=uid, apiKey=api_key)
117         except eveapi.Error:
118             return None
119
120         return auth
121
122     def get_char_sheet(self, uid, char_id):
123         """
124         Returns an object containing information about the character specified
125         by the provided character ID.
126         """
127         try:
128             sheet = self.get_auth(uid).character(char_id).CharacterSheet()
129         except eveapi.Error:
130             # TODO: we should really have a logger that logs this error somewhere
131             return None
132
133         return sheet
134
135     def charid2uid(self, char_id):
136         """
137         Takes a character ID and returns the user ID of the account containing
138         the character.
139
140         Returns None if the character isn't found in any of the registered accounts.
141
142         """
143         acct_dict = self.get_accounts()
144         
145         for uid, api_key in acct_dict.items():
146             auth = self.cached_api.auth(userID=uid, apiKey=api_key)
147             api_char_list = auth.account.Characters()
148             
149             for character in api_char_list.characters:
150                 if character.characterID == char_id:
151                     return uid
152
153         
154         return None
155     
156     def char_id2name(self, char_id):
157         """
158         Takes a character ID and returns the character name associated with
159         that ID.
160         The EVE API accepts a comma-separated list of IDs, but for now we
161         will just handle a single ID.
162         """
163         try:
164             chars = self.cached_api.eve.CharacterName(ids=char_id).characters
165             name = chars[0].characterName
166         except eveapi.Error:
167             return None
168
169         return name
170
171     def char_name2id(self, name):
172         """
173         Takes the name of an EVE character and returns the characterID.
174         
175         The EVE api accepts a comma separated list of names, but for now
176         we will just handle single names/
177         """
178         try:
179             chars = self.cached_api.eve.CharacterID(names=name).characters
180             char_id = chars[0].characterID
181             char_name = chars[0].name
182         except eveapi.Error:
183             return None
184
185         return char_id
186
187     def get_chars_from_acct(self, uid):
188         """
189         Returns a list of characters associated with the provided user ID.
190         """
191         auth = self.get_auth(uid)
192         if not auth:
193             return None
194         else:
195             try:
196                 api_char_list = auth.account.Characters()
197                 char_list = [char.name for char in api_char_list.characters]
198             except eveapi.Error:
199                 return None
200
201         return char_list
202
203     def get_characters(self):
204         """
205         Returns a list of (character_name, image_path, uid) tuples from all the
206         accounts that are registered to mEveMon.
207         
208         If there is an authentication issue, then instead of adding a valid
209         pair to the list, it appends an 'error message' 
210
211         """
212         ui_char_list = []
213         err_img = "/usr/share/mevemon/imgs/error.jpg"
214
215         placeholder_chars = ("Please check your API settings.", err_img, "0")
216         
217         acct_dict = self.get_accounts()
218         if not acct_dict:
219             return [placeholder_chars]
220
221         for uid in acct_dict.keys():
222             char_names = self.get_chars_from_acct(uid)
223             
224             if not char_names:
225                 ui_char_list.append(placeholder_chars)
226             else:
227                 # append each char we get to the list we'll return to the
228                 # UI --danny
229                 for char_name in char_names:
230                     ui_char_list.append((char_name, self.get_portrait(char_name, 64) , uid) )
231         
232         return ui_char_list
233
234     def get_portrait(self, char_name, size):
235         """
236         Returns the file path of the retrieved portrait
237         """
238         char_id = self.char_name2id(char_name)
239         
240         return fetchimg.portrait_filename(char_id, size)
241
242     def get_skill_tree(self):
243         """
244         Returns an object from eveapi containing skill tree info
245         """
246         try:
247             tree = self.cached_api.eve.SkillTree()
248         except eveapi.Error:
249             return None
250         
251         return tree
252
253     def get_skill_in_training(self, uid, char_id):
254         """
255         Returns an object from eveapi containing information about the
256         current skill in training
257
258         """
259         try:
260             skill = self.get_auth(uid).character(char_id).SkillInTraining()
261         except eveapi.Error:
262             return None
263
264         return skill
265
266
267 if __name__ == "__main__":
268     app = mEveMon()
269     app.run()