diff --git a/.gitignore b/.gitignore index 13d1490..ff4821b 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,5 @@ dmypy.json # Pyre type checker .pyre/ +.idea + diff --git a/ApkTool/MakeTool.py b/ApkTool/MakeTool.py new file mode 100644 index 0000000..756269e --- /dev/null +++ b/ApkTool/MakeTool.py @@ -0,0 +1,387 @@ +# -*- coding:utf-8 -*- +import re +import os +import stat +import shutil +import json +print(os.path.abspath(__name__)) + +import sys + + +RD, WD, XD = 4, 2, 1 +BNS = [RD, WD, XD] +MDS = [ + [stat.S_IRUSR, stat.S_IRGRP, stat.S_IROTH], + [stat.S_IWUSR, stat.S_IWGRP, stat.S_IWOTH], + [stat.S_IXUSR, stat.S_IXGRP, stat.S_IXOTH] +] + +def chmod(path, mode): + if isinstance(mode, int): + mode = str(mode) + if not re.match("^[0-7]{1,3}$", mode): + raise Exception("mode does not conform to ^[0-7]{1,3}$ pattern") + mode = "{0:0>3}".format(mode) + mode_num = 0 + for midx, m in enumerate(mode): + for bnidx, bn in enumerate(BNS): + if (int(m) & bn) > 0: + mode_num += MDS[bnidx][midx] + # os.chmod(path, mode_num) + +#遍历res下的所有文件 +def isFindApk (parent): + for i in os.listdir(parent) : + if i.endswith('.apk') : + print ('find apk file-===%s' %i) + return i; + print ('no apk file=====') + return '' + +def readChannelfile(filename): + try: + print (filename) + f = open(filename) + global channelList + except Exception as e: + print(e) + exit(0) + channelList = json.load(f) + +def backUpManifest(): + if os.path.exists('./AndroidManifest.xml'): + os.remove('./AndroidManifest.xml') + manifestPath = './temp/AndroidManifest.xml' + shutil.copyfile(manifestPath, './AndroidManifest.xml') + print ('manifest info--%s' %manifestPath) + +def modifyChannel(value): + tempXML = '' + f = open('./AndroidManifest.xml') + for line in f : + if line.find('leguChannel') > 0 and easyName != '' : + if easyNameSuffix == "1" : + if value < 10 : + line = '' % (easyName, value) + else : + line = '' % (easyName, value) + else : + line = '' % (easyName) + elif line.find('owner') > 0 and owner != '' : + print ('owner====%s' %line) + line = '' % (owner) + elif line.find('package') > 0 and packageId != '' : + print ('package====%s' %line) + line = '' % (packageId) + elif line.find('appid') > 0 and appid != '' : + print ('appid====%s' %line) + line = '' % (appid) + elif line.find('gism_id') > 0 and gism_id != '' : + print ('gism_id====%s' %line) + line = '' % (gism_id) + elif line.find('gism_name') > 0 and gism_name != '' : + print ('gism_name====%s' %line) + line = '' % (gism_name) + elif line.find('gism_channel') > 0 and gism_channel != '' : + print ('gism_channel====%s' %line) + line = '' % (gism_channel) + elif line.find('lg_ad_id') > 0 and lg_ad_id != '' : + print ('lg_ad_id====%s' %line) + line = '' % (lg_ad_id) + elif line.find('lg_ad_name') > 0 and lg_ad_name != '' : + print ('lg_ad_name====%s' %line) + line = '' % (lg_ad_name) + elif line.find('gactionId') > 0 and gactionId != '' : + print ('gactionId====%s' %line) + line = '' % (gactionId) + elif line.find('gappSecretKey') > 0 and gappSecretKey != '' : + print ('gappSecretKey====%s' %line) + line = '' % (gappSecretKey) + elif line.find('baiduId') > 0 and baiduId != '' : + print ('baiduId====%s' %line) + line = '' % (baiduId) + elif line.find('baiduSecretKey') > 0 and baiduSecretKey != '' : + print ('baiduSecretKey====%s' %line) + line = '' % (baiduSecretKey) + elif line.find('lg_reyun_game_appkey') > 0 and lg_reyun_game_appkey != '' : + print ('lg_reyun_game_appkey====%s' %line) + line = '' % (lg_reyun_game_appkey) + elif line.find('lg_reyun_game_channelId') > 0 and lg_reyun_game_channelId != '' : + print ('lg_reyun_game_channelId====%s' %line) + line = '' % (lg_reyun_game_channelId) + elif line.find('lg_reyun_io_appkey') > 0 and lg_reyun_io_appkey != '' : + print ('lg_reyun_io_appkey====%s' %line) + line = '' % (lg_reyun_io_appkey) + elif line.find('lg_reyun_io_channelId') > 0 and lg_reyun_io_channelId != 0 : + print ('lg_reyun_io_channelId====%s' %line) + line = '' % (lg_reyun_io_channelId) + elif line.find('eventType') > 0 and eventType != '' : + print ('eventType====%s' %line) + line = '' % (eventType) + tempXML += line + f.close() + + output = open('./temp/AndroidManifest.xml', 'w') + output.write(tempXML) + output.close() + if value < 10 : + unsignApk = r'./bin/%s_0%d_unsigned.apk'% (easyName, value) + #chmod(unsignApk, "777") + else : + unsignApk = r'./bin/%s_%d_unsigned.apk'% (easyName, value) + chmod(unsignApk, "777") + + cmdPack = r'java -jar apktool.jar b temp -o %s'% (unsignApk) + os.system(cmdPack) + + if value < 10 : + signedjar = r'./bin/%s_0%d.apk'% (easyName, value) + unsignedjar = r'./bin/%s_0%d_unsigned.apk'% (easyName, value) + chmod(signedjar, "777") + chmod(unsignedjar, "777") + else : + signedjar = r'./bin/%s_%d.apk'% (easyName, value) + unsignedjar = r'./bin/%s_%d_unsigned.apk'% (easyName, value) + chmod(signedjar, "777") + chmod(unsignedjar, "777") + + cmd_sign = r'jarsigner -verbose -digestalg SHA1 -sigalg MD5withRSA -keystore %s -storepass %s -keypass %s -signedjar %s %s %s'% (keystore, storepass, keypass, signedjar, unsignedjar, alianame) + os.system(cmd_sign) + os.remove(unsignedjar); + + +channelList = {} +# +os.system('java -jar apkool.jar empty-framework-dir --force') +readChannelfile('./channel') + +apkName = "" +apkNameSuffix = "0" + +packageId = "" +packageIdSuffix = "0" + +easyName = "" +easyNameSuffix = "0" + +keystore = '' +storepass = '' +alianame = '' +keypass = '' + +owner = '' + +packNum = 0 +start = 0 + +#----------------------- third qudao start---------------------- +appid = '' +gism_id = '' +gism_name = '' +gism_channel = '' +lg_ad_id = '' +lg_ad_name = '' +gactionId = '' +gappSecretKey = '' +baiduId = '' +baiduSecretKey = '' +lg_reyun_game_appkey = '' +lg_reyun_game_channelId = '' +lg_reyun_io_appkey = '' +lg_reyun_io_channelId = '' +eventType = '' + + +#----------------------- third qudao end------------------------ + +print ('-------------------- your channel values --------------------') +#print 'channel list: ', channelList + +if 'apkname' in channelList : + print ('apkname==%s' %channelList['apkname']) + print ('apkname value==%s' %channelList['apkname']['value']) + print ('apkname suffix==%s' %channelList['apkname']['suffix']) + apkName = channelList['apkname']['value'] + apkNameSuffix = channelList['apkname']['suffix'] +else : + apkName = isFindApk('./') + + +if 'packageId' in channelList : + print ('packageId==%s' %channelList['packageId']) + print ('packageId value==%s' %channelList['packageId']['value']) + print ('packageId suffix==%s' %channelList['packageId']['suffix']) + packageId = channelList['packageId']['value'] + packageIdSuffix = channelList['packageId']['suffix'] +else : + print ("no key packageId") + +if 'leguChannel' in channelList : + print ('leguchannel==%s' %channelList['leguChannel']) + print ('leguchannel value==%s' %channelList['leguChannel']['value']) + print ('leguchannel suffix==%s' %channelList['leguChannel']['suffix']) + easyName = channelList['leguChannel']['value'] + easyNameSuffix = channelList['leguChannel']['suffix'] +else : + print ("no key leguChannel") + +if 'keystore' in channelList : + print ('keystore==%s' %channelList['keystore']) + print ('keystore filename==%s' %channelList['keystore']['filename']) + print ('keystore storepass==%s' %channelList['keystore']['storepass']) + print ('keystore alianame==%s' %channelList['keystore']['alianame']) + print ('keystore keypass==%s' %channelList['keystore']['keypass']) + keystore = channelList['keystore']['filename'] + storepass = channelList['keystore']['storepass'] + alianame = channelList['keystore']['alianame'] + keypass = channelList['keystore']['keypass'] +else : + print ("no key keystore") + +if 'owner' in channelList : + print ('owner==%s' %channelList['owner']) + print ('owner value==%s' %channelList['owner']['value']) + owner = channelList['owner']['value'] +else : + print ("no key owner") + +if 'num' in channelList : + print ('num==%s' %channelList['num']) + print ('num value==%s' %channelList['num']['value']) + print ('num start==%s' %channelList['num']['start']) + packNum = int(channelList['num']['value']) + 1 + start = int(channelList['num']['start']) +else : + print ("no key num") + + +if 'appid' in channelList : + print ('appid==%s' %channelList['appid']) + print ('appid value==%s' %channelList['appid']['value']) + gism_id = channelList['appid']['value'] +else : + print ("no key appid") + +if 'gism_id' in channelList : + print ('gism_id==%s' %channelList['gism_id']) + print ('gism_id value==%s' %channelList['gism_id']['value']) + gism_id = channelList['gism_id']['value'] +else : + print ("no key gism_id") + +if 'gism_name' in channelList : + print ('gism_name==%s' %channelList['gism_name']) + print ('gism_name value==%s' %channelList['gism_name']['value']) + gism_name = channelList['gism_name']['value'] +else : + print ("no key gism_name") + +if 'gism_channel' in channelList : + print ('gism_channel==%s' %channelList['gism_channel']) + print ('gism_channel value==%s' %channelList['gism_channel']['value']) + gism_channel = channelList['gism_channel']['value'] +else : + print ("no key gism_channel") + +if 'lg_ad_id' in channelList : + print ('lg_ad_id==%s' %channelList['lg_ad_id']) + print ('lg_ad_id value==%s' %channelList['lg_ad_id']['value']) + lg_ad_id = channelList['lg_ad_id']['value'] +else : + print ("no key lg_ad_id") + +if 'lg_ad_name' in channelList : + print ('lg_ad_name==%s' %channelList['lg_ad_name']) + print ('lg_ad_name value==%s' %channelList['lg_ad_name']['value']) + lg_ad_name = channelList['lg_ad_name']['value'] +else : + print ("no key lg_ad_name") + +if 'gactionId' in channelList : + print ('gactionId==%s' %channelList['gactionId']) + print ('gactionId value==%s' %channelList['gactionId']['value']) + gactionId = channelList['gactionId']['value'] +else : + print ("no key gactionId") + +if 'gappSecretKey' in channelList : + print ('gappSecretKey==%s' %channelList['gappSecretKey']) + print ('gappSecretKey value==%s' %channelList['gappSecretKey']['value']) + gism_id = channelList['gappSecretKey']['value'] +else : + print ("no key gappSecretKey") + +if 'baiduId' in channelList : + print ('baiduId ==%s' %channelList['baiduId']) + print ('baiduId value==%s' %channelList['baiduId']['value']) + gism_id = channelList['baiduId']['value'] +else : + print ("no key baiduId") + +if 'baiduSecretKey' in channelList : + #print 'baiduSecretKey==', channelList['baiduSecretKey'] + #print 'baiduSecretKey value==', channelList['baiduSecretKey']['value'] + gism_id = channelList['baiduSecretKey']['value'] +else : + print ("no key baiduSecretKey") + +if 'lg_reyun_game_appkey' in channelList : + #print 'lg_reyun_game_appkey==', channelList['lg_reyun_game_appkey'] + #print 'lg_reyun_game_appkey value==', channelList['lg_reyun_game_appkey']['value'] + gism_id = channelList['lg_reyun_game_appkey']['value'] +else : + print ("no key lg_reyun_game_appkey") + +if 'lg_reyun_game_channelId' in channelList : + #print 'lg_reyun_game_channelId==', channelList['lg_reyun_game_channelId'] + #print 'lg_reyun_game_channelId value==', channelList['lg_reyun_game_channelId']['value'] + gism_id = channelList['lg_reyun_game_channelId']['value'] +else : + print ("no key lg_reyun_game_channelId") + +if 'lg_reyun_io_appkey' in channelList : + #print 'lg_reyun_io_appkey==', channelList['lg_reyun_io_appkey'] + #print 'lg_reyun_io_appkey value==', channelList['lg_reyun_io_appkey']['value'] + gism_id = channelList['lg_reyun_io_appkey']['value'] +else : + print ("no key lg_reyun_io_appkey") + +if 'lg_reyun_io_channelId' in channelList : + #print 'lg_reyun_io_channelId==', channelList['lg_reyun_io_channelId'] + #print 'lg_reyun_io_channelId value==', channelList['lg_reyun_io_channelId']['value'] + gism_id = channelList['lg_reyun_io_channelId']['value'] +else : + print ("no key lg_reyun_io_channelId") + +if 'eventType' in channelList : + #print 'eventType==', channelList['eventType'] + #print 'eventType value==', channelList['eventType']['value'] + gism_id = channelList['eventType']['value'] +else : + print ("no key eventType") + + + + +output_apk_dir="./bin" +if os.path.exists(output_apk_dir): + shutil.rmtree(output_apk_dir) + +print ('apkname--==%s' %apkName) +if apkName == '' : + print ('apkName no, stop ...') + sys.exit() +else : + cmdExtract = r'java -jar apktool.jar d -f -s %s -o temp'% (apkName) + os.system(cmdExtract) + backUpManifest() + +for channel in range(start, packNum) : + modifyChannel(channel) + +if os.path.exists('./temp'): + shutil.rmtree('./temp') +if os.path.exists('./AndroidManifest.xml'): + os.remove('./AndroidManifest.xml') +print ('Done') \ No newline at end of file diff --git a/ApkTool/channel b/ApkTool/channel new file mode 100644 index 0000000..ce7e2ca --- /dev/null +++ b/ApkTool/channel @@ -0,0 +1 @@ +{"leguChannel": {"value": "test7", "suffix": "1"}, "num": {"value": "1", "start": "1"}, "keystore": {"filename": "/www/wwwroot/legusdk/app/Components/SDK/ApkTool/keystore/legu729.keystore", "storepass": "123456", "alianame": "legu", "keypass": "123456"}} \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..723a260 --- /dev/null +++ b/Pipfile @@ -0,0 +1,11 @@ +[[source]] +name = "pypi" +url = "https://pypi.douban.com/simple" +verify_ssl = true + +[dev-packages] + +[packages] + +[requires] +python_version = "3.6" diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..c5533ff --- /dev/null +++ b/api/__init__.py @@ -0,0 +1,8 @@ +# coding:utf-8 +from fastapi import APIRouter + +from .endpoints import apk_tools + +api_router = APIRouter() + +api_router.include_router(apk_tools.router, tags=["打包"]) diff --git a/api/endpoints/__init__.py b/api/endpoints/__init__.py new file mode 100644 index 0000000..3c0358d --- /dev/null +++ b/api/endpoints/__init__.py @@ -0,0 +1 @@ +# coding:utf-8 \ No newline at end of file diff --git a/api/endpoints/apk_tools.py b/api/endpoints/apk_tools.py new file mode 100644 index 0000000..521b55a --- /dev/null +++ b/api/endpoints/apk_tools.py @@ -0,0 +1,81 @@ +# coding:utf-8 +import json +import os +import time + +from fastapi import APIRouter, File, BackgroundTasks + +import schemas +from core.config import settings +from utils import * + +router = APIRouter() + + +# +# @router.post("/channel") +# async def channel( +# data_in: schemas.BaleCreate +# ) -> schemas.Msg: +# file = os.path.join(settings.ROOT_DIR, 'ApkTool/channel') +# with open(file, 'w') as f: +# json.dump(data_in.channel, f) +# +# resp = schemas.Msg( +# code=0, +# msg='ok', +# data=data_in +# ) +# +# return resp + + +@router.post("/keystore") +async def keystore( + file: bytes = File(...) +) -> schemas.Msg: + file_path = os.path.join(settings.ROOT_DIR, 'ApkTool/keystore/legu.keystore') + with open(file_path, 'wb') as f: + f.write(file) + + resp = schemas.Msg( + code=0, + msg='ok', + data=file_path + ) + + return resp + + +@router.post("/run") +async def run( + data_in: schemas.BaleCreate, + background_tasks: BackgroundTasks +): + r = os.popen('ps -ef|grep MakeTool.py') + res = r.readlines() + if 'python' in ''.join(res) or bale.status == 'busy': + resp = schemas.Msg( + code=-1, + msg='已存在打包任务,请等待' + ) + return resp + + if bale.status == 'upload': + resp = schemas.Msg( + code=-1, + msg='正在上传,请等待' + ) + return resp + + file = os.path.join(settings.ROOT_DIR, 'ApkTool/channel') + with open(file, 'w') as f: + json.dump(data_in.channel, f) + + background_tasks.add_task(bale.run_bale_apk, f'{data_in.dir}_{int(time.time())}', data_in.id) + + resp = schemas.Msg( + code=0, + msg='开始打包任务' + ) + return resp diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..3c0358d --- /dev/null +++ b/core/__init__.py @@ -0,0 +1 @@ +# coding:utf-8 \ No newline at end of file diff --git a/core/config.py b/core/config.py new file mode 100644 index 0000000..e2e0aa2 --- /dev/null +++ b/core/config.py @@ -0,0 +1,11 @@ +# coding:utf-8 +import os + +from pydantic import BaseSettings + + +class Settings(BaseSettings): + ROOT_DIR = os.path.dirname(os.path.abspath(__name__)) + + +settings = Settings() diff --git a/main.py b/main.py new file mode 100644 index 0000000..f4c76a2 --- /dev/null +++ b/main.py @@ -0,0 +1,35 @@ +# coding:utf-8 +import uvicorn +from fastapi import FastAPI +from fastapi.exceptions import RequestValidationError +from fastapi import Response +from starlette.middleware.cors import CORSMiddleware + +import schemas +from api import api_router + +app = FastAPI(openapi_url='/bale_apk/openapi.json') + +app.include_router(api_router) + +app.add_middleware( + CORSMiddleware, + allow_origins=['*'], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +# @app.exception_handler(RequestValidationError) +# async def validation_exception_handler(request, exc): +# return Response(schemas.Msg(code='-1', msg='服务器错误', data=str(exc)), status_code=200) +# +# +# @app.exception_handler(Exception) +# async def http_exception_handler(request, exc): +# return Response(schemas.Msg(code='-1', msg='服务器错误'), status_code=200) + + +if __name__ == '__main__': + uvicorn.run(app='main:app', host="0.0.0.0", port=7889, reload=True, debug=True) diff --git a/schemas/__init__.py b/schemas/__init__.py new file mode 100644 index 0000000..11f9351 --- /dev/null +++ b/schemas/__init__.py @@ -0,0 +1,3 @@ +# coding:utf-8 +from .channel import BaleCreate +from .msg import Msg \ No newline at end of file diff --git a/schemas/channel.py b/schemas/channel.py new file mode 100644 index 0000000..6330ee4 --- /dev/null +++ b/schemas/channel.py @@ -0,0 +1,8 @@ +# coding:utf-8 +from pydantic import BaseModel + + +class BaleCreate(BaseModel): + channel: dict + dir: str + id: int diff --git a/schemas/msg.py b/schemas/msg.py new file mode 100644 index 0000000..4f5e6e9 --- /dev/null +++ b/schemas/msg.py @@ -0,0 +1,10 @@ +# coding:utf-8 +from typing import Any + +from pydantic import BaseModel + + +class Msg(BaseModel): + code: int + msg: str + data: Any = None diff --git a/test.py b/test.py new file mode 100644 index 0000000..4b004ec --- /dev/null +++ b/test.py @@ -0,0 +1,3 @@ +from utils import bale + +bale.run_bale_apk('aa',334) \ No newline at end of file diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..12619de --- /dev/null +++ b/utils/__init__.py @@ -0,0 +1,2 @@ +# coding:utf-8 +from .bale import bale diff --git a/utils/bale.py b/utils/bale.py new file mode 100644 index 0000000..e4fa959 --- /dev/null +++ b/utils/bale.py @@ -0,0 +1,59 @@ +# coding:utf-8 +import json +import os + +import requests + +from core.config import settings +from .put_file import put_file + + +class Bale: + status = 'idle' + + @classmethod + def run_bale_apk(cls, dir_, id_): + try: + pkg_num = 0 + with open(os.path.join(settings.ROOT_DIR, 'ApkTool/channel'), 'r') as f: + props = json.load(f) + pkg_num = int(props.get('num', {}).get('value', 0)) + + cls.status = 'busy' + cmd = os.path.join(settings.ROOT_DIR, 'ApkTool/run.sh') + os.system(cmd) + + path = os.path.join(settings.ROOT_DIR, 'ApkTool/bin') + if not os.path.exists(path): + return + cls.status = 'upload' + print('开始上传包') + count = 0 + for item in os.listdir(path): + if item.endswith('.apk'): + count += 1 + print(f'开始上传:{item}') + is_ok, msg = put_file(f'{dir_}/{item}', os.path.join(path, item)) + os.remove(os.path.join(path, item)) + if not is_ok: + continue + data = { + 'id': id_, + 'url': msg, + 'apkname': item, + 'done': int(count >= pkg_num) + } + resp = requests.post('http://gamesdk.legu.cc/api/subpackageRecord/getRecord', data=data) + print(f'上传:{item} 完成') + + + + except Exception as e: + with open('log.log', 'w') as f: + f.write(str(e)) + + finally: + cls.status = 'idle' + + +bale = Bale() diff --git a/utils/put_file.py b/utils/put_file.py new file mode 100644 index 0000000..fb2938c --- /dev/null +++ b/utils/put_file.py @@ -0,0 +1,36 @@ +# coding:utf-8 +from obs import ObsClient + + +def put_file(objectKey, file_path): + try: + obsClient = ObsClient( + access_key_id='UPEO770G619UPU8TU61Y', + secret_access_key='M7zVRT1pjRtGSZ2TOZwKBRoVJLeWAOf633kHaNcu', + server='https://obs.cn-east-2.myhuaweicloud.com' + ) + resp = obsClient.putFile('legu-cdn-source', objectKey, file_path) + obsClient.close() + + if resp.status < 300: + print('requestId:', resp.requestId) + print('etag:', resp.body.etag) + print('versionId:', resp.body.versionId) + print('storageClass:', resp.body.storageClass) + url: str = resp.body.objectUrl + url = url.replace('https://legu-cdn-source.obs.cn-east-2.myhuaweicloud.com', 'http://hw-obs-cdn.legu.cc') + return True, url + else: + print('errorCode:', resp.errorCode) + print('errorMessage:', resp.errorMessage) + return False, resp.errorMessage + + except: + import traceback + + print(traceback.format_exc()) + return False, '上传文件未知错误' + + +if __name__ == '__main__': + put_file('bale.py', '/data/bale_apk/utils/bale.py')