mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2025-01-09 17:53:50 +00:00
csmud: adjust remotedb
This commit is contained in:
parent
0c04d9d876
commit
49b26c4103
3 changed files with 82 additions and 33 deletions
|
@ -87,7 +87,7 @@ def checkName(name, otherCheckFuncs = [], font = None):
|
||||||
tn = TextNode('NameCheck')
|
tn = TextNode('NameCheck')
|
||||||
tn.setFont(font)
|
tn.setFont(font)
|
||||||
for c in name:
|
for c in name:
|
||||||
if not tn.hasCharacter(unicode(c)):
|
if not tn.hasCharacter(c.decode('utf-8')):
|
||||||
notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c))
|
notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c))
|
||||||
return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(c)
|
return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(c)
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,30 @@
|
||||||
#!/usr/bin/env python2
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
from panda3d.core import *
|
from pandac.PandaModules import *
|
||||||
|
|
||||||
|
|
||||||
username = os.environ['ttsUsername']
|
username = os.environ['ttsUsername']
|
||||||
password = os.environ['ttsPassword']
|
password = os.environ['ttsPassword']
|
||||||
|
|
||||||
accountServerEndpoint = ConfigVariableString(
|
accountServerEndpoint = 'http://www.toontownstride.com/api/'
|
||||||
'account-server-endpoint',
|
session = requests.Session()
|
||||||
'http://tigercat1.me/tmpremote/api/').getValue()
|
csrf_query = session.get(accountServerEndpoint + 'login/')
|
||||||
request = requests.post(
|
csrf = session.cookies.get_dict().get('csrftoken', '')
|
||||||
|
request = session.post(
|
||||||
accountServerEndpoint + 'login/',
|
accountServerEndpoint + 'login/',
|
||||||
data={'n': username, 'p': password})
|
data={'username': username, 'password': password, 'csrfmiddlewaretoken': csrf})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = json.loads(request.text)
|
response = json.loads('{'+request.text.split('{', 1)[1]) # so that we ignore the csrf token
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print "Couldn't verify account credentials."
|
print "Couldn't verify account credentials."
|
||||||
else:
|
else:
|
||||||
if not response['success']:
|
if response['status'] != 7:
|
||||||
print response['reason']
|
print response['message']
|
||||||
else:
|
else:
|
||||||
os.environ['TTS_PLAYCOOKIE'] = response['token']
|
os.environ['TTS_PLAYCOOKIE'] = response['token']
|
||||||
|
os.environ['TTS_GAMESERVER'] = response['gameserver']
|
||||||
|
|
||||||
# Start the game:
|
# Start the game:
|
||||||
import toontown.toonbase.ClientStart
|
import toontown.toonbase.ClientStart
|
||||||
|
|
|
@ -15,7 +15,7 @@ from panda3d.core import *
|
||||||
|
|
||||||
import hashlib, hmac, json
|
import hashlib, hmac, json
|
||||||
import anydbm, math, os
|
import anydbm, math, os
|
||||||
import urllib2, time
|
import urllib2, time, urllib, base64
|
||||||
|
|
||||||
def rejectConfig(issue, securityIssue=True, retarded=True):
|
def rejectConfig(issue, securityIssue=True, retarded=True):
|
||||||
print
|
print
|
||||||
|
@ -42,10 +42,14 @@ def entropyIdeal(length):
|
||||||
accountDBType = config.GetString('accountdb-type', 'developer')
|
accountDBType = config.GetString('accountdb-type', 'developer')
|
||||||
accountServerSecret = config.GetString('account-server-secret', 'dev')
|
accountServerSecret = config.GetString('account-server-secret', 'dev')
|
||||||
accountServerHashAlgo = config.GetString('account-server-hash-algo', 'sha512')
|
accountServerHashAlgo = config.GetString('account-server-hash-algo', 'sha512')
|
||||||
|
apiSecret = accountServerSecret = config.GetString('api-key', 'dev')
|
||||||
if accountDBType == 'remote':
|
if accountDBType == 'remote':
|
||||||
if accountServerSecret == 'dev':
|
if accountServerSecret == 'dev':
|
||||||
rejectConfig('you have not changed the secret in config/local.prc')
|
rejectConfig('you have not changed the secret in config/local.prc')
|
||||||
|
|
||||||
|
if apiSecret == 'dev':
|
||||||
|
rejectConfig('you have not changed the api key in config/local.prc')
|
||||||
|
|
||||||
if len(accountServerSecret) < 16:
|
if len(accountServerSecret) < 16:
|
||||||
rejectConfig('the secret is too small! Make it 16+ bytes', retarded=False)
|
rejectConfig('the secret is too small! Make it 16+ bytes', retarded=False)
|
||||||
|
|
||||||
|
@ -67,18 +71,17 @@ minAccessLevel = config.GetInt('min-access-level', 100)
|
||||||
|
|
||||||
def executeHttpRequest(url, **extras):
|
def executeHttpRequest(url, **extras):
|
||||||
# TO DO: THIS IS QUITE DISGUSTING
|
# TO DO: THIS IS QUITE DISGUSTING
|
||||||
# INSTEAD OF USING THE SAME SECRET, WE SHOULD HAVE AN API KEY EXCLUSIVE TO THAT
|
|
||||||
# MOVE THIS TO ToontownInternalRepository (this might be interesting for AI)
|
# MOVE THIS TO ToontownInternalRepository (this might be interesting for AI)
|
||||||
request = urllib2.Request('http://tigercat1.me/tmpremote/api/' + url)
|
_data = {}
|
||||||
timestamp = str(int(time.time()))
|
if len(extras.items()) != 0:
|
||||||
signature = hashlib.sha256(timestamp + accountServerSecret + "h*^ahJGHA017JI&A&*uyhU07")
|
|
||||||
request.add_header('User-Agent', 'TTS-CSM')
|
|
||||||
request.add_header('X-CSM-Timestamp', timestamp)
|
|
||||||
request.add_header('X-CSM-Signature', signature.hexdigest())
|
|
||||||
for k, v in extras.items():
|
for k, v in extras.items():
|
||||||
request.add_header('X-CSM-' + k, v)
|
_data[k] = v
|
||||||
|
signature = hashlib.sha512(json.dumps(_data) + apiSecret).hexdigest()
|
||||||
|
data = urllib.urlencode({'data': json.dumps(_data), 'hmac': signature})
|
||||||
|
req = urllib2.Request('http://www.toontownstride.com/api/' + url, data)
|
||||||
|
req.get_method = lambda: "POST"
|
||||||
try:
|
try:
|
||||||
return urllib2.urlopen(request).read()
|
return urllib2.urlopen(req).read()
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -103,7 +106,8 @@ def executeHttpRequestAndLog(url, **extras):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
blacklist = executeHttpRequest('names/blacklist.json')
|
#blacklist = executeHttpRequest('names/blacklist.json') # todo; create a better system for this
|
||||||
|
blacklist = json.dumps(["none"])
|
||||||
if blacklist:
|
if blacklist:
|
||||||
blacklist = json.loads(blacklist)
|
blacklist = json.loads(blacklist)
|
||||||
|
|
||||||
|
@ -139,7 +143,7 @@ class AccountDB:
|
||||||
def addNameRequest(self, avId, name):
|
def addNameRequest(self, avId, name):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getNameStatus(self, avId):
|
def getNameStatus(self, avId, callback = None):
|
||||||
return 'APPROVED'
|
return 'APPROVED'
|
||||||
|
|
||||||
def removeNameRequest(self, avId):
|
def removeNameRequest(self, avId):
|
||||||
|
@ -183,17 +187,36 @@ class RemoteAccountDB(AccountDB):
|
||||||
# CURRENTLY IT MAKES n REQUESTS FOR EACH AVATAR
|
# CURRENTLY IT MAKES n REQUESTS FOR EACH AVATAR
|
||||||
# IN THE FUTURE, MAKE ONLY 1 REQUEST
|
# IN THE FUTURE, MAKE ONLY 1 REQUEST
|
||||||
# WHICH RETURNS ALL PENDING AVS
|
# WHICH RETURNS ALL PENDING AVS
|
||||||
|
# ^ done, check before removing todo note
|
||||||
notify = directNotify.newCategory('RemoteAccountDB')
|
notify = directNotify.newCategory('RemoteAccountDB')
|
||||||
|
|
||||||
def addNameRequest(self, avId, name):
|
|
||||||
return executeHttpRequest('names/append', ID=str(avId), Name=name)
|
|
||||||
|
|
||||||
def getNameStatus(self, avId):
|
def addNameRequest(self, avId, name, accountID = None):
|
||||||
#return executeHttpRequest('names/status/?Id=' + str(avId))
|
username = avId
|
||||||
return 'APPROVED' # Override temporarily.
|
if accountID is not None:
|
||||||
|
username = accountID
|
||||||
|
|
||||||
|
res = executeHttpRequest('names', action='set', username=str(username),
|
||||||
|
avId=str(avId), wantedName=name)
|
||||||
|
if res is not None:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getNameStatus(self, accountId, callback = None):
|
||||||
|
r = executeHttpRequest('names', action='get', username=str(accountId))
|
||||||
|
try:
|
||||||
|
r = json.loads(r)
|
||||||
|
if callback is not None:
|
||||||
|
callback(r)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def removeNameRequest(self, avId):
|
def removeNameRequest(self, avId):
|
||||||
return executeHttpRequest('names/remove', ID=str(avId))
|
r = executeHttpRequest('names', action='del', avId=str(avId))
|
||||||
|
if r:
|
||||||
|
return 'SUCCESS'
|
||||||
|
return 'FAILURE'
|
||||||
|
|
||||||
def lookup(self, token, callback):
|
def lookup(self, token, callback):
|
||||||
'''
|
'''
|
||||||
|
@ -213,7 +236,6 @@ class RemoteAccountDB(AccountDB):
|
||||||
try:
|
try:
|
||||||
token = token.decode('base64')
|
token = token.decode('base64')
|
||||||
hash, token = token[:hashSize], token[hashSize:]
|
hash, token = token[:hashSize], token[hashSize:]
|
||||||
|
|
||||||
correctHash = hashAlgo(token + accountServerSecret).digest()
|
correctHash = hashAlgo(token + accountServerSecret).digest()
|
||||||
if len(hash) != len(correctHash):
|
if len(hash) != len(correctHash):
|
||||||
raise ValueError('Invalid hash.')
|
raise ValueError('Invalid hash.')
|
||||||
|
@ -234,6 +256,7 @@ class RemoteAccountDB(AccountDB):
|
||||||
|
|
||||||
return AccountDB.lookup(self, token, callback)
|
return AccountDB.lookup(self, token, callback)
|
||||||
|
|
||||||
|
|
||||||
# --- FSMs ---
|
# --- FSMs ---
|
||||||
class OperationFSM(FSM):
|
class OperationFSM(FSM):
|
||||||
TARGET_CONNECTION = False
|
TARGET_CONNECTION = False
|
||||||
|
@ -457,6 +480,9 @@ class CreateAvatarFSM(OperationFSM):
|
||||||
|
|
||||||
self.account = fields
|
self.account = fields
|
||||||
|
|
||||||
|
# For use in calling name requests:
|
||||||
|
self.accountID = self.account['ACCOUNT_ID']
|
||||||
|
|
||||||
self.avList = self.account['ACCOUNT_AV_SET']
|
self.avList = self.account['ACCOUNT_AV_SET']
|
||||||
# Sanitize:
|
# Sanitize:
|
||||||
self.avList = self.avList[:6]
|
self.avList = self.avList[:6]
|
||||||
|
@ -508,6 +534,8 @@ class CreateAvatarFSM(OperationFSM):
|
||||||
{'ACCOUNT_AV_SET': self.account['ACCOUNT_AV_SET']},
|
{'ACCOUNT_AV_SET': self.account['ACCOUNT_AV_SET']},
|
||||||
self.__handleStoreAvatar)
|
self.__handleStoreAvatar)
|
||||||
|
|
||||||
|
self.accountID = self.account['ACCOUNT_ID']
|
||||||
|
|
||||||
def __handleStoreAvatar(self, fields):
|
def __handleStoreAvatar(self, fields):
|
||||||
if fields:
|
if fields:
|
||||||
self.demand('Kill', 'Database failed to associate the new avatar to your account!')
|
self.demand('Kill', 'Database failed to associate the new avatar to your account!')
|
||||||
|
@ -533,6 +561,9 @@ class AvatarOperationFSM(OperationFSM):
|
||||||
|
|
||||||
self.account = fields
|
self.account = fields
|
||||||
|
|
||||||
|
# For use in calling name requests:
|
||||||
|
self.accountID = self.account['ACCOUNT_ID']
|
||||||
|
|
||||||
self.avList = self.account['ACCOUNT_AV_SET']
|
self.avList = self.account['ACCOUNT_AV_SET']
|
||||||
# Sanitize:
|
# Sanitize:
|
||||||
self.avList = self.avList[:6]
|
self.avList = self.avList[:6]
|
||||||
|
@ -546,6 +577,7 @@ class GetAvatarsFSM(AvatarOperationFSM):
|
||||||
|
|
||||||
def enterStart(self):
|
def enterStart(self):
|
||||||
self.demand('RetrieveAccount')
|
self.demand('RetrieveAccount')
|
||||||
|
self.nameStateData = None
|
||||||
|
|
||||||
def enterQueryAvatars(self):
|
def enterQueryAvatars(self):
|
||||||
self.pendingAvatars = set()
|
self.pendingAvatars = set()
|
||||||
|
@ -585,7 +617,10 @@ class GetAvatarsFSM(AvatarOperationFSM):
|
||||||
if wishNameState == 'OPEN':
|
if wishNameState == 'OPEN':
|
||||||
nameState = 1
|
nameState = 1
|
||||||
elif wishNameState == 'PENDING':
|
elif wishNameState == 'PENDING':
|
||||||
actualNameState = self.csm.accountDB.getNameStatus(avId)
|
if self.nameStateData is None:
|
||||||
|
self.demand('QueryNameState')
|
||||||
|
return
|
||||||
|
actualNameState = self.nameStateData[str(avId)]
|
||||||
self.csm.air.dbInterface.updateObject(
|
self.csm.air.dbInterface.updateObject(
|
||||||
self.csm.air.dbId,
|
self.csm.air.dbId,
|
||||||
avId,
|
avId,
|
||||||
|
@ -610,6 +645,16 @@ class GetAvatarsFSM(AvatarOperationFSM):
|
||||||
self.csm.sendUpdateToAccountId(self.target, 'setAvatars', [potentialAvs])
|
self.csm.sendUpdateToAccountId(self.target, 'setAvatars', [potentialAvs])
|
||||||
self.demand('Off')
|
self.demand('Off')
|
||||||
|
|
||||||
|
def enterQueryNameState(self):
|
||||||
|
def gotStates(data):
|
||||||
|
self.nameStateData = data
|
||||||
|
taskMgr.doMethodLater(0, GetAvatarsFSM.demand, 'demand-QueryAvatars',
|
||||||
|
extraArgs=[self, 'QueryAvatars'])
|
||||||
|
|
||||||
|
self.csm.accountDB.getNameStatus(self.account['ACCOUNT_ID'], gotStates)
|
||||||
|
# We should've called the taskMgr action by now.
|
||||||
|
|
||||||
|
|
||||||
# This inherits from GetAvatarsFSM, because the delete operation ends in a
|
# This inherits from GetAvatarsFSM, because the delete operation ends in a
|
||||||
# setAvatars message being sent to the client.
|
# setAvatars message being sent to the client.
|
||||||
class DeleteAvatarFSM(GetAvatarsFSM):
|
class DeleteAvatarFSM(GetAvatarsFSM):
|
||||||
|
@ -671,6 +716,7 @@ class SetNameTypedFSM(AvatarOperationFSM):
|
||||||
def enterStart(self, avId, name):
|
def enterStart(self, avId, name):
|
||||||
self.avId = avId
|
self.avId = avId
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.set_account_id = None
|
||||||
|
|
||||||
if self.avId:
|
if self.avId:
|
||||||
self.demand('RetrieveAccount')
|
self.demand('RetrieveAccount')
|
||||||
|
@ -680,6 +726,8 @@ class SetNameTypedFSM(AvatarOperationFSM):
|
||||||
self.demand('JudgeName')
|
self.demand('JudgeName')
|
||||||
|
|
||||||
def enterRetrieveAvatar(self):
|
def enterRetrieveAvatar(self):
|
||||||
|
if self.accountID:
|
||||||
|
self.set_account_id = self.accountID
|
||||||
if self.avId and self.avId not in self.avList:
|
if self.avId and self.avId not in self.avList:
|
||||||
self.demand('Kill', 'Tried to name an avatar not in the account!')
|
self.demand('Kill', 'Tried to name an avatar not in the account!')
|
||||||
return
|
return
|
||||||
|
@ -703,7 +751,7 @@ class SetNameTypedFSM(AvatarOperationFSM):
|
||||||
status = judgeName(self.name)
|
status = judgeName(self.name)
|
||||||
|
|
||||||
if self.avId and status:
|
if self.avId and status:
|
||||||
if self.csm.accountDB.addNameRequest(self.avId, self.name):
|
if self.csm.accountDB.addNameRequest(self.avId, self.name, accountID=self.set_account_id):
|
||||||
self.csm.air.dbInterface.updateObject(
|
self.csm.air.dbInterface.updateObject(
|
||||||
self.csm.air.dbId,
|
self.csm.air.dbId,
|
||||||
self.avId,
|
self.avId,
|
||||||
|
|
Loading…
Reference in a new issue