mrDoctorWho/vk4xmpp

View on GitHub
modules/mod_iq_vcard.py

Summary

Maintainability
B
6 hrs
Test Coverage
# coding: utf-8
# This file is a part of VK4XMPP transport
# © simpleApps, 2014 — 2016.

from __main__ import *
from __main__ import _

VCARD_SEMAPHORE = threading.Semaphore()

DESCRIPTION = "VK4XMPP Transport\n© simpleApps, 2013 — 2016."
GITHUB_URL = "https://github.com/mrDoctorWho/vk4xmpp"
BIRTHDAY = "30.08.2013"

KEY_NICKNAME = "NICKNAME"
KEY_NAME = "FN"
KEY_DESC = "DESC"
KEY_PHOTO = "PHOTO"
KEY_BINVAL = "BINVAL"
KEY_URL = "URL"
KEY_ADR = "ADR"
KEY_HOME = "HOME"
KEY_BDAY = "BDAY"
KEY_CTRY = "CTRY"
KEY_PHONE_HOME = "HOME"
KEY_PHONE_MOBILE = "MOBILE"
KEY_TEL = "TEL"
KEY_NUMBER = "NUMBER"
KEY_VOICE = "VOICE"
KEY_LOCALITY = "LOCALITY"

if AdditionalAbout:
    DESCRIPTION = "%s\n%s" % (DESCRIPTION, AdditionalAbout)


# Vcard defaults
VCARD_TEMPLATE = {KEY_NICKNAME: IDENTIFIER["short"],
    KEY_NAME: IDENTIFIER["name"],
    KEY_DESC: DESCRIPTION,
    KEY_PHOTO: URL_VCARD_NO_IMAGE,
    KEY_URL: GITHUB_URL,
    KEY_BDAY: BIRTHDAY,
    KEY_CTRY: "United States",  # database.getCountriesById and database.getCitiesById
    KEY_PHONE_HOME: None,
    KEY_PHONE_MOBILE: None,
    KEY_LOCALITY: {"title": "Los Angeles"}  # you'd love it here (yeah, here...)
    }


VCARD_FIELDS = {KEY_NICKNAME: "screen_name",
                KEY_NAME: "name",
                KEY_URL: "https://vk.com/id%(id)s",
                KEY_BDAY: "bdate",
                KEY_CTRY: "country",
                KEY_LOCALITY: "city",
                KEY_PHONE_HOME: "home_phone",
                KEY_PHONE_MOBILE: "mobile_phone",
                KEY_URL: "site",
                KEY_PHOTO: PhotoSize,
                KEY_DESC: None,
                }


def buildVcard(data, template=VCARD_TEMPLATE, fields=VCARD_FIELDS, user=None):
    """
    Builds a vcard.
    Uses VCARD_TEMPLATE as the base, then adds values from data.
    Values from data are get with the help of the VCARD_FIELDS dict.
    Args:
        data: users.get result
        user: the user object
    Returns:
        The user's VCARD.
    """
    vcard = xmpp.Node("vCard", {"xmlns": xmpp.NS_VCARD})
    for key, value in template.iteritems():
        value = data.get(fields[key], value)
        if key == KEY_PHOTO:
            photo = vcard.setTag(KEY_PHOTO)
            photo.setTagData(KEY_BINVAL, utils.getLinkData(value))

        elif key in (KEY_CTRY, KEY_LOCALITY) and value:
            adr = vcard.getTag(KEY_ADR) or vcard.setTag(KEY_ADR)
            adr.setTagData(key, value.get("title"))

        elif key == KEY_PHONE_MOBILE and value:
            tel = vcard.getTag(KEY_TEL) or vcard.setTag(KEY_TEL)
            tel.setTagData(KEY_NUMBER, value)

        elif key == KEY_PHONE_HOME and value:
            tel = vcard.getTag(KEY_TEL) or vcard.setTag(KEY_TEL)
            tel.setTagData(KEY_PHONE_HOME, value)

        elif key == KEY_BDAY and value:
            if value.count(".") == 1:
                value += time.strftime(".%Y")
            value = time.strftime("%Y-%m-%d", time.strptime(value, "%d.%m.%Y"))
            vcard.setTagData(key, value)

        elif value and value != "None":
            vcard.setTagData(key, value)
    return vcard


@utils.threaded
def vcard_handler(cl, iq):
    # Vcard feature makes transport hang (especially the photo part)
    # Many clients love to query vcards so much, so the solution was in adding a semaphore here and sleep() at the bottom
    # This is probably not a good idea, but for now this is the best one
    with VCARD_SEMAPHORE:
        jidFrom = iq.getFrom()
        jidTo = iq.getTo()
        source = jidFrom.getStripped()
        destination = jidTo.getStripped()
        result = iq.buildReply("result")

        logger.debug("got vcard request to %s (jid: %s)", destination, source)
        if destination == TransportID:
            template = VCARD_TEMPLATE.copy()
            vcard = buildVcard(template, template, template)
            result.setPayload([vcard])

        elif source in Users:
            user = Users[source]
            if user.friends:
                id = vk2xmpp(destination)
                args = ("screen_name", "bdate", "city", "country", "contacts", "home_town", "site", PhotoSize)  # todo: a feature to show the user's site instead of their URL?
                data = user.vk.getData(id, args)
                data["id"] = id
                if not user.settings.use_nicknames:
                    data["screen_name"] = data["name"]
                vCard = buildVcard(data, VCARD_TEMPLATE, VCARD_FIELDS, user)
                result.setPayload([vCard])
            else:
                result = utils.buildIQError(iq, xmpp.ERR_BAD_REQUEST, _("Your friend-list is empty."))
        else:
            result = utils.buildIQError(iq, xmpp.ERR_REGISTRATION_REQUIRED, _("You're not registered for this action."))
        sender(cl, result)


MOD_TYPE = "iq"
MOD_HANDLERS = ((vcard_handler, "get", xmpp.NS_VCARD, False),)
MOD_FEATURES = [xmpp.NS_VCARD]