update gitignore and reformat files with black #13

Merged
bmartin5692 merged 2 commits from dev into master 2019-03-12 02:34:08 +01:00
5 changed files with 475 additions and 387 deletions
Showing only changes of commit af3e4ab1ce - Show all commits

View file

@ -52,14 +52,10 @@ def main():
bumper_clients=bumper.bumper_clients_var, bumper_clients=bumper.bumper_clients_var,
) )
conf_server = bumper.ConfServer( conf_server = bumper.ConfServer(
conf_address_443, conf_address_443, usessl=True, helperbot=mqtt_helperbot
usessl=True,
helperbot=mqtt_helperbot,
) )
conf_server_2 = bumper.ConfServer( conf_server_2 = bumper.ConfServer(
conf_address_8007, conf_address_8007, usessl=False, helperbot=mqtt_helperbot
usessl=False,
helperbot=mqtt_helperbot,
) )
# add user # add user
@ -93,7 +89,7 @@ def main():
bumper.revoke_expired_tokens() bumper.revoke_expired_tokens()
disconnected_clients = bumper.get_disconnected_xmpp_clients() disconnected_clients = bumper.get_disconnected_xmpp_clients()
for client in disconnected_clients: for client in disconnected_clients:
xmpp_server.remove_client_byuid(client['userid']) xmpp_server.remove_client_byuid(client["userid"])
except KeyboardInterrupt: except KeyboardInterrupt:
bumper.bumperlog.info("Bumper Exiting - Keyboard Interrupt") bumper.bumperlog.info("Bumper Exiting - Keyboard Interrupt")

View file

