File indexing completed on 2024-04-21 04:01:56
0001 # -*- coding: utf-8 -*- 0002 0003 """ 0004 Copyright (C) 2009-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de> 0005 0006 SPDX-License-Identifier: GPL-2.0 0007 0008 0009 The DBPasswordChecker is based on an example from the book 0010 Twisted Network Programming Essentials by Abe Fettig, 2006 0011 O'Reilly Media, Inc., ISBN 0-596-10032-9 0012 """ 0013 0014 import datetime 0015 0016 from twisted.internet.defer import fail 0017 from twisted.spread import pb 0018 0019 from common import Internal, Debug, Options, StrMixin 0020 from servercommon import srvError 0021 from log import logDebug 0022 from mi18n import i18nE 0023 from query import Query 0024 0025 class User(pb.Avatar, StrMixin): 0026 0027 """the twisted avatar""" 0028 0029 def __init__(self, userid): 0030 self.name = Query( 0031 'select name from player where id=?', 0032 (userid, 0033 )).records[0][0] 0034 self.mind = None 0035 self.server = None 0036 self.dbIdent = None 0037 self.voiceId = None 0038 self.maxGameId = None 0039 self.lastPing = None 0040 self.pinged() 0041 0042 def pinged(self): 0043 """time of last ping or message from user""" 0044 self.lastPing = datetime.datetime.now() 0045 if self.server: 0046 self.server.lastPing = self.lastPing 0047 0048 def source(self): 0049 """how did he connect?""" 0050 result = str(self.mind.broker.transport.getPeer()) 0051 if 'UNIXAddress' in result: 0052 # socket: we want to get the socket name 0053 result = Options.socket 0054 return result 0055 0056 def attached(self, mind): 0057 """override pb.Avatar.attached""" 0058 self.mind = mind 0059 self.server.login(self) 0060 0061 def detached(self, unusedMind): 0062 """override pb.Avatar.detached""" 0063 if Debug.connections: 0064 logDebug( 0065 '%s: connection detached from %s' % 0066 (self, self.source())) 0067 self.server.logout(self) 0068 self.mind = None 0069 0070 def perspective_setClientProperties( 0071 self, dbIdent, voiceId, maxGameId, clientVersion=None): 0072 """perspective_* methods are to be called remotely""" 0073 self.pinged() 0074 self.dbIdent = dbIdent 0075 self.voiceId = voiceId 0076 self.maxGameId = maxGameId 0077 serverVersion = str(Internal.defaultPort) 0078 if clientVersion != serverVersion: 0079 # we assume that versions x.y.* are compatible 0080 if clientVersion is None: 0081 # client passed no version info 0082 return fail(srvError(pb.Error, 0083 i18nE( 0084 'Your client has a version older than 4.9.0 but you need %1 for this server'), 0085 serverVersion)) 0086 commonDigits = len([x for x in zip( 0087 clientVersion.split('.'), 0088 serverVersion.split('.')) 0089 if x[0] == x[1]]) 0090 if commonDigits < 2: 0091 return fail(srvError(pb.Error, 0092 i18nE( 0093 'Your client has version %1 but you need %2 for this server'), 0094 clientVersion or '<4.9.0', 0095 '.'.join(serverVersion.split('.')[:2]) + '.*')) 0096 if Debug.table: 0097 logDebug('client has dbIdent={} voiceId={} maxGameId={} clientVersion {}'.format( 0098 self.dbIdent, self.voiceId, self.maxGameId, clientVersion)) 0099 self.server.sendTables(self) 0100 return None 0101 0102 def perspective_ping(self): 0103 """perspective_* methods are to be called remotely""" 0104 return self.pinged() 0105 0106 def perspective_needRulesets(self, rulesetHashes): 0107 """perspective_* methods are to be called remotely""" 0108 return self.server.needRulesets(rulesetHashes) 0109 0110 def perspective_joinTable(self, tableid): 0111 """perspective_* methods are to be called remotely""" 0112 return self.server.joinTable(self, tableid) 0113 0114 def perspective_leaveTable(self, tableid): 0115 """perspective_* methods are to be called remotely""" 0116 return self.server.leaveTable(self, tableid, None) 0117 0118 def perspective_newTable( 0119 self, ruleset, playOpen, autoPlay, wantedGame: str, tableId=None): 0120 """perspective_* methods are to be called remotely""" 0121 return self.server.newTable(self, ruleset, playOpen, autoPlay, wantedGame, tableId) 0122 0123 def perspective_startGame(self, tableid): 0124 """perspective_* methods are to be called remotely""" 0125 return self.server.startGame(self, tableid) 0126 0127 def perspective_logout(self): 0128 """perspective_* methods are to be called remotely""" 0129 self.detached(None) 0130 0131 def perspective_chat(self, chatString): 0132 """perspective_* methods are to be called remotely""" 0133 self.pinged() 0134 return self.server.chat(chatString) 0135 0136 def __str__(self): 0137 return self.name