TeamspeakStats/tsstats/client.py

174 lines
4.6 KiB
Python
Raw Permalink Normal View History

# -*- coding: utf-8 -*-
import datetime
import logging
2023-01-14 06:16:21 -05:00
from collections.abc import MutableMapping
logger = logging.getLogger('tsstats')
class Clients(MutableMapping):
'''
A high-level-interface to multiple Client-objects
'''
def __init__(self, ident_map=None, *args, **kwargs):
'''
Initialize a new Client-collection
:param ident_map: Identity-map (see :doc:`identmap`)
:type ident_map: dict
'''
self.ident_map = ident_map or {}
self.store = dict()
self.update(dict(*args, **kwargs))
def apply_events(self, events):
'''
Apply events to this Client-collection
:param events: list of events to apply
:type events: list
'''
for event in events:
# find corresponding client
client = self.setdefault(
event.identifier,
Client(self.ident_map.get(event.identifier, event.identifier))
)
if event.action == 'set_nick':
client.nick = event.arg
continue
if event.arg_is_client:
# if arg is client, replace identifier with Client-obj
event = event._replace(
arg=self.setdefault(event.arg, Client(event.arg))
)
client.__getattribute__(event.action)(event.arg)
def __add__(self, client):
'''
Add a Client to the collection
:param client: Client to add to the collection
:type id_or_uid: Client
'''
2017-05-14 17:28:59 -04:00
identifier = client.identifier
self.store[self.ident_map.get(identifier, identifier)] = client
2016-05-19 09:23:11 -04:00
return self
def __iter__(self):
'''
Yield all Client-objects from the collection
'''
return iter(self.store.keys())
def __getitem__(self, key):
2016-05-19 09:22:16 -04:00
return self.store[self.ident_map.get(key, key)]
def __delitem__(self, key):
del self.store[key]
def __len__(self):
return len(self.store)
def __setitem__(self, key, value):
self.store[self.ident_map.get(key, key)] = value
def __str__(self):
return str(list(map(str, self)))
2016-05-11 14:53:17 -04:00
class Client(object):
'''
Client provides high-level-access to a Teamspeak-Client
'''
def __init__(self, identifier, nick=None):
'''
Initialize a new Client
:param identifier: Identifier of the client
:type identifier: int or str
'''
# public
self.identifier = identifier
self._nick = nick
self.nick_history = set()
self.connected = 0
self.onlinetime = datetime.timedelta()
self.kicks = 0
self.pkicks = 0
self.bans = 0
self.pbans = 0
self.last_seen = None
# private
self._last_connect = 0
@property
def nick(self):
return self._nick
@nick.setter
def nick(self, new_nick):
if self._nick and new_nick != self._nick:
# add old nick to history
self.nick_history.add(self._nick)
# set new nick
self._nick = new_nick
def connect(self, timestamp):
'''
Connect client at `timestamp`
:param timestamp: time of connect
:type timestamp: int
'''
logger.debug('[%s] CONNECT %s', timestamp, self)
self.connected += 1
self._last_connect = timestamp
def disconnect(self, timestamp):
'''
Disconnect client at `timestamp`
:param timestamp: time of disconnect
:type timestamp: int
'''
logger.debug('[%s] DISCONNECT %s', timestamp, self)
if not self.connected:
logger.debug('^ disconnect before connect')
return
self.connected -= 1
session_time = timestamp - self._last_connect
logger.debug('Session lasted %s', session_time)
self.onlinetime += session_time
self.last_seen = timestamp
def kick(self, target):
'''
Let client kick `target`
:param target: client to kick
:type target: Client
'''
2016-05-11 14:45:42 -04:00
logger.debug('KICK %s -> %s', self, target)
target.pkicks += 1
self.kicks += 1
def ban(self, target):
'''
Let client ban `target`
:param target: client to ban
:type target: Client
'''
2016-05-11 14:45:42 -04:00
logger.debug('BAN %s -> %s', self, target)
target.pbans += 1
self.bans += 1
def __str__(self):
return u'<{}, {}>'.format(self.identifier, self.nick)
2017-08-23 14:42:28 -04:00
def __repr__(self):
return self.__str__()