home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyo (Python 2.6)
-
- import sys
- import time
- import datetime
- import struct
- import logging
- import traceback
- import email
- import util.allow_once as once
- import util.callbacks as callbacks
- from util import callsback, RoundRobinProducer, strip_html, Timer
- from util.primitives.funcs import get
- from util.Events import event
- import common
- from util.observe import ObservableDict
- from common import Conversation, pref
- import msn
- import msn.AddressBook as MSNAB
- import msn.SOAP.services as SOAPServices
- from msn.P2P.P2PData2 import P2PTransport
- from msn import NSSBAdapter, oim
- import msn.MSNCommands as MSNC
- from msn.MSNCommands import MSNTextMessage
- log = logging.getLogger('msn.p21.conv')
-
- class CircleNotReadyException(Exception):
- pass
-
-
- class MSNP21Conversation(Conversation, P2PTransport):
- events = P2PTransport.events | set(('send_p2p_msg',))
-
- def __init__(self, msn, to_invite = (), **k):
- self.client = msn
- self._to_invite = set(to_invite)
- self._closed = False
- self._waschat = len(self._to_invite) > 1
- Conversation.__init__(self, msn)
- self.protocol.register_conv(self)
- log.info("Added %r to msn's conversation list", self)
- if len(to_invite) >= 1:
- self._chatbuddy = to_invite[0]
- if len(to_invite) == 1:
- self._chat_target_name = to_invite[0]
- cinfo = self.protocol.get_contact_info(self._chat_target_name)
- if cinfo is None:
- self._chat_target_type = MSNAB.ClientType.to_int(MSNAB.ClientType.ChatMember)
- else:
- self._chat_target_type = cinfo.type
- else:
- self._chat_target_name = None
- self._chat_target_type = MSNAB.ClientType.to_int(MSNAB.ClientType.ChatMember)
- else:
- self._chatbuddy = None
- self.buddies = { }
- self.typing_status = ObservableDict()
- self._pending_invite_callbacks = { }
- P2PTransport.__init__(self, msn)
- self.room_list.append(self.self_buddy)
- if self.ischat:
- cb = self.client.circle_buddies[self._chatbuddy]
- self.client.ns.JoinCircleConversation(self._chatbuddy)
- for bname in cb.buddy_names:
- if bname.lower().startswith(str(cb.guid).lower()):
- continue
-
- self.buddy_join(bname)
-
-
-
- chat_room_name = None
-
- def connected(self):
- if self.protocol.ns is not None:
- pass
- return self.protocol.ns.connected()
-
-
- def Disconnect(self):
- log.info('Disconnecting. unregistering %r from client (%r)', self, self.client)
- self.client.unregister_conv(self)
-
-
- def exit(self, force_close = False):
- log.info('%r exiting', self)
- self._closed = True
- Conversation.exit(self)
-
-
- def name(self):
- names = self._clean_list()
- count = len(names)
- aliases = _[1]
- if count == 2:
- who = aliases[0]
- elif count == 3:
- who = '%s and %s' % tuple(sorted(aliases))
- else:
- who = '%d people' % (count - 1)
- return who
-
- name = property(name)
-
- def chat_id(self):
- if self._chat_target_name is None:
- raise CircleNotReadyException()
- self._chat_target_name is None
- return '%s:%s' % (self._chat_target_type, self._chat_target_name)
-
- chat_id = property(chat_id)
-
- def ischat(self):
- destination_type = int(self.chat_id.split(':', 1)[0])
- return MSNAB.ClientType.from_int(destination_type) in (MSNAB.ClientType.ChatMember, MSNAB.ClientType.CircleMember)
-
- ischat = property(ischat)
-
- def buddy(self):
- l = self._clean_list()
-
- try:
- l.remove(self.self_buddy.name)
- except ValueError:
- pass
-
- if len(l) == 1:
- answer = l[0]
- if isinstance(answer, basestring):
- answer = self.protocol.get_buddy(answer)
-
- return answer
- return self.protocol.get_buddy(self._chatbuddy)
-
- buddy = property(buddy)
-
- def _clean_list(self):
- l = set((lambda .0: for x in .0:
- x.name)(self.room_list)) | set(self._to_invite)
- circle = self.client.circle_buddies.get(self._chatbuddy, None)
- if circle is not None:
- l.update(circle.buddy_names)
-
- return list(l)
-
-
- def self_buddy(self):
- return self.protocol.self_buddy
-
- self_buddy = property(self_buddy)
-
- def _send_message(self, text, callback = None, **k):
- pass
-
- _send_message = callbacks.callsback(_send_message)
-
- def invite(self, buddy, callback = None):
- name = getattr(buddy, 'name', buddy)
- self._pending_invite_callbacks[name] = callback
-
- def do_invites(circle_name):
- circle = self.protocol.circle_buddies[circle_name]
- old_name = self._chatbuddy
- self._chatbuddy = circle_name
- self._chat_target_name = circle_name
- self._chat_target_type = None if getattr(circle, 'circle', None) is not None else MSNAB.IMAddressInfoType.TemporaryGroup
- if old_name != self._chatbuddy:
- self.protocol.ns.invite_to_circle(circle_name, old_name)
-
- self.protocol.ns.invite_to_circle(circle_name, name)
-
- if self._chat_target_type not in (MSNAB.IMAddressInfoType.Circle, MSNAB.IMAddressInfoType.TemporaryGroup):
- self.protocol.ns.make_temp_circle(success = do_invites, error = callback.error)
- else:
- do_invites(self._chatbuddy)
-
- invite = callbacks.callsback(invite)
-
- def on_message_recv(self, name, msg, sms = False):
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
- self.typing_status[buddy] = None
- if hasattr(msg, 'html'):
- message = msg.html().replace('\n', '<br />')
- content_type = 'text/html'
- else:
- message = msg
- content_type = 'text/plain'
- did_receive = self.received_message(buddy, message, sms = sms, content_type = content_type)
- if name != self.self_buddy.name and did_receive:
- Conversation.incoming_message(self)
-
-
-
- def on_action_recv(self, name, action_type, action_text):
- if action_type == 'custom':
- text = action_text
- else:
- text = dict(wink = _('winked at you!'), nudge = _('nudged you!')).get(action_type, None)
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
- if text is not None:
- message = '%s %s' % (buddy.alias, text)
-
- self.system_message(message)
-
-
- def on_typing_notification(self, name, typing):
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
- self.typing_status[buddy] = None if typing else None
- None(log.info, '%s is %styping', name if typing else 'not ')
-
-
- def buddy_join(self, name):
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
- if buddy is not self.self_buddy and self.self_buddy not in self.room_list:
- self.on_buddy_join(self.self_buddy.name)
-
- if buddy not in self.room_list:
- self.room_list.append(buddy)
-
- if not self._chatbuddy:
- self._chatbuddy = name
-
- self.event('contacts_changed')
- log.info('Got buddy join event (%s). self.ischat = %r', name, self.ischat)
- self.notify('ischat')
- super(MSNP21Conversation, self).buddy_join(buddy)
- self.invite_success(name)
-
-
- def invite_success(self, name):
- cb = self._pending_invite_callbacks.pop(name, None)
- if cb is not None:
- cb.success()
-
-
-
- def invite_failure(self, name):
- cb = self._pending_invite_callbacks.pop(name, None)
- if cb is not None:
- cb.error()
-
-
-
- def on_buddy_leave(self, name, notify = True):
- self._type_override = None
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
-
- try:
- self.room_list.remove(buddy)
- except ValueError:
- log.info("Buddy %r wasn't in room but left anyway (?)", name)
-
- in_room = set(self._clean_list()) - self._to_invite
- in_room.discard(self.self_buddy.name)
- self.typing_status.pop(buddy, None)
- self.event('contacts_changed')
- super(MSNP21Conversation, self).buddy_leave(buddy)
- self.notify('ischat')
-
-
- def fed_message(self, msg):
- self.recv_msg(msg)
-
-
- def recv_msg(self, msg):
- if msg.name not in self.room_list:
- if not self.ischat:
- self.buddy_join(msg.name)
-
-
-
- try:
- getattr(self, 'recv_msg_%s' % msg.type, self.recv_msg_unknown)(msg)
- except Exception:
- e = None
- import traceback
- traceback.print_exc()
- log.error('Exception handling MSG: %r, msg = %r', e, msg)
-
-
-
- def recv_msg_control_typing(self, msg, typing = True):
- name = msg.name
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
- self.typing_status[buddy] = None if typing else None
- None(log.info, '%s is %styping', name if typing else 'not ')
-
-
- def recv_msg_unknown(self, msg):
- log.info('Got an unknown message: %r (%r)', msg.type, str(msg))
-
-
- def recv_msg_signal_forceabchsync(self, msg):
- if msg.name == self.self_buddy.name:
- payload = msg.get_payload()
- log.info('Got addressbook sync signal from a different endpoint: %r', payload)
- doc = etree.fromstring(payload)
- self.protocol.ns._sync_addressbook(abid = doc.find('.//Service').attrib['id'])
-
-
-
- def recv_msg_wink(self, msg):
- self.on_action_recv(msg.name, 'wink', None)
-
-
- def recv_msg_nudge(self, msg):
- self.on_action_recv(msg.name, 'nudge', None)
-
-
- def recv_msg_text(self, msg):
- name = msg.name
- textmsg = MSNTextMessage.from_net(msg.payload)
- buddy = self.buddies[name] = self.protocol.get_buddy(name)
- self.typing_status[buddy] = None
- if hasattr(textmsg, 'html'):
- message = textmsg.html().replace('\n', '<br />')
- content_type = 'text/html'
- else:
- message = textmsg
- content_type = 'text/plain'
- service_channel = offline = msg.payload.get('Service-Channel', None)
- sms = service_channel == 'IM/Mobile'
- offline = service_channel == 'IM/Offline'
- timestamp_str = msg.payload.get('Original-Arrival-Time', None)
- if timestamp_str is None:
- timestamp = None
- else:
- timestamp = datetime.datetime.fromtimestamp(SOAPServices.strptime_highres(timestamp_str))
- did_receive = self.received_message(buddy, message, sms = sms, content_type = content_type, offline = offline, timestamp = timestamp)
- if name != self.self_buddy.name and did_receive:
- Conversation.incoming_message(self)
-
-
-
- def recv_msg_data(self, msg):
- return self.recv_msg_signal_p2p(msg)
-
-
- def recv_msg_signal_p2p(self, msg):
- from_header = msg.payload.get('From')
- from_name = from_header.split(':', 1)[-1].split(';epid=', 1)[0]
- return None
- self.on_p2p_recv(from_name, msg.payload.get_payload())
-
-
- def send(self, *a, **k):
- return self.protocol.ns.socket.send(*a, **k)
-
-
- def message_header(self, first = None, second = None):
- lines = [
- 'Routing: 1.0',
- 'To: %s;path=IM' % self.chat_id,
- 'From: 1:%s;epid={%s}' % (self.protocol.self_buddy.name, str(self.protocol.get_machine_guid()).lower())]
- if first is not None:
- lines.extend(first)
-
- lines.extend([
- '',
- 'Reliability: 1.0'])
- if second is not None:
- lines.extend(first)
-
- lines.extend([
- '',
- ''])
- return '\r\n'.join(lines)
-
-
- def send_typing_status(self, status):
- if status != 'typing':
- return None
- if not self.buddy.online:
- return None
- lines = [
- 'Messaging: 2.0',
- 'Message-Type: Control/Typing',
- 'Content-Length: 0',
- '',
- '']
- data = '\r\n'.join(lines)
- self.send(MSNC.SDG(payload = self.message_header() + data), trid = True, callback = sentinel)
-
-
- def send_text_message(self, body, callback = None):
- log.info('message body: %r, %r', type(body), body)
- body_parts = body.split('\r\n')
- body_parts[0] = 'Content-Length: %d' % len(body_parts[-1])
- lines = [
- 'Messaging: 2.0',
- 'Message-Type: Text',
- 'IM-Display-Name: %s' % self.protocol.self_buddy.remote_alias.encode('utf8')]
- lines.extend(body_parts)
- data = '\r\n'.join(lines)
- header_args = []
- if not self.buddy.online:
- header_args.append('Service-Channel: IM/Offline')
- elif self.buddy.mobile and self.buddy.sms:
- header_args.append('Service-Channel: IM/Mobile')
-
- self.send(MSNC.SDG(payload = self.message_header(header_args) + data), trid = True, callback = callback)
-
- send_text_message = callbacks.callsback(send_text_message)
-
- def _send_message(self, msg, callback = None, **k):
- cl = set(self._clean_list())
- cl -= set([
- self.self_buddy.name])
- if not cl:
- callback.error()
- self.system_message("You can't message yourself using MSN.")
- return None
- body = msg.format_as('msn')
-
- def check_nak(sck, emsg):
- log.error('Error sending message: %r', emsg)
- cmd = getattr(emsg, 'cmd', None)
- if cmd == 'NAK':
- self._send_message_im(msg, callback = callback)
- elif cmd == '217':
- self.system_message('Offline messaging not yet supported')
- else:
- callback.error(emsg)
-
- self.send_text_message(body, error = check_nak)
- callback.success()
-
- _send_message = callbacks.callsback(_send_message)
-
- def on_p2p_recv(self, name, data):
- log.info('Got p2p data: %r', data)
- self.event('recv_data', self, name, data)
-
-
- def p2p_rating(self):
- return 0
-
- p2p_rating = property(p2p_rating)
-
- def p2p_max_msg_size(self):
- return sys.maxint
-
- p2p_max_msg_size = property(p2p_max_msg_size)
-
- def p2p_overhead(self):
- return 40
-
- p2p_overhead = property(p2p_overhead)
-
- def p2p_peers(self):
- if self.ischat:
- return []
- return [
- self.buddy.name]
-
- p2p_peers = property(p2p_peers)
-
- def push_with_producer(self, prod, callback = None):
- data = prod.more()
- if data is not None:
- self.p2p_send(data, callback = callback)
-
-
- push_with_producer = callbacks.callsback(push_with_producer)
-
- def p2p_send(self, data, callback = None):
- from_id = '1:%s;epid={%s}' % (self.self_buddy.name, str(self.protocol.get_machine_guid()).lower())
- body = MSNP2PMessage(self.chat_id, from_id, data)
- log.info('P2Psend: %r', str(body))
- cmd = msn.MSNCommands.SDG(payload = str(body))
- self.send(cmd, trid = True, callback = callback)
- self.event('send_p2p_msg', body)
-
- p2p_send = callbacks.callsback(p2p_send)
-
- def build_data(self, header, body, footer):
- return header + body + footer
-
-
-
- class MSNP2PMessage(object):
-
- def __init__(self, to_id, from_id, body, offset_size = 1254):
- self.to_id = to_id
- self.from_id = from_id
- self.body = body
- self.offset_size = offset_size
-
-
- def __str__(self):
- sz = 0
- offsets = []
- while sz < len(self.body):
- offsets.append(str(sz))
- sz += self.offset_size
- return '\r\n'.join([
- 'Routing: 1.0',
- 'To: %(to_id)s',
- 'From: %(from_id)s',
- 'Options: 0',
- 'Service-Channel: PE',
- '',
- 'Reliability: 1.0',
- '',
- 'Messaging: 2.0',
- 'Message-Type: Data',
- 'Content-Transfer-Encoding: binary',
- 'Content-Type: application/x-msnmsgrp2p',
- 'Bridging-Offsets: %s' % ','.join(offsets),
- 'Content-Length: %d' % len(self.body),
- '',
- '%(body)s']) % vars(self)
-
-
-