Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mrDoctorWho/vk4xmpp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Smith <mrdoctorwho@helldev.net>2019-05-14 07:25:18 +0300
committerJohn Smith <mrdoctorwho@helldev.net>2019-05-14 07:25:18 +0300
commitd687b7b62278580afdd5b881ed71fe7c59d03bb2 (patch)
treeb83a9c0db37f52f76cf293a19ac89e5ffe415e60
parent42bea0f685fc83b9e9b172a4cd301b0a297a6000 (diff)
Bring API v5 back. Add timezone support, use intellectual date format
-rw-r--r--extensions/attachments.py6
-rw-r--r--extensions/avatar_hash.py2
-rw-r--r--extensions/forwarded_messages.py45
-rw-r--r--extensions/groupchats.py13
-rw-r--r--gateway.py81
-rw-r--r--library/longpoll.py2
-rw-r--r--library/rostermanager.py4
-rw-r--r--library/utils.py4
-rw-r--r--library/vkapi.py4
-rw-r--r--modules/mod_iq_disco.py2
10 files changed, 102 insertions, 61 deletions
diff --git a/extensions/attachments.py b/extensions/attachments.py
index 1aca767..3b65376 100644
--- a/extensions/attachments.py
+++ b/extensions/attachments.py
@@ -10,7 +10,7 @@ VK_AUDIO_SEARCH_LINK = "https://vk.com/search?c[q]=%s&c[section]=audio"
WALL_LINK = "https://vk.com/wall%(to_id)s_%(id)s"
WALL_COMMENT_LINK = "https://vk.com/wall%(owner_id)s_%(post_id)s?w=wall%(owner_id)s3_%(post_id)s"
-PHOTO_SIZES = ("src_xxxbig", "src_xxbig", "src_xbig", "src_big", "src", "url", "src_small")
+PHOTO_SIZES = ("photo_2560", "photo_1280", "photo_807", "photo_604", "photo_130", "photo_75")
STICKER_SIZES = ("photo_256", "photo_128", "photo_64")
ATTACHMENT_REGEX = re.compile(r"^(?P<type>Photo|Document|Sticker)\:\s(?P<name>“.+?”\s—\s)?(?P<url>http[s]?:\/\/[^\s]+)$", re.UNICODE)
@@ -87,7 +87,7 @@ def parseAttachments(self, msg, spacer=""):
elif type == "wall_reply":
# TODO: What if it's a community? from_id will be negative.
# TODO: Remove "[idxxx|Name]," from the text or make it a link if XHTML is allowed
- current["name"] = self.vk.getName(current["uid"])
+ current["name"] = self.vk.getName(current["from_id"])
current["text"] = uhtml(compile_eol.sub("\n" + spacer, current["text"]))
current["url"] = WALL_COMMENT_LINK % current
@@ -105,7 +105,7 @@ def parseAttachments(self, msg, spacer=""):
current["desc"] += "%(views)d views" % current
current["time"] = "%d:%d" % (current["duration"] // 60, current["duration"] % 60)
- body += "Video: %(title)s (%(desc)s, %(time)s min) — https://vk.com/video%(owner_id)s_%(vid)s" % current
+ body += "Video: %(title)s (%(desc)s, %(time)s min) — https://vk.com/video%(owner_id)s_%(id)s" % current
elif type in SIMPLE_ATTACHMENTS:
body += SIMPLE_ATTACHMENTS[type] % current
diff --git a/extensions/avatar_hash.py b/extensions/avatar_hash.py
index 3e62946..2f2a7e1 100644
--- a/extensions/avatar_hash.py
+++ b/extensions/avatar_hash.py
@@ -42,7 +42,7 @@ class AvatarHash(object):
return data
def sendPhotoRequest(self, user, uids):
- data = user.vk.method("execute.getPhotos",
+ data = user.vk.method("execute.getPhotos_new",
{"users": self.join(uids), "size": PhotoSize}) or []
return data
diff --git a/extensions/forwarded_messages.py b/extensions/forwarded_messages.py
index 98c7095..f052ec7 100644
--- a/extensions/forwarded_messages.py
+++ b/extensions/forwarded_messages.py
@@ -2,7 +2,7 @@
# This file is a part of VK4XMPP transport
# © simpleApps, 2013 — 2015.
-from datetime import datetime
+from datetime import datetime, timedelta, tzinfo, date
if not require("attachments"):
raise AssertionError("'forwardMessages' requires 'attachments'")
@@ -10,27 +10,58 @@ if not require("attachments"):
BASE_SPACER = chr(32) + unichr(183) + chr(32)
+class TimezoneOffset(tzinfo):
+
+ def __init__(self, offset=0):
+ self.offset = timedelta(hours=offset)
+
+ def utcoffset(self, dt):
+ return self.offset
+
+ def tzname(self, dt):
+ return None
+
+ def dst(self, dt):
+ return timedelta(0)
+
+
def parseForwardedMessages(self, msg, depth=0):
body = ""
- if msg.has_key("fwd_messages"):
+ if "fwd_messages" in msg:
spacer = BASE_SPACER * depth
body = "\n" + spacer
body += _("Forwarded messages:")
fwd_messages = sorted(msg["fwd_messages"], sortMsg)
for fwd in fwd_messages:
- source = fwd["uid"]
- date = fwd["date"]
+ source = fwd["user_id"]
fwdBody = escape("", uhtml(compile_eol.sub("\n" + spacer + BASE_SPACER, fwd["body"])))
- date = datetime.fromtimestamp(date).strftime("%d.%m.%Y %H:%M:%S")
+ date = getUserDate(self, fwd["date"])
name = self.vk.getName(source)
- body += "\n%s[%s] <%s> %s" % (spacer + BASE_SPACER, date, name, fwdBody)
+ body += "\n%s[%s] %s> %s" % (spacer + BASE_SPACER, date, name, fwdBody)
body += parseAttachments(self, fwd, spacer + (BASE_SPACER * 2))
if depth < MAXIMUM_FORWARD_DEPTH:
body += parseForwardedMessages(self, fwd, (depth + 1))
return body
+
+def getUserDate(user, timestamp):
+ timezone = user.vk.getUserPreferences()[1]
+ offset = TimezoneOffset(timezone)
+ _date = datetime.fromtimestamp(timestamp, offset)
+ today = datetime.fromtimestamp(time.time(), offset)
+ _format = ""
+ delta = today - _date
+ if delta.days > 0:
+ _format += "%d.%m"
+ if delta.days > 300:
+ _format += ".%Y"
+ if _format:
+ _format += " "
+ _format += "%H.%M:%S"
+ return _date.strftime(_format)
+
+
if not isdef("MAXIMUM_FORWARD_DEPTH"):
MAXIMUM_FORWARD_DEPTH = 29
registerHandler("msg01", parseForwardedMessages)
-
diff --git a/extensions/groupchats.py b/extensions/groupchats.py
index 04cbaf8..ed6632f 100644
--- a/extensions/groupchats.py
+++ b/extensions/groupchats.py
@@ -144,8 +144,10 @@ def handleOutgoingChatMessage(user, vkChat):
"""
Handles outging VK messages and sends them to XMPP
"""
+ # peer_id for newer APIs
+ chatID = vkChat.get("chat_id", 0)
- if "chat_id" in vkChat:
+ if chatID:
# check if the groupchats support enabled in user's settings
if not user.settings.groupchats:
return None
@@ -153,7 +155,6 @@ def handleOutgoingChatMessage(user, vkChat):
if not hasattr(user, "chats"):
user.chats = {}
- chatID = vkChat["chat_id"]
chatJID = "%s_chat#%s@%s" % (user.vk.userID, chatID, ConferenceServer)
chat = createChat(user, chatJID)
if not chat.initialized:
@@ -292,8 +293,8 @@ class Chat(object):
# how would it get in there?
if TransportID in everyone:
everyone.remove(TransportID)
- if userObject.vk.getUserID() in everyone:
- everyone.remove(userObject.vk.getUserID())
+ if userObject.vk.getUserPreferences()[0] in everyone:
+ everyone.remove(userObject.vk.getUserPreferences()[0])
for user in everyone:
jid = vk2xmpp(user)
@@ -368,7 +369,7 @@ class Chat(object):
body += parseAttachments(user, vkChat)
body += parseForwardedMessages(user, vkChat)
if body:
- chatMessage(self.jid, body, vk2xmpp(vkChat["uid"]), None)
+ chatMessage(self.jid, body, vk2xmpp(vkChat["from_id"]), None)
else:
source = "unknown"
userObject = self.getUserObject(self.jid)
@@ -448,7 +449,7 @@ class Chat(object):
def getUserByID(id):
for jid, user in Users.iteritems():
if hasattr(user, "vk"):
- if user.vk.getUserID() == id:
+ if user.vk.getUserPreferences()[0] == id:
return user
return None
diff --git a/gateway.py b/gateway.py
index 3dee4f0..c3a6452 100644
--- a/gateway.py
+++ b/gateway.py
@@ -228,7 +228,7 @@ 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 first, second: first.get("mid", 0) - second.get("mid", 0)
+sortMsg = lambda first, second: first.get("id", 0) - second.get("id", 0)
require = lambda name: os.path.exists("extensions/%s.py" % name)
isdef = lambda var: var in globals()
findUserInDB = lambda source: runDatabaseQuery("select * from users where jid=?", (source,), many=False)
@@ -261,14 +261,15 @@ class VK(object):
self.engine = None
self.cache = {}
self.permissions = 0
+ self.timezone = 0
logger.debug("VK initialized (jid: %s)", source)
def __str__(self):
- return ("user id: %s; online: %s; token: %s" %
- (self.userID, self.online, self.token))
+ return ("user id: %s; timezone: %s; online: %s; token: %s" %
+ (self.userID, self.timezone, self.online, self.token))
def init(self):
- self.getUserID()
+ self.getUserPreferences()
self.getPermissions()
getToken = lambda self: self.engine.token
@@ -442,9 +443,10 @@ class VK(object):
"""
fields = fields or self.friends_fields
raw = self.method("friends.get", {"fields": str.join(",", fields)}) or {}
+ raw = raw.get("items", {})
friends = {}
for friend in raw:
- uid = friend["uid"]
+ uid = friend["id"]
online = friend["online"]
name = self.formatName(friend)
friends[uid] = {"name": name, "online": online, "lists": friend.get("lists")}
@@ -452,16 +454,6 @@ class VK(object):
friends[uid][key] = friend.get(key)
return friends
- def getLists(self):
- """
- Receive the list of the user friends' groups
- Returns:
- a list of user friends groups
- """
- if not self.lists:
- self.lists = self.method("friends.getLists")
- return self.lists
-
@staticmethod
def getPeerIds(conversations, source=None):
"""
@@ -507,15 +499,15 @@ class VK(object):
"start_message_id": mid,
"count": count})
if response:
- for message in response:
+ messages.extend(response[0].get("items", []))
# skipping count-only reponses
- if len(message) > 1:
- if isinstance(message, list):
- first = message[0]
- # removing the unread count
- if isinstance(first, (int, long)):
- message.remove(first)
- messages.extend(message)
+ # if len(message) > 1:
+ # if isinstance(message, list):
+ # first = message[0]
+ # # removing the unread count
+ # if isinstance(first, (int, long)):
+ # message.remove(first)
+ # messages.extend(message)
else:
# not sure if that's okay
# VK is totally unpredictable now
@@ -543,15 +535,19 @@ class VK(object):
return self.getMessagesBulk(peers, count=count, mid=mid)
# TODO: put this in the DB
- def getUserID(self):
+ def getUserPreferences(self):
"""
- Receives the user id
+ Receives the user's id and timezone
Returns:
The current user id
"""
- if not self.userID:
- self.userID = self.method("execute.getUserID")
- return self.userID
+ if not self.userID or not self.timezone:
+ data = self.method("users.get", {"fields": "timezone"})
+ if data:
+ data = data.pop()
+ self.timezone = data.get("timezone")
+ self.userID = data.get("id")
+ return (self.userID, self.timezone)
def getPermissions(self):
"""
@@ -563,6 +559,16 @@ class VK(object):
self.permissions = self.method("account.getAppPermissions")
return self.permissions
+ def getLists(self):
+ """
+ Receive the list of the user friends' groups
+ Returns:
+ a list of user friends groups
+ """
+ if not self.lists:
+ self.lists = self.method("friends.getLists")
+ return self.lists
+
@utils.cache
def getGroupData(self, gid, fields=None):
"""
@@ -746,7 +752,7 @@ class User(object):
self.sendInitPresence()
if resource:
self.resources.add(resource)
- utils.runThread(self.vk.getUserID)
+ utils.runThread(self.vk.getUserPreferences)
if first:
self.sendMessages(True, filter_="unread")
else:
@@ -820,12 +826,13 @@ class User(object):
# check if message wasn't sent by our user
if not message["out"]:
Stats["msgin"] += 1
- frm = message["uid"]
- mid = message["mid"]
+ frm = message["user_id"]
+ mid = message["id"]
if frm in self.typing:
del self.typing[frm]
fromjid = vk2xmpp(frm)
- body = uhtml(message["body"])
+ body = message["body"]
+ body = uhtml(body)
iter = Handlers["msg01"].__iter__()
for func in iter:
try:
@@ -846,11 +853,11 @@ class User(object):
self.lastMsgByUser[frm] = mid
sendMessage(self.source, fromjid, escape("", body), date, mid=mid)
if messages:
- newLastMsgID = messages[-1]["mid"]
- if self.lastMsgID < newLastMsgID:
- self.lastMsgID = newLastMsgID
- runDatabaseQuery("update users set lastMsgID=? where jid=?",
- (newLastMsgID, self.source), True)
+ newLastMsgID = messages[-1]["id"]
+ # if self.lastMsgID < newLastMsgID:
+ self.lastMsgID = newLastMsgID
+ runDatabaseQuery("update users set lastMsgID=? where jid=?",
+ (newLastMsgID, self.source), True)
def updateTypingUsers(self, cTime):
"""
diff --git a/library/longpoll.py b/library/longpoll.py
index fb3e814..51d5de8 100644
--- a/library/longpoll.py
+++ b/library/longpoll.py
@@ -112,7 +112,7 @@ def processPollResult(user, data):
chat = (uid > MIN_CHAT_UID) # a groupchat always has uid > 2000000000
if not out:
if not attachments and not chat:
- message = [{"out": 0, "uid": uid, "mid": mid, "date": date, "body": body}]
+ message = [{"out": 0, "user_id": uid, "id": mid, "date": date, "body": body}]
utils.runThread(user.sendMessages, (False, message, mid - 1, uid), "sendMessages-%s" % user.source)
elif typ == TYPE_MSG_READ_OUT:
diff --git a/library/rostermanager.py b/library/rostermanager.py
index 896f204..6a52d89 100644
--- a/library/rostermanager.py
+++ b/library/rostermanager.py
@@ -6,7 +6,7 @@ from __main__ import *
from __main__ import _
# Finds list name by id
-findListByID = lambda id, list: [key for key in list if key["lid"] == id]
+findListByID = lambda id, list: [key for key in list if key["id"] == id]
RosterSemaphore = threading.Semaphore()
@@ -35,7 +35,7 @@ class Roster:
for uid, value in dist.iteritems():
item = cls.getNode(vk2xmpp(uid), value["name"], action)
if lists and value["lists"]:
- list = findListByID(value["lists"][0], lists)
+ list = findListByID(value["lists"][0], lists["items"])
if list:
item.setTagData("group", list[0]["name"])
items.append(item)
diff --git a/library/utils.py b/library/utils.py
index f9e4875..a79be40 100644
--- a/library/utils.py
+++ b/library/utils.py
@@ -84,8 +84,8 @@ def cache(func):
result = func(self, uid, fields)
if result:
result["fields"] = fieldsStr
- if "uid" in result:
- del result["uid"]
+ if "user_id" in result:
+ del result["user_id"]
if uid in self.cache:
self.cache[uid].update(result)
else:
diff --git a/library/vkapi.py b/library/vkapi.py
index b7860ef..2058bc2 100644
--- a/library/vkapi.py
+++ b/library/vkapi.py
@@ -30,6 +30,8 @@ REQUEST_RETRIES = 3
APP_ID = 3789129
# VK APP scope
SCOPE = 69638
+# VK API VERSION
+API_VERSION = "5.13"
socket.setdefaulttimeout(SOCKET_TIMEOUT)
@@ -332,7 +334,7 @@ class APIBinding(RequestProcessor):
values = values or {}
if not notoken:
values["access_token"] = self.token
- values["v"] = "3.0"
+ values["v"] = API_VERSION
if "key" in self.captcha:
values["captcha_sid"] = self.captcha["sid"]
diff --git a/modules/mod_iq_disco.py b/modules/mod_iq_disco.py
index 7622cac..660759c 100644
--- a/modules/mod_iq_disco.py
+++ b/modules/mod_iq_disco.py
@@ -134,7 +134,7 @@ def checkAPIToken(token):
raise api.AuthError("Auth failed!")
else:
vk.online = True
- userID = vk.getUserID()
+ userID = vk.getUserPreferences()[0]
name = vk.getUserData(userID)
data = {"auth": auth, "name": name, "friends_count": len(vk.getFriends())}
except (api.VkApiError, Exception):