def remove_account(self): #get current item: w = self.widgets item = w.accounts.currentItem() #get the index (ugh.. this is tedious) itemindex = w.accounts.indexOfTopLevelItem(item) if itemindex == -1: log_err("couldn't get index!") return account = self.account_items[item] #remove the item from the widget: w.accounts.takeTopLevelItem(itemindex) #find the account in our global config list index = -1 for i in xrange(0, len(self.config.accounts)): a = self.config.accounts[i] if str(a["name"]) == str(account["name"]) and str(a["improto"]) == str(account["improto"]): index = i break else: pass if index >= 0: log_debug("index:", index) self.config.accounts.pop(index) #finally, remove it from the mapping self.account_items.pop(item)
def logHelper(self, obj): msg = obj.msg who, txt = (msg.who, msg.txt) txt = txt if txt else "" who = who if who else msg.name msgtype = None if msg.commflags & yobotproto.YOBOT_MSG_TYPE_CHAT: msgtype = CONV_TYPE_CHAT elif msg.commflags & yobotproto.YOBOT_MSG_TYPE_IM: msgtype = CONV_TYPE_IM if not msgtype: return #system message, don't need to log it... #get account info: #FIXME: hack.. might want to see what purple does with its usersplit thingy acct, _ = self.accounts.byId(msg.acctid) if acct.improto == yobotproto.YOBOT_JABBER: name = msg.name.split("/", 1)[0] else: name = msg.name try: self.logger.logMsg(msgtype, acct.user, yobotops.imprototostr(acct.improto), name, msg.txt, who, msg.time) except msglogger.IntegrityError, e: log_err(e)
def purple_handle_acct_connection(self, obj, proto): """This will handle account events coming from purple..""" evt = obj.evt log_info(evt) acct_id = evt.objid if evt.event in (yobotproto.YOBOT_EVENT_AUTH_FAIL, yobotproto.YOBOT_EVENT_LOGIN_ERR, yobotproto.YOBOT_EVENT_DISCONNECTED): #find account and trigger its errback: try: acct, _ = self.accounts.byId(acct_id) except TypeError: log_err("account does not exist (anymore)") return try: acct.timeoutCb.cancel() except Exception, e: log_warn(e) #relay the segment now because the client/account lookup will be #broken after the account has been deleted: self._relay_segment(obj, acct_id) try: if not evt.event == yobotproto.YOBOT_EVENT_DISCONNECTED: acct.connectedCb.errback(AccountRemoved("Login Failed")) else: acct.connectedCb.errback(AccountRemoved("Disconnected")) except defer.AlreadyCalledError, e: log_err(e)
def delAcct(self, id=None,userproto=None): """Deletes an account indexed by ID or (user,proto) pair. If the account exists, it will return the data portion of the entry. This will also delete the account from the connected protocol instances.. Raises KeyError if something doesn't exist""" (acct, data) = None, None if id: log_debug("looking up ID") #get account from ID and remove from other dict: res = self._ids.pop(id) if res == RESERVED_ID: log_debug("Reserved ID") return None acct, data = res self._accounts.pop((acct.user,acct.improto)) elif userproto: log_debug("looking up userproto") res = self._accounts.pop((userproto)) assert res acct, data = res self._ids.pop(acct.id) else: log_err("oops.. neither id or userproto was specified") raise TypeError, "Must provide a (user,proto) or ID as a key" for conn in data: self._connections[conn].remove(acct.id) log_debug("done")
def update_icon(self, obj, proto): _, data = getNameAndData(obj) cksum = sha1(data).digest() try: _, protos = self.accounts.byId(obj.evt.objid) except Exception, e: log_err(e) return
def _currentChanged(self, index): oldmenubar = self.menuWidget() if oldmenubar and getattr(oldmenubar, "real_owner", None): try: oldmenubar.real_owner.setMenuWidget(oldmenubar) del oldmenubar.real_owner except RuntimeError, e: log_err(e)
def doRegister(self, proto, obj): """Check if this is a registration response from the server, if it is, then give ourselves the cid assigned by the server, otherwise lose the connection""" if (obj.struct_type == yobotproto.YOBOT_PROTOCLIENT_YEVTI and obj.base.event == yobotproto.YOBOT_EVENT_CLIENT_REGISTERED): proto.cid = obj.base.objid proto.registered = True log_info( "client received registration response with cid", proto.cid) else: log_err( "not expecting this...") proto.transport.loseConnection()
def topicChanged(self, acct, room, topic): from gui import yahoo_captcha import re self._plugin_hook_invoke("topicChanged", (acct, room, topic)) if acct.improto == yobotproto.YOBOT_YAHOO: m = re.search(r"http://\S*captcha\S*", topic, re.I) if m: url = m.group(0) prompter = yahoo_captcha.CaptchaPrompter() prompter.prompt(url) else: log_err("NO MATCH!!!")
def _plugin_hook_invoke(self, hook_name, hook_args): for p in self.plugins: try: getattr(p, hook_name)(*hook_args) except AttributeError, e: #first make sure that the actual exception comes from not having #the plugin implementing the hook, and not e.g. bad arguments or some #other error if not getattr(p, hook_name, None): log_err("Object %r has not implemented %s" % (p, hook_name)) else: raise
def removeFromContainer(self): if self.tabcontainer: #find ourself in the widget.. index = self.tabcontainer.tabwidget.indexOf(self) if index == -1: log_err("invalid index for widget", str(id(self))) self.tabcontainer = None return False self.tabcontainer.tabwidget.removeTab(index) self.tabcontainer = None return True log_err("tabcontainer has not been set!") return False
def index(self, row, column = 0, parent = QModelIndex()): if column != 0 or row <0: return QModelIndex() parent_item = parent.internalPointer() if not parent_item: #top level account.. try: acct_obj = self.backend[int(row)] ret = self.createIndex(row, 0, acct_obj) return ret except (IndexError, KeyError), e: log_err(e) return QModelIndex()
def __init__(self, parent=None, acct_obj=None, target=None, factory=None, initial_text="",tabwidget = None): """Factory takes a target username and an account object. Supposed to respawn/activate a chat window""" self.type = type self.target = target self.account = acct_obj self.factory = factory self._initial_text = initial_text if not target or not acct_obj: log_err( "must have target and account for chatwindow") return ChatPane.__init__(self, parent, tabcontainer=tabwidget, title=target) self.setAttribute(Qt.WA_DeleteOnClose)
def model_dump(self): return for a in self.backend: log_warn(a) for b in a.blist: log_warn("\t", b) log_err("now recursing") rows = self.rowCount() log_err("rows: ", rows) if rows > 0: for r in xrange(0, rows): acct_index = self.index(r) log_warn("Account", acct_index.internalPointer().name) c_rows = self.rowCount(acct_index) if c_rows > 0: for cr in xrange(0, c_rows): c_index = self.index(cr, 0, acct_index) log_warn("\tBuddy", c_index.internalPointer().name)
def relayOfflines(self, obj, proto): acct, _ = self.accounts.byId(obj.cmd.acctid) if not acct: log_err("account is none") return if not acct.lastClientDisconnected: log_info("not relaying offlines while other clients are still connected") return for msg in self.logger.getMsgs(acct.name, yobotops.imprototostr(acct.improto), timerange = (acct.lastClientDisconnected, time.time()), count=0): msg.acctid = obj.cmd.acctid msg.yprotoflags |= (yobotproto.YOBOT_BACKLOG|yobotproto.YOBOT_OFFLINE_MSG) proto.sendSegment(msg) print msg self.logger.dump() log_warn("done") log_info(acct.lastClientDisconnected) acct.lastClientDisconnected = 0
def verifyObj(self, obj, proto): """Verify that the acct ID referenced in the incoming client message indeed belongs to the client""" acctid = 0 if obj.cmd: acctid = obj.cmd.acctid elif obj.evt: acctid = obj.evt.objid if acctid != 0: acct_entry = self.accounts.byId(acctid) if not acct_entry: #Account doesn't exist. log_err( "verification failing.. no such account", acctid) return False _, protos = acct_entry if not protos: #there's no protocol instance currently connected log_err( "verification failing, no connected instances", acctid) return False if proto in protos: #Account exits and has this CID in its list of clients return True #Account exits but CID not found log_err( "verification failing, CID %d not in associated client list for account %d" % (proto.cid, acctid)) return False #Account ID is the special value of 0 return True
def purple_request_responder(self, obj, proto): """What we do here is simple.. look at the commflags for a "YOBOT_RESPONSE", and if so, relay the segment to the client""" #first get the type... if obj.commflags & yobotproto.YOBOT_RESPONSE_END: self.requests.pop(obj.reference, None) log_debug("request done.. removing..") return if not obj.commflags & yobotproto.YOBOT_RESPONSE: log_err("how the hell did this get here..") return client = self.requests.get(obj.reference, None) if not client: log_err("couldn't get client!") return #check that the client is associated with the account ID still (this is #a really paranoid provision, for e.g. a new client which has taken the #old id of the previous client....) #if not self.verifyObj(obj, client): # raise UnauthorizedTransmission() #finally.. relay.. log_debug(obj.evt) client.sendPrefixed(obj.raw)
def handle_cmd(self, obj, proto): """Handle account-related commands, otherwise we just relay to purple""" if not self.verifyObj(obj, proto): log_err("unauthorized transmission: client %d, account %d" % (proto.cid, obj.cmd.acctid)) return #raise UnauthorizedTransmission( # "Client %d not authorized for account %d" % # (proto.cid, obj.cmd.acctid)) command = obj.cmd.cmd if command == yobotproto.YOBOT_CMD_ACCT_ID_REQUEST: new_id = self.accounts.reserveId(31) if not new_id: raise Exception("New ID cannot be allocated!!!!") proto.sendAccountEvent(yobotproto.YOBOT_EVENT_ACCT_ID_NEW, new_id) elif command == yobotproto.YOBOT_CMD_CLIENT_REGISTER: log_info( "not relaying registration command to purple..") elif command in (yobotproto.YOBOT_CMD_FETCH_BUDDIES, yobotproto.YOBOT_CMD_ROOM_FETCH_USERS, yobotproto.YOBOT_CMD_FETCH_BUDDY_ICONS): #generate reference.. reference = get_rand(8,self.requests.keys()) if not reference: log_err( "CAN'T ALLOCATE REQUEST ID!") return #generate new command.. obj.cmd.reference = reference self.requests[reference] = proto #re-encode because we added a reference ID... self.prpl_server.sendSegment(obj.cmd) elif command == yobotproto.YOBOT_CMD_REQUEST_BACKLOG: self.logRetriever(obj, proto) elif command == yobotproto.YOBOT_CMD_CLIENT_RMACCT: self.accounts.delConnection(proto, id=obj.cmd.acctid) proto.sendAccountEvent(yobotproto.YOBOT_EVENT_DISCONNECTED, obj.cmd.acctid, txt=("Your location is no longer associated with " "this account, as you requested")) elif command == yobotproto.YOBOT_CMD_ACCT_REMOVE: try: _, protos = self.accounts.byId(obj.cmd.acctid) for p in protos: addr = ":".join([str(c) for c in proto.transport.getPeer()]) p.sendAccountEvent(yobotproto.YOBOT_EVENT_AGENT_NOTICE_GENERIC, obj.cmd.acctid, txt=("Disconnect requested by client %d [%s]" % (proto.cid, addr))) except Exception, e: log_err(e) raise self.prpl_server.sendPrefixed(obj.raw)
def data(self, index, role = Qt.DisplayRole): if not index.isValid(): #log_err("returning QVariant()") return QVariant() #type = INDEX_BUDDY if index.parent().isValid() else INDEX_ACCT item = index.internalPointer() type = INDEX_BUDDY if item.parent else INDEX_ACCT if role == Qt.DisplayRole: return_text = item.name #log_err("returning",return_text) return QVariant(return_text) elif role == Qt.FontRole: font = QFont() if type == INDEX_ACCT: font.setWeight(QFont.Bold) return font elif role == ROLE_SMALL_BUDDY_TEXT: #ret = " ".join([str(i) for i in ( # item.status_message, index.row(),index.column(), index.parent().isValid())]) return QVariant(item.status_message) elif role == Qt.DecorationRole: #get font stuff.. map the status to the right icon.. etc. try: improto = item.improto if type == INDEX_ACCT else item.account.improto except (AttributeError), e: log_err("INDEX_ACCT" if type==INDEX_ACCT else "INDEX_BUDDY") log_err(e) log_err("item", index.internalPointer(), "parent", index.parent().internalPointer()) raise #see if we have a status icon available... status_name = STATUS_ICON_MAPS.get(item.status, None) if not status_name: return QVariant(getProtoStatusIcon(IMPROTOS_BY_CONSTANT[improto])) else: return QVariant(getProtoStatusIcon(status_name, proto_int = improto))
def disconnectAll(self, fromServer): if fromServer: self.svc.disconnectAll() else: return log_err("reactor.stop")
def delItem(self, item): log_err("not implemented!")
def beginChildRemove(self, parent_index, child_index): "hack, override this" log_err("Override me")
def dataChanged(self, parent_index, child_index): log_err("override me") # raise Exception() "hack, override this"
def _logchanged(childindex, parentindex): log_err("called")
log_err("rows: ", rows) if rows > 0: for r in xrange(0, rows): acct_index = self.index(r) log_warn("Account", acct_index.internalPointer().name) c_rows = self.rowCount(acct_index) if c_rows > 0: for cr in xrange(0, c_rows): c_index = self.index(cr, 0, acct_index) log_warn("\tBuddy", c_index.internalPointer().name) try: from PyQt4.QtCore import QPropertyAnimation HAS_QPROPERTY_ANIMATION = True except ImportError, e: log_err(e) HAS_QPROPERTY_ANIMATION = False class ConnectionWidget(QWidget): def __init__(self, parent = None, connect_cb = None): QWidget.__init__(self, parent) self.widgets = connection_properties.Ui_connection_widget() w = self.widgets w.setupUi(self) self.container_height_exclusive = self.sizeHint().height() - self.widgets.proxy_params.sizeHint().height() self.combined_height = self.sizeHint().height() if HAS_QPROPERTY_ANIMATION: self.pp_show_animation = QPropertyAnimation(self, "size", self) self.pp_show_animation.setDuration(100) self.pp_show_animation.setStartValue(QSize(self.width(), self.container_height_exclusive))
def statusChange(self, status_int, status_message = ""): if status_int > yobotproto.PURPLE_STATUS_NUM_PRIMITIVES: log_err("requested status that doesn't exist") return self.svc.statusChange(self, status_int, status_message)
#agent handlers: def _agentconn_failed(self, connector, reason): #remove all accounts first: self.disconnectAll(True) #arg doesn't matter self.svc.accounts.clear() ##### GUI HOOKS ##### def connectToAgent(self, address=None, port=None, disconnect_from_server=True): try: self.disconnectAll(disconnect_from_server) except Exception, e: log_warn(e) if not address and not port: _address = self.config.globals.get("agent_address", "localhost:7770") log_err(_address) a = _address.rsplit(":") if len(a) >= 2: address = a[0] port = int(a[1]) else: address = a[0] port = 7770 elif address and not port: port = 7770 log_debug("creating new factory") f = YobotClientFactory() self.svc.polishClientFactory(f) f.clientConnectionFailed = self._agentconn_failed
def beginChildAdd(self, parent_index, child_index): "hack, override this" log_err("override me")
def uiClosed(self): #stop the reactor.. log_err("") reactor.stop()
def accountConnectionFailed(self, acct, txt): acct._logged_in = False log_err( "AUTHORIZATION FAILED!", txt, acct) self._plugin_hook_invoke("accountConnectionFailed", (acct, txt))
def roomLeft(self, acct, room): try: self.joined_rooms[acct].remove(room) except Exception, e: log_err("couldn't remove room %s from room list for account %s: %s" %( room, str(acct), str(e)))