@ -23,7 +23,7 @@ server_cert = "./certs/cert.pem"
server_key = "./certs/key.pem" server_key = "./certs/key.pem"
use_auth = False use_auth = False
token_validity_seconds = 3600 #1 hour token_validity_seconds = 3600 # 1 hour
# Logs # Logs
bumperlog = logging.getLogger("bumper") bumperlog = logging.getLogger("bumper")
@ -44,23 +44,26 @@ xmppserverlog = logging.getLogger("xmppserver")
def get_milli_time(timetoconvert): def get_milli_time(timetoconvert):
return int(round(timetoconvert * 1000)) return int(round(timetoconvert * 1000))
def db_file(): def db_file():
if platform.system() == 'Windows': if platform.system() == "Windows":
return os.path.join(os.getenv('APPDATA'), 'bumper.db') return os.path.join(os.getenv("APPDATA"), "bumper.db")
else: else:
return os.path.expanduser('~/.config/bumper.db') return os.path.expanduser("~/.config/bumper.db")
def db_get(): def db_get():
#Will create the database if it doesn't exist # Will create the database if it doesn't exist
db = TinyDB(db_file()) db = TinyDB(db_file())
#Will create the tables if they don't exist # Will create the tables if they don't exist
users_table = db.table('users') users_table = db.table("users")
clients_table = db.table('clients') clients_table = db.table("clients")
bots_table = db.table('bots') bots_table = db.table("bots")
return db return db
class BumperUser(object): class BumperUser(object):
def __init__(self, userid=""): def __init__(self, userid=""):
self.userid = userid self.userid = userid
@ -68,11 +71,8 @@ class BumperUser(object):
self.bots = [] self.bots = []
def asdict(self): def asdict(self):
return { return {"userid": self.userid, "devices": self.devices, "bots": self.bots}
"userid": self.userid,
"devices": self.devices,
"bots": self.bots,
}
def user_add(userid): def user_add(userid):
newuser = BumperUser() newuser = BumperUser()
@ -83,116 +83,139 @@ def user_add(userid):
bumperlog.info("Adding new user with userid: {}".format(newuser.userid)) bumperlog.info("Adding new user with userid: {}".format(newuser.userid))
user_full_upsert(newuser.asdict()) user_full_upsert(newuser.asdict())
def user_get(userid): def user_get(userid):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
return users.get(User.userid == userid) return users.get(User.userid == userid)
def user_by_deviceid(deviceid): def user_by_deviceid(deviceid):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
return users.get(User.devices.any([deviceid])) return users.get(User.devices.any([deviceid]))
def user_full_upsert(user): def user_full_upsert(user):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
users.upsert(user, User.did == user['userid']) users.upsert(user, User.did == user["userid"])
def user_add_device(userid, devid): def user_add_device(userid, devid):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
user = users.get(User.userid == userid) user = users.get(User.userid == userid)
userdevices = list(user['devices']) userdevices = list(user["devices"])
if not devid in userdevices: if not devid in userdevices:
userdevices.append(devid) userdevices.append(devid)
users.upsert({'devices': userdevices}, User.userid == userid) users.upsert({"devices": userdevices}, User.userid == userid)
def user_remove_device(userid, devid): def user_remove_device(userid, devid):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
user = users.get(User.userid == userid) user = users.get(User.userid == userid)
userdevices = list(user['devices']) userdevices = list(user["devices"])
if devid in userdevices: if devid in userdevices:
userdevices.remove(devid) userdevices.remove(devid)
users.upsert({'devices': userdevices}, User.userid == userid) users.upsert({"devices": userdevices}, User.userid == userid)
def user_add_bot(userid, did): def user_add_bot(userid, did):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
user = users.get(User.userid == userid) user = users.get(User.userid == userid)
userbots = list(user['bots']) userbots = list(user["bots"])
if not did in userbots: if not did in userbots:
userbots.append(did) userbots.append(did)
users.upsert({'bots': userbots}, User.userid == userid) users.upsert({"bots": userbots}, User.userid == userid)
def user_remove_bot(userid, did): def user_remove_bot(userid, did):
users = db_get().table('users') users = db_get().table("users")
User = Query() User = Query()
user = users.get(User.userid == userid) user = users.get(User.userid == userid)
userbots = list(user['bots']) userbots = list(user["bots"])
if did in userbots: if did in userbots:
userbots.remove(did) userbots.remove(did)
users.upsert({'bots': userbots}, User.userid == userid) users.upsert({"bots": userbots}, User.userid == userid)
def user_get_tokens(userid): def user_get_tokens(userid):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
return tokens.search((Query().userid == userid)) return tokens.search((Query().userid == userid))
def user_get_token(userid, token): def user_get_token(userid, token):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
return tokens.get((Query().userid == userid) & (Query().token == token)) return tokens.get((Query().userid == userid) & (Query().token == token))
def user_add_token(userid, token): def user_add_token(userid, token):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token)) tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if not tmptoken: if not tmptoken:
tokens.insert({'userid':userid, 'token':token, 'expiration':"{}".format(datetime.now() + timedelta(seconds=token_validity_seconds))}) tokens.insert(
{
"userid": userid,
"token": token,
"expiration": "{}".format(
datetime.now() + timedelta(seconds=token_validity_seconds)
),
}
)
def user_revoke_all_tokens(userid): def user_revoke_all_tokens(userid):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tsearch = tokens.search(Query().userid == userid) tsearch = tokens.search(Query().userid == userid)
for i in tsearch: for i in tsearch:
tokens.remove(doc_ids=[i.doc_id]) tokens.remove(doc_ids=[i.doc_id])
def user_revoke_expired_tokens(userid): def user_revoke_expired_tokens(userid):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tsearch = tokens.search(Query().userid == userid) tsearch = tokens.search(Query().userid == userid)
for i in tsearch: for i in tsearch:
if datetime.now() >= datetime.fromisoformat(i['expiration']): if datetime.now() >= datetime.fromisoformat(i["expiration"]):
bumperlog.debug("Removing token {} due to expiration".format(i['token'])) bumperlog.debug("Removing token {} due to expiration".format(i["token"]))
tokens.remove(doc_ids=[i.doc_id]) tokens.remove(doc_ids=[i.doc_id])
def user_revoke_token(userid, token): def user_revoke_token(userid, token):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token)) tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if tmptoken: if tmptoken:
tokens.remove(doc_ids=[tmptoken.doc_id]) tokens.remove(doc_ids=[tmptoken.doc_id])
def user_add_authcode(userid, token, authcode): def user_add_authcode(userid, token, authcode):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token)) tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if tmptoken: if tmptoken:
tokens.upsert({'authcode': authcode}, ((Query().userid == userid) & (Query().token == token))) tokens.upsert(
{"authcode": authcode},
((Query().userid == userid) & (Query().token == token)),
)
def user_revoke_authcode(userid, token, authcode): def user_revoke_authcode(userid, token, authcode):
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token)) tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if tmptoken: if tmptoken:
tokens.upsert({'authcode': ''}, ((Query().userid == userid) & (Query().token == token))) tokens.upsert(
{"authcode": ""}, ((Query().userid == userid) & (Query().token == token))
)
class VacBotDevice(object): class VacBotDevice(object):
def __init__( def __init__(
self, self, did="", vac_bot_device_class="", resource="", name="", nick="", company=""
did="",
vac_bot_device_class="",
resource="",
name="",
nick="",
company="",
): ):
self.vac_bot_device_class = vac_bot_device_class self.vac_bot_device_class = vac_bot_device_class
self.company = company self.company = company
@ -212,7 +235,7 @@ class VacBotDevice(object):
"nick": self.nick, "nick": self.nick,
"resource": self.resource, "resource": self.resource,
"mqtt_connection": self.mqtt_connection, "mqtt_connection": self.mqtt_connection,
"xmpp_connection": self.xmpp_connection "xmpp_connection": self.xmpp_connection,
} }
@ -230,45 +253,54 @@ class VacBotClient(object):
"realm": self.realm, "realm": self.realm,
"resource": self.resource, "resource": self.resource,
"mqtt_connection": self.mqtt_connection, "mqtt_connection": self.mqtt_connection,
"xmpp_connection": self.xmpp_connection "xmpp_connection": self.xmpp_connection,
} }
def get_disconnected_xmpp_clients(): def get_disconnected_xmpp_clients():
clients = db_get().table('clients') clients = db_get().table("clients")
Client = Query() Client = Query()
return clients.search(Client.xmpp_connection == False) return clients.search(Client.xmpp_connection == False)
def check_authcode(uid, authcode): def check_authcode(uid, authcode):
bumperlog.debug("Checking for authcode: {}".format(authcode)) bumperlog.debug("Checking for authcode: {}".format(authcode))
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tmpauth = tokens.get( tmpauth = tokens.get(
(Query().authcode == authcode) & #Match authcode (Query().authcode == authcode)
((Query().userid == uid.replace("fuid_","")) | (Query().userid == "fuid_{}".format(uid))) #Userid with or without fuid_ & ( # Match authcode
(Query().userid == uid.replace("fuid_", ""))
| (Query().userid == "fuid_{}".format(uid))
) # Userid with or without fuid_
) )
if tmpauth: if tmpauth:
return True return True
return False return False
def check_token(uid, token): def check_token(uid, token):
bumperlog.debug("Checking for token: {}".format(token)) bumperlog.debug("Checking for token: {}".format(token))
tokens = db_get().table('tokens') tokens = db_get().table("tokens")
tmpauth = tokens.get( tmpauth = tokens.get(
(Query().token == token) & #Match token (Query().token == token)
((Query().userid == uid.replace("fuid_","")) | (Query().userid == "fuid_{}".format(uid))) #Userid with or without fuid_ & ( # Match token
(Query().userid == uid.replace("fuid_", ""))
| (Query().userid == "fuid_{}".format(uid))
) # Userid with or without fuid_
) )
if tmpauth: if tmpauth:
return True return True
return False return False
def revoke_expired_tokens(): def revoke_expired_tokens():
tokens = db_get().table('tokens').all() tokens = db_get().table("tokens").all()
for i in tokens: for i in tokens:
if datetime.now() >= datetime.fromisoformat(i['expiration']): if datetime.now() >= datetime.fromisoformat(i["expiration"]):
bumperlog.debug("Removing token {} due to expiration".format(i['token'])) bumperlog.debug("Removing token {} due to expiration".format(i["token"]))
db_get().table('tokens').remove(doc_ids=[i.doc_id]) db_get().table("tokens").remove(doc_ids=[i.doc_id])
def bot_add(sn, did, devclass, resource, company): def bot_add(sn, did, devclass, resource, company):
@ -281,38 +313,47 @@ def bot_add(sn, did, devclass, resource, company):
bot = bot_get(did) bot = bot_get(did)
if not bot: if not bot:
bumperlog.info("Adding new bot with SN: {} DID: {}".format(newbot.name, newbot.did)) bumperlog.info(
"Adding new bot with SN: {} DID: {}".format(newbot.name, newbot.did)
)
bot_full_upsert(newbot.asdict()) bot_full_upsert(newbot.asdict())
def bot_remove(did): def bot_remove(did):
bots = db_get().table('bots') bots = db_get().table("bots")
bot = bot_get(did) bot = bot_get(did)
bots.remove(doc_ids=[bot.doc_id]) bots.remove(doc_ids=[bot.doc_id])
def bot_get(did): def bot_get(did):
bots = db_get().table('bots') bots = db_get().table("bots")
Bot = Query() Bot = Query()
return bots.get(Bot.did == did) return bots.get(Bot.did == did)
def bot_full_upsert(vacbot): def bot_full_upsert(vacbot):
bots = db_get().table('bots') bots = db_get().table("bots")
Bot = Query() Bot = Query()
bots.upsert(vacbot, Bot.did == vacbot['did']) bots.upsert(vacbot, Bot.did == vacbot["did"])
def bot_set_nick(did, nick): def bot_set_nick(did, nick):
bots = db_get().table('bots') bots = db_get().table("bots")
Bot = Query() Bot = Query()
bots.upsert({'nick': nick}, Bot.did == did) bots.upsert({"nick": nick}, Bot.did == did)
def bot_set_mqtt(did, mqtt): def bot_set_mqtt(did, mqtt):
bots = db_get().table('bots') bots = db_get().table("bots")
Bot = Query() Bot = Query()
bots.upsert({'mqtt_connection': mqtt}, Bot.did == did) bots.upsert({"mqtt_connection": mqtt}, Bot.did == did)
def bot_set_xmpp(did, xmpp): def bot_set_xmpp(did, xmpp):
bots = db_get().table('bots') bots = db_get().table("bots")
Bot = Query() Bot = Query()
bots.upsert({'xmpp_connection': xmpp}, Bot.did == did) bots.upsert({"xmpp_connection": xmpp}, Bot.did == did)
def client_add(userid, realm, resource): def client_add(userid, realm, resource):
newclient = VacBotClient() newclient = VacBotClient()
@ -325,25 +366,30 @@ def client_add(userid, realm, resource):
bumperlog.info("Adding new client with resource {}".format(newclient.resource)) bumperlog.info("Adding new client with resource {}".format(newclient.resource))
client_full_upsert(newclient.asdict()) client_full_upsert(newclient.asdict())
def client_get(resource): def client_get(resource):
clients = db_get().table('clients') clients = db_get().table("clients")
Client = Query() Client = Query()
return clients.get(Client.resource == resource) return clients.get(Client.resource == resource)
def client_full_upsert(client): def client_full_upsert(client):
clients = db_get().table('clients') clients = db_get().table("clients")
Client = Query() Client = Query()
clients.upsert(client, Client.resource == client['resource']) clients.upsert(client, Client.resource == client["resource"])
def client_set_mqtt(resource, mqtt): def client_set_mqtt(resource, mqtt):
clients = db_get().table('clients') clients = db_get().table("clients")
Client = Query() Client = Query()
clients.upsert({'mqtt_connection': mqtt}, Client.resource == resource) clients.upsert({"mqtt_connection": mqtt}, Client.resource == resource)
def client_set_xmpp(resource, xmpp): def client_set_xmpp(resource, xmpp):
clients = db_get().table('clients') clients = db_get().table("clients")
Client = Query() Client = Query()
clients.upsert({'xmpp_connection': xmpp}, Client.resource == resource) clients.upsert({"xmpp_connection": xmpp}, Client.resource == resource)
RETURN_API_SUCCESS = "0000" RETURN_API_SUCCESS = "0000"
ERR_ACTIVATE_TOKEN_TIMEOUT = "1006" ERR_ACTIVATE_TOKEN_TIMEOUT = "1006"

View file

@ -37,13 +37,7 @@ logging.getLogger("aiohttp.access").addFilter(aiohttp_filter())
class ConfServer: class ConfServer:
def __init__(self, address, usessl=False, helperbot=None):
def __init__(
self,
address,
usessl=False,
helperbot=None,
):
self.helperbot = helperbot self.helperbot = helperbot
self.usessl = usessl self.usessl = usessl
self.address = address self.address = address
@ -166,7 +160,7 @@ class ConfServer:
async def handle_base(self, request): async def handle_base(self, request):
try: try:
#TODO - API Options here for viewing clients, tokens, restarting the server, etc. # TODO - API Options here for viewing clients, tokens, restarting the server, etc.
text = "Bumper!" text = "Bumper!"
return web.json_response(text) return web.json_response(text)
@ -187,19 +181,23 @@ class ConfServer:
): # Performing basic "auth" using devid, super insecure ): # Performing basic "auth" using devid, super insecure
user = bumper.user_by_deviceid(user_devid) user = bumper.user_by_deviceid(user_devid)
if "checkLogin" in request.path: if "checkLogin" in request.path:
self.check_token(countrycode, user, request.query["accessToken"]) self.check_token(
countrycode, user, request.query["accessToken"]
)
else: else:
#Deactivate old tokens and authcodes # Deactivate old tokens and authcodes
bumper.user_revoke_expired_tokens(user['userid']) bumper.user_revoke_expired_tokens(user["userid"])
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
"accessToken": self.generate_token(user), # generate a new token "accessToken": self.generate_token(
user
), # generate a new token
"country": countrycode, "country": countrycode,
"email": "null@null.com", "email": "null@null.com",
"uid": "fuid_{}".format(user['userid']), "uid": "fuid_{}".format(user["userid"]),
"username": "fusername_{}".format(user['userid']), "username": "fusername_{}".format(user["userid"]),
}, },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()), "time": bumper.get_milli_time(time.time()),
@ -223,21 +221,16 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
def check_token(self, countrycode, user, token): def check_token(self, countrycode, user, token):
if ( if bumper.check_token(user["userid"], token):
bumper.check_token(user['userid'], token)
):
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
"accessToken": token, "accessToken": token,
"country": countrycode, "country": countrycode,
"email": "null@null.com", "email": "null@null.com",
"uid": "fuid_{}".format(user['userid']), "uid": "fuid_{}".format(user["userid"]),
"username": "fusername_{}".format( "username": "fusername_{}".format(user["userid"]),
user['userid']
),
}, },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()), "time": bumper.get_milli_time(time.time()),
@ -255,41 +248,42 @@ class ConfServer:
def generate_token(self, user): def generate_token(self, user):
tmpaccesstoken = uuid.uuid4().hex tmpaccesstoken = uuid.uuid4().hex
bumper.user_add_token(user['userid'],tmpaccesstoken) bumper.user_add_token(user["userid"], tmpaccesstoken)
return tmpaccesstoken return tmpaccesstoken
def generate_authcode(self, user, countrycode, token): def generate_authcode(self, user, countrycode, token):
tmpauthcode = "{}_{}".format(countrycode, uuid.uuid4().hex) tmpauthcode = "{}_{}".format(countrycode, uuid.uuid4().hex)
bumper.user_add_authcode(user['userid'], token, tmpauthcode) bumper.user_add_authcode(user["userid"], token, tmpauthcode)
return tmpauthcode return tmpauthcode
def _auth_any(self, devid, country, request): def _auth_any(self, devid, country, request):
try: try:
user_devid = devid user_devid = devid
countrycode = country countrycode = country
user = bumper.user_by_deviceid(user_devid) user = bumper.user_by_deviceid(user_devid)
bots = bumper.db_get().table('bots').all() bots = bumper.db_get().table("bots").all()
if user: #Default to user 0 if user: # Default to user 0
tmpuser = user tmpuser = user
bumper.user_add_device(tmpuser['userid'], user_devid) bumper.user_add_device(tmpuser["userid"], user_devid)
else: else:
bumper.user_add("tmpuser") #Add a new user bumper.user_add("tmpuser") # Add a new user
tmpuser = bumper.user_get("tmpuser") tmpuser = bumper.user_get("tmpuser")
bumper.user_add_device(tmpuser['userid'], user_devid) bumper.user_add_device(tmpuser["userid"], user_devid)
for bot in bots: #Add all bots to the user for bot in bots: # Add all bots to the user
bumper.user_add_bot(tmpuser['userid'], bot['did']) bumper.user_add_bot(tmpuser["userid"], bot["did"])
if "checkLogin" in request.path: #If request was to check a token do so if "checkLogin" in request.path: # If request was to check a token do so
checkToken = self.check_token(countrycode, user, request.query["accessToken"]) checkToken = self.check_token(
countrycode, user, request.query["accessToken"]
)
isGood = json.loads(checkToken.text) isGood = json.loads(checkToken.text)
if isGood['code'] == "0000": if isGood["code"] == "0000":
return isGood return isGood
#Deactivate old tokens and authcodes # Deactivate old tokens and authcodes
bumper.user_revoke_expired_tokens(tmpuser['userid']) bumper.user_revoke_expired_tokens(tmpuser["userid"])
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -297,8 +291,8 @@ class ConfServer:
"accessToken": self.generate_token(tmpuser), # Generate a token "accessToken": self.generate_token(tmpuser), # Generate a token
"country": countrycode, "country": countrycode,
"email": "null@null.com", "email": "null@null.com",
"uid": "fuid_{}".format(tmpuser['userid']), "uid": "fuid_{}".format(tmpuser["userid"]),
"username": "fusername_{}".format(tmpuser['userid']), "username": "fusername_{}".format(tmpuser["userid"]),
}, },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()), "time": bumper.get_milli_time(time.time()),
@ -315,11 +309,11 @@ class ConfServer:
if not user_devid == "": if not user_devid == "":
user = bumper.user_by_deviceid(user_devid) user = bumper.user_by_deviceid(user_devid)
if user: if user:
if ( if bumper.check_token(user["userid"], request.query["accessToken"]):
bumper.check_token(user['userid'], request.query["accessToken"]) # Deactivate old tokens and authcodes
): bumper.user_revoke_token(
#Deactivate old tokens and authcodes user["userid"], request.query["accessToken"]
bumper.user_revoke_token(user['userid'], request.query["accessToken"]) )
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -340,13 +334,19 @@ class ConfServer:
if not user_devid == "": if not user_devid == "":
user = bumper.user_by_deviceid(user_devid) user = bumper.user_by_deviceid(user_devid)
if user: if user:
token = bumper.user_get_token(user['userid'], request.query["accessToken"]) token = bumper.user_get_token(
user["userid"], request.query["accessToken"]
)
if token: if token:
authcode = "" authcode = ""
if not 'authcode' in token: if not "authcode" in token:
authcode = self.generate_authcode(user, request.match_info.get("country", "us"), request.query["accessToken"]) authcode = self.generate_authcode(
user,
request.match_info.get("country", "us"),
request.query["accessToken"],
)
else: else:
authcode = token['authcode'] authcode = token["authcode"]
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -534,9 +534,7 @@ class ConfServer:
body = {"result": "ok", "ip": "47.88.66.164", "port": 8005} body = {"result": "ok", "ip": "47.88.66.164", "port": 8005}
elif todo == "loginByItToken": elif todo == "loginByItToken":
if ( if bumper.check_authcode(postbody["userId"], postbody["token"]):
bumper.check_authcode(postbody["userId"], postbody["token"])
):
body = { body = {
"resource": postbody["resource"], "resource": postbody["resource"],
"result": "ok", "result": "ok",
@ -546,13 +544,16 @@ class ConfServer:
} }
elif todo == "GetDeviceList": elif todo == "GetDeviceList":
body = {"devices": bumper.db_get().table('bots').all(), "result": "ok", "todo": "result"} body = {
"devices": bumper.db_get().table("bots").all(),
"result": "ok",
"todo": "result",
}
elif todo == "SetDeviceNick": elif todo == "SetDeviceNick":
bumper.bot_set_nick(postbody["did"], postbody["nick"]) bumper.bot_set_nick(postbody["did"], postbody["nick"])
body = {"result": "ok", "todo": "result"} body = {"result": "ok", "todo": "result"}
elif todo == "AddOneDevice": elif todo == "AddOneDevice":
bumper.bot_set_nick(postbody["did"], postbody["nick"]) bumper.bot_set_nick(postbody["did"], postbody["nick"])
body = {"result": "ok", "todo": "result"} body = {"result": "ok", "todo": "result"}
@ -570,7 +571,6 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_lookup(self, request): async def handle_lookup(self, request):
try: try:
@ -590,9 +590,11 @@ class ConfServer:
if service == "EcoMsgNew": if service == "EcoMsgNew":
srvip = socket.gethostbyname(socket.gethostname()) srvip = socket.gethostbyname(socket.gethostname())
msgserver = {"ip":srvip,"port":5223,"result":"ok"} msgserver = {"ip": srvip, "port": 5223, "result": "ok"}
msgserver = json.dumps(msgserver) msgserver = json.dumps(msgserver)
msgserver = msgserver.replace(" ","") #bot seems to be very picky about having no spaces, only way was with text msgserver = msgserver.replace(
" ", ""
) # bot seems to be very picky about having no spaces, only way was with text
confserverlog.debug( confserverlog.debug(
"\r\n POST: {} \r\n Response: {}".format(postbody, msgserver) "\r\n POST: {} \r\n Response: {}".format(postbody, msgserver)
@ -615,9 +617,9 @@ class ConfServer:
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
randomid = "".join(random.sample(string.ascii_letters, 6)) randomid = "".join(random.sample(string.ascii_letters, 6))
if "toId" in json_body: #Its a command if "toId" in json_body: # Its a command
bot = bumper.bot_get(json_body["toId"]) bot = bumper.bot_get(json_body["toId"])
if bot['company'] == 'eco-ng' and bot['mqtt_connection'] == True: if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
retcmd = await self.helperbot.send_command(json_body, randomid) retcmd = await self.helperbot.send_command(json_body, randomid)
body = retcmd body = retcmd
confserverlog.debug( confserverlog.debug(
@ -625,7 +627,7 @@ class ConfServer:
) )
return web.json_response(body) return web.json_response(body)
else: else:
#No response, send error back # No response, send error back
confserverlog.error( confserverlog.error(
"No bots with DID: {} connected to MQTT".format( "No bots with DID: {} connected to MQTT".format(
json_body["toId"] json_body["toId"]
@ -634,11 +636,9 @@ class ConfServer:
body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"} body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
return web.json_response(body) return web.json_response(body)
else: else:
if "td" in json_body: #Seen when doing initial wifi config if "td" in json_body: # Seen when doing initial wifi config
if json_body["td"] == "PollSCResult": if json_body["td"] == "PollSCResult":
body = { body = {"ret": "ok"}
"ret": "ok"
}
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:

View file

@ -333,7 +333,11 @@ class BumperMQTTServer_Plugin:
): ):
tmpbotdetail = str(didsplit[1]).split("/") tmpbotdetail = str(didsplit[1]).split("/")
bumper.bot_add( bumper.bot_add(
username, didsplit[0], tmpbotdetail[0], tmpbotdetail[1], "eco-ng" username,
didsplit[0],
tmpbotdetail[0],
tmpbotdetail[1],
"eco-ng",
) )
mqttserverlog.debug( mqttserverlog.debug(
"new bot authenticated SN: {} DID: {}".format( "new bot authenticated SN: {} DID: {}".format(
@ -379,14 +383,14 @@ class BumperMQTTServer_Plugin:
bot = bumper.bot_get(didsplit[0]) bot = bumper.bot_get(didsplit[0])
if bot: if bot:
bumper.bot_set_mqtt(bot['did'], True) bumper.bot_set_mqtt(bot["did"], True)
return return
clientuserid = didsplit[0] clientuserid = didsplit[0]
clientresource = didsplit[1].split("/")[1] clientresource = didsplit[1].split("/")[1]
client = bumper.client_get(clientresource) client = bumper.client_get(clientresource)
if client: if client:
bumper.client_set_mqtt(client['resource'], True) bumper.client_set_mqtt(client["resource"], True)
return return
except Exception as e: except Exception as e:
@ -398,13 +402,13 @@ class BumperMQTTServer_Plugin:
bot = bumper.bot_get(didsplit[0]) bot = bumper.bot_get(didsplit[0])
if bot: if bot:
bumper.bot_set_mqtt(bot['did'], False) bumper.bot_set_mqtt(bot["did"], False)
clientuserid = didsplit[0] clientuserid = didsplit[0]
clientresource = didsplit[1].split("/")[1] clientresource = didsplit[1].split("/")[1]
client = bumper.client_get(clientresource) client = bumper.client_get(clientresource)
if client: if client:
bumper.client_set_mqtt(client['resource'], False) bumper.client_set_mqtt(client["resource"], False)
except Exception as e: except Exception as e:
mqttserverlog.exception("{}".format(e)) mqttserverlog.exception("{}".format(e))

View file

@ -217,7 +217,7 @@ class Client(threading.Thread):
except BrokenPipeError as e: except BrokenPipeError as e:
xmppserverlog.error("{}".format(e)) xmppserverlog.error("{}".format(e))
self._set_state('DISCONNECT') self._set_state("DISCONNECT")
except ConnectionResetError as e: except ConnectionResetError as e:
xmppserverlog.error("{}".format(e)) xmppserverlog.error("{}".format(e))
@ -231,11 +231,11 @@ class Client(threading.Thread):
bot = bumper.bot_get(self.uid) bot = bumper.bot_get(self.uid)
if bot: if bot:
bumper.bot_set_xmpp(bot['did'], False) bumper.bot_set_xmpp(bot["did"], False)
client = bumper.client_get(self.clientresource) client = bumper.client_get(self.clientresource)
if client: if client:
bumper.client_set_xmpp(client['resource'], False) bumper.client_set_xmpp(client["resource"], False)
self.connection.close() self.connection.close()
@ -285,8 +285,7 @@ class Client(threading.Thread):
if xml.get("type") == "set": if xml.get("type") == "set":
if ( if (
"com:sf" in data "com:sf" in data and xml.get("to") == "rl.ecorobot.net"
and xml.get("to") == "rl.ecorobot.net"
): # Android bind? Not sure what this does yet. ): # Android bind? Not sure what this does yet.
self.send( self.send(
'<iq id="{}" to="{}@{}/{}" from="rl.ecorobot.net" type="result"/>'.format( '<iq id="{}" to="{}@{}/{}" from="rl.ecorobot.net" type="result"/>'.format(
@ -308,33 +307,37 @@ class Client(threading.Thread):
# forward # forward
for client in XMPPServer.clients: for client in XMPPServer.clients:
if client.bumper_jid != self.bumper_jid and client.state == client.READY: if (
client.bumper_jid != self.bumper_jid
and client.state == client.READY
):
ctl_to = xml.get("to") ctl_to = xml.get("to")
xml.attrib["from"] = "{}".format(self.bumper_jid) xml.attrib["from"] = "{}".format(self.bumper_jid)
rxmlstring = ET.tostring(xml).decode("utf-8") rxmlstring = ET.tostring(xml).decode("utf-8")
#clean up string to remove namespaces added by ET # clean up string to remove namespaces added by ET
rxmlstring = rxmlstring.replace("xmlns:ns0=", "xmlns=") rxmlstring = rxmlstring.replace("xmlns:ns0=", "xmlns=")
rxmlstring = rxmlstring.replace("ns0:", "") rxmlstring = rxmlstring.replace("ns0:", "")
rxmlstring = rxmlstring.replace('iq xmlns="com:ctl"', "iq") rxmlstring = rxmlstring.replace('iq xmlns="com:ctl"', "iq")
rxmlstring = rxmlstring.replace('<query','<query xmlns="com:ctl"') rxmlstring = rxmlstring.replace("<query", '<query xmlns="com:ctl"')
if client.type == self.BOT: if client.type == self.BOT:
if client.uid.lower() in ctl_to.lower(): if client.uid.lower() in ctl_to.lower():
xmppserverlog.info("Sending ctl to bot: {}".format(rxmlstring)) xmppserverlog.info(
"Sending ctl to bot: {}".format(rxmlstring)
)
client.send(rxmlstring) client.send(rxmlstring)
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
def _handle_ping(self, xml, data): def _handle_ping(self, xml, data):
try: try:
if xml.get("to").find("@") == -1: #No to address if xml.get("to").find("@") == -1: # No to address
# Ping to server - respond # Ping to server - respond
pingresp = '<iq type="result" id="{}" from="{}" />'.format( pingresp = '<iq type="result" id="{}" from="{}" />'.format(
xml.get("id"), xml.get("to") xml.get("id"), xml.get("to")
) )
#xmppserverlog.debug("Server Ping resp: {}".format(pingresp)) # xmppserverlog.debug("Server Ping resp: {}".format(pingresp))
self.send(pingresp) self.send(pingresp)
else: else:
@ -343,19 +346,24 @@ class Client(threading.Thread):
xml.attrib["from"] = pingfrom xml.attrib["from"] = pingfrom
pingstring = ET.tostring(xml).decode("utf-8") pingstring = ET.tostring(xml).decode("utf-8")
#clean up string to remove namespaces added by ET # clean up string to remove namespaces added by ET
pingstring = pingstring.replace("xmlns:ns0=", "xmlns=") pingstring = pingstring.replace("xmlns:ns0=", "xmlns=")
pingstring = pingstring.replace("ns0:", "") pingstring = pingstring.replace("ns0:", "")
pingstring = pingstring.replace('iq xmlns="com:ctl"', "iq") pingstring = pingstring.replace('iq xmlns="com:ctl"', "iq")
pingstring = pingstring.replace('<query','<query xmlns="com:ctl"') pingstring = pingstring.replace("<query", '<query xmlns="com:ctl"')
for client in XMPPServer.clients: for client in XMPPServer.clients:
if client.bumper_jid != self.bumper_jid and client.state == client.READY: if (
client.bumper_jid != self.bumper_jid
and client.state == client.READY
):
if pingto.lower() in client.bumper_jid.lower(): if pingto.lower() in client.bumper_jid.lower():
pingsend = '<iq type="result" id="{}" from="{}" to="{}" />'.format( pingsend = '<iq type="result" id="{}" from="{}" to="{}" />'.format(
xml.get("id"), pingfrom, pingto xml.get("id"), pingfrom, pingto
) )
xmppserverlog.debug("ping from {} to {}".format(pingfrom, pingto)) xmppserverlog.debug(
"ping from {} to {}".format(pingfrom, pingto)
)
client.send(pingstring) client.send(pingstring)
except Exception as e: except Exception as e:
@ -365,61 +373,81 @@ class Client(threading.Thread):
try: try:
ctl_to = xml.get("to") ctl_to = xml.get("to")
xml.attrib["from"] = self.bumper_jid xml.attrib["from"] = self.bumper_jid
if "errno='103' error='permission denied," in data: #No permissions, usually if bot was last on Ecovac network if (
"errno='103' error='permission denied," in data
): # No permissions, usually if bot was last on Ecovac network
if self.type == self.BOT: if self.type == self.BOT:
xquery = xml.getchildren() xquery = xml.getchildren()
ctl = xquery[0].getchildren() ctl = xquery[0].getchildren()
ctlerr = ctl[0].attrib["error"] ctlerr = ctl[0].attrib["error"]
adminuser = ctlerr.replace("permission denied, please contact ","") adminuser = ctlerr.replace("permission denied, please contact ", "")
adminuser = adminuser.replace(" ","") adminuser = adminuser.replace(" ", "")
if not (adminuser.startswith("fuid_") or bumper.use_auth): #if not fuid_ then its ecovacs OR ignore bumper auth if not (
#TODO: Implement auth later, should this user have access to bot? adminuser.startswith("fuid_") or bumper.use_auth
): # if not fuid_ then its ecovacs OR ignore bumper auth
# TODO: Implement auth later, should this user have access to bot?
#Add user jid to bot # Add user jid to bot
newuser = ctl_to.split("/")[0] newuser = ctl_to.split("/")[0]
adduser = '<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="AddUser" id="0000" jid="{}" /></query></iq>'.format( adduser = '<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="AddUser" id="0000" jid="{}" /></query></iq>'.format(
uuid.uuid4(), adminuser, self.bumper_jid, newuser) uuid.uuid4(), adminuser, self.bumper_jid, newuser
)
xmppserverlog.debug("Add User: {}".format(adduser)) xmppserverlog.debug("Add User: {}".format(adduser))
self.send(adduser) self.send(adduser)
#Add user ACs - Manage users, settings, and clean (full access) # Add user ACs - Manage users, settings, and clean (full access)
adduseracs = '<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="SetAC" id="1111" jid="{}"><acs><ac name="userman" allow="1"/><ac name="setting" allow="1"/><ac name="clean" allow="1"/></acs></ctl></query></iq>'.format( adduseracs = '<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="SetAC" id="1111" jid="{}"><acs><ac name="userman" allow="1"/><ac name="setting" allow="1"/><ac name="clean" allow="1"/></acs></ctl></query></iq>'.format(
uuid.uuid4(), adminuser, self.bumper_jid, newuser) uuid.uuid4(), adminuser, self.bumper_jid, newuser
)
xmppserverlog.debug("Add User ACs: {}".format(adduseracs)) xmppserverlog.debug("Add User ACs: {}".format(adduseracs))
self.send(adduseracs) self.send(adduseracs)
#GetUserInfo - Just to confirm it set correctly # GetUserInfo - Just to confirm it set correctly
self.send( self.send(
'<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="GetUserInfo" id="4444" /><UserInfos/></query></iq>'.format( '<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="GetUserInfo" id="4444" /><UserInfos/></query></iq>'.format(
uuid.uuid4(), adminuser, self.bumper_jid) uuid.uuid4(), adminuser, self.bumper_jid
)
) )
else: else:
rxmlstring = ET.tostring(xml).decode("utf-8") rxmlstring = ET.tostring(xml).decode("utf-8")
#clean up string to remove namespaces added by ET # clean up string to remove namespaces added by ET
rxmlstring = rxmlstring.replace("xmlns:ns0=", "xmlns=") rxmlstring = rxmlstring.replace("xmlns:ns0=", "xmlns=")
rxmlstring = rxmlstring.replace("ns0:", "") rxmlstring = rxmlstring.replace("ns0:", "")
rxmlstring = rxmlstring.replace('iq xmlns="com:ctl"', "iq") rxmlstring = rxmlstring.replace('iq xmlns="com:ctl"', "iq")
rxmlstring = rxmlstring.replace('<query','<query xmlns="com:ctl"') rxmlstring = rxmlstring.replace("<query", '<query xmlns="com:ctl"')
if self.type == self.BOT: if self.type == self.BOT:
if ctl_to == "de.ecorobot.net": #Send to all clients if ctl_to == "de.ecorobot.net": # Send to all clients
xmppserverlog.debug("Sending to all clients because of de: {}".format(rxmlstring)) xmppserverlog.debug(
"Sending to all clients because of de: {}".format(
rxmlstring
)
)
for client in XMPPServer.clients: for client in XMPPServer.clients:
client.send(rxmlstring) client.send(rxmlstring)
if xml.get("to").find("@") == -1: #No to address if xml.get("to").find("@") == -1: # No to address
ctl_to = xml.get("to") ctl_to = xml.get("to")
else: else:
ctl_to = "{}@ecouser.net".format(ctl_to.split("@")[0]) ctl_to = "{}@ecouser.net".format(ctl_to.split("@")[0])
for client in XMPPServer.clients: for client in XMPPServer.clients:
if client.bumper_jid != self.bumper_jid and client.state == client.READY: if (
if not "@" in ctl_to: #No user@, send to all clients? client.bumper_jid != self.bumper_jid
#TODO: Revisit later, this may be wrong and client.state == client.READY
):
if not "@" in ctl_to: # No user@, send to all clients?
# TODO: Revisit later, this may be wrong
client.send(rxmlstring) client.send(rxmlstring)
elif client.uid.lower() in ctl_to.lower(): #If client matches TO= elif (
xmppserverlog.debug("Sending from {} to client {}: {}".format(self.uid, client.uid, rxmlstring)) client.uid.lower() in ctl_to.lower()
): # If client matches TO=
xmppserverlog.debug(
"Sending from {} to client {}: {}".format(
self.uid, client.uid, rxmlstring
)
)
client.send(rxmlstring) client.send(rxmlstring)
except Exception as e: except Exception as e:
@ -435,7 +463,7 @@ class Client(threading.Thread):
sc = data.decode("utf-8").find("to=") sc = data.decode("utf-8").find("to=")
ec = data.decode("utf-8").find(".ecorobot.net") ec = data.decode("utf-8").find(".ecorobot.net")
if ec > -1: if ec > -1:
self.devclass = data.decode("utf-8")[sc+4:ec] self.devclass = data.decode("utf-8")[sc + 4 : ec]
# ack jabbr:client # ack jabbr:client
# no STARTTLS # no STARTTLS
self.send( self.send(
@ -456,9 +484,11 @@ class Client(threading.Thread):
self.send("</stream>") self.send("</stream>")
else: else:
if "jabber:iq:auth" in xml.tag: # Handle iq-auth if "jabber:iq:auth" in xml.tag: # Handle iq-auth
self._handle_iq_auth(xml) self._handle_iq_auth(xml)
elif "urn:ietf:params:xml:ns:xmpp-sasl" in xml.tag: #Handle SASL Auth elif (
"urn:ietf:params:xml:ns:xmpp-sasl" in xml.tag
): # Handle SASL Auth
self._handle_sasl_auth(xml) self._handle_sasl_auth(xml)
else: else:
xmppserverlog.error("Couldn't handle: {}".format(xml)) xmppserverlog.error("Couldn't handle: {}".format(xml))
@ -491,8 +521,6 @@ class Client(threading.Thread):
else: else:
xmppserverlog.error("Couldn't handle: {}".format(xml)) xmppserverlog.error("Couldn't handle: {}".format(xml))
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
@ -575,9 +603,7 @@ class Client(threading.Thread):
except ET.ParseError as e: except ET.ParseError as e:
if "no element found" in e.msg: if "no element found" in e.msg:
xmppserverlog.debug( xmppserverlog.debug(
"xml parse error - {} - {}".format( "xml parse error - {} - {}".format(data.decode("utf-8"), e)
data.decode("utf-8"), e
)
) )
elif "not well-formed (invalid token)" in e.msg: elif "not well-formed (invalid token)" in e.msg:
xmppserverlog.debug( xmppserverlog.debug(
@ -610,7 +636,7 @@ class Client(threading.Thread):
if not self.uid.startswith("fuid"): if not self.uid.startswith("fuid"):
# Need sample data to see details here # Need sample data to see details here
bumper.bot_add(self.uid, self.uid, self.devclass, "atom","eco-legacy") bumper.bot_add(self.uid, self.uid, self.devclass, "atom", "eco-legacy")
self.type = self.BOT self.type = self.BOT
xmppserverlog.info("bot authenticated {}".format(self.uid)) xmppserverlog.info("bot authenticated {}".format(self.uid))
# Send response # Send response
@ -657,17 +683,19 @@ class Client(threading.Thread):
bot = bumper.bot_get(self.uid) bot = bumper.bot_get(self.uid)
if bot: if bot:
bumper.bot_set_xmpp(bot['did'], True) bumper.bot_set_xmpp(bot["did"], True)
client = bumper.client_get(self.clientresource) client = bumper.client_get(self.clientresource)
if client: if client:
bumper.client_set_xmpp(client['resource'], True) bumper.client_set_xmpp(client["resource"], True)
clientbindxml = xml.getchildren() clientbindxml = xml.getchildren()
clientresourcexml = clientbindxml[0].getchildren() clientresourcexml = clientbindxml[0].getchildren()
if self.devclass: #its a bot if self.devclass: # its a bot
self.name = "XMPP_Client_{}_{}".format(self.uid,self.devclass) self.name = "XMPP_Client_{}_{}".format(self.uid, self.devclass)
self.bumper_jid = "{}@{}.ecorobot.net/atom".format(self.uid, self.devclass) self.bumper_jid = "{}@{}.ecorobot.net/atom".format(
self.uid, self.devclass
)
xmppserverlog.debug("new bot {}".format(self.uid)) xmppserverlog.debug("new bot {}".format(self.uid))
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format( res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(
xml.get("id"), self.bumper_jid xml.get("id"), self.bumper_jid
@ -675,7 +703,9 @@ class Client(threading.Thread):
elif len(clientresourcexml) > 0: elif len(clientresourcexml) > 0:
self.clientresource = clientresourcexml[0].text self.clientresource = clientresourcexml[0].text
self.name = "XMPP_Client_{}".format(self.clientresource) self.name = "XMPP_Client_{}".format(self.clientresource)
self.bumper_jid = "{}@{}/{}".format(self.uid, XMPPServer.server_id, self.clientresource) self.bumper_jid = "{}@{}/{}".format(
self.uid, XMPPServer.server_id, self.clientresource
)
xmppserverlog.debug( xmppserverlog.debug(
"new client {} using resource {}".format( "new client {} using resource {}".format(
self.uid, self.clientresource self.uid, self.clientresource
@ -685,7 +715,7 @@ class Client(threading.Thread):
xml.get("id"), self.bumper_jid xml.get("id"), self.bumper_jid
) )
else: else:
self.name = "XMPP_Client_{}_{}".format(self.uid,self.address) self.name = "XMPP_Client_{}_{}".format(self.uid, self.address)
self.bumper_jid = "{}@{}".format(self.uid, XMPPServer.server_id) self.bumper_jid = "{}@{}".format(self.uid, XMPPServer.server_id)
xmppserverlog.debug("new client {}".format(self.uid)) xmppserverlog.debug("new client {}".format(self.uid))
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format( res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(
@ -712,20 +742,18 @@ class Client(threading.Thread):
if len(xml) and xml[0].tag == "status": if len(xml) and xml[0].tag == "status":
xmppserverlog.debug( xmppserverlog.debug(
"bot presence {} ".format(ET.tostring(xml, encoding="utf-8")) "bot presence {} ".format(ET.tostring(xml, encoding="utf-8"))
) )
#Most likely a bot, possibly hello world in text # Most likely a bot, possibly hello world in text
#Send dummy return # Send dummy return
self.send( self.send(
'<presence to="{}"> dummy </presence>'.format( '<presence to="{}"> dummy </presence>'.format(self.bumper_jid)
self.bumper_jid
)
) )
#If it is a BOT, send extras # If it is a BOT, send extras
if self.type == self.BOT: if self.type == self.BOT:
#get device info # get device info
self.send( self.send(
'<iq type="set" id="14" to="{}" from="{}"><query xmlns="com:ctl"><ctl td="GetDeviceInfo"/></query></iq>'.format( '<iq type="set" id="14" to="{}" from="{}"><query xmlns="com:ctl"><ctl td="GetDeviceInfo"/></query></iq>'.format(
self.bumper_jid, XMPPServer.server_id self.bumper_jid, XMPPServer.server_id
@ -734,49 +762,55 @@ class Client(threading.Thread):
else: else:
xmppserverlog.debug( xmppserverlog.debug(
"client presence - {} ".format(ET.tostring(xml, encoding="utf-8")) "client presence - {} ".format(ET.tostring(xml, encoding="utf-8"))
) )
if xml.get("type") == "available": if xml.get("type") == "available":
xmppserverlog.debug( xmppserverlog.debug(
"client presence available - {} ".format(ET.tostring(xml, encoding="utf-8")) "client presence available - {} ".format(
) ET.tostring(xml, encoding="utf-8")
#Send dummy return
self.send(
'<presence to="{}"> dummy </presence>'.format(
self.bumper_jid
) )
) )
# Send dummy return
self.send(
'<presence to="{}"> dummy </presence>'.format(self.bumper_jid)
)
elif xml.get("type") == "unavailable": elif xml.get("type") == "unavailable":
xmppserverlog.debug( xmppserverlog.debug(
"client presence unavailable (DISCONNECT) - {} ".format(ET.tostring(xml, encoding="utf-8")) "client presence unavailable (DISCONNECT) - {} ".format(
ET.tostring(xml, encoding="utf-8")
)
) )
self._set_state("DISCONNECT") self._set_state("DISCONNECT")
else: else:
#Sometimes the android app sends these # Sometimes the android app sends these
xmppserverlog.debug( xmppserverlog.debug(
"client presence (UNKNOWN) - {} ".format(ET.tostring(xml, encoding="utf-8")) "client presence (UNKNOWN) - {} ".format(
) ET.tostring(xml, encoding="utf-8")
#Send dummy return
self.send(
'<presence to="{}"> dummy </presence>'.format(
self.bumper_jid
) )
) )
# Send dummy return
self.send(
'<presence to="{}"> dummy </presence>'.format(self.bumper_jid)
)
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
def _parse_data(self, data): def _parse_data(self, data):
if data.decode("utf-8").startswith(
if data.decode("utf-8").startswith("<?xml"): #Strip <?xml and add artificial root "<?xml"
newdata = re.sub(r"(<\?xml[^>]+\?>)", r"<root>",data.decode("utf-8")) + "</root>" ): # Strip <?xml and add artificial root
newdata = (
re.sub(r"(<\?xml[^>]+\?>)", r"<root>", data.decode("utf-8")) + "</root>"
)
else: else:
newdata = "<root>{}</root>".format(data.decode("utf-8")) #Add artificial root newdata = "<root>{}</root>".format(
data.decode("utf-8")
) # Add artificial root
try: try:
root = ET.fromstring(newdata) root = ET.fromstring(newdata)
@ -785,13 +819,20 @@ class Client(threading.Thread):
if item.tag == "iq": if item.tag == "iq":
if self.log_incoming_data: if self.log_incoming_data:
xmppserverlog.debug( xmppserverlog.debug(
"from {} - {}".format(self.address, str(ET.tostring(item, encoding="utf-8").decode("utf-8")).replace("ns0:","")) "from {} - {}".format(
self.address,
str(
ET.tostring(item, encoding="utf-8").decode(
"utf-8"
)
).replace("ns0:", ""),
)
) )
self._handle_iq(item, newdata) self._handle_iq(item, newdata)
item.clear() item.clear()
elif "auth" in item.tag: elif "auth" in item.tag:
if "urn:ietf:params:xml:ns:xmpp-sasl" in item.tag: #SASL Auth if "urn:ietf:params:xml:ns:xmpp-sasl" in item.tag: # SASL Auth
self._handle_sasl_auth(item) self._handle_sasl_auth(item)
item.clear() item.clear()
@ -801,9 +842,15 @@ class Client(threading.Thread):
else: else:
if self.log_incoming_data: if self.log_incoming_data:
xmppserverlog.debug( xmppserverlog.debug(
"Unparsed Item - {}".format(str(ET.tostring(item, encoding="utf-8").decode("utf-8")).replace("ns0:","")) "Unparsed Item - {}".format(
) str(
ET.tostring(item, encoding="utf-8").decode(
"utf-8"
)
).replace("ns0:", "")
)
)
except ET.ParseError as e: except ET.ParseError as e:
if ( if (
@ -822,14 +869,12 @@ class Client(threading.Thread):
elif "not well-formed (invalid token)" in e.msg: elif "not well-formed (invalid token)" in e.msg:
# If a lone </stream:stream> - client is signalling end of session/disconnect # If a lone </stream:stream> - client is signalling end of session/disconnect
if not "</stream:stream>" in newdata: if not "</stream:stream>" in newdata:
xmppserverlog.error( xmppserverlog.error("xml parse error - {} - {}".format(newdata, e))
"xml parse error - {} - {}".format(newdata, e)
)
else: else:
self.send("</stream:stream>") # Close stream self.send("</stream:stream>") # Close stream
else: else:
if "<stream:stream" in newdata: #Handle start stream and connect if "<stream:stream" in newdata: # Handle start stream and connect
if self.state == self.CONNECT or self.state == self.INIT: if self.state == self.CONNECT or self.state == self.INIT:
xmppserverlog.debug( xmppserverlog.debug(
"Handling connect data - {}".format(newdata) "Handling connect data - {}".format(newdata)
@ -838,13 +883,12 @@ class Client(threading.Thread):
else: else:
if not "</stream:stream>" in newdata: if not "</stream:stream>" in newdata:
xmppserverlog.error( xmppserverlog.error(
"xml parse error - {} - {}".format(newdata, e) "xml parse error - {} - {}".format(newdata, e)
) )
else: else:
self.send("</stream:stream>") # Close stream self.send("</stream:stream>") # Close stream
self._set_state("DISCONNECT") self._set_state("DISCONNECT")
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
@ -899,5 +943,3 @@ class Client(threading.Thread):
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))