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 autoconnect(self): log_info("autoconnecting..") #auto-connect all accounts in our config.. if self.config and self.config.do_autoconnect: config = self.config for a in config.accounts: log_debug("found account: %s/%s" % (a["name"], a["improto"])) if not a.get("autoconnect", False): continue #create positional arguments: user, password, improto = a.get("name"), a.get("password"), a.get("improto") if not (user and password and improto): continue improto = getattr(yobotproto, improto, -1) if improto == -1: continue args = (user, password, improto) kwargs = {} if a.get("use_proxy", False): while True: if not (a.get("proxy_address") and a.get("proxy_type")): break kwargs["proxy_host"] = a["proxy_address"] kwargs["proxy_type"] = a["proxy_type"].lower() kwargs["proxy_port"] = int(a["proxy_port"]) if a["proxy_port"] else None kwargs["proxy_username"] = a.get("proxy_username", None) kwargs["proxy_password"] = a.get("proxy_password", None) break self.connect(*args, **kwargs)
def __init__(self, svc): self._initvars() self.svc = svc #register ourselves only a single time: store = yobot_interfaces.component_registry.get_component("account-store") if not store: yobot_interfaces.component_registry.register_component("account-store", self) log_info("registered") else: return store
def _tryRegister(self,protocol): """ Just generate a random CID """ newcid = get_rand(16,self.clients.keys()) if not newcid: return None else: log_info( "newcid:", newcid) return newcid
def changeId(self, obj, proto): #get the old ID cur_id = obj.evt.objid new_id = int(obj.evt.txt) log_info( "cur_id:", cur_id, "new id:", new_id) acct = self.accounts.delAccount(cur_id) acct.changeid(new_id) self.accounts.addAccount(new_id, acct) #notify that we're connected, since in ID_CHANGE message is granted #only when the account is indeed authorized self.uihooks.accountConnected(self.accounts.getAccount(new_id))
def gotNewId(self, obj, proto): self.id_pool.add(obj.evt.objid) #find an account that's pending... acct = self.pending_accounts.get(block=False) if acct: log_info( "APPLYING GRANTED ID TO ACCOUNT") #assign it an ID... acct.changeid(self.id_pool.pop()) self.accounts.addAccount(acct.id, acct) #send the request... proto.sendSegment(acct)
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 callback(self, ret): if not self.svc: log_warn("service was not specified") return cmd = YobotCommand() cmd.acctid = self.evt.objid cmd.cmd = yobotproto.YOBOT_CMD_PURPLE_REQUEST_GENERIC_RESPONSE cmd.data = str(ret) cmd.reference = self.evt.reference self.svc.sendSegment(cmd) log_info("send response - %s" % (cmd.reference,))
def gotmsg(self, msg): """This should be overridden by the GUI""" log_debug( msg) if msg.yprotoflags & yobotproto.YOBOT_MSG_TYPE_CHAT: #find room... for room in self.rooms: if room.name == msg.name: room.gotmsg(msg) elif msg.yprotoflags & yobotproto.YOBOT_MSG_ATTENTION: log_info( msg.name, "Has buzzed you!!") elif msg.yprotoflags & yobotproto.YOBOT_MSG_TYPE_IM: pass
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 gotBuddyStatus(self, name, status, text=None): if not name: #self: self.status = status self.status_message = text self.notifier.dataChanged(self.index, -1) return log_info( "adding buddy %s with status %d" % (name, status)) buddy = self._getBuddy(name) #process events.. buddy.status = status buddy.status_message = text if text else buddystatustostr(status) log_info("status message", buddy.status_message) self.notifier.dataChanged(self.index, buddy.index)
def dropEvent(self, event): log_debug("") m = event.mimeData() s = event.source() if "action" in m.formats() and m.data("action") == "window_drag": event.acceptProposedAction() log_debug("Got drop request for window") if not getattr(s, "current_widget", None): log_debug("Not a valid object for dropping:", s) return widget = s.current_widget if id(widget) in self.tabwidget.tab_ids: log_info("drop requested, but widget %r already exists" % (widget)) return widget.addToContainer(self)
def buddyEvent(self, obj, proto): #find account... log_info( "id: ", obj.evt.objid) acct = self.accounts.getAccount(obj.evt.objid) if not acct: log_warn( "Couldn't find account!") log_debug(acct) name, data = getNameAndData(obj) if name == "*": name = None if obj.evt.event == yobotproto.YOBOT_EVENT_BUDDY_GOT_ICON: acct.gotBuddyIcon(name, data) else: acct.gotBuddyStatus(name, obj.evt.event, data)
def chatUserEvent(self, obj, proto): evt = obj.evt joined = False if evt.event == yobotproto.YOBOT_EVENT_ROOM_USER_LEFT else True room, user = evt.txt.split(yobotproto.YOBOT_TEXT_DELIM, 1) log_info("room:", room, "user:"******"couldn't find account") return if joined: self.uihooks.chatUserJoined(acct, room, user) else: self.uihooks.chatUserLeft(acct, room, user) log_info( obj.evt)
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 startup(args=sys.argv[1:]): import optparse parser = optparse.OptionParser() parser.add_option("-l", "--listen", help="listening address:port", default="localhost:7770", dest="listening_addrinfo") parser.add_option("-c", "--connect", help="purple address:port", default="localhost:7771", dest="purple_addrinfo") parser.add_option("-s", help="does nothing. for compatibility", action="store_true", dest="dummy") options, args = parser.parse_args(args) tmp = options.listening_addrinfo.rsplit(":", 1) assert len(tmp) >= 2 listen_address = tmp[0] listen_port = int(tmp[1]) tmp = options.purple_addrinfo.rsplit(":", 1) assert len(tmp) >= 2 connect_address = tmp[0] connect_port = int(tmp[1]) if True: debuglog.init("Agent", title_color="cyan") log_info( "INSTALLING REACTOR...") from twisted.internet import reactor as _reactor global reactor reactor = _reactor yobotproto.yobot_proto_setlogger("Agent") svc = YobotServerService() log_info("connecting to purple at %s:%d" % (connect_address, connect_port)) reactor.connectTCP(connect_address, connect_port, svc.getYobotPurpleFactory()) log_info("listening on %s:%d" % (listen_address, listen_port)) reactor.listenTCP(listen_port, svc.getYobotServerFactory(), interface=listen_address) reactor.run()
def __init__(self, parent = None, tabcontainer = None, title = ""): """Note that the caller is responsible to ensure that this widget has draggable content, e.g. insert a DragBar class somewhere""" super(ChatPane, self).__init__(parent) self.setAcceptDrops(True) self.title = title self.tabcontainer = None self.setupWidgets() if not tabcontainer: tabcontainer = TabContainer.getContainer() if not tabcontainer: tabcontainer = TabContainer(parent, destroy_parent_on_close=False) tabcontainer.show() tabcontainer.resize(self.sizeHint()) TabContainer.refs.add(tabcontainer) if isinstance(tabcontainer, TabContainer): self.addToContainer(tabcontainer) signal_connect(self, SIGNAL("destroyed()"), lambda: log_info("destroyed"))
def clientRegistered(self): log_info("REGISTERED") self.autoconnect()
def accountConnected(self, acct): log_info( "ACCOUNT CONNECTED", acct) self._plugin_hook_invoke("accountConnected", (acct,))
def roomJoined(self, acct, room): self.joined_rooms[acct].append(room) self._plugin_hook_invoke("roomJoined", (acct, room)) log_info("ROOM JOINED:", room)
def test_acct(self): return log_info("creating new test account") new_account = YCAccount(self.svc, "[email protected]/", "1", yobotproto.YOBOT_JABBER) # proxy_host="localhost", proxy_port="3128", proxy_type="http") new_account.connect()
def release(self, purple): """Call with the purple protocol class. All the queued functions will be called""" log_info("calling delayed queue purple protocol class methods") self.deferred.callback(purple)
def handle_evt(self, obj, proto): log_info(obj.evt) self.dispatchEvent(obj, proto)
def clientRegistered(self, obj, proto): log_info( "client registered") self.uihooks.clientRegistered()
def fetchBuddies(self): self.svc.fetchBuddies(self) self.svc.fetchBuddyIcons(self) log_info( "Fetching buddies..")
def connect(self): #assume we have an ID... self.svc.addAcct(self) log_info( "adding self to connected list...")
def setPurple(self, proto): log_info("connected to purple server") self.prpl_server.release(proto) self.prpl_server = proto
def purpleDoRegister(self, proto, obj): obj = obj.base if obj.struct_type == yobotproto.YOBOT_PROTOCLIENT_YEVTI: if obj.event == yobotproto.YOBOT_EVENT_CLIENT_REGISTERED: proto.registered = True log_info( "Purple is ", self.prpl_server, "REGISTERED!")
"""Removes a connection from the account's data list""" #FIXME: accept iterables for id and userproto ((acct, st), lookup_table) = self._getacct(id, userproto) try: st.remove(connection) except KeyError, e: log_warn( e) return try: if connection in acct.authenticated_clients and len(acct.authenticated_clients) == 1: #we're removing the last connection acct.lastClientDisconnected = time() acct.authenticated_clients.remove(connection) except KeyError: log_info("seems connection %s was not authenticated" % (str(connection),)) self._update_both(acct, st, lookup_table) try: self._connections[connection].remove(acct.id) except KeyError, e: log_warn( e) return def getConnectionData(self, connection): return self._connections.get(connection, None) def reserveId(self,bits): if bits > 31: return None
def clientConnectionFailed(connector, reason): log_err("Attempt %d/%d failed: %s" % (f.attempts, max_attempts, reason)) if f.attempts < max_attempts: log_info("trying again in 1.5 secs") reactor.callLater(1.5, connector.connect) f.attempts += 1