diff options
author | mrDoctorWho <mrdoctorwho@gmail.com> | 2014-09-13 17:06:08 +0400 |
---|---|---|
committer | mrDoctorWho <mrdoctorwho@gmail.com> | 2014-09-13 17:06:08 +0400 |
commit | aecf1235acc74d50862d15df077da4d5e462c104 (patch) | |
tree | 72001704794ca684de782d949a4f65fa22d5e2c5 | |
parent | b4d079b7a9702f9371c087672c85ce41965dd921 (diff) |
A couple fixes
Details:
* Attachments in forwarded messages is now have spacer just like text
* Fixed zero-id error in groupchats (lol, how many times it was fixed)
* Probably fixed error when user has handled when he was offline (not in Transport dictionary)
* A little code cleanup in captcha_forms.py, mod_iq_register.py and other files
* Extended groupchats debug. There was no jids for whom groupchats were created
* Added priority for ujson usage instead of simplejson (it faster)
* Fixed a little typo in runThread() and also added 3 retries
* Forced "account.setOffline" method call, because it wasn't called at all
* User will be deleted from database if record exists (now i wonder why i did it)
* Fixed socket.timeout in utils.getLinkData (vk, i "love" you!)
* Extended xmpp.DataForms() support in utils.buildDataForm()
* Fixed AttributeError() in mod_xhtml
* A little translations fixes
Well, that's a really huge list for project that not-supported-anymore, but project should NOT have errors when
it development is stopped.
-rw-r--r-- | extensions/attachments.py | 73 | ||||
-rw-r--r-- | extensions/avatar_hash.py | 3 | ||||
-rw-r--r-- | extensions/captcha_forms.py | 4 | ||||
-rw-r--r-- | extensions/forwarded_messages.py | 2 | ||||
-rw-r--r-- | extensions/groupchats.py | 10 | ||||
-rw-r--r-- | extensions/status-to-vk.py | 2 | ||||
-rw-r--r-- | gateway.py | 70 | ||||
-rw-r--r-- | library/utils.py | 69 | ||||
-rw-r--r-- | library/vkapi.py | 4 | ||||
-rw-r--r-- | library/xmpp/protocol.py | 12 | ||||
-rw-r--r-- | locales/locale.ru | 6 | ||||
-rw-r--r-- | modules/mod_iq_disco.py | 11 | ||||
-rw-r--r-- | modules/mod_iq_register.py | 58 | ||||
-rw-r--r-- | modules/mod_msg_main.py | 3 | ||||
-rw-r--r-- | modules/mod_prs_main.py | 2 | ||||
-rw-r--r-- | modules/mod_xhtml.py | 2 |
16 files changed, 183 insertions, 148 deletions
diff --git a/extensions/attachments.py b/extensions/attachments.py index daa17fc..c7fe872 100644 --- a/extensions/attachments.py +++ b/extensions/attachments.py @@ -4,45 +4,58 @@ import urllib -def parseAttachments(self, msg): +VK_AUDIO_SEARCH = "https://vk.com/search?c[q]=%s&c[section]=audio" + +def parseAttachments(self, msg, spacer=""): result = "" if msg.has_key("attachments"): + +## Add new line and "Attachments" if msg["body"]: - result += _("\nAttachments:") - searchlink = "https://vk.com/search?c[q]=%s&c[section]=audio" + result += chr(10) + spacer + _("Attachments:") + chr(10) + attachments = msg["attachments"] - for att in attachments: - body = "" - key = att.get("type") - if key == "wall": - body += "\nWall: https://vk.com/feed?w=wall%(to_id)s_%(id)s" - elif key == "photo": + for num, att in enumerate(attachments): + typ = att.get("type") + body = spacer + if num: + body = chr(10) + spacer + + if typ == "wall": + body += "Wall: https://vk.com/feed?w=wall%(to_id)s_%(id)s" + + elif typ == "photo": keys = ("src_xxxbig", "src_xxbig", "src_xbig", "src_big", "src", "url", "src_small") - for _key in keys: - if _key in att[key]: - body += "\n" + att[key][_key] + for key in keys: + if key in att[typ]: + body += att[typ][key] ## No new line needed if we have just one photo and no text break - elif key == "video": - body += "\nVideo: http://vk.com/video%(owner_id)s_%(vid)s — %(title)s" - elif key == "audio": - for _key in ("performer", "title"): - if att[key].has_key(_key): - att[key][_key] = uHTML(att[key][_key]) - - url = searchlink % urllib.quote(str("%(performer)s %(title)s" % att[key])) - att[key]["url"] = url - body += "\nAudio: %(performer)s — %(title)s — %(url)s" - elif key == "doc": - body += "\nDocument: %(title)s — %(url)s" - elif key == "sticker": + + elif typ == "video": + body += "Video: http://vk.com/video%(owner_id)s_%(vid)s — %(title)s" + + elif typ == "audio": + for key in ("performer", "title"): + if att[typ].has_key(key): + att[typ][key] = uHTML(att[typ][key]) + + url = VK_AUDIO_SEARCH % urllib.quote(str("%(performer)s %(title)s" % att[typ])) + att[typ]["url"] = url + body += "Audio: %(performer)s — %(title)s — %(url)s" + + elif typ == "doc": + body += "Document: %(title)s — %(url)s" + + elif typ == "sticker": keys = ("photo_256", "photo_128", "photo_64") - for _key in keys: - if _key in att[key]: - body += "\nSticker: " + att[key][_key] + for key in keys: + if key in att[typ]: + body += "Sticker: " + att[typ][key] break + else: - body += "\nUnknown attachment: " + str(att[key]) - result += body % att.get(key, {}) + body += "Unknown attachment: " + str(att[typ]) + result += body % att.get(typ, {}) return result registerHandler("msg01", parseAttachments) diff --git a/extensions/avatar_hash.py b/extensions/avatar_hash.py index c306d11..f067eb5 100644 --- a/extensions/avatar_hash.py +++ b/extensions/avatar_hash.py @@ -32,10 +32,9 @@ def makePhotoHash(user, list=None): for key in photos: user.hashes[key["uid"]] = sha1(utils.getLinkData(key["photo"], False)).hexdigest() - def addPresenceHash(prs, destination, source): - if not prs.getType(): + if destination in Transport and not prs.getType(): uid = vk2xmpp(source) user = Transport[destination] if not uid in user.hashes: diff --git a/extensions/captcha_forms.py b/extensions/captcha_forms.py index 24fa0f4..102ef0f 100644 --- a/extensions/captcha_forms.py +++ b/extensions/captcha_forms.py @@ -28,9 +28,7 @@ def captchaSend(self): oob = msg.setTag("data", {"cid": "sha1+%s@bob.xmpp.org" % hash, "type": "image/jpg", "max-age": "0"}, xmpp.NS_URN_OOB) oob.setData(encoded) sender(Component, msg) - Presence = xmpp.protocol.Presence(self.source, frm=TransportID) - Presence.setStatus(body) - Presence.setShow("xa") + Presence = xmpp.protocol.Presence(self.source, show="xa", status=body, frm=TransportID) sender(Component, Presence) diff --git a/extensions/forwarded_messages.py b/extensions/forwarded_messages.py index 3225162..3738079 100644 --- a/extensions/forwarded_messages.py +++ b/extensions/forwarded_messages.py @@ -21,7 +21,7 @@ def parseForwardedMessages(self, msg, depth = 0): date = datetime.fromtimestamp(date).strftime("%d.%m.%Y %H:%M:%S") name = self.vk.getUserData(source)["name"] body += "\n%s[%s] <%s> %s" % (spacer, date, name, fwdBody) - body += parseAttachments(self, fwd) + body += parseAttachments(self, fwd, spacer) if depth < MAXIMUM_FORWARD_DEPTH: body += parseForwardedMessages(self, fwd, (depth + 1)) return body diff --git a/extensions/groupchats.py b/extensions/groupchats.py index 1b5e061..efc5364 100644 --- a/extensions/groupchats.py +++ b/extensions/groupchats.py @@ -78,7 +78,7 @@ def outgoungChatMessageHandler(self, msg): self.vk.getUserID() if chat not in self.chatUsers: - logger.debug("groupchats: creating %s. Users: %s; owner: %s" % (chat, msg["chat_active"], owner)) + logger.debug("groupchats: creating %s. Users: %s; owner: %s (jid: %s)" % (chat, msg["chat_active"], owner, self.source)) self.chatUsers[chat] = [] joinChat(chat, self.vk.getUserData(owner)["name"], TransportID) setChatConfig(chat, TransportID) @@ -90,7 +90,7 @@ def outgoungChatMessageHandler(self, msg): for user in users: if not user in self.chatUsers[chat]: - logger.debug("groupchats: user %s has joined the chat %s" % (user, chat)) + logger.debug("groupchats: user %s has joined the chat %s (jid: %s)" % (user, chat, self.source)) self.chatUsers[chat].append(user) uName = self.vk.getUserData(user)["name"] user = vk2xmpp(user) @@ -99,7 +99,7 @@ def outgoungChatMessageHandler(self, msg): for user in self.chatUsers[chat]: if not user in users: - logger.debug("groupchats: user %s has left the chat %s" % (user, chat)) + logger.debug("groupchats: user %s has left the chat %s (jid: %s)" % (user, chat, self.source)) self.chatUsers[chat].remove(user) uName = self.vk.getUserData(user)["name"] leaveChat(chat, vk2xmpp(user)) @@ -132,12 +132,12 @@ def incomingChatMessageHandler(msg): Node, Domain = source.split("@") if Domain == ConferenceServer: id = int(Node.split("_")[0]) - if destination == TransportID: + if destination == TransportID and id: jid = jidToID[id] if jid in Transport: user = Transport[jid] if html and html.getTag("body"): ## XHTML-IM! - logger.debug("groupchats: fetched xhtml image from %s" % source) + logger.debug("groupchats: fetched xhtml image (jid: %s)" % source) try: xhtml = mod_xhtml.parseXHTML(user, html, source, source, "chat_id") except Exception: diff --git a/extensions/status-to-vk.py b/extensions/status-to-vk.py index d1e913e..8479c2e 100644 --- a/extensions/status-to-vk.py +++ b/extensions/status-to-vk.py @@ -7,7 +7,7 @@ VK_ACCESS += 1024 GLOBAL_USER_SETTINGS["status_to_vk"] = {"label": "Publish my status in VK", "value": 0} def statusChange(source, prs): - if source in Transport and prs.getType() in ("available", None): + if source in Transport and prs.getType() in ("available", None): ## do we need to check prs type? user = Transport[source] if user.settings.status_to_vk: mask = user.vk.method("account.getAppPermissions") or 0 @@ -6,7 +6,6 @@ # Program published under MIT license. import gc -import json import httplib import logging import os @@ -110,6 +109,12 @@ except Exception: wException() exit() +## Trying to use faster library usjon instead of simplejson +try: + import ujson as json +except ImportError: + import json + logger = logging.getLogger("vk4xmpp") logger.setLevel(LOG_LEVEL) loggerHandler = logging.FileHandler(logFile) @@ -178,15 +183,6 @@ def execute(handler, list=()): crashLog(handler.func_name) return result -def apply(instance, args=()): - """ - Same as execute(), but just return none on error - """ - try: - code = instance(*args) - except Exception: - code = None - return code ## TODO: execute threaded handlers def registerHandler(type, func): @@ -206,22 +202,29 @@ def executeHandlers(type, list=()): for handler in Handlers[type]: execute(handler, list) -def runThread(func, args=(), name=None): +def runThread(func, args=(), name=None, att=3): """ Runs a thread with custom args and name Needed to reduce code + Parameters: + func: function needed to be run in thread + args: function arguments + name: thread namespace + att: number of attemptfs """ thr = threading.Thread(target=execute, args=(func, args), name=name or func.func_name) try: thr.start() except threading.ThreadError: - crashlog("runThread.%s" % name) + if retry: + return runThread(func, args, name, (att - 1)) + crashLog("runThread.%s" % name) def getGatewayRev(): """ Gets gateway revision using git or custom revision number """ - revNumber, rev = 192, 0 + revNumber, rev = 205, 0 shell = os.popen("git describe --always && git log --pretty=format:''").readlines() if shell: revNumber, rev = len(shell), shell[0] @@ -233,9 +236,9 @@ def vk2xmpp(id): Returns id if parameter "id" is id@TransportID Returns TransportID if "id" is TransportID """ - if not isNumber(id) and "@" in id: + if not utils.isNumber(id) and "@" in id: id = id.split("@")[0] - if isNumber(id): + if utils.isNumber(id): id = int(id) elif id != TransportID: id = u"%s@%s" % (id, TransportID) @@ -249,7 +252,6 @@ badChars = [x for x in xrange(32) if x not in (9, 10, 13)] + [57003, 65535] escape = re.compile("|".join(unichr(x) for x in badChars), re.IGNORECASE | re.UNICODE | re.DOTALL).sub sortMsg = lambda msgOne, msgTwo: msgOne.get("mid", 0) - msgTwo.get("mid", 0) require = lambda name: os.path.exists("extensions/%s.py" % name) -isNumber = lambda obj: (not apply(int, (obj,)) is None) class Settings(object): @@ -455,7 +457,7 @@ class VK(object): Poll.remove(Transport[self.source]) self.online = False executeHandlers("evt06") - runThread(self.method, ("account.setOffline", None, True)) ## Maybe this one should be started in separate thread to do not let VK freeze main thread + runThread(self.method, ("account.setOffline", None, True, True)) ## Maybe this one should be started in separate thread to do not let VK freeze main thread def getFriends(self, fields=None): """ @@ -502,6 +504,8 @@ class VK(object): Otherwise will request method users.get Default fields is ["screen_name"] """ +# if not self.source in Transport: ## That looks impossible, but it happened at least once. Thanks, bedbmak@! +# return None user = Transport[self.source] if not fields: if uid in user.friends: @@ -557,17 +561,29 @@ class User(object): self.friends = {} self.chatUsers = {} self.hashes = {} - self.resources = [] + self.resources = set([]) self.settings = Settings(source) self.last_udate = time.time() self.__sync = threading._allocate_lock() self.vk = VK(self.username, self.password, self.source) logger.debug("initializing User (jid: %s)" % self.source) + + def __eq__(self, user): + if isinstance(user, User): + return user.source == self.source + return self.source == user + + def connect(self, raise_exc=False): + """ + Calls VK.auth() and calls captchaChallenge on captcha + Updates db if auth() is done + Raises exception if raise_exc == True + """ with Database(DatabaseFile, Semaphore) as db: db("select * from users where jid=?", (self.source,)) data = db.fetchone() if data: - if not self.token or not self.password: + if not self.token and not self.password: logger.debug("User exists in database. Using his information (jid: %s)" % self.source) self.exists = True self.source, self.username, self.token, self.lastMsgID, self.rosterSet = data @@ -575,17 +591,6 @@ class User(object): logger.debug("User: %s exists in database. Record would be deleted." % self.source) runThread(removeUser, (self,)) - def __eq__(self, user): - if isinstance(user, User): - return user.source == self.source - return self.source == user - - def connect(self, raise_exc=False): - """ - Calls VK.auth() and calls captchaChallenge on captcha - Updates db if auth() is done - Raises exception if needed -1 if an exception if raise_exc == True - """ logger.debug("User: connecting (jid: %s)" % self.source) self.auth = False ## TODO: Check the code below @@ -630,13 +635,14 @@ class User(object): resource: add resource in self.resources to prevent unneeded stanza sending """ logger.debug("User: called init for user %s" % self.source) + Transport[self.source] = self if not self.friends: self.friends = self.vk.getFriends() if self.friends and not self.rosterSet or force: logger.debug("User: sending subscribe presence with force:%s (jid: %s)" % (force, self.source)) self.sendSubPresence(self.friends) if send: self.sendInitPresence() - if resource: self.resources.append(resource) + if resource: self.resources.add(resource) runThread(self.vk.getUserID) Poll.add(self) self.sendMessages(True) @@ -711,7 +717,7 @@ class User(object): crashLog("handle.%s" % func.__name__) if result is None: for func in iter: - apply(func, (self, message)) + utils.apply(func, (self, message)) break else: body += result diff --git a/library/utils.py b/library/utils.py index 00e0360..e6daf2b 100644 --- a/library/utils.py +++ b/library/utils.py @@ -2,38 +2,79 @@ # This file is a part of VK4XMPP transport # © simpleApps, 2014. -import xmpp, urllib +import xmpp +import urllib +from socket import error from hashlib import sha1 -##needed: requred fields -## needed: form title -def buildDataForm(form=None, type="submit", fields=[], title=None): - form = form or xmpp.DataForm(type, title=title) +def apply(instance, args=()): + """ + Executes instance(*args), but just return None on error occurred + """ + try: + code = instance(*args) + except Exception: + code = None + return code + +isNumber = lambda obj: (not apply(int, (obj,)) is None) + +def buildDataForm(form=None, type="submit", fields=[], title=None, data=[]): + """ + Provides easier method to build data forms using dict for each form object + Parameters: + form: xmpp.DataForm object + type: form type + fields: list of form objects represented as dict, e.g. + [{"var": "cool", "type": "text-single", + "desc": "my cool description", "value": "cool"}] + title: form title + data: advanced data for form. e.g. instructions (if string in the list), look at xmpp/protocol.py:1326 + """ + form = form or xmpp.DataForm(type, data, title) for key in fields: - field = form.setField(key["var"], key.get("value"), key.get("type"), key.get("options")) - if key.get("payload"): + field = form.setField(key["var"], key.get("value"), + key.get("type"), key.get("desc"), key.get("options")) + if key.has_key("payload"): field.setPayload(key["payload"]) - if key.get("label"): + if key.has_key("label"): field.setLabel(key["label"]) - if key.get("requred"): + if key.has_key("requred"): field.setRequired() - return form -def buildIQError(stanza, error=None, text=None): - if not error: - error = xmpp.ERR_FEATURE_NOT_IMPLEMENTED +def buildIQError(stanza, error=xmpp.ERR_FEATURE_NOT_IMPLEMENTED, text=None): + """ + Provides a way to build IQ error reply + """ error = xmpp.Error(stanza, error, True) if text: eTag = error.getTag("error") eTag.setTagData("text", text) return error +def normalizeValue(value): + """ + Normalizes boolean values from dataform replies + """ + if isNumber(value): + value = int(value) + elif value and value.lower() == "true": + value = 1 + else: + value = 0 + return value + def getLinkData(url, encode=True): + """ + Gets link data and ignores any exceptions + Parameters: + encode: base64 data encode + """ try: opener = urllib.urlopen(url) - except Exception: + except (Exception, error): return "" data = opener.read() if data and encode: diff --git a/library/vkapi.py b/library/vkapi.py index 8d6f18e..6bc07c1 100644 --- a/library/vkapi.py +++ b/library/vkapi.py @@ -356,12 +356,14 @@ class APIBinding: def retry(self): """ Tries to execute last method again - Needed after captcha is entered + Usually called after captcha is entered """ result = None if self.lastMethod: try: result = self.method(*self.lastMethod) + except CaptchaNeeded: + raise except Exception: pass return result diff --git a/library/xmpp/protocol.py b/library/xmpp/protocol.py index d6a3905..c268aaa 100644 --- a/library/xmpp/protocol.py +++ b/library/xmpp/protocol.py @@ -1164,14 +1164,14 @@ class DataReported(Node): """
return self.getTag("field", attrs={"var": name})
- def setField(self, name, typ=None, label=None, options=[]):
+ def setField(self, name, typ=None, label=None, desc=None, options=[]):
"""
Create if nessessary or get the existing datafield object with name "name" and return it.
If created, attributes "type" and "label" are applied to new datafield.
"""
field = self.getField(name)
if not field:
- field = self.addChild(node=DataField(name, None, typ, 0, label, options=options))
+ field = self.addChild(node=DataField(name, None, typ, 0, label, desc=desc, options=options))
return field
def asDict(self):
@@ -1236,13 +1236,13 @@ class DataItem(Node): """
return self.getTag("field", attrs={"var": name})
- def setField(self, name, value=None, typ=None, options=[]):
+ def setField(self, name, value=None, typ=None, desc=None, options=[]):
"""
Create if nessessary or get the existing datafield object with name "name" and return it.
"""
field = self.getField(name)
if not field:
- field = self.addChild(node=DataField(name, value, typ, options=options))
+ field = self.addChild(node=DataField(name, value, typ, desc=desc, options=options))
return field
def asDict(self):
@@ -1383,13 +1383,13 @@ class DataForm(Node): """
return self.getTag("field", attrs={"var": name})
- def setField(self, name, value=None, typ=None, options=[]):
+ def setField(self, name, value=None, typ=None, desc=None, options=[]):
"""
Create if nessessary or get the existing datafield object with name "name" and return it.
"""
field = self.getField(name)
if not field:
- field = self.addChild(node=DataField(name, value, typ, options=options))
+ field = self.addChild(node=DataField(name, value, typ, desc=desc, options=options))
return field
def asDict(self):
diff --git a/locales/locale.ru b/locales/locale.ru index a8a6d47..2b6b581 100644 --- a/locales/locale.ru +++ b/locales/locale.ru @@ -3,7 +3,7 @@ Captcha valid.=Капча введена верно. Captcha invalid.=Капча введена неверно. Not now. Ok?=Не сейчас. Phone incorrect.=Неверный номер. -Empty password=Пустой пароль или access-token! +Empty password/token field=Поле пароль/access-token не может быть пустым! Incorrect password or access token!=Неправильный пароль или access-token! Initialization failed.=Ошибка инициализации. Feature not implemented.=Возможность не реализована. @@ -15,10 +15,10 @@ Your friend-list is empty.=Ваш список друзей пуст! You're not registered for this action.=Вы должны быть зарегистрированы для этого дейстия. Auth failed! If this error repeated, please register again. This incident will be reported.=Авторизация не удалась. Если эта ошибка повторяется, пожалуйста, зарегистрируйтесь заново. Об этом инциденте будет сообщено. Forwarded messages:=Пересланные сообщения: -\nAttachments:=\nВложения: +Attachments:=Вложения: Enter shown text=Введите показанный текст New user registered: %s=Зарегистрирован новый пользователь: %s -User removed registration: %s=Пользователь удалил регистрацию: %s +User has removed registration: %s=Пользователь удалил регистрацию: %s Type data in fields=Введите данные в поля Autorization page=Страница авторизации If you won't get access-token automatically, please, follow authorization link and authorize app,\nand then paste url to password field.=Если же вы не хотите получить access-token автоматически, то пройдите по ссылке из поля, авторизируйте приложение,\nа затем введите полученный URL из адресной строки браузера в последнее поле вместо пароля. diff --git a/modules/mod_iq_disco.py b/modules/mod_iq_disco.py index b32ae7d..910341c 100644 --- a/modules/mod_iq_disco.py +++ b/modules/mod_iq_disco.py @@ -65,15 +65,6 @@ def disco_handler(cl, iq): sender(cl, result) -def normalizeValue(value): - if isNumber(value): - value = int(value) - elif value and value.lower() == "true": - value = 1 - else: - value = 0 - return value - def getUsersList(): with Database(DatabaseFile) as db: db("select jid from users") @@ -172,7 +163,7 @@ def commands_handler(cl, iq): form = xmpp.DataForm(node=form).asDict() for key in form.keys(): if key in config.keys(): - Transport[source].settings[key] = normalizeValue(form[key]) + Transport[source].settings[key] = utils.normalizeValue(form[key]) completed = True if completed: diff --git a/modules/mod_iq_register.py b/modules/mod_iq_register.py index d64bbed..164bf9d 100644 --- a/modules/mod_iq_register.py +++ b/modules/mod_iq_register.py @@ -23,11 +23,11 @@ def initializeUser(user, cl, iq): user.initialize() except api.CaptchaNeeded: user.vk.captchaChallenge() - except Exception: + except Exception: ## is there could be any other exception? crashLog("user.init") result = utils.buildIQError(iq, xmpp.ERR_BAD_REQUEST, _("Initialization failed.")) else: - Transport[source] = user +## Transport[source] = user watcherMsg(_("New user registered: %s") % source) else: logger.error("user connection failed (jid: %s)" % source) @@ -50,47 +50,33 @@ def register_handler(cl, iq): if destination == TransportID: if iType == "get" and not queryChildren: - logger.debug("Sending registration form to user (jid: %s)" % source) - form = xmpp.DataForm() - form.addChild(node=xmpp.Node("instructions")).setData(_("Type data in fields")) ## TODO: Complete this by forms - link = form.setField("link", URL_ACCEPT_APP, "text-single") - link.setLabel(_("Autorization page")) - link.setDesc(_("If you won't get access-token automatically, please, follow authorization link and authorize app,\n"\ - "and then paste url to password field.")) - phone = form.setField("phone", "+", "text-single") - phone.setLabel(_("Phone number")) - phone.setDesc(_("Enter phone number in format +71234567890")) - use_password = form.setField("use_password", "0", "boolean") - use_password.setLabel(_("Get access-token automatically")) - use_password.setDesc(_("Try to get access-token automatically. (NOT recommended, password required!)")) - password = form.setField("password", None, "text-private") - password.setLabel(_("Password/Access-token")) - password.setDesc(_("Type password, access-token or url (recommended)")) - result.setQueryPayload((form,)) + logger.debug("Send registration form to user (jid: %s)" % source) + form = utils.buildDataForm(fields = [ + {"var": "link", "type": "text-single", "label": _("Autorization page"), + "desc": ("If you won't get access-token automatically, please, follow authorization link and authorize app,\n"\ + "and then paste url to password field."), "value": URL_ACCEPT_APP}, + {"var": "phone", "type": "text-single", "desc": _("Enter phone number in format +71234567890"), "value": "+"}, + {"var": "use_password", "type": "boolean", "label": _("Get access-token automatically"), "desc": _("Try to get access-token automatically. (NOT recommended, password required!)")}, #"value": "0"},#, "0"} + {"var": "password", "type": "text-private", "label": _("Password/Access-token"), "desc": _("Type password, access-token or url (recommended)")} + + ], data = [_("Type data in fields")]) + result.setQueryPayload([form]) elif iType == "set" and queryChildren: - phone, password, use_password, token = False, False, False, False + phone, password, use_password, token = False, False, False, False #? query = iq.getTag("query") - if query.getTag("x"): - for node in iq.getTags("query", namespace=xmpp.NS_REGISTER): - for node in node.getTags("x", namespace=xmpp.NS_DATA): - phone = node.getTag("field", {"var": "phone"}) - phone = phone and phone.getTagData("value") - password = node.getTag("field", {"var": "password"}) - password = password and password.getTagData("value") - use_password = node.getTag("field", {"var": "use_password"}) - use_password = use_password and use_password.getTagData("value") + data = query.getTag("x", namespace=xmpp.NS_DATA) + if data: + form = xmpp.DataForm(node=data).asDict() + print form + phone = form.get("phone") + password = form.get("password") + use_password = utils.normalizeValue(form.get("use_password")) if not password: - result = utils.buildIQError(iq, xmpp.ERR_BAD_REQUEST, _("Empty password")) + result = utils.buildIQError(iq, xmpp.ERR_BAD_REQUEST, _("Empty password/token field")) ## Some clients send "true" or "false" instead of 1/0 - if not isNumber(use_password): - if use_password and use_password.lower() == "true": - use_password = 1 - else: - usd_password = 0 - user = User(source=source) use_password = int(use_password) diff --git a/modules/mod_msg_main.py b/modules/mod_msg_main.py index 5d8ceda..2b31a3e 100644 --- a/modules/mod_msg_main.py +++ b/modules/mod_msg_main.py @@ -31,8 +31,7 @@ def acceptCaptcha(cl, args, jidTo, source): if success: logger.debug("retry for user %s successed!" % source) answer = _("Captcha valid.") - Presence = xmpp.Presence(source, frm = TransportID) - Presence.setShow("available") + Presence = xmpp.Presence(source, show=None, frm = TransportID) sender(Component, Presence) user.tryAgain() else: diff --git a/modules/mod_prs_main.py b/modules/mod_prs_main.py index 7ef0518..f2c6d32 100644 --- a/modules/mod_prs_main.py +++ b/modules/mod_prs_main.py @@ -39,7 +39,7 @@ def presence_handler(cl, prs): if jidTo == TransportID: if resource not in user.resources: logger.debug("Received presence %s from user. Will send sendInitPresence (jid: %s)" % (pType, source)) - user.resources.append(resource) + user.resources.add(resource) runThread(user.sendInitPresence, ()) runThread(executeHandlers, ("prs01", (source, prs))) diff --git a/modules/mod_xhtml.py b/modules/mod_xhtml.py index cc5c295..ca633d5 100644 --- a/modules/mod_xhtml.py +++ b/modules/mod_xhtml.py @@ -31,7 +31,7 @@ def sendPhoto(user, data, type, address, mType): urlencode = False)[0]) id = user.vk.method("photos.saveMessagesPhoto", response)[0].get("id", 0) - user.msg("", address, mType, {"attachment": id}) + user.sendMessage("", address, mType, {"attachment": id}) logger.debug("sendPhoto: image was successfully sent by user %s" % user.source) answer = _("Your image was successfully sent.") else: |