from urllib import urlencode | |
from urllib2 import urlopen,HTTPError,URLError | |
import socket | |
import re | |
import json | |
try: | |
from unescape_charref import unescape_charref | |
except ImportError: | |
unescape_charref=None | |
class DEE2JSONDecoder(json.JSONDecoder): | |
def __init__(self,encoding=None,**kwgs): | |
# some control sequences are not escaped in string | |
# ex. eventid=105(headline) line 319 u'\t\t\t"Info" : "...\t(^^)"' | |
# toavoid this set strict=False | |
json.JSONDecoder.__init__(self,encoding,strict=False,**kwgs) | |
class DEE2EventData(object): | |
DEE2_URL='http://manbow.nothing.sh/event/event.cgi' | |
GETJSON_PARAM=(('action','JSONList'),) | |
def __init__(self,eventid,name=None): | |
self._eventid=int(eventid) | |
self._name=name if isinstance(name,basestring) else None | |
self._songlist=[] | |
self._headline=[] | |
def getsonglist(self,utf8=False): | |
tmpjson=self._getjson(utf8) | |
if self._name is None: | |
self._name=tmpjson.get('EventName') | |
self._songlist=tmpjson['Data'] | |
def getheadline(self,utf8=False): | |
tmpjson=self._getjson(utf8,(('output','headline'),)) | |
if self._name is None: | |
self._name=tmpjson.get('EventName') | |
self._headline=tmpjson['Data'] | |
def get(self,utf8=False): | |
self.getsonglist(utf8) | |
self.getheadline(utf8) | |
def _getjson(self,utf8,iterable=None): | |
param=self.GETJSON_PARAM | |
if utf8==True: | |
param+=(('utf-8','on'),) | |
if iterable: | |
param+=iterable | |
query=urlencode(param+(('event',self._eventid),)) | |
try: | |
ret=urlopen(self.DEE2_URL+'?'+query).read() | |
except URLError,e: | |
if isinstance(e.reason, socket.timeout): | |
raise Exception("timeout: %s" % e) | |
else: | |
raise | |
except socket.timeout,e: | |
raise Exception("timeout: %s" % e) | |
# fix structure error: [{...},{...},...,{...},] -> [{...},{...},...,{...}] | |
# this may be happen when last registered entry is deleted | |
# ex. eventid=104 BOFU2015 | |
ret=re.sub( | |
r'}\s*,\s*\]\s*}\s*\Z', | |
r'}]}', | |
ret | |
) | |
if not utf8: | |
# remove extra escapes for Damemoji: [cp932 1st byte]\\ -> [cp932 1st byte]\ | |
ret=re.sub( | |
'([\x81-\x9f\xe0-\xfc]'+r'\\)\\', | |
r'\1', | |
ret | |
) | |
# for output=headline | |
# truncated multibyte character involves '"' when decoded | |
# to avoid this, first, inserting ' ' before '"' | |
ret=re.sub( | |
r'^(\s*\".*?\"\s*:\s*\".*)\"(\s*[,\]}]?\s*)$', | |
r'\1 "\2', | |
ret,flags=re.MULTILINE | |
) | |
# second, decode this with errors='replace' | |
# truncated character('[\x81-\x9f\xe0-\xfc] ') generates '\ufffd' | |
# valid string does not change ' ' | |
ret=ret.decode('cp932',errors='replace') | |
# and last, remove ' ' or '\ufffd' from end of each string | |
ret=re.sub( | |
ur'^(\s*\".*?\"\s*:\s*\".*)[ \ufffd]\"(\s*[,\]}]?\s*)$', | |
ur'\1"\2', | |
ret,flags=re.MULTILINE | |
) | |
else: | |
# if utf8 mode, only to do is decoding string | |
ret=ret.decode('cp932',errors='replace') | |
if unescape_charref: | |
# unescape character reference | |
ret=unescape_charref(ret) | |
# in some cases strings contain unescaped '"' | |
# ex. eventid=26 line 2 '\t"EventName" : "B-1 "Unrestricted"" ,' | |
# add escapes to those | |
ret=re.sub( | |
ur'(^\s*\".*?\"\s*:\s*\")(.*\".*)(?=\"\s*[,\]}]?\s*$)', | |
lambda s:s.group(1)+re.sub( | |
ur'((^|[^\\])(?:\\\\)*)(?=\")', | |
ur'\1'+ur'\\', | |
s.group(2) | |
), | |
ret,flags=re.MULTILINE | |
) | |
return json.loads(ret,cls=DEE2JSONDecoder) | |
def clear(self): | |
self._eventid=None | |
self._name=None | |
self._songlist=[] | |
self._headline=[] | |
@property | |
def eventid(self): | |
return self._eventid | |
@eventid.setter | |
def eventid(self,evid): | |
if not getattr(evid,'__int__') or int(evid)<=0: | |
raise ValueError('eventid must be positive integer') | |
elif int(evid)==self.eventid: | |
self._eventid=int(evid) | |
else: | |
self.clear() | |
self._eventid=int(evid) | |
@eventid.deleter | |
def eventid(self): | |
self.clear() | |
@property | |
def eventname(self): | |
return self._name | |
@eventname.setter | |
def eventname(self,name): | |
self._name=name | |
@eventname.deleter | |
def eventname(self): | |
self._name=None | |
@property | |
def songlist(self): | |
return self._songlist | |
@songlist.setter | |
def songlist(self,sl): | |
if getattr(sl, '__iter__'): | |
self._songlist=list(sl) | |
else: | |
self._songlist=[] | |
@songlist.deleter | |
def songlist(self): | |
self._songlist=[] | |
@property | |
def headline(self): | |
return self._headline | |
@headline.setter | |
def headline(self,hl): | |
if getattr(hl, '__iter__'): | |
self._headline=list(hl) | |
else: | |
self._headline=[] | |
@headline.deleter | |
def headline(self): | |
self._headline=[] | |
if __name__=='__main__': | |
import sys | |
import time | |
args=sys.argv | |
if len(args)>=2: | |
for evid in args[1:]: | |
try: | |
ev=DEE2EventData(evid) | |
except: | |
continue | |
ev.get() | |
print u'EventID={} EventName={} songs={}'.format( | |
ev.eventid,ev.eventname,len(ev.songlist) | |
) | |
ev.clear() | |
if len(args)>2:time.sleep(1) | |
else: | |
print u'Usage: dee2.py ID1 ID2 ...' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment