Files
caminus/api/handlers.py
2012-11-18 09:20:04 -05:00

207 lines
8.2 KiB
Python

from piston.handler import AnonymousBaseHandler, BaseHandler
import time
from django.core.cache import cache
from django.conf import settings
import appversion
from minecraft.models import MinecraftProfile
from local.models import Quote
from minecraft.models import MOTD, Server, PlayerSession, Item
from django.db.models import F
from django.http import HttpResponse
from urllib2 import urlopen
import json
from datetime import datetime
from models import cachePlayerList
from events import server_queue, web_queue, chat, server_broadcast, send_web_event, QuitEvent, JoinEvent, PlayerDeathEvent, ServerHeartbeatEvent
from bounty.models import Bounty
from vault.models import VaultSlot
class MOTDHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
def read(self, request, username):
motd = "No MOTD configured!"
motdList = MOTD.objects.all()
if len(motdList) > 0:
motd = motdList[0].text
quote = Quote.objects.order_by('?')
if len(quote) > 0:
motd += "\n"+'"'+quote[0].text+'"'
return {"motd":motd.split('\n')}
class NewPlayerSessionHandler(BaseHandler):
allowed_methods = ('POST',)
def create(self, request, playername):
try:
profile = MinecraftProfile.objects.all().filter(mc_username__iexact=playername)[0]
except IndexError, e:
return {'success': False, 'error': 'User not found', 'permissions': []}
if profile.user.is_active:
if profile.isBanned():
return {'success': False, 'error': 'Your account is banned.', 'permissions': []}
ip = request.POST['ip']
server = request.server
profile = MinecraftProfile.objects.get(mc_username__exact=playername)
session = PlayerSession.objects.create(server=server, player=profile, ip=ip)
send_web_event(JoinEvent(playername))
return {'success': True, 'error': '', 'permissions': profile.serverPermissions(), 'sessionId': session.id}
else:
return {'success': False, 'error': 'Your account is inactive.', 'permissions': []}
class ClosePlayerSessionHandler(BaseHandler):
allowed_methods = ('GET',)
def read(self, request, playername):
sessions = PlayerSession.objects.all().filter(player__mc_username__iexact=playername, end=None)
for session in sessions:
session.end = datetime.now()
session.save()
send_web_event(QuitEvent(playername))
return {'valid': True}
class EconomyHandler(BaseHandler):
allowed_methods = ('PUT','GET')
def read(self, request, playername):
player = MinecraftProfile.objects.get(mc_username__exact=playername)
return {'balance': player.currencyaccount.balance}
def update(self, request, playername):
player = MinecraftProfile.objects.get(mc_username__exact=playername)
delta = request.POST['delta']
newBalance = player.currencyaccount.balance+float(delta)
if newBalance >= 0:
player.currencyaccount.balance = F('balance')+float(delta)
player.currencyaccount.save()
return {'success': True, 'balance': newBalance, 'message': ""}
else:
return {'success': False, 'balance': player.currencyaccount.balance, 'message': "Insufficient balance"}
class ServerPingHandler(BaseHandler):
allowed_methods = ('GET',)
def read(self, request):
return {'identity': request.server, 'api-version': 2, 'server-version': appversion.version()}
class ServerEventHandler(BaseHandler):
allowed_methods = ('GET', 'POST', 'PUT')
def read(self, request):
queue = server_queue(request.server)
queue.watch('caminus-broadcast-%s'%request.server.id)
events = []
job = queue.reserve(timeout=30)
while job:
job.bury()
events.append({'id': job.jid, 'event': json.loads(job.body)})
job = queue.reserve(timeout=0)
return {'events': events, 'is-live': settings.CAMINUS_USE_BEANSTALKD}
def create(self, request):
queue = server_queue(request.server)
try:
queue.delete(int(request.POST['job']))
except Exception, e:
pass
return {'result': 'success'}
def update(self, request):
events = json.loads(request.POST['events'])['events']
for evt in events:
if evt['type'] == 'chat':
chat(evt['payload']['sender'], evt['payload']['message'])
if evt['type'] == 'player-death':
send_web_event(PlayerDeathEvent(evt['payload']['player'],
evt['payload']['message']))
if evt['type'] == 'heartbeat':
cache.set('caminus-server-heartbeat-%s'%(request.server.id), evt['payload'], 86400)
send_web_event(ServerHeartbeatEvent(request.server, evt['payload']))
if evt['type'] == 'player-murder':
bounties = Bounty.objects.filter(target__mc_username=evt['payload']['player'])
killer = MinecraftProfile.objects.get(mc_username=evt['payload']['killer'])
for bounty in bounties:
bounty.close(killer)
if len(bounties) > 0:
server_broadcast("The bounty on %s has been collected."%(evt['payload']['player']))
return {'result': 'success'}
class ChatHandler(BaseHandler):
allowed_methods = ('POST',)
def create(self, request):
chat(request.user.minecraftprofile.mc_username, request.POST['message'])
server_broadcast("<%s> %s"%(request.user.minecraftprofile.mc_username,
request.POST['message']))
class PollHandler(BaseHandler):
allowed_methods = ('GET',)
def read(self, request, timestamp):
serverInfo = cache.get('caminus-server-info')
if serverInfo == None:
cachePlayerList()
pollData = {}
info = {'server': {}, 'user': {}}
info['server'] = cache.get('caminus-server-info')
pollData['is-live'] = settings.CAMINUS_USE_BEANSTALKD
if not request.user.is_anonymous():
info['user']['balance'] = request.user.minecraftprofile.currencyaccount.balance
pollData['events'] = []
pollData['info'] = info
pollData['poll-id'] = timestamp
if timestamp == "0" and settings.CAMINUS_USE_BEANSTALKD:
pollData['poll-id'] = time.time()
latestEvents = cache.get('minecraft-web-events')
if not latestEvents:
latestEvents = []
for e in latestEvents:
pollData['events'].append(json.loads(e))
elif settings.CAMINUS_USE_BEANSTALKD:
eventQueue = web_queue(timestamp)
event = eventQueue.reserve(timeout=30)
while event:
pollData['events'].append(json.loads(event.body))
event.delete()
event = eventQueue.reserve(timeout=0)
return pollData
class VaultHandler(BaseHandler):
allowed_methods = ('PUT','GET')
def read(self, request, playername):
player = MinecraftProfile.objects.get(mc_username__exact=playername)
items = []
for slot in player.vault_slots.all():
data = {}
data['quantity'] = slot.quantity
data['position'] = slot.position
data['item'] = None
data['damage'] = 0
data['data'] = 0
if slot.item:
data['data'] = slot.item.data
data['item'] = slot.item.material
data['damage'] = slot.item.damage
items.append(data)
return {'items': items}
def update(self, request, playername):
player = MinecraftProfile.objects.get(mc_username__exact=playername)
vaultContents = json.loads(request.POST['contents'])['items']
stacks = player.vault_slots.all()
for stack in vaultContents:
updated = False
slot,created = VaultSlot.objects.get_or_create(player=player,
position=stack['position'])
item = Item.get(stack['item'], stack['damage'], stack['data'])
if slot.item != item:
slot.item = item
updated = True
if slot.quantity != stack['quantity']:
slot.quantity = stack['quantity']
updated = True
if updated:
slot.save()
return {'success': True}