user.py 4.46 KB
Newer Older
louiz’'s avatar
louiz’ committed
1
# Copyright 2010-2011 Florent Le Coz <louiz@louiz.org>
2 3 4 5
#
# This file is part of Poezio.
#
# Poezio is free software: you can redistribute it and/or modify
6
# it under the terms of the zlib license. See the COPYING file.
7 8
"""
Define the user class.
9
A user is a MUC participant, not a roster contact (see contact.py)
10 11
"""

mathieui's avatar
mathieui committed
12
import logging
13
from datetime import timedelta, datetime
14
from hashlib import md5
mathieui's avatar
mathieui committed
15 16
from random import choice
from typing import Optional, Tuple
17

mathieui's avatar
mathieui committed
18
from poezio import xhtml, colors
mathieui's avatar
mathieui committed
19
from poezio.theming import get_theme
mathieui's avatar
mathieui committed
20
from slixmpp import JID
21

22 23
log = logging.getLogger(__name__)

mathieui's avatar
mathieui committed
24 25
ROLE_DICT = {'': 0, 'none': 0, 'visitor': 1, 'participant': 2, 'moderator': 3}

26

27
class User:
28
    """
29
    keep track of a user in a Room
30
    """
mathieui's avatar
mathieui committed
31 32 33 34
    __slots__ = ('last_talked', 'jid', 'chatstate', 'affiliation', 'show',
                 'status', 'role', 'nick', 'color')

    def __init__(self,
mathieui's avatar
mathieui committed
35 36 37 38 39 40
                 nick: str,
                 affiliation: str,
                 show: str,
                 status: str,
                 role: str,
                 jid: JID,
mathieui's avatar
mathieui committed
41
                 deterministic=True,
42
                 color='') -> None:
mathieui's avatar
mathieui committed
43 44
        # The oldest possible time
        self.last_talked = datetime(1, 1, 1)  # type: datetime
45 46
        self.update(affiliation, show, status, role)
        self.change_nick(nick)
mathieui's avatar
mathieui committed
47 48 49
        self.jid = jid  # type: JID
        self.chatstate = None  # type: Optional[str]
        self.color = (1, 1)  # type: Tuple[int, int]
50 51
        if color != '':
            self.change_color(color, deterministic)
52
        else:
53 54 55 56
            if deterministic:
                self.set_deterministic_color()
            else:
                self.color = choice(get_theme().LIST_COLOR_NICKNAMES)
57

58
    def set_deterministic_color(self) -> None:
59
        theme = get_theme()
60 61
        if theme.ccg_palette:
            # use XEP-0392 CCG
62
            if self.jid and self.jid.domain:
Jonas Schäfer's avatar
Jonas Schäfer committed
63
                input_ = self.jid.bare
64 65 66
            else:
                input_ = self.nick
            fg_color = colors.ccg_text_to_color(theme.ccg_palette, input_)
67 68 69
            self.color = fg_color, -1
        else:
            mod = len(theme.LIST_COLOR_NICKNAMES)
Link Mauve's avatar
Link Mauve committed
70 71
            nick_pos = int(md5(self.nick.encode('utf-8')).hexdigest(),
                           16) % mod
72
            self.color = theme.LIST_COLOR_NICKNAMES[nick_pos]
73

mathieui's avatar
mathieui committed
74
    def update(self, affiliation: str, show: str, status: str, role: str):
75 76 77
        self.affiliation = affiliation
        self.show = show
        self.status = status
Link Mauve's avatar
Link Mauve committed
78
        if role not in ROLE_DICT:  # avoid invalid roles
louiz’'s avatar
louiz’ committed
79
            role = ''
80 81
        self.role = role

mathieui's avatar
mathieui committed
82
    def change_nick(self, nick: str):
83
        self.nick = nick
84

mathieui's avatar
mathieui committed
85
    def change_color(self, color_name: Optional[str], deterministic=False):
86
        color = xhtml.colors.get(color_name)
mathieui's avatar
mathieui committed
87
        if color is None:
mathieui's avatar
mathieui committed
88
            log.error('Unknown color "%s"', color_name)
89 90 91 92 93 94 95
            if deterministic:
                self.set_deterministic_color()
            else:
                self.color = choice(get_theme().LIST_COLOR_NICKNAMES)
        else:
            self.color = (color, -1)

mathieui's avatar
mathieui committed
96
    def set_last_talked(self, time: datetime):
97 98 99
        """
        time: datetime object
        """
100 101
        if time > self.last_talked:
            self.last_talked = time
102

mathieui's avatar
mathieui committed
103
    def has_talked_since(self, t: int) -> bool:
104
        """
105
        t: int
106 107 108 109 110 111 112 113
        Return True if the user talked since the last s seconds
        """
        if self.last_talked is None:
            return False
        delta = timedelta(0, t)
        if datetime.now() - delta > self.last_talked:
            return False
        return True
114

mathieui's avatar
mathieui committed
115
    def __repr__(self) -> str:
116
        return ">%s<" % (self.nick)
117

mathieui's avatar
mathieui committed
118
    def __eq__(self, b) -> bool:
mathieui's avatar
mathieui committed
119
        return self.role == b.role and self.nick == b.nick
120

mathieui's avatar
mathieui committed
121
    def __gt__(self, b) -> bool:
122 123 124 125
        if ROLE_DICT[self.role] == ROLE_DICT[b.role]:
            return self.nick.lower() > b.nick.lower()
        return ROLE_DICT[self.role] < ROLE_DICT[b.role]

mathieui's avatar
mathieui committed
126
    def __ge__(self, b) -> bool:
127 128 129 130
        if ROLE_DICT[self.role] == ROLE_DICT[b.role]:
            return self.nick.lower() >= b.nick.lower()
        return ROLE_DICT[self.role] <= ROLE_DICT[b.role]

mathieui's avatar
mathieui committed
131
    def __lt__(self, b) -> bool:
132 133 134 135
        if ROLE_DICT[self.role] == ROLE_DICT[b.role]:
            return self.nick.lower() < b.nick.lower()
        return ROLE_DICT[self.role] > ROLE_DICT[b.role]

mathieui's avatar
mathieui committed
136
    def __le__(self, b) -> bool:
137 138 139
        if ROLE_DICT[self.role] == ROLE_DICT[b.role]:
            return self.nick.lower() <= b.nick.lower()
        return ROLE_DICT[self.role] >= ROLE_DICT[b.role]