diff --git a/README.md b/README.md index e9e9c5b..0601a10 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [更新历史](https://github.com/fffonion/maClient/wiki/HISTORY) ##说明 -密钥已删除,请自行搜索 +no hiding of AES keys any longer, enjoy :) 有关API,请参阅[二次开发文档](https://github.com/fffonion/maClient/wiki/%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3) diff --git a/db/revision.txt b/db/revision.txt index 412451d..d7a42d1 100644 --- a/db/revision.txt +++ b/db/revision.txt @@ -1,2 +1,2 @@ cn,185,184 -tw,176,158 \ No newline at end of file +tw,178,158 \ No newline at end of file diff --git a/maclient.py b/maclient.py index ecf5b7f..abbe0fe 100644 --- a/maclient.py +++ b/maclient.py @@ -26,13 +26,10 @@ import maclient_smart __version__=1.49 #CONSTS: -EXPLORE_BATTLE,NORMAL_BATTLE,WAKE_BATTLE=0,1,2 +EXPLORE_BATTLE,NORMAL_BATTLE,TAIL_BATTLE,WAKE_BATTLE=0,1,2,3 GACHA_FRIENNSHIP_POINT,GACHA_GACHA_TICKET,GACHA_11=1,2,4 EXPLORE_HAS_BOSS,EXPLORE_NO_FLOOR,EXPLORE_OK,EXPLORE_ERROR,EXPLORE_NO_BC= -2,-1,0,1,2 SERV_CN,SERV_CN2,SERV_TW='cn','cn2','tw' -# -NAME_WAKE_RARE=['-NOTHING-'] -NAME_WAKE=NAME_WAKE_RARE+['觉醒','覺醒','超電磁砲'] #eval dicts eval_fairy_select={'LIMIT':'time_limit','NOT_BATTLED':'not_battled','.lv':'.fairy.lv','IS_MINE':'user.id == self.player.id','IS_WAKE_RARE':'wake_rare','IS_WAKE':'wake','STILL_ALIVE':"self.player.fairy['alive']"} eval_fairy_select_carddeck={'IS_MINE':'discoverer_id == self.player.id','IS_WAKE_RARE':'wake_rare','IS_WAKE':'wake','STILL_ALIVE':"self.player.fairy['alive']",'LIMIT':'time_limit'} @@ -149,7 +146,7 @@ def load_config(self): self.loc=='tw' and random.choice(['大家好.','問好']) or random.choice(['你好!','你好!请多指教!'])) self.cfg_factor_getnew=not self._read_config('tactic','factor_getnew') == '0' self.cfg_auto_update= not self._read_config('system','auto_update') == '0' - logging.basicConfig(level=self._read_config('system','loglevel')) + logging.basicConfig(level=self._read_config('system','loglevel') or '2') logging.setlogfile('events_%s.log'%self.loc) self.cfg_delay=float(self._read_config('system','delay')) self.cfg_display_ani=(self._read_config('system','display_ani') or '1')=='1' @@ -157,7 +154,7 @@ def load_config(self): def set_remote(self,remoteInstance): self.remote=remoteInstance self.remoteHdl=(self.remote ==None and (lambda method=None,fairy='':True) or self.remote_Hdl_()) - if self.remote !=None: + if self.remote: res,msg=self.remote.login() if res: logging.debug('remote_hdl:%s'%msg) @@ -447,7 +444,7 @@ def initplayer(self,xml): self.stitle.start() def auto_check(self,doingwhat): - if not doingwhat in ['login','check_inspection','notification/post_devicetoken','card/exchange', 'trunk/sell','roundtable/edit','cardselect/savedeckcard','friend/like_user','comment/send']: + if doingwhat in ['exploration/fairybattle','exploration/explore','gacha/buy']: if int(self.player.card.count) >= getattr(maclient_smart,'max_card_count_%s'%self.loc): if self.cfg_auto_sell: logging.info(du8('卡片放满了,自动卖卡 v( ̄▽ ̄*)')) @@ -1004,9 +1001,9 @@ def fairy_select(self,cond=''): fairy['time_limit']=int(fairy.fairy.time_limit) fairy['wake']=False fairy['wake_rare']=False - for k in NAME_WAKE: + for k in maclient_smart.name_wake: fairy['wake']=fairy['wake'] or (k in fairy.fairy.name) - for k in NAME_WAKE_RARE: + for k in maclient_smart.name_wake_rare: fairy['wake_rare']=fairy['wake_rare'] or fairy.fairy.name.startswith(k) ftime=(self._read_config('fairy',fairy.fairy.serial_id)+',,').split(',') fairy['not_battled']= ftime[0]=='' @@ -1042,7 +1039,7 @@ def _fairy_rewards(self): rwname.append(rw.item_name) logging.info(', '.join(rwname)+du8(' 已获得')) - def _fairy_battle(self,fairy,type=NORMAL_BATTLE,is_tail=False): + def _fairy_battle(self,fairy,type=NORMAL_BATTLE): while time.time()-self.lastfairytime<20: logging.sleep(du8('等待20s战斗冷却')) time.sleep(5) @@ -1053,8 +1050,9 @@ def fairy_floor(f=fairy): return None else: return XML2Dict().fromstring(ct).response.body.fairy_floor.explore.fairy - if type==NORMAL_BATTLE: - #除了explore中碰到的妖精外,传入的fairy只有部分信息,因此客户端都会POST一个fairy_floor来取得完整信息 + if type==NORMAL_BATTLE or type==TAIL_BATTLE: + #列表打开时,传入的fairy只有部分信息,因此客户端都会POST一个fairy_floor来取得完整信息 + #尾刀需要重新获得妖精血量等 #包含了发现者,小伙伴数量,剩余血量等等s fairy=fairy_floor() if not fairy: @@ -1063,12 +1061,11 @@ def fairy_floor(f=fairy): if fairy.hp=='0': logging.warning(du8('妖精已被消灭')) return False - self.lastfairytime=time.time() fairy['lv']=int(fairy.lv) fairy['hp']=int(fairy.hp) fairy['time_limit']=int(fairy.time_limit) fairy['wake_rare']=False - for k in NAME_WAKE_RARE: + for k in maclient_smart.name_wake_rare: fairy['wake_rare']=fairy['wake_rare'] or k in fairy.name fairy['wake']= fairy.rare_flg=='1' or fairy['wake_rare'] if not 'attacker' in fairy.attacker_history: @@ -1109,8 +1106,9 @@ def fairy_floor(f=fairy): rare_fairy=None need_tail=False win=False - paramf='serial_id=%s&user_id=%s'%(fairy.serial_id,fairy.discoverer_id) + self.lastfairytime=time.time() savet=(cardd=='min') + paramf='serial_id=%s&user_id=%s'%(fairy.serial_id,fairy.discoverer_id) resp,ct=self._dopost('exploration/fairybattle',postdata=paramf,savetraffic=savet) if len(ct)==0: logging.info(du8('舔刀卡组,省流模式开启')) @@ -1141,7 +1139,7 @@ def fairy_floor(f=fairy): win=True logging.info(du8('YOU WIN 233')) #如果是自己的妖精则设为死了 - if type==EXPLORE_BATTLE or type==WAKE_BATTLE:#探索中遇到的和打死变成觉醒后的 + if type!=NORMAL_BATTLE:#探索中遇到的、打死变成觉醒后的和尾刀的 self.player.fairy={'id':0,'alive':False} #觉醒 body=XML2Dict().fromstring(ct).response.body @@ -1164,7 +1162,7 @@ def fairy_floor(f=fairy): hpleft=int(XML2Dict().fromstring(ct).response.body.explore.fairy.hp) logging.info(du8('YOU LOSE- - Fairy-HP:%d'%hpleft)) #立即尾刀触发,如果补刀一次还没打死,就不打了-v- - if self.cfg_fairy_final_kill_hp>=hpleft and not is_tail: + if self.cfg_fairy_final_kill_hp>=hpleft and not type==TAIL_BATTLE: need_tail=True #金币以及经验 logging.info(du8('EXP:+%d(%s) G:+%d(%s)'%( @@ -1244,7 +1242,7 @@ def fairy_floor(f=fairy): #立即尾刀 if need_tail: logging.debug('_fairy_battle:tail battle!') - self._fairy_battle(fairy,type=type,is_tail=True) + self._fairy_battle(fairy,type=TAIL_BATTLE) #接着打醒妖: if rare_fairy!=None: rare_fairy=fairy_floor(f=rare_fairy)# @@ -1252,7 +1250,7 @@ def fairy_floor(f=fairy): logging.info(du8('妖精真正的力量觉醒!'.center(39))) logging.warning('WARNING WARNING WARNING WARNING WARNING') time.sleep(3) - self.player.fairy={'alive':True,'id':rare_fairy.id} + self.player.fairy={'alive':True,'id':rare_fairy.serial_id} self._fairy_battle(rare_fairy,type=WAKE_BATTLE) self.like() #输了,回到妖精界面; 尾刀时是否回妖精界面由尾刀决定,父过程此处跳过 diff --git a/maclient_network.py b/maclient_network.py index 85582dd..8e00b07 100644 --- a/maclient_network.py +++ b/maclient_network.py @@ -8,6 +8,7 @@ import base64 import socket import urllib +import maclient_smart try: import httplib except ImportError: @@ -15,13 +16,7 @@ try: import httplib2 except ImportError: - print('httplib2 not found on this machine. You can download it here. https://github.com/fffonion/httplib2-plus') -#key={'res': '*'*16,'helper':'*'*16,'crypt':'*'*16 -# } -key_cntw={'res': '*'*16,'helper':'*'*16,'crypt':'*'*16 - } -key_jp={'res': 'A1dPUcrvur2CRQyl','helper':'A1dPUcrvur2CRQyl','crypt':'uH9JF2cHf6OppaC1' - } + print('httplib2 not found in python libs. You can download it here: https://github.com/fffonion/httplib2-plus') serv={'cn':'http://game1-CBT.ma.sdo.com:10001/connect/app/','cn_data':'http://MA.webpatch.sdg-china.com/', 'cn2':'http://game2-CBT.ma.sdo.com:10001/connect/app/','cn2_data':'http://MA.webpatch.sdg-china.com/', @@ -34,10 +29,7 @@ SLOW_MODE=False def init_cipher(loc='cn'): - if loc in ['cn','tw']: - _key=key_cntw - else: - _key=key_jp + _key=getattr(maclient_smart,'key_%s'%loc) try: from Crypto.Cipher import AES return AES.new(_key['res'], AES.MODE_ECB),\ @@ -50,8 +42,7 @@ def init_cipher(loc='cn'): True COD_RES,COD_DATA,SLOW_MODE=init_cipher() -BS=16 -pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) +pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16) unpad = lambda s : s[0:-ord(s[-1])] du8=lambda str:str.decode('utf-8') ht=httplib2.Http(timeout=15) @@ -75,13 +66,13 @@ def encode_data64(bytein): def encode_param(param): p=param.split('&') - p_enc='%0A&'.join([p[i].split('=')[0]+'='+encode_data64(p[i].split('=')[1]) for i in xrange(len(p))]) + p_enc='%0A&'.join(['%s=%s'%(p[i].split('=')[0],encode_data64(p[i].split('=')[1])) for i in xrange(len(p))]) #print p_enc return p_enc.replace('\n','') def decode_param(param_enc): p_enc=param_enc.split('&') - p='%0A&'.join([p_enc[i].split('=')[0]+'='+decode_data64(p_enc[i].split('=')[1]) for i in xrange(len(p_enc))]) + p='%0A&'.join(['%s=%s'%(p_enc[i].split('=')[0],decode_data64(p_enc[i].split('=')[1])) for i in xrange(len(p_enc))]) return p def urlunescape(url): @@ -166,6 +157,11 @@ def post(self,uri,postdata='',usecookie=True,setcookie=True,extraheader={'Cookie self.logger.warning('post:socket closed, retrying in %d times'%(ttimes-trytime)) except httplib2.ServerNotFoundError: self.logger.warning('post:no internet, retrying in %d times'%(ttimes-trytime)) + except TypeError:#使用了官方版的httplib2 + if savetraffic and self.issavetraffic: + self.logger.warning(du8('你正在使用官方版的httplib2,因此省流模式将无法正常工作')) + resp,content=ht.request('%s%s%s'%(serv[self.servloc],uri,not noencrypt and '?cyt=1' or ''),method='POST',headers=header,body=postdata) + break else: if int(resp['status'])<400: break @@ -196,4 +192,4 @@ def post(self,uri,postdata='',usecookie=True,setcookie=True,extraheader={'Cookie return resp,dec if __name__=="__main__": - print(decode_param('S=l%2BSLkFbck3jK7ftUq4XEWUgdXcgDbKVDRxUYqRmWhpE%3D%0A&revision=NzgOGTK08BvkZN5q8XvG6Q%3D%3D%0A')) \ No newline at end of file + print(decode_param('')) \ No newline at end of file diff --git a/maclient_player.py b/maclient_player.py index 9d9d788..a5349be 100644 --- a/maclient_player.py +++ b/maclient_player.py @@ -36,7 +36,9 @@ def calc_ap_bc(self): #正常计算AP BC 变动 for key in ['ap','bc']: if self.hasattr(key): - getattr(self,key)['current']+=(time.time()-int(getattr(self,key)['current_time']))/int(getattr(self,key)['interval_time']) + getattr(self,key)['current']+=( + time.time()-int(getattr(self,key)['current_time']))/int(getattr(self,key)['interval_time']) + getattr(self,key)['current_time']=int(time.time()) if getattr(self,key)['current']>=getattr(self,key)['max']: getattr(self,key)['current']=getattr(self,key)['max'] diff --git a/maclient_smart.py b/maclient_smart.py index 554e383..a8a8380 100644 --- a/maclient_smart.py +++ b/maclient_smart.py @@ -9,7 +9,13 @@ max_card_count_tw=250 max_fp_cn=max_fp_cn=10000 max_fp_tw=1000000 - +key_cn=key_tw={'res': 'A1dPUcrvur2CRQyl','helper':'A1dPUcrvur2CRQyl','crypt':'rBwj1MIAivVN222b' + } +key_jp={'res': 'A1dPUcrvur2CRQyl','helper':'A1dPUcrvur2CRQyl','crypt':'uH9JF2cHf6OppaC1' + } +#wake +name_wake_rare=['-NOTHING-'] +name_wake=name_wake_rare+['觉醒','覺醒','超電磁砲'] #snda gplus class snda_gplus(): def __init__(self):