Python fir 下载脚本兼容iOS

思路

方法一:类似Android处理,用接口下载文件后,直接通过数据线进行安装
方法二:通过服务端返回下载URL,iOS用快捷指令处理

 

最后选取的第二种方法。对之前脚本做如下修改:
1 新增平台参数,补充对应分支token
2 因Android有渠道包判断,所以增加判断:若为iOS平台,则无需判断changelog
3 根据fir提供文档,处理iOS URL

import requests, os, time
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
from pathlib import Path
from tqdm import tqdm
from threading import Thread
from time import time
from urllib.parse import urlencode, quote_plus
from urllib.parse import quote

downloadPath = Path.cwd().parent.parent.parent.joinpath("apk", "download")


def Interrupt_exception(func):
    '''
    定义一个装饰器:
    捕捉手动停止错误
    '''

    def wrapper(*args, **kwargs):
        try:
            result = func(*args, **kwargs)
            return result
        except KeyboardInterrupt:
            print("手动停止")
            os._exit(0)

    return wrapper


class myloadApk():

    def __init__(self, platform, which, version=None, bulid=None, changelog="Inner"):
        self.platform = platform
        self.which = which
        self.version = version
        self.build = bulid
        self.changelog = changelog
        self.thread_num = 3
        self.url = None
        self.total_size = None

    @Interrupt_exception
    def findApk(self):
        '''
        查找下载APP id
        '''
        for i in range(1, 10):
            print("正在查询第" + str(i) + "页")
            url = "http://fir-api.fircli.cn/apps/" + self.id + "/releases?api_token=" + self.api_token + "&page=" + str(
                i)
            respones = requests.get(url, verify=False)
            allHistory = respones.json()['datas']
            for build_version in allHistory:
                print(build_version["version"])
                print(build_version["build"])
                print(build_version["changelog"])
                print(build_version["id"])
                print("--------********---------")
                if (self.version == None or build_version["version"] == self.version) and (
                        self.build == None or build_version["build"] == self.build) and (
                        self.changelog in build_version["changelog"] or self.platform == "iOS"):
                    self.version = build_version["version"]
                    self.build = build_version["build"]
                    return build_version["id"]

    def download_token(self):
        '''
        获取download_token
        '''
        url = "http://api.bq04.com/apps/" + self.id + "/download_token?api_token=" + self.api_token
        respones = requests.get(url, verify=False)
        return respones.json()['download_token']

    def bytes_format(self, value):
        '''
        文件大小自转换
        '''
        units = ["B", "KB", "MB", "GB", "TB", "PB"]
        size = 1024.0
        for i in range(len(units)):
            if (value / size) < 1:
                return "%.2f%s" % (value, units[i])
            value = value / size

    def get_url(self):
        '''
        获取下载url
        '''
        down_token = self.download_token()
        releaseid = self.findApk()
        print("%s : %s(%s) %s" % (self.which, self.version, self.build, self.changelog))
        url = "http://download.bq04.com/apps/" + self.id + "/install?download_token=" + down_token + "&release_id=" + releaseid
        return url

    def get_iOSurl(self):
        '''
        获取下载 iOSurl
        '''
        down_token = self.download_token()
        releaseid = self.findApk()
        print("%s : %s(%s) %s" % (self.which, self.version, self.build, self.changelog))
        url = "https://download.bq04.com/apps/" + self.id + "/install?download_token=" + down_token + "&release_id=" + releaseid
        return "itms-services://?action=download-manifest&url=" + quote_plus(url)

    def get_total_size(self):
        '''
        获取下载文件大小
        '''
        Response = requests.get(self.url, stream=True, verify=False)
        # 总大小
        total_size = int(Response.headers.get('content-length', 0))
        print(self.bytes_format(total_size))
        return total_size


    @Interrupt_exception
    def loadAPK(self):
        '''
        单线程下载ing
        '''
        start = time()
        self.url = self.get_url()
        self.total_size = self.get_total_size()
        paths = str(downloadPath) + "/HelloTalk_" + self.version + "_" + self.build + "_" + self.which + ".apk"
        # stream=True的作用是仅让响应头被下载,连接保持打开状态,
        if Path(paths).exists():
            temp_size = os.path.getsize(paths)
            print("已下载文件 " + self.bytes_format(temp_size))
        else:
            temp_size = 0
        if temp_size >= self.total_size:
            print("下载完成")
            return paths
        header = {"Range": f"bytes={temp_size}-{self.total_size}"}
        Req = requests.get(self.url, headers=header, stream=True, verify=False, timeout=10)
        with open(paths, "ab") as file, tqdm(
                initial=temp_size,
                desc="正在下载",
                total=self.total_size,
                unit='',
                unit_scale=True,
                unit_divisor=1024,
        ) as bar:
            for data in Req.iter_content(chunk_size=1024):  # 边下载边存硬盘
                size = file.write(data)
                bar.update(size)
        end = time()
        print('总共耗费了%.2f秒.' % (end - start))
        return paths


    @Interrupt_exception
    def adb_install(self):
        '''
        安装ing
        '''
        # try:
        file_names = self.loadAPK()
        print("正在安装...")
        cmd_shell = "adb -d install -r -d " + file_names
        openApp = os.system(cmd_shell)
        if openApp == 0:
            os.system("adb -d shell am start -n com.hellotalk/.lib.main.launch.ui.LaunchActivity")
        # except:
        #     self.checking()


 

优势

无需连接,可以直接下载

 

劣势

公司网络不稳定,导致需要手动切换网络or更改IP

 

总结

快捷指令🐮

posted @ 2023-02-03 00:11  青山原  阅读(25)  评论(0编辑  收藏  举报