import re from datetime import datetime from xml.dom import minidom from operator import itemgetter from django.contrib.auth.models import User from django.http import HttpResponse from django.core.urlresolvers import reverse from django.shortcuts import get_object_or_404 from django.conf import settings from django.utils.timezone import now from BeautifulSoup import BeautifulSoup from piston.handler import BaseHandler from piston.utils import rc, throttle from gargoyle import gargoyle from api.models import AuthAPIKey, AuthAPILog from eve_proxy.models import CachedDocument from eve_proxy.exceptions import * from eve_api.app_defines import * from eve_api.models import EVEAccount, EVEPlayerCharacter from sso.models import ServiceAccount, Service from hr.app_defines import * from hr.models import Blacklist class UserHandler(BaseHandler): allowed_methods = ('GET') def read(self, request): if 'userid' in request.GET: try: u = User.objects.get(id=request.GET['userid']) except (User.DoesNotExist, ValueError): return {'auth': 'missing', 'missing': 'userid'} elif 'user' in request.GET: try: u = User.objects.get(username=request.GET['user']) except User.DoesNotExist: return {'auth': 'missing', 'missing': 'username'} elif 'serviceuid' in request.GET: try: u = ServiceAccount.objects.get(service_uid=request.GET['serviceuid']).user except ServiceAccount.DoesNotExist: return {'auth': 'missing', 'missing': 'ServiceAccount'} elif 'apiuserid' in request.GET: try: u = EVEAccount.objects.get(api_user_id=request.GET['apiuserid']).user except EVEAccount.DoesNotExist: return {'auth': 'missing', 'missing': 'apiuserid'} chars = [] for a in u.eveaccount_set.all(): chars.extend(a.characters.all()) d = {'id': u.id, 'username': u.username, 'email': u.email, 'serviceaccounts': u.serviceaccount_set.all(), 'characters': chars, 'groups': u.groups.all(), 'staff': u.is_staff, 'superuser': u.is_superuser, 'redditaccounts': u.redditaccount_set.filter(validated=True) } return d class LoginHandler(BaseHandler): allowed_methods = ('GET') def read(self, request): username = request.GET.get('user', None) character = request.GET.get('character', None) password = request.GET.get('pass', None) if username: u = User.objects.filter(username=username) elif character: u = User.objects.filter(profile__primary_character__name__iexact=character) else: u = User.objects.none() if not u.count(): return {'auth': 'failed', 'error': 'none'} elif u.count() > 1: return {'auth': 'failed', 'error': 'multiple'} else: u = u[0] if u.is_active and password and password == u.get_profile().api_service_password: pchar = u.get_profile().primary_character if pchar: pchardict = {'id': pchar.id, 'name': pchar.name, 'corporation': {'name': pchar.corporation.name, 'id': pchar.corporation.id, 'ticker': pchar.corporation.ticker }, } if pchar.corporation.alliance: pchardict['alliance'] = {'id': pchar.corporation.alliance.id, 'name': pchar.corporation.alliance.name, 'ticker': pchar.corporation.alliance.ticker } else: pchardict['alliance'] = None else: pchardict = None glist = [] for g in u.groups.all(): if u in g.groupinformation.admins.all(): admin = True else: admin = False glist.append({'id': g.id, 'name': g.name, 'admin': admin}) return {'auth': 'ok', 'id': u.id, 'username': u.username, 'email': u.email, 'groups': glist, 'staff': u.is_staff, 'superuser': u.is_superuser, 'primarycharacter': pchardict} else: return {'auth': 'failed', 'error': 'password'} return {'auth': 'missing', 'missing': 'all'} class EveAPIHandler(BaseHandler): allowed_methods = ('GET') exclude = ('api_key') def read(self, request): s = None if request.GET.get('id', None): s = get_object_or_404(EVEAccount, pk=id) elif request.GET.get('userid', None): s = EVEAccount.objects.filter(user=request.GET['userid']) elif request.GET.get('corpid', None): s = EVEAccount.objects.filter(characters__corporation__id=request.GET['corpid']) elif request.GET.get('allianceid', None): s = EVEAccount.objects.filter(characters__corporation__alliance__id=request.GET['allianceid']) if s: return {'keys': s.values('api_user_id', 'user_id', 'api_status', 'api_keytype', 'api_last_updated')} return {'keys': []} class EveAPIProxyHandler(BaseHandler): allowed_methods = ('GET') def read(self, request): url_path = request.META['PATH_INFO'].replace(reverse('api-eveapiproxy'), "/") params = {} for key, value in request.GET.items(): params[key.lower()] = value if 'userid' in params or 'keyid' in params: try: obj = get_object_or_404(EVEAccount, pk=params['userid']) except ValueError: return rc.BAD_REQUEST # "Fix" new style keys if obj.api_keytype >= 3: params['keyid'] = params['userid'] del params['userid'] params['vcode'] = obj.api_key else: params['apikey'] = obj.api_key try: cached_doc = CachedDocument.objects.api_query(url_path, params, service=request.api_key.name) except DocumentRetrievalError, exc: return rc.INTERNAL_ERROR else: return HttpResponse(cached_doc.body) class OpTimerHandler(BaseHandler): allowed_methods = ('GET') def read(self, request, id=None): obj = get_object_or_404(EVEAccount, pk=settings.FULL_API_USER_ID) if gargoyle.is_active('eve-cak'): params = {'keyid': obj.pk, 'vcode': obj.api_key, 'characterID': settings.FULL_API_CHARACTER_ID} else: params = {'userID': obj.pk, 'apiKey': obj.api_key, 'characterID': settings.FULL_API_CHARACTER_ID} error_doc = {'ops': [{'startsIn': -1, 'eventID': 0, 'ownerName': '', 'eventDate': '', 'eventTitle': '
The EVE API calendar is unavailable
', 'duration': 0, 'isImportant': 0, 'eventText': 'Fuck CCP tbqh imho srsly', 'endsIn':-1, 'forumLink': ''}]} try: cached_doc = CachedDocument.objects.api_query('/char/UpcomingCalendarEvents.xml.aspx', params, timeout=10, service="Optimer") except DocumentRetrievalError: return error_doc dom = minidom.parseString(cached_doc.body.encode('utf-8')) if dom.getElementsByTagName('error'): error_doc['raw_xml'] = cached_doc.body return error_doc events = [] for node in dom.getElementsByTagName('rowset')[0].childNodes: if node.nodeType == 1: ownerID = node.getAttribute('ownerID') if ownerID != '1': dt = datetime.strptime(node.getAttribute('eventDate'), '%Y-%m-%d %H:%M:%S').replace(tzinfo=utc) startsIn = int(dt.strftime('%s')) - int(now().strftime('%s')) duration = int(node.getAttribute('duration')) fid = re.search('topic=[\d]+', node.getAttribute('eventText')) if fid: forumlink = 'http://forum.pleaseignore.com/index.php?%s' % fid.group(0) else: forumlink = '' #In case people forget to set a duration, we'll give a default of 1 hour if duration == 0: duration = 60 endsIn = startsIn + (duration * 60) if startsIn < 0: startsIn = 0 if endsIn > 0: event = { 'startsIn': startsIn, 'eventID': int(node.getAttribute('eventID')), 'ownerName': node.getAttribute('ownerName'), 'eventDate': date, 'eventTitle': node.getAttribute('eventTitle'), 'duration': duration, 'isImportant': int(node.getAttribute('importance')), 'eventText': ' '.join(BeautifulSoup(node.getAttribute('eventText')).findAll(text=True)), 'endsIn':endsIn, 'forumLink': forumlink} events.append(event) if len(events) == 0: return {'ops':[{ 'startsIn': -1, 'eventID': 0, 'ownerName': '', 'eventDate': '', 'eventTitle': '
No ops are currently scheduled
', 'duration': 0, 'isImportant': 0, 'eventText': 'Add ops using EVE-Gate or the in-game calendar', 'endsIn':-1, 'forumLink': ''}]} else: events.sort(key=itemgetter('startsIn')) return {'ops': events, 'doc_time': cached_doc.time_retrieved, 'cache_until': cached_doc.cached_until, 'current_time': now() } class BlacklistHandler(BaseHandler): model = Blacklist allowed_methods = ('GET') fields = ('type', 'value', 'level', 'source', ('name', 'ticker'), 'created_date', 'expiry_date', 'reason') def read(self, request): if request.GET.get('value'): obj = Blacklist.objects.select_related('blacklistsource').filter(level__lte=BLACKLIST_LEVEL_ADVISORY,value__icontains=request.GET.get('value')) if obj.count() and request.GET.get('type'): obj = obj.filter(type=request.GET.get('type')) else: obj = [] return obj class CharacterHandler(BaseHandler): allowed_methods = ('GET') fields = ('id', 'name', ('corporation', ('id', 'name', ('alliance', ('id', 'name')))), 'corporation_date', 'balance', 'total_sp', 'security_status', 'director', 'skillset') @classmethod def skillset(cls, instance): return instance.eveplayercharacterskill_set.all().values('skill__id', 'skill__name', 'level', 'skillpoints') def read(self, request): s = [] if request.GET.get('id', None): s = get_object_or_404(EVEPlayerCharacter, pk=id) elif request.GET.get('corpid', None): s = EVEPlayerCharacter.objects.filter(corporation__id=request.GET['corpid']) elif request.GET.get('allianceid', None): s = EVEPlayerCharacter.objects.filter(corporation__alliance__id=request.GET['allianceid']) return s class AnnounceHandler(BaseHandler): allowed_methods = ('GET') def read(self, request): sid = request.GET.get('sid', None) users = request.GET.getlist('users') groups = request.GET.getlist('groups') servers = request.GET.getlist('servers') message = request.GET.get('message', None) subject = request.GET.get('subject', None) if sid and message: srv = get_object_or_404(Service, pk=sid) if not srv.api == 'sso.services.jabber': return {'result': 'invalid'} api = srv.api_class return {'result': api.announce(api.settings['jabber_server'], message, subject, users=users, groups=groups, servers=servers) } return {'result': 'invalid'} class EDKApiHandler(BaseHandler): allowed_methods = ('GET',) def read(self, request): alliance = request.GET.get('alliance', None) if not alliance: return {'auth': 'missing', 'missing': 'alliance'} objs = EVEAccount.objects.filter(characters__corporation__alliance=alliance, api_keytype=API_KEYTYPE_CORPORATION, api_status=API_STATUS_OK).extra(where=['(api_accessmask & 256) > 0']) return objs.values('api_user_id', 'api_key', 'characters__id', 'characters__name', 'characters__corporation__name')