2016-06-07 11:42:53 -04:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2016-06-12 11:52:44 -04:00
|
|
|
import datetime
|
2016-05-08 15:32:37 -04:00
|
|
|
import logging
|
2016-06-10 10:48:45 -04:00
|
|
|
from collections import MutableMapping
|
2016-05-08 15:32:37 -04:00
|
|
|
|
|
|
|
from tsstats.exceptions import InvalidLog
|
|
|
|
|
2016-05-10 16:50:34 -04:00
|
|
|
logger = logging.getLogger('tsstats')
|
|
|
|
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-18 16:42:42 -04:00
|
|
|
class Clients(MutableMapping):
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
2016-05-18 16:42:42 -04:00
|
|
|
A high-level-interface to multiple Client-objects
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
2016-05-18 16:42:42 -04:00
|
|
|
def __init__(self, ident_map=None, *args, **kwargs):
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
|
|
|
Initialize a new Client-collection
|
|
|
|
|
2016-06-08 16:11:37 -04:00
|
|
|
:param ident_map: Identity-map (see :doc:`identmap`)
|
2016-05-18 15:27:18 -04:00
|
|
|
:type ident_map: dict
|
|
|
|
'''
|
2016-05-18 16:42:42 -04:00
|
|
|
self.ident_map = ident_map or {}
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-18 16:42:42 -04:00
|
|
|
self.store = dict()
|
|
|
|
self.update(dict(*args, **kwargs))
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-18 16:42:42 -04:00
|
|
|
def __add__(self, client):
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
|
|
|
Add a Client to the collection
|
|
|
|
|
2016-05-18 16:42:42 -04:00
|
|
|
:param client: Client to add to the collection
|
|
|
|
:type id_or_uid: Client
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
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
|
2016-05-08 15:32:37 -04:00
|
|
|
|
|
|
|
def __iter__(self):
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
|
|
|
Yield all Client-objects from the collection
|
|
|
|
'''
|
2016-05-18 16:42:42 -04:00
|
|
|
return iter(self.store.values())
|
|
|
|
|
|
|
|
def __getitem__(self, key):
|
2016-05-19 09:22:16 -04:00
|
|
|
return self.store[self.ident_map.get(key, key)]
|
2016-05-18 16:42:42 -04:00
|
|
|
|
|
|
|
def __delitem__(self, key):
|
|
|
|
del self.store[key]
|
|
|
|
|
|
|
|
def __len__(self):
|
|
|
|
return len(self.store)
|
|
|
|
|
|
|
|
def __setitem__(self, key, value):
|
2017-03-31 16:39:57 -04:00
|
|
|
self.store[self.ident_map.get(key, key)] = value
|
2016-05-08 15:32:37 -04:00
|
|
|
|
|
|
|
|
2016-05-11 14:53:17 -04:00
|
|
|
class Client(object):
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
|
|
|
Client provides high-level-access to a Teamspeak-Client
|
|
|
|
'''
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-19 09:24:18 -04:00
|
|
|
def __init__(self, identifier, nick=None):
|
2016-05-18 15:27:18 -04:00
|
|
|
'''
|
|
|
|
Initialize a new Client
|
|
|
|
|
|
|
|
:param identifier: Identifier of the client
|
|
|
|
:type identifier: int or str
|
|
|
|
'''
|
2016-05-08 15:32:37 -04:00
|
|
|
# public
|
|
|
|
self.identifier = identifier
|
2016-05-19 09:24:18 -04:00
|
|
|
self.nick = nick
|
2017-02-11 16:14:34 -05:00
|
|
|
self.nick_history = set()
|
2016-05-08 15:32:37 -04:00
|
|
|
self.connected = 0
|
2016-06-12 11:52:44 -04:00
|
|
|
self.onlinetime = datetime.timedelta()
|
2016-05-08 15:32:37 -04:00
|
|
|
self.kicks = 0
|
|
|
|
self.pkicks = 0
|
|
|
|
self.bans = 0
|
|
|
|
self.pbans = 0
|
2016-06-12 11:52:44 -04:00
|
|
|
self.last_seen = None
|
2016-05-08 15:32:37 -04:00
|
|
|
# private
|
|
|
|
self._last_connect = 0
|
|
|
|
|
|
|
|
def connect(self, timestamp):
|
|
|
|
'''
|
2016-05-18 15:27:18 -04:00
|
|
|
Connect client at `timestamp`
|
|
|
|
|
|
|
|
:param timestamp: time of connect
|
|
|
|
:type timestamp: int
|
2016-05-08 15:32:37 -04:00
|
|
|
'''
|
2016-10-04 09:18:08 -04:00
|
|
|
logger.debug('[%s] CONNECT %s', timestamp, self)
|
2016-05-08 15:32:37 -04:00
|
|
|
self.connected += 1
|
|
|
|
self._last_connect = timestamp
|
|
|
|
|
|
|
|
def disconnect(self, timestamp):
|
|
|
|
'''
|
2016-05-18 15:27:18 -04:00
|
|
|
Disconnect client at `timestamp`
|
|
|
|
|
|
|
|
:param timestamp: time of disconnect
|
|
|
|
:type timestamp: int
|
2016-05-08 15:32:37 -04:00
|
|
|
'''
|
2016-10-04 09:18:08 -04:00
|
|
|
logger.debug('[%s] DISCONNECT %s', timestamp, self)
|
2016-05-08 15:32:37 -04:00
|
|
|
if not self.connected:
|
2016-05-10 16:50:34 -04:00
|
|
|
logger.debug('^ disconnect before connect')
|
2016-05-08 15:32:37 -04:00
|
|
|
raise InvalidLog('disconnect before connect!')
|
|
|
|
self.connected -= 1
|
|
|
|
session_time = timestamp - self._last_connect
|
2016-10-04 09:21:05 -04:00
|
|
|
logger.debug('Session lasted %s', session_time)
|
2016-05-08 15:32:37 -04:00
|
|
|
self.onlinetime += session_time
|
|
|
|
self.last_seen = timestamp
|
|
|
|
|
|
|
|
def kick(self, target):
|
|
|
|
'''
|
2016-05-18 15:27:18 -04:00
|
|
|
Let client kick `target`
|
|
|
|
|
|
|
|
:param target: client to kick
|
|
|
|
:type target: Client
|
2016-05-08 15:32:37 -04:00
|
|
|
'''
|
2016-05-11 14:45:42 -04:00
|
|
|
logger.debug('KICK %s -> %s', self, target)
|
2016-05-08 15:32:37 -04:00
|
|
|
target.pkicks += 1
|
|
|
|
self.kicks += 1
|
|
|
|
|
|
|
|
def ban(self, target):
|
|
|
|
'''
|
2016-05-18 15:27:18 -04:00
|
|
|
Let client ban `target`
|
|
|
|
|
|
|
|
:param target: client to ban
|
|
|
|
:type target: Client
|
2016-05-08 15:32:37 -04:00
|
|
|
'''
|
2016-05-11 14:45:42 -04:00
|
|
|
logger.debug('BAN %s -> %s', self, target)
|
2016-05-08 15:32:37 -04:00
|
|
|
target.pbans += 1
|
|
|
|
self.bans += 1
|
|
|
|
|
|
|
|
def __str__(self):
|
2017-05-15 16:47:04 -04:00
|
|
|
return u'<{},{}>'.format(self.identifier, self.nick)
|