mrDoctorWho/vk4xmpp

View on GitHub
modules/mod_groupchat_prs.py

Summary

Maintainability
C
1 day
Test Coverage
# coding: utf-8
# This file is a part of VK4XMPP transport
# © simpleApps, 2013 — 2016.

"""
Module purpose is to handle presences from groupchats
"""

from __main__ import *
from __main__ import _


def handleChatErrors(source, prs):
    """
    Handles error presences from groupchats
    Args:
        source: the source jid
        prs: the xmpp.Presence object
    """
    # todo: leave on 401, 403, 405
    # and rejoin timer on 404, 503
    destination = prs.getTo().getStripped()
    error = prs.getErrorCode()
    status = int(prs.getStatusCode() or 0)
    nick = prs.getFrom().getResource()
    jid = prs.getJid()
    errorType = prs.getTagAttr("error", "type")
    user = Chat.getUserObject(source)
    pType = prs.getType()

    if user and source in getattr(user, "chats", {}):
        chat = user.chats[source]
        if chat.creation_failed:
            raise xmpp.NodeProcessed()

        if error == "409" and errorType == "cancel":
            id = vk2xmpp(destination)
            if id in chat.users:
                nick += "."
                if not chat.created and id == TransportID:
                    chat.users[id]["name"] = nick
                    chat.create(user)
                else:
                    joinChat(source, nick, destination)

        if status == "303":
            if jid == user.source:
                chat.owner_nickname = prs.getNick()
                runDatabaseQuery("update groupchats where jid=? set nick=?",
                    (source, chat.owner_nickname), set=True)
        elif error or (status / 100 >= 3):
            logger.debug("groupchats: presence error (error #%s, status #%s) "
                "from source %s (jid: %s)" % (error, status, source, user.source if user else "unknown"))

    if pType in ("available", None) and destination == TransportID:
        if prs.getTag("x", namespace=xmpp.NS_MUC_USER):
            raise xmpp.NodeProcessed()

    raise xmpp.NodeProcessed()


def handleChatPresences(source, prs):
    """
    Makes the old users leave
    Args:
        source: stanza source
        prs: xmpp.Presence object
    """
    jid = prs.getJid() or ""
    if "@" in jid and prs.getType() != "unavailable":
        user = Chat.getUserObject(source)
        if user and source in getattr(user, "chats", {}):
            chat = user.chats[source]
            if jid.split("@")[1] == TransportID and chat.created:
                id = vk2xmpp(jid)
                if id != TransportID and id not in chat.users.keys():
                    if (time.gmtime().tm_mon, time.gmtime().tm_mday) == (4, 1):
                        setAffiliation(source, "outcast", jid, reason=_("Get the hell outta here!"))
                    else:
                        leaveChat(source, jid)

                if (prs.getRole(), prs.getAffiliation()) == ("moderator", "owner"):
                    if jid != TransportID:
                        runDatabaseQuery("update groupchats set owner=? where jid=?", (source, jid), set=True)

                if chat.isUpdateRequired():
                    updateLastUsed(chat)

            # TODO: don't rewrite it every time we get a presence
            if jid.split("/")[0] == user.source:
                nick = prs.getFrom().getResource()
                if chat.owner_nickname != nick:
                    chat.owner_nickname = nick
                    runDatabaseQuery("update groupchats set nick=? where jid=? ", (nick, source), set=True)
                    logger.debug("mod_groupchat_prs: setting user nickname to: %s for chat %s and user: %s", nick, source, user.source)
            raise xmpp.NodeProcessed()

        elif user:
            chat = createChat(user, source)
            chat.invited = True  # assume the user's joined themselves



def presence_handler_groupchat(cl, prs):
    """
    xmpppy presence callback
    Args:
        cl: the xmpp.Client object
        prs: the xmpp.Presence object
    """
    source = prs.getFrom().getStripped()
    code = prs.getStatusCode()
    if code or prs.getType() == "error":
        handleChatErrors(source, prs)
    handleChatPresences(source, prs)  # It won't be called if handleChatErrors was called in the first time


MOD_TYPE = "presence"

MOD_HANDLERS = ((presence_handler_groupchat, "", "", True),)
MOD_FEATURES = []