1
from ..main import Application
2
from shutil import move, rmtree, copytree
5
from time import time, sleep
6
from ConfigParser import ConfigParser
7
from string import Formatter
8
from buddy import new_buddy
9
from inspect import getsourcefile
11
class AccountInfo(object):
13
'XMPP' : 'prpl-jabber',
16
def __init__(self, name, credentials):
17
if not isinstance(credentials, ConfigParser):
18
creds_fn = credentials
19
credentials = ConfigParser()
20
credentials.read(creds_fn)
21
self.details = dict(credentials.items(name))
24
def __getattr__(self, name):
26
return self.details[name]
31
def prpl_protocol(self):
32
return self.PURPLE_PROTOCOLS[self.protocol]
36
return self._get_username(False)
40
return self.details.get('alias', self._get_username(False))
43
def username_and_domain(self):
44
return self._get_username(True)
47
def template_args(self):
49
for arg in ('prpl_protocol', 'username_and_domain',
51
args[arg] = getattr(self, arg)
54
def _get_username(self, include_resource=False):
55
if self.protocol == 'XMPP':
56
username = '%s@%s' % (self.details['username'],
57
self.details['domain'])
59
username += '/%s' % self.details['resource']
61
username = self.details['username']
64
class Pidgin(Application):
66
Class that manages the Pidgin IM application
69
WINDOW = "frmBuddyList"
72
TTBL_BUDDIES = "ttbl0"
74
DLG_ACCOUNTS = "dlgAccounts"
75
DLG_ADD_ACCOUNT = "dlgAddAccount"
77
CBO_PROTOCOL = "cboProtocol"
80
MNU_CLOSE = "mnuClose"
83
ldtp.generatekeyevent('<alt><F9>')
86
def open(self, clean_profile=True, credentials=''):
88
It saves the old profile (if needed) and
89
set up a new one. After this initial process,
90
it opens the application
92
@type clean_profile: boolean
93
@param clean_profile: True, to back up the old profile and create a
95
@type credentials: string
96
@param credentials: Path to the config file with accounts information
98
clean_profile = clean_profile not in ('False', '0', False)
99
self.creds_fn = self._normalize_path(credentials)
100
self.credentials = ConfigParser()
101
self.credentials.read(self.creds_fn)
107
Application.open(self)
109
def generate_profile(self, profile_template, template_args=None):
111
It uses the profile_template and the
112
credentials to build a new profile folder
114
os.mkdir(os.path.expanduser('~/.purple'))
116
formatter = Formatter()
117
for fn in os.listdir(profile_template):
118
if os.path.isdir(os.path.join(profile_template, fn)):
119
copytree(os.path.join(profile_template, fn),
120
os.path.join(os.path.expanduser('~/.purple'), fn))
122
buf = open(os.path.join(profile_template, fn)).read()
123
f = open(os.path.join(os.path.expanduser('~/.purple'), fn), 'w')
125
buf = formatter.format(buf, **template_args)
128
'no section/key in %s: %s' % (self.creds_fn, e)
132
def _normalize_path(cls, path):
134
# return os.path.normpath(
135
# os.path.join(os.path.dirname(getsourcefile(cls)), path))
136
_normalize_path = classmethod(_normalize_path)
138
def backup_config(self):
140
It saves the configuration of Pidgin in a path
141
called ~/.purple.bak{.n}
143
p = os.path.expanduser('~/.purple.bak')
146
while os.path.exists(backup_path):
147
backup_path = '%s.%d' % (p, i)
151
move(os.path.expanduser('~/.purple'), backup_path)
155
self.backup_path = backup_path
157
def restore_config(self):
159
It deletes the configuration folder and restore then
160
one backed up (at backup_path)
168
move(self.backup_path,
169
os.path.expanduser('~/.purple'))
171
traceback.print_exc()
173
def wait_for_account_connect(self, account_info, timeout=15):
175
It waits for an account to be connected.
176
A timeout value can be passed, being default 15secs.
178
It raises an exception if the timeout expires.
180
@param account_info: The account information.
181
@type account_info: L{AccountInfo}
182
@param timeout: Number of seconds to wait for the accout to be connected (default:15s)
183
@type timeout: integer
186
while not self.account_connected(account_info):
187
if time() - starttime >= timeout:
188
raise Exception('IM server connection timed out')
189
exists = ldtp.waittillguiexist('dlgSSLCertificateVerification',
192
ldtp.click('dlgSSLCertificateVerification', 'btnAccept')
194
def account_connected(self, account_info):
196
Checks to see if a specified account is connected,
197
@param account_info: The account information.
198
@type account_info: L{AccountInfo}
200
@return True, if the account if connected, False if not.
202
ldtp.remap(self.WINDOW)
203
window = ooldtp.context(self.WINDOW)
204
objs = window.getobjectlist()
205
# It parses the account's submenu, if there is a menu
206
# item "no actions available", then the account is not yet connected.
208
if obj.startswith('mnuNoactionsavailable'):
209
parent = ldtp.getobjectproperty(self.WINDOW,obj, 'parent')
210
# TODO, put in resource and protocol for more accuracy.
211
if parent.startswith(
212
'mnu%s' % account_info.username_and_domain) and \
213
parent.endswith('(%s)' % account_info.protocol):
217
def buddy_available(self, alias):
219
It searches for a given alias to be in the buddy list
222
@param alias: The name of the buddy to search
224
@return 1, if the buddy is available, 0 otherwise.
226
return ldtp.doesrowexist(self.WINDOW, self.TTBL_BUDDIES, alias)
228
def wait_for_buddy(self, alias, timeout=15):
230
It waits for a buddy to be connected.
231
A timeout value can be passed, being default 15secs.
233
It raises an exception if the timeout expires.
236
@param alias: The name of the buddy to wait to be available
237
@type timeout: integer
238
@param timeout: Number of seconds to wait for the buddy to be connected (default:15s)
241
while not self.buddy_available(alias):
242
if time() - starttime >= timeout:
243
raise Exception('waiting for buddy timed out')
246
def send_message(self, alias, msg):
248
It sends a message to a particular buddy.
250
It raises an exception if the particuar buddy is not online.
253
@param alias: The name of the buddy to send the message to
255
@param msg: The message to send to the buddy
257
if not ldtp.doesrowexist(self.WINDOW, self.TTBL_BUDDIES, alias):
258
raise Exception("user %s is not online" % alias)
259
ldtp.selectrow(self.WINDOW, self.TTBL_BUDDIES, alias)
260
ldtp.generatekeyevent('<return>')
262
ldtp.waittillguiexist('frm' + alias.replace(' ', ''))
264
frame = ooldtp.context('frm' + alias.replace(' ', ''))
266
frame.settextvalue('txt1', msg)
268
ldtp.generatekeyevent('<return>')
270
def get_conversation_log(self, alias):
272
It gets the text of a on-going conversation (no backlog)
275
@param alias: The buddy to get the conversation text
277
@return The text of the conversion. '' if the conversation does not exist
279
if not ldtp.guiexist('frm' + alias.replace(' ', '')):
282
return ldtp.gettextvalue('frm' + alias.replace(' ', ''), 'txt0')
286
It restore the previous configuration of Pidgin and exists
288
if hasattr(self, 'backup_path'):
289
self.restore_config()
290
Application.close(self)
292
def get_all_windows(self):
294
It gets the list of the pidgin windows
296
@return A list containing the name of the windows
299
for w in ldtp.getwindowlist():
301
if ldtp.getobjectproperty(w, w, 'parent') == 'pidgin':
303
except LdtpExecutionError:
307
def close_conversation(self, window_name):
309
It closes a conversation window
311
@type window_name: string
312
@param window_name: The name of the conversation to close
314
ldtp.selectmenuitem(window_name, self.MNU_CLOSE)
316
def buddy_login(self, account_info):
318
new_buddy(account_info.username,
319
account_info.password,
320
account_info.protocol)
322
print 'connecting buddy'
324
print 'connected buddy'