예제 #1
0
파일: zapi.py 프로젝트: wszg5/studyGit
def slotService():
    reqs = request.json

    action = request.json['action']
    if 'id' in request.json:
        id = request.json['id']

    serial = request.json['serial']
    type = request.json['type']

    if 'remark' in request.json:
        remark = request.json['remark']
    else:
        remark = "Backed";

    if 'page' in reqs:
        page = reqs['page']
    else:
        page = 1;

    if not action:
        return jsonify({'success': False, 'msg': u'paramter action is missed'})

    if not serial:
        return jsonify({'success': False, 'msg': u'paramter serial is missed'})

    slot = Slot(serial, type)
    if action == "save":
        if remark == "":
            remark = "BackUp"
        slot.backup(id, remark)
        return jsonify({'success': True, 'msg': u'Save slot success'})

    if action == "restore":
        slot.restore(id)
        return jsonify({'success': True, 'msg': u'Restore slot success'})

    if action == "clear":
        slot.clear(id)
        return jsonify({'success': True, 'msg': u'Clear slot success'})

    if action == "list":
        result = []
        slots = slot.getSlots()
        if not slots:
            slots = {};
        idFrom = (page - 1)*20 + 1
        idTo = (page-1) * 20 + 20
        for index in range(idFrom, idTo + 1):
            if slots.has_key(str(index)) :
                obj = slots[str(index)]
                obj['empty'] = False;
                obj['id'] = index
            else:
                obj = {'id':index, 'empty': True}
            result.append(obj)

        return jsonify({'slots': result })

    return "-"
예제 #2
0
class MobilqqLogin:
    def __init__(self):
        self.type = 'mobileqq'
        self.repo = Repo()

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        # 生成当前时间
        randomNum = random.randint(0, 1000)
        # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum)
        uniqueNum = str(nowTime) + str(randomNum)
        return uniqueNum

    def WebViewBlankPages(self, d):
        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])

        W_H = width / height
        screenScale = round(W_H, 2)

        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))

        if screenScale == 0.56:
            left = 60  # 验证码的位置信息
            top = 500
            right = 290
            bottom = 600
        if screenScale == 0.61:
            left = 60  # 验证码的位置信息
            top = 490
            right = 210
            bottom = 510

        # left = width * 7 / 135  # 验证码的位置信息
        # top = height * 245 / 444
        # right = width * 51 / 54
        # bottom = height * 275 / 444

        d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

        img = Image.open(sourcePng)
        box = (left, top, right, bottom)  # left top right bottom
        region = img.crop(box)  # 截取验证码的图片
        # show(region)    #展示资料卡上的信息
        image = region.convert('RGBA')
        # 生成缩略图,减少计算量,减小cpu压力
        image.thumbnail((200, 200))
        max_score = None
        dominant_color = None
        for count, (r, g, b,
                    a) in image.getcolors(image.size[0] * image.size[1]):
            # 跳过纯黑色
            if a == 0:
                continue
            saturation = colorsys.rgb_to_hsv(r / 255.0, g / 255.0,
                                             b / 255.0)[1]
            y = min(
                abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235)
            y = (y - 16.0) / (235 - 16)
            # 忽略高亮色
            if y > 0.9:
                continue

            score = (saturation + 0.1) * count
            if score > max_score:
                max_score = score
                dominant_color = (r, g, b)  # 红绿蓝
        return dominant_color

    def WebViewPlayCode(self, d, z):
        z.toast("开始截图打码")

        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])
        W_H = width / height
        screenScale = round(W_H, 2)

        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        icode = imageCode()
        im_id = ""
        for i in range(0, 1):  # 打码循环
            if i > 0:
                icode.reportError(im_id)

            d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕
            if screenScale == 0.61:
                p = {
                    "x1": 30 / width,
                    "y1": 200 / height,
                    "x2": 271 / width,
                    "y2": 300 / height
                }
            if screenScale == 0.56:
                p = {
                    "x1": 40 / width,
                    "y1": 270 / height,
                    "x2": 362 / width,
                    "y2": 400 / height
                }
            cropedImg = z.img_crop(sourcePng, p)
            im = open(cropedImg, 'rb')
            codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR, 60)
            code = codeResult["Result"]
            im_id = codeResult["Id"]
            os.remove(sourcePng)
            z.heartbeat()
            z.sleep(5)
            if screenScale == 0.61:
                d.click(360, 240)
            if screenScale == 0.56:
                d.click(500, 350)
            z.input(code)
            z.sleep(2)
            if screenScale == 0.61:
                d.click(270, 450)
            if screenScale == 0.56:
                d.click(360, 600)

            while d(className='android.widget.ProgressBar',
                    index=0).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                z.sleep(2)
            z.sleep(8)

            if not d(textContains='验证码').exists:
                z.toast("机器人打码跳出--")
                break

    def BindAddressBook(self, z, d, args):
        z.toast("点击开始绑定")
        self.scode = smsCode(d.server.adb.device_serial())
        d(text='马上绑定').click()
        while d(text='验证手机号码').exists:

            PhoneNumber = None
            j = 0
            while PhoneNumber is None:
                j += 1
                PhoneNumber = self.scode.GetPhoneNumber(
                    self.scode.QQ_CONTACT_BIND)  # 获取接码平台手机号码
                z.heartbeat()
                if j == 2:
                    z.toast('取不到手机号码')
                    if (args["time_delay"]):
                        z.sleep(int(args["time_delay"]))
                    return

            if not d(textContains='+86').exists:
                d(description='点击选择国家和地区').click()
                if d(text='中国').exists:
                    d(text='中国').click()
                else:
                    str = d.info  # 获取屏幕大小等信息
                    height = str["displayHeight"]
                    width = str["displayWidth"]
                    d.click(width * 5 / 12, height * 5 / 32)
                    z.sleep(1.5)
                    z.input('中国')
                    z.sleep(2)
                    d(text='+86').click()

            z.input(PhoneNumber)
            z.sleep(1.5)
            if d(text='下一步').exists:
                d(text='下一步').click()
                z.sleep(3)

            e = 0
            while d(text='正在发送请求').exists:
                z.sleep(2)
            z.sleep(10)
            z.heartbeat()
            if d(text='确定').exists:
                d(text='确定').click()
                z.sleep(2)
            code = self.scode.GetVertifyCode(PhoneNumber,
                                             self.scode.QQ_CONTACT_BIND,
                                             '4')  # 获取接码验证码
            self.scode.defriendPhoneNumber(PhoneNumber,
                                           self.scode.QQ_CONTACT_BIND)
            if code == '':
                z.toast(PhoneNumber + '手机号,获取不到验证码')
                if d(text='返回').exists:
                    d(text='返回').click()
                if not d(textContains='中国').exists:
                    if d(text='返回').exists:
                        d(text='返回').click()
                if d(className='android.view.View',
                     descriptionContains='删除').exists:
                    d(className='android.view.View',
                      descriptionContains='删除').click()
                continue
            z.heartbeat()
            z.input(code)
            if d(text='完成').exists:
                d(text='完成').click()
            z.sleep(15)
            break

    def login(self, d, args, z):
        z.heartbeat()
        self.scode = smsCode(d.server.adb.device_serial())
        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
        cate_id = args["repo_cate_id"]

        time_limit1 = args['time_limit1']
        numbers = self.repo.GetAccount(cate_id, time_limit1, 1)
        while len(numbers) == 0:
            z.heartbeat()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\""
                % (cate_id, time_limit1)).communicate()
            z.sleep(2)
            return 0

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']
        z.sleep(1)
        z.heartbeat()
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.mobileqq").communicate()  # 清除缓存
        d.server.adb.cmd(
            "shell",
            "am start -n com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity"
        ).communicate()  # 拉起来
        while d(textContains='正在更新数据').exists:
            z.sleep(2)

        z.sleep(20)
        z.heartbeat()
        d.dump(compressed=False)
        if d(text='登 录',
             resourceId='com.tencent.mobileqq:id/btn_login').exists:
            d(text='登 录').click()

        z.sleep(1)
        # d(className='android.widget.EditText', index=0).set_text(QQNumber)  # 1918697054----xiake1234.  QQNumber
        d(className='android.widget.EditText',
          index=0).click()  # 1918697054----xiake1234.  QQNumber
        z.input(QQNumber)
        z.sleep(1)
        # d(resourceId='com.tencent.mobileqq:id/password').set_text(QQPassword)  # Bn2kJq5l     QQPassword
        d(resourceId='com.tencent.mobileqq:id/password').click(
        )  # Bn2kJq5l     QQPassword
        z.input(QQPassword)
        z.heartbeat()
        logger = util.logger
        print('QQ号:%s,QQ密码:%s' % (QQNumber, QQPassword))
        d.dump(compressed=False)
        d(text='登 录', resourceId='com.tencent.mobileqq:id/login').click()
        z.sleep(1)
        while d(text='登录中').exists:
            z.sleep(2)
        z.sleep(20)
        z.heartbeat()

        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(text='消息').exists and d(text='联系人').exists and d(
                    text='动态').exists:
                loginStatusList = {'success': True}
            else:
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            return QQNumber

        detection_robot = d(index='3', className="android.widget.EditText")
        not_detection_robot = d(resourceId='com.tencent.mobileqq:id/name',
                                index='2',
                                className="android.widget.EditText")
        if detection_robot.exists or not_detection_robot.exists:  # 需要验证码的情况
            z.toast("非网页打码")
            icode = imageCode()
            im_id = ""
            for i in range(0, 4):  # 打码循环
                if i > 0:
                    icode.reportError(im_id)
                obj = d(resourceId='com.tencent.mobileqq:id/name',
                        className='android.widget.ImageView'
                        )  # 当弹出选择QQ框的时候,定位不到验证码图片
                if not obj.exists:
                    obj = d(index='2', className='android.widget.Image')
                obj = obj.info
                obj = obj['bounds']  # 验证码处的信息
                left = obj["left"]  # 验证码的位置信息
                top = obj['top']
                right = obj['right']
                bottom = obj['bottom']

                d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

                img = Image.open(sourcePng)
                box = (left, top, right, bottom)  # left top right bottom
                region = img.crop(box)  # 截取验证码的图片

                img = Image.new('RGBA', (right - left, bottom - top))
                img.paste(region, (0, 0))

                img.save(codePng)
                im = open(codePng, 'rb')

                codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR,
                                           60)

                code = codeResult["Result"]
                im_id = codeResult["Id"]
                os.remove(sourcePng)
                os.remove(codePng)
                z.heartbeat()
                z.sleep(5)
                if not_detection_robot.exists:
                    d(resourceId='com.tencent.mobileqq:id/name',
                      index='2',
                      className="android.widget.EditText").set_text(code)
                else:
                    detection_robot.set_text(code)
                z.sleep(3)
                if d(descriptionContains='验证',
                     className='android.view.View').exists:
                    d(descriptionContains='验证',
                      className='android.view.View').click()
                else:
                    d(text='完成',
                      resourceId='com.tencent.mobileqq:id/ivTitleBtnRightText'
                      ).click()
                z.sleep(6)
                z.heartbeat()
                while d(className='android.widget.ProgressBar',
                        index=0).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                    z.sleep(2)
                z.sleep(3)
                z.heartbeat()
                if detection_robot.exists or not_detection_robot.exists:
                    continue
                else:
                    break
            z.sleep(5)
            if d(textContains='验证码').exists:
                return "nothing"
        else:
            if self.WebViewBlankPages(d)[2] > 200:
                z.toast("不是空白页")
                self.WebViewPlayCode(d, z)

        z.heartbeat()
        # z.toast( "强制停止,拉起" )
        # d.server.adb.cmd( "shell", "am force-stop com.tencent.mobileqq" ).communicate( )  # 强制停止
        # z.sleep( 1 )
        # d.server.adb.cmd( "shell",
        #                   "am start -n com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来

        z.sleep(5)
        z.heartbeat()
        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(text='消息').exists and d(text='联系人').exists and d(
                    text='动态').exists:
                loginStatusList = {'success': True}
            else:
                z.toast("登陆新场景,现无法判断登陆状态")
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            z.toast("卡槽QQ状态正常,继续执行")
        else:
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(cate_id, 'frozen', QQNumber, '',
                                     '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(cate_id, 'normal', QQNumber, '', '')

            z.toast("卡槽QQ状态异常,跳过此模块")
            return "nothing"

        if d(text='马上绑定').exists:
            self.BindAddressBook(z, d, args)

        if d(text='匹配手机通讯录').exists:  # 登陆上后弹出t通讯录的情况
            d(text='匹配手机通讯录').click()
            z.sleep(1.5)
            if d(text='取消').exists:
                d(text='取消').child()

        if d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
            z.toast("我是小米神隐")
            d(text='我知道了').click()

        return QQNumber

    def qiehuan(self, d, z, args):
        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽
        if not slotObj is None:
            slotnum = slotObj['id']
        while slotnum == 0:  # 2小时没有用过的卡槽也为空的情况
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
            ).communicate()
            z.heartbeat()
            z.sleep(30)
            slotObj = self.slot.getAvailableSlot(
                time_limit)  # 没有空卡槽,取2小时没用过的卡槽
            if not slotObj is None:
                slotnum = slotObj['id']
        z.heartbeat()
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.mobileqq").communicate()  # 清除缓存

        d.server.adb.cmd(
            "shell", "settings put global airplane_mode_on 1").communicate()
        d.server.adb.cmd(
            "shell",
            "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true"
        ).communicate()
        z.sleep(6)
        z.heartbeat()
        d.server.adb.cmd(
            "shell", "settings put global airplane_mode_on 0").communicate()
        d.server.adb.cmd(
            "shell",
            "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
        ).communicate()
        z.heartbeat()
        while True:
            ping = d.server.adb.cmd("shell",
                                    "ping -c 3 baidu.com").communicate()
            print(ping)
            if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                break
            z.sleep(2)

        obj = self.slot.getSlotInfo(slotnum)
        remark = obj['remark']
        remarkArr = remark.split("_")
        if len(remarkArr) == 3:
            slotInfo = d.server.adb.device_serial(
            ) + '_' + self.type + '_' + slotnum
            cateId = remarkArr[2]
            numbers = self.repo.Getserial(cateId, slotInfo)
            featureCodeInfo = numbers[0]['imei']
            z.set_serial("com.tencent.mobileqq", featureCodeInfo)

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽

        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            str(slotnum) + "号\"").communicate()
        z.sleep(2)
        if d(textContains='主题装扮').exists:
            d(text='关闭').click()
            z.sleep(1)

        d.server.adb.cmd(
            "shell",
            "am start -n com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity"
        ).communicate()  # 拉起来
        z.sleep(2)
        z.heartbeat()

        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(text='消息').exists and d(text='联系人').exists and d(
                    text='动态').exists:
                loginStatusList = {'success': True}
            else:
                z.toast("登陆新场景,现无法判断登陆状态")
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            z.toast("卡槽QQ状态正常,继续执行")
        else:
            obj = self.slot.getSlotInfo(slotnum)
            remark = obj['remark']
            remarkArr = remark.split("_")
            QQnumber = remarkArr[1]
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '',
                                     '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(cate_id, 'normal', QQnumber, '', '')

            self.slot.clear(slotnum)  # 清空改卡槽,并补登
            z.toast("卡槽QQ状态异常,补登陆卡槽")
            self.action(d, z, args)

        if d(text='马上绑定').exists:
            self.BindAddressBook(z, d, args)

        if d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
            z.toast("我是小米神隐")
            d(text='我知道了').click()

        if d(text='匹配手机通讯录').exists:  # 登陆上后弹出t通讯录的情况
            d(text='匹配手机通讯录').click()
            z.sleep(1.5)
            if d(text='取消').exists:
                d(text='取消').child()

    def action(self, d, z, args):
        z.toast("正在ping网络是否通畅")
        z.heartbeat()
        i = 0
        while i < 200:
            i += 1
            ping = d.server.adb.cmd("shell",
                                    "ping -c 3 baidu.com").communicate()
            print(ping)
            if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                z.toast("网络通畅。开始执行:普通QQ登录有卡槽")
                break
            z.sleep(2)
        if i > 200:
            z.toast("网络不通,请检查网络状态")
            if (args["time_delay"]):
                z.sleep(int(args["time_delay"]))
            return

        z.heartbeat()
        z.generate_serial("com.tencent.mobileqq")  # 随机生成手机特征码

        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotnum = self.slot.getEmpty()  # 取空卡槽
        if slotnum == 0:  #没有空卡槽的话
            slotObj = self.slot.getAvailableSlot(time_limit)  # 取空卡槽,取2小时没用过的卡槽
            if not slotObj is None:
                slotnum = slotObj['id']
            print(slotnum)
            while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
                d.server.adb.cmd(
                    "shell",
                    "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
                ).communicate()
                z.heartbeat()
                z.sleep(30)
                slotObj = self.slot.getAvailableSlot(time_limit)
                if not slotObj is None:
                    slotnum = slotObj['id']
            z.heartbeat()
            d.server.adb.cmd(
                "shell", "pm clear com.tencent.mobileqq").communicate()  # 清除缓存

            d.server.adb.cmd(
                "shell",
                "settings put global airplane_mode_on 1").communicate()  #开飞行模式
            d.server.adb.cmd(
                "shell",
                "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true"
            ).communicate()
            z.sleep(6)
            z.heartbeat()

            d.server.adb.cmd("shell", "settings put global airplane_mode_on 0"
                             ).communicate()  # 关飞行模式
            d.server.adb.cmd(
                "shell",
                "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
            ).communicate()

            z.heartbeat()
            while True:
                ping = d.server.adb.cmd("shell",
                                        "ping -c 3 baidu.com").communicate()
                print(ping)
                if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                    break
                z.sleep(2)

            obj = self.slot.getSlotInfo(slotnum)
            remark = obj['remark']
            remarkArr = remark.split("_")
            if len(remarkArr) == 3:
                slotInfo = d.server.adb.device_serial(
                ) + '_' + self.type + '_' + slotnum
                cateId = remarkArr[2]
                numbers = self.repo.Getserial(cateId, slotInfo)
                featureCodeInfo = numbers[0]['imei']
                z.set_serial("com.tencent.mobileqq", featureCodeInfo)

            self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
            z.sleep(2)
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
                slotnum + "号\"").communicate()
            z.sleep(2)

            d.server.adb.cmd(
                "shell",
                "am start -n com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity"
            ).communicate()  # 拉起来

            z.sleep(2)
            z.heartbeat()

            loginStatusList = z.qq_getLoginStatus(d)
            if loginStatusList is None:
                if d(text='消息').exists and d(text='联系人').exists and d(
                        text='动态').exists:
                    loginStatusList = {'success': True}
                else:
                    z.toast("登陆新场景,现无法判断登陆状态")
                    loginStatusList = {'success': False}

            loginStatus = loginStatusList['success']
            if loginStatus:
                z.toast("卡槽QQ状态正常,继续执行")
            else:
                obj = self.slot.getSlotInfo(slotnum)
                remark = obj['remark']
                remarkArr = remark.split("_")
                QQnumber = remarkArr[1]
                if d(text='去安全中心').exists:
                    self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '',
                                         '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

                else:
                    self.repo.BackupInfo(cate_id, 'normal', QQnumber, '', '')

                self.slot.clear(slotnum)  # 清空改卡槽,并补登
                z.toast("卡槽QQ状态异常,补登陆卡槽")
                self.action(d, z, args)

            if d(text='马上绑定').exists:
                self.BindAddressBook(z, d, args)

            if d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
                z.toast("我是小米神隐")
                d(text='我知道了').click()

            if d(text='匹配手机通讯录').exists:  # 登陆上后弹出t通讯录的情况
                d(text='匹配手机通讯录').click()
                z.sleep(1.5)
                if d(text='取消').exists:
                    d(text='取消').child()

        else:  # 有空卡槽的情况
            d.server.adb.cmd(
                "shell", "pm clear com.tencent.mobileqq").communicate()  # 清除缓存

            d.server.adb.cmd(
                "shell",
                "settings put global airplane_mode_on 1").communicate()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true"
            ).communicate()
            z.sleep(6)
            d.server.adb.cmd(
                "shell",
                "settings put global airplane_mode_on 0").communicate()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
            ).communicate()
            z.heartbeat()
            while True:
                ping = d.server.adb.cmd("shell",
                                        "ping -c 3 baidu.com").communicate()
                print(ping)
                if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                    break
                z.sleep(2)
            serialinfo = d.server.adb.device_serial()
            # print('登陆时的serial%s'%serialinfo)
            z.heartbeat()
            QQnumber = self.login(d, args, z)
            if QQnumber == 'nothing':
                self.slot.clear(slotnum)  # 清空改卡槽,并补登
                self.action(d, z, args)
            if QQnumber == 0:
                z.toast("仓库为空,无法登陆。开始切换卡槽")
                self.qiehuan(d, z, args)
            z.heartbeat()

            featureCodeInfo = z.get_serial("com.tencent.mobileqq")
            self.slot.backup(slotnum,
                             str(slotnum) + '_' + QQnumber + '_' +
                             cate_id)  # 设备信息,卡槽号,QQ号
            self.repo.BackupInfo(cate_id, 'using', QQnumber, featureCodeInfo,
                                 '%s_%s_%s' %
                                 (d.server.adb.device_serial(), self.type,
                                  slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号

        if (args["time_delay"]):
            z.sleep(int(args["time_delay"]))
예제 #3
0
class InternationqqLogin:
    def __init__(self):
        self.type = 'mobileqqi'
        self.repo = Repo()
        self.codedll = codeDLL()

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S");  # 生成当前时间
        randomNum = random.randint(0, 1000);  # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum);
        uniqueNum = str(nowTime) + str(randomNum);
        return uniqueNum

    def playCode(self, codeImgObj):
        z.toast("非网页视图打码")
        self.scode = smsCode(d.server.adb.device_serial())
        base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
        icode = imageCode()
        im_id = ""
        for i in range(0, 4):  # 打码循环
            if i > 0:
                icode.reportError(im_id)

            obj = d(resourceId='com.tencent.mobileqqi:id/0', className='android.widget.ImageView')  # 当弹出选择QQ框的时候,定位不到验证码图片
            if not obj.exists:
                return False

            obj = obj.info
            obj = obj['bounds']  # 验证码处的信息
            left = obj["left"]  # 验证码的位置信息
            top = obj['top']
            right = obj['right']
            bottom = obj['bottom']

            d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

            img = Image.open(sourcePng)
            box = (left, top, right, bottom)  # left top right bottom
            region = img.crop(box)  # 截取验证码的图片

            img = Image.new('RGBA', (right - left, bottom - top))
            img.paste(region, (0, 0))

            img.save(codePng)

            with open( codePng, 'rb' ) as im:
                codeResult = self.codedll.QQPlayCode( im )
            # im = open(codePng, 'rb')
    #
    #         codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR, 60)
    #
    #         code = codeResult["Result"]
    #         im_id = codeResult["Id"]
    #         os.remove(sourcePng)
    #         os.remove(codePng)
    #
    #         z.sleep(3)
    #         z.heartbeat()
    #         codeImgObj.set_text(code)  # 输入获取的验证码
    #
    #         z.sleep(2)
    #         d(description='完成').click()
    #
    #         z.sleep(10)
    #         z.heartbeat()
    #         if codeImgObj.exists:
    #             continue
    #         else:
    #             break
    #     z.sleep(3)
    #     if d(textContains='验证码').exists:
    #         return True
    #     else:
    #         return False

    def login(self, d, args, z, numbers):

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']

        z.heartbeat()
        d.server.adb.cmd("shell", "pm clear com.tencent.mobileqqi").communicate()  # 清除缓存
        d.server.adb.cmd("shell", "am start -n com.tencent.mobileqqi/com.tencent.mobileqq.activity.SplashActivity").communicate()  # 拉起来

        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)
        z.sleep(15)
        z.heartbeat()

        d.dump(compressed=False)
        d(className='android.widget.EditText', index=0).click()  # 1918697054----xiake1234.  QQNumber
        z.input(QQNumber)

        z.sleep(1)
        d(resourceId='com.tencent.mobileqqi:id/password').click()  # Bn2kJq5l     QQPassword
        z.input(QQPassword)

        print('QQ号:%s,QQ密码:%s' % (QQNumber, QQPassword))

        z.sleep(1)
        d.dump(compressed=False)
        d(resourceId='com.tencent.mobileqqi:id/login').click()  # 点击登陆按钮

        z.sleep(2)
        flag = 0
        while not d(text='输入验证码').exists and flag < 3:
            flag += 1
            z.sleep(10)
            z.heartbeat()

        not_detection_robot = d(resourceId='com.tencent.mobileqqi:id/0', className="android.widget.EditText")
        if not_detection_robot.exists:
            if self.playCode(not_detection_robot):
                return False

        z.sleep(5)
        z.heartbeat()
        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(resourceId='com.tencent.mobileqqi:id/0').exists and d(description='建讨论组').exists:
                loginStatusList = {'success': True}
            elif d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
                z.toast(u"我是小米神隐")
                d(text='我知道了').click()
            else:
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            z.toast("QQ登陆成功,模块结束运行")
            return True
        else:
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(args["repo_cate_id"], 'frozen', QQNumber, '', '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(args["repo_cate_id"], 'normal', QQNumber, '', '')

            z.toast(u"QQ登陆失败,模块重新运行。")
            return False

        # if d(text='马上绑定').exists:
        #     self.BindAddressBook(z, d, args)

    def qiehuan(self , d, z, args):
        time_limit = int(args['time_limit'])
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽
        slotnum = None
        if not slotObj is None:
            slotnum = slotObj['id']

        while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
            d.server.adb.cmd("shell",
                              "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\"").communicate()
            z.heartbeat()
            z.sleep(30)
            slotObj = self.slot.getAvailableSlot(time_limit)
            if not slotObj is None:
                slotnum = slotObj['id']
                break

        z.heartbeat()
        d.server.adb.cmd("shell", "pm clear com.tencent.mobileqqi").communicate()  # 清除缓存

        # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()  # 开飞行模式
        # d.server.adb.cmd("shell",
        #                   "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
        # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()  # 关飞行模式
        # d.server.adb.cmd("shell",
        #                   "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()

        z.heartbeat()
        while True:
            ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
            print(ping)
            if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                break
            z.sleep(2)

        obj = self.slot.getSlotInfo(slotnum)
        remark = obj['remark']
        remarkArr = remark.split("_")
        cateId = ""
        if len(remarkArr) == 3:
            slotInfo = d.server.adb.device_serial() + '_' + self.type + '_' + slotnum
            cateId = remarkArr[2]
            numbers = self.repo.Getserial(cateId, slotInfo)
            if len(numbers) != 0:
                featureCodeInfo = numbers[0]['imei']
                z.set_serial("com.tencent.mobileqqi", featureCodeInfo)

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
        z.sleep(2)

        d.server.adb.cmd("shell",
                          "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" + slotnum + "号\"").communicate()
        z.sleep(2)
        d.server.adb.cmd("shell",
                          "am start -n com.tencent.mobileqqi/com.tencent.mobileqq.activity.SplashActivity").communicate()  # 拉起来
        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)
        z.sleep(15)

        z.heartbeat()
        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(resourceId='com.tencent.mobileqqi:id/0').exists and d(description='建讨论组').exists:
                loginStatusList = {'success': True}
            elif d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
                z.toast(u"我是小米神隐")
                d(text='我知道了').click()
                loginStatusList = {'success': True}
            else:
                z.toast("登陆新场景,现无法判断登陆状态")
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            z.toast(u"卡槽QQ状态正常,继续执行")
            return True
        else:
            QQnumber = remarkArr[1]
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(cateId, 'frozen', QQnumber, '', '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(cateId, 'normal', QQnumber, '', '')

            self.slot.clear(slotnum)  # 清空改卡槽,并补登
            z.toast(u"卡槽QQ状态异常,补登陆卡槽")
            return False

    def action(self, d, z, args):
        while True:
            z.toast("正在ping网络是否通畅")
            i = 0
            # while i < 200:
            #     i += 1
            #     ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
            #     print(ping)
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         z.toast(u"网络通畅。开始执行:国际版QQ登录  有卡槽")
            #         break
            #     z.sleep(2)
            # if i > 200 :
            #     z.toast(u"网络不通,请检查网络状态")
            #     if (args["time_delay"]):
            #         z.sleep(int(args["time_delay"]))
            #     return
            #
            # z.heartbeat()
            # z.generate_serial("com.tencent.mobileqqi") # 随机生成手机特征码
            cate_id = args["repo_cate_id"]

            time_limit1 = args['time_limit1']
            numbers = self.repo.GetAccount(cate_id, time_limit1, 1)
            if len(numbers) == 0:
                d.server.adb.cmd("shell", "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\"" % (cate_id, time_limit1)).communicate()

            serial = d.server.adb.device_serial()
            self.slot = Slot(serial, self.type)
            slotnum = self.slot.getEmpty()  # 取空卡槽
            if slotnum == 0 or len(numbers) == 0:    #没有空卡槽的话
               if self.qiehuan(d, z, args):
                   break

            else:  # 有空卡槽的情况
                # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
                # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
                # z.sleep(6)
                # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
                # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
                z.heartbeat()
                while True:
                    ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
                    print(ping)
                    if 'icmp_seq'and 'bytes from'and'time' in ping[0]:
                        break
                    z.sleep(2)

                z.heartbeat()
                if self.login(d, args, z, numbers):
                    z.heartbeat()
                    featureCodeInfo = z.get_serial("com.tencent.mobileqq")
                    self.slot.backup(slotnum, str(slotnum) + '_' + numbers[0]['number'] + '_' + cate_id)  # 设备信息,卡槽号,QQ号
                    self.repo.BackupInfo(cate_id, 'using', numbers[0]['number'], featureCodeInfo, '%s_%s_%s' % (d.server.adb.device_serial(), self.type, slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号
                    break

        if args["time_delay"]:
            z.sleep(int(args["time_delay"]))
예제 #4
0
class TIMLoginSlot:

    def __init__(self):
        self.repo = Repo()
        self.type = 'tim'

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S");  # 生成当前时间
        randomNum = random.randint(0, 1000);  # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum);
        uniqueNum = str(nowTime) + str(randomNum);
        return uniqueNum

    def WebViewBlankPages(self, d):
        z.toast( "判断是否是空白页" )
        Str = d.info  # 获取屏幕大小等信息
        height = float( Str["displayHeight"] )
        width = float( Str["displayWidth"] )

        W_H = width / height
        screenScale = round( W_H, 2 )

        base_dir = os.path.abspath( os.path.join( os.path.dirname( __file__ ), os.path.pardir, "tmp" ) )
        if not os.path.isdir( base_dir ):
            os.mkdir( base_dir )
        sourcePng = os.path.join( base_dir, "%s_s.png" % (self.GetUnique( )) )

        if screenScale == 0.56:
            left = 60  # 验证码的位置信息
            top = 655
            right = 290
            bottom = 680
        if screenScale == 0.61:
            left = 60  # 验证码的位置信息
            top = 490
            right = 210
            bottom = 510

        left = width * 7 / 135  # 验证码的位置信息
        top = height * 245 / 444
        right = width * 51 / 54
        bottom = height * 275 / 444

        d.screenshot( sourcePng )  # 截取整个输入验证码时的屏幕

        img = Image.open( sourcePng )
        box = (left, top, right, bottom)  # left top right bottom
        region = img.crop( box )  # 截取验证码的图片
        # show(region)    #展示资料卡上的信息
        image = region.convert( 'RGBA' )
        # 生成缩略图,减少计算量,减小cpu压力
        image.thumbnail( (200, 200) )
        max_score = None
        dominant_color = None
        for count, (r, g, b, a) in image.getcolors( image.size[0] * image.size[1] ):
            # 跳过纯黑色
            if a == 0:
                continue
            saturation = colorsys.rgb_to_hsv( r / 255.0, g / 255.0, b / 255.0 )[1]
            y = min( abs( r * 2104 + g * 4130 + b * 802 + 4096 + 131072 ) >> 13, 235 )
            y = (y - 16.0) / (235 - 16)
            # 忽略高亮色
            if y > 0.9:
                continue

            score = (saturation + 0.1) * count
            if score > max_score:
                max_score = score
                dominant_color = (r, g, b)  # 红绿蓝
        return dominant_color

    def WebViewPlayCode(self, d, z):
        z.toast( "开始截图打码" )

        Str = d.info  # 获取屏幕大小等信息
        height = float( Str["displayHeight"] )
        width = float( Str["displayWidth"] )
        W_H = width / height
        screenScale = round( W_H, 2 )

        base_dir = os.path.abspath( os.path.join( os.path.dirname( __file__ ), os.path.pardir, "tmp" ) )
        if not os.path.isdir( base_dir ):
            os.mkdir( base_dir )
        sourcePng = os.path.join( base_dir, "%s_s.png" % (self.GetUnique( )) )
        icode = imageCode( )
        im_id = ""
        for i in range( 0, 1 ):  # 打码循环
            if i > 0:
                icode.reportError( im_id )

            d.screenshot( sourcePng )  # 截取整个输入验证码时的屏幕
            if screenScale == 0.61:
                p = {"x1": 30 / width, "y1": 283 / height, "x2": 271 / width, "y2": 379 / height}
            if screenScale == 0.56:
                p = {"x1": 40 / width, "y1": 375 / height, "x2": 362 / width, "y2": 505 / height}
            cropedImg = z.img_crop( sourcePng, p )
            im = open( cropedImg, 'rb' )
            codeResult = icode.getCode( im, icode.CODE_TYPE_4_NUMBER_CHAR, 60 )
            code = codeResult["Result"]
            im_id = codeResult["Id"]
            os.remove( sourcePng )
            z.heartbeat( )
            z.sleep( 5 )
            d.click( width * 300 / 540, height * 330 / 888 )
            self.input( z, height, code )
            z.sleep( 2 )
            d.click( width * 270 / 540, height * 525 / 888 )
            while d( className='android.widget.ProgressBar', index=0 ).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                z.sleep( 2 )
            z.sleep( 8 )
            z.toast( "机器人打码--" )
            if not d( textContains='验证码' ).exists:
                z.toast( "机器人打码跳出--" )
                break

    def LoginPlayCode(self, d, z):
        self.scode = smsCode( d.server.adb.device_serial( ) )
        base_dir = os.path.abspath( os.path.join( os.path.dirname( __file__ ), os.path.pardir, "tmp" ) )
        if not os.path.isdir( base_dir ):
            os.mkdir( base_dir )
        sourcePng = os.path.join( base_dir, "%s_s.png" % (self.GetUnique( )) )
        codePng = os.path.join( base_dir, "%s_c.png" % (self.GetUnique( )) )
        detection_robot = d( index='3', className="android.widget.EditText" )
        not_detection_robot = d( resourceId='com.tencent.tim:id/name', index='2',
                                 className="android.widget.EditText" )
        if detection_robot.exists or not_detection_robot.exists:  # 需要验证码的情况
            icode = imageCode( )
            im_id = ""
            for i in range( 0, 4 ):  # 打码循环
                # if i > 0:
                #     icode.reportError( im_id )
                obj = d( resourceId='com.tencent.tim:id/name',
                         className='android.widget.ImageView' )  # 当弹出选择QQ框的时候,定位不到验证码图片
                if not obj.exists:
                    obj = d( index='2', className='android.widget.Image' )
                obj = obj.info
                obj = obj['bounds']  # 验证码处的信息
                left = obj["left"]  # 验证码的位置信息
                top = obj['top']
                right = obj['right']
                bottom = obj['bottom']

                d.screenshot( sourcePng )  # 截取整个输入验证码时的屏幕

                img = Image.open( sourcePng )
                box = (left, top, right, bottom)  # left top right bottom
                region = img.crop( box )  # 截取验证码的图片

                img = Image.new( 'RGBA', (right - left, bottom - top) )
                img.paste( region, (0, 0) )

                img.save( codePng )
                with open( codePng, 'rb' ) as f:
                    # file = f.read()
                    file = "data:image/jpeg;base64," + base64.b64encode( f.read( ) )
                    da = {"IMAGES": file}
                    path = "/ocr.index"
                    headers = {"Content-Type": "application/x-www-form-urlencoded",
                               "Connection": "Keep-Alive"}
                    conn = httplib.HTTPConnection( "162626i1w0.51mypc.cn", 10082, timeout=30 )
                    params = urllib.urlencode( da )
                    conn.request( method="POST", url=path, body=params, headers=headers )
                    response = conn.getresponse( )
                    if response.status == 200:
                        code = response.read( )
                    else:
                        continue
                os.remove( sourcePng )
                os.remove( codePng )
                z.heartbeat( )
                z.sleep( 5 )
                if not_detection_robot.exists:
                    d( resourceId='com.tencent.tim:id/name', index='2',
                       className="android.widget.EditText" ).set_text( code )
                else:
                    detection_robot.set_text( code )
                z.sleep( 3 )
                if d( descriptionContains='验证', className='android.view.View' ).exists:
                    d( descriptionContains='验证', className='android.view.View' ).click( )
                else:
                    d( text='完成', resourceId='com.tencent.tim:id/ivTitleBtnRightText' ).click( )
                z.sleep( 5 )
                z.heartbeat( )
                while d( className='android.widget.ProgressBar', index=0 ).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                    z.sleep( 2 )
                z.heartbeat( )
                if detection_robot.exists or not_detection_robot.exists:
                    continue
                else:
                    break
            z.sleep( 5 )
            if d( textContains='验证码' ).exists:
                return "no"
            else:
                return "yes"
        else:
            return "no"

    def login(self,d,args,z):
        z.heartbeat()
        Str = d.info  # 获取屏幕大小等信息
        height = float( Str["displayHeight"] )
        width = float( Str["displayWidth"] )

        cate_id = args["repo_cate_id"]
        time_limit1 = args['time_limit1']
        numbers = self.repo.GetAccount( cate_id, time_limit1, 1 )
        while len( numbers ) == 0:
            z.heartbeat( )
            d.server.adb.cmd( "shell", "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\"" % (
            cate_id, time_limit1) ).communicate( )
            z.sleep( 2 )
            return 0

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']
        z.sleep( 1 )
        z.heartbeat( )
        d.server.adb.cmd("shell", "pm clear com.tencent.tim").communicate( )  # 清除缓存
        # d.server.adb.cmd("shell",
        #                   "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来
        z.server.adb.run_cmd( "shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" )
        z.sleep(10)
        while d( textContains='正在更新数据' ).exists:
            z.sleep( 2 )
        z.sleep(10)
        z.heartbeat()
        z.server.adb.run_cmd( "shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" )
        z.sleep( 5 )
        z.heartbeat( )
        if d(className='android.widget.ImageView',resourceId='com.tencent.tim:id/title',index=1).exists:
            for i in range(0,2):
                d.swipe( width - 20, height / 2, 0, height / 2, 5 )
                z.sleep(1.5)
            if d(text='立即体验').exists:
                d(text='立即体验').click()
        z.sleep(2)
        if d(text='登 录').exists:
            d(text='登 录').click()
        else:
           d( text='QQ号登录' ).click( )
        z.sleep( 1 )
        # d(className='android.widget.EditText', index=0).set_text(QQNumber)  # 1918697054----xiake1234.  QQNumber
        d(className='android.widget.EditText', index=0).click()  # 1918697054----xiake1234.  QQNumber
        self.input( z, height, QQNumber )

        z.sleep( 1 )
        # d(resourceId='com.tencent.mobileqq:id/password').set_text(QQPassword)  # Bn2kJq5l     QQPassword
        d(resourceId='com.tencent.tim:id/password').click()  # Bn2kJq5l     QQPassword
        self.input( z, height, QQPassword )
        z.heartbeat()
        logger = util.logger
        print('QQ号:%s,QQ密码:%s' % (QQNumber, QQPassword))
        d.dump(compressed=False )
        d( text='登 录', resourceId='com.tencent.tim:id/login' ).click( )
        z.sleep(1)
        while d(text='登录中').exists:
            z.sleep(2)

        z.sleep(int(args['time_delay1']))
        z.heartbeat()

        detection_robot = d( index='3', className="android.widget.EditText" )
        not_detection_robot = d( resourceId='com.tencent.tim:id/name', index='2',
                                 className="android.widget.EditText" )
        playCodeResult = ''
        if detection_robot.exists or not_detection_robot.exists:
            playCodeResult = self.LoginPlayCode( d, z )  # 打验证码
        else:
            if self.WebViewBlankPages( d )[2] > 200:
                z.toast( "不是空白页" )
                self.WebViewPlayCode( d, z )
            else:
                z.toast( "是空白页" )
                return "nothing"


        if playCodeResult == "no":
            return "nothing"

        z.sleep(10)
        z.heartbeat()
        if d( text='马上绑定' ).exists:
            return QQNumber

        if d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
            z.toast("我是小米神隐")
            return QQNumber

        if d( text='匹配手机通讯录' ).exists:  # 登陆上后弹出t通讯录的情况
            d( text='匹配手机通讯录' ).click()
            z.sleep(1.5)
            if d(text='取消').exists:
                d(text='取消').child()
            return QQNumber

        if d(text='消息').exists and d(description='快捷入口').exists:
            z.toast("卡槽QQ状态正常,继续执行")
            return QQNumber

        if d( text='去安全中心' ).exists:
            self.repo.BackupInfo( cate_id, 'frozen', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            z.toast( "登陆失败,重新登陆" )
            return "nothing"
        elif d(resourceId="com.tencent.tim:id/login",description="登录").exists:
            failCount = int(args["failCount"])
            for r in range(failCount):
                result = self.againLogin(d,z)
                if result is True:
                    return QQNumber
                elif result is False:
                    self.repo.BackupInfo( cate_id, 'frozen', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    return "nothing"
                elif result is None:
                    return "nothing"
        else:
            self.repo.BackupInfo( cate_id, 'normal', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            z.toast( "登陆失败,重新登陆" )
            return "nothing"

    def qiehuan(self, d, z, args):
        Str = d.info  # 获取屏幕大小等信息
        height = float( Str["displayHeight"] )
        width = float( Str["displayWidth"] )
        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial( )
        self.slot = Slot( serial, self.type )
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽
        while slotObj is None:  # 2小时没有用过的卡槽也为空的情况
            d.server.adb.cmd("shell",
                             "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\"").communicate()
            z.heartbeat()
            z.sleep(10)
            slotObj = self.slot.getAvailableSlot( time_limit )  # 没有空卡槽,取2小时没用过的卡槽

        if not slotObj is None:
            slotnum = slotObj['id']
        z.heartbeat()
        d.server.adb.cmd("shell", "pm clear com.tencent.tim").communicate()  # 清除缓存

        # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
        # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
        # z.sleep(6)
        # z.heartbeat()
        # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
        # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
        z.heartbeat()
        z.toast( "正在ping网络是否通畅" )
        while True:
            ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
            print(ping)
            if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                break
            z.sleep(2)

        obj = self.slot.getSlotInfo( slotnum )
        remark = obj['remark']
        remarkArr = remark.split( "_" )
        if len( remarkArr ) == 3:
            slotInfo = d.server.adb.device_serial( ) + '_' + self.type + '_' + slotnum
            cateId = remarkArr[2]
            numbers = self.repo.Getserial( cateId, slotInfo )
            if len( numbers ) != 0:
                featureCodeInfo = numbers[0]['imei']
                z.set_serial( "com.tencent.tim", featureCodeInfo )

        self.slot.restore( slotnum )  # 有time_limit分钟没用过的卡槽情况,切换卡槽

        d.server.adb.cmd("shell", "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" + str(slotnum) + "号\"").communicate()
        z.sleep(2)
        # d.server.adb.cmd("shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity").communicate()  # 拉起来
        z.server.adb.run_cmd( "shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" )

        z.sleep( 5 )
        while d( textContains='正在更新数据' ).exists:
            z.sleep( 2 )

        z.sleep( 3 )
        z.server.adb.run_cmd( "shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" )
        z.sleep(3)
        z.heartbeat()
        if d(className='android.widget.ImageView',resourceId='com.tencent.tim:id/title',index=1).exists:
            for i in range(0,2):
                d.swipe( width - 20, height / 2, 0, height / 2, 5 )
                z.sleep(1.5)
            if d(text='立即体验').exists:
                d(text='立即体验').click()
        z.sleep(3)

        if d( textContains="请在小米神隐模式中将TIM设置为“无限制”。" ).exists:
            z.toast( "我是小米神隐" )
            d( text='我知道了' ).click( )
            d( text='我知道了' ).click( )
        elif d( text='消息' ).exists or d( text='马上绑定' ).exists or d( text='匹配手机通讯录' ).exists:
            if d( text='匹配手机通讯录' ).exists:  # 登陆上后弹出t通讯录的情况
                d( text='匹配手机通讯录' ).click( )
                z.sleep( 1.5 )
                if d( text='取消' ).exists:
                    d( text='取消' ).child( )
            z.toast( "卡槽QQ切换成功,继续执行" )
        else:
            obj = self.slot.getSlotInfo( slotnum )
            remark = obj['remark']
            remarkArr = remark.split( "_" )
            QQnumber = remarkArr[1]
            if d( text='去安全中心' ).exists:
                self.repo.BackupInfo( cate_id, 'frozen', QQnumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo( cate_id, 'normal', QQnumber, '', '' )
            self.slot.clear( slotnum )  # 清空改卡槽,并补登
            z.toast( "卡槽QQ状态异常,补登陆卡槽" )
            self.action( d, z, args )

    def againLogin(self, d , z):
        if d(resourceId="com.tencent.tim:id/login",description="登录").exists:
            d( resourceId="com.tencent.tim:id/login", description="登录" ).click()
            z.sleep( 1 )
            while d( text='登录中' ).exists:
                z.sleep( 2 )

            z.sleep( int( args['time_delay1'] ) )
            z.heartbeat( )

            detection_robot = d( index='3', className="android.widget.EditText" )
            not_detection_robot = d( resourceId='com.tencent.tim:id/name', index='2',
                                     className="android.widget.EditText" )
            playCodeResult = ''
            if detection_robot.exists or not_detection_robot.exists:
                playCodeResult = self.LoginPlayCode( d, z )  # 打验证码
            else:
                if self.WebViewBlankPages( d )[2] > 200:
                    z.toast( "不是空白页" )
                    self.WebViewPlayCode( d, z )
                else:
                    z.toast( "是空白页" )
                    return "nothing"

            if playCodeResult == "no":
                return "nothing"

            z.sleep( 10 )
            z.heartbeat( )
            if d( text='马上绑定' ).exists:
                return True

            if d( textContains="请在小米神隐模式中将TIM设置为“无限制”。" ).exists:
                z.toast( "我是小米神隐" )
                return True

            if d( text='匹配手机通讯录' ).exists:  # 登陆上后弹出t通讯录的情况
                d( text='匹配手机通讯录' ).click( )
                z.sleep( 1.5 )
                if d( text='取消' ).exists:
                    d( text='取消' ).child( )
                return True

            if d( text='消息' ).exists and d( description='快捷入口' ).exists:
                z.toast( "卡槽QQ状态正常,继续执行" )
                return True

            if d( text='去安全中心' ).exists:
                # self.repo.BackupInfo( cate_id, 'frozen', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                z.toast( "登陆失败,重新登陆" )
                return False
            if d( resourceId="com.tencent.tim:id/login", description="登录" ).exists:
                return "nothing"
            else:
                # self.repo.BackupInfo( cate_id, 'normal', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                z.toast( "登陆失败,重新登陆" )
                return

    def input(self, z, height, text):
        if height>888:
            z.input(text)
        else:
            z.cmd( "shell", "am broadcast -a ZY_INPUT_TEXT --es text \\\"%s\\\"" % text )

    def action(self,d,z,args):
        Str = d.info  # 获取屏幕大小等信息
        height = float( Str["displayHeight"] )
        width = float( Str["displayWidth"] )

        z.generate_serial("com.tencent.tim")  # 随机生成手机特征码
        z.toast("随机生成手机特征码")


        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotnum = self.slot.getEmpty()  # 取空卡槽
        if slotnum == 0:  # 没有空卡槽的话
            slotObj = self.slot.getAvailableSlot(time_limit)  # 取空卡槽,取2小时没用过的卡槽
            if not slotObj is None:
                slotnum = slotObj['id']
            print(slotnum)
            while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
                d.server.adb.cmd( "shell",
                                  "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\"" ).communicate( )
                z.heartbeat()
                z.sleep(10)
                slotObj = self.slot.getAvailableSlot(time_limit)
                if not slotObj is None:
                    slotnum = slotObj['id']
            z.heartbeat()
            d.server.adb.cmd( "shell", "pm clear com.tencent.tim" ).communicate( )  # 清除缓存
            # d.server.adb.cmd( "shell", "am force-stop com.tencent.tim" ).communicate( )  # 强制停止


            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate() #开数据流量
            # d.server.adb.cmd("shell","am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()#开飞行模式
            # z.sleep( 6 )
            # z.heartbeat( )
            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate() # 关数据流量
            # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()#开飞行模式

            # z.heartbeat( )
            # z.toast( "正在ping网络是否通畅" )
            # while True:
            #     ping = d.server.adb.cmd( "shell", "ping -c 3 baidu.com" ).communicate( )
            #     print( ping )
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         break
            #     z.sleep( 2 )
            obj = self.slot.getSlotInfo( slotnum )
            remark = obj['remark']
            remarkArr = remark.split( "_" )
            if len( remarkArr ) == 3:
                slotInfo = d.server.adb.device_serial() + '_' + self.type + '_' + slotnum
                cateId = remarkArr[2]
                numbers = self.repo.Getserial( cateId, slotInfo)
                if len(numbers) != 0:
                    featureCodeInfo = numbers[0]['imei']
                    z.set_serial( "com.tencent.tim", featureCodeInfo )

            self.slot.restore( slotnum )  # 有time_limit分钟没用过的卡槽情况,切换卡槽

            d.server.adb.cmd( "shell",
                              "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" + slotnum + "号\"" ).communicate( )
            z.sleep( 2 )
            # d.server.adb.cmd( "shell",
            #                   "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来
            z.server.adb.run_cmd( "shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" )

            z.sleep(5)
            while d( textContains='正在更新数据' ).exists:
                z.sleep( 2 )
            z.sleep( 3 )
            z.server.adb.run_cmd( "shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" )
            z.sleep( 3 )

            if d( className='android.widget.ImageView', resourceId='com.tencent.tim:id/title', index=1 ).exists:
                for i in range( 0, 2 ):
                    d.swipe( width - 20, height / 2, 0, height / 2, 5 )
                    z.sleep( 1.5 )
                if d( text='立即体验' ).exists:
                    d( text='立即体验' ).click( )
            z.sleep( 2 )
            z.heartbeat()
            if d( textContains="请在小米神隐模式中将TIM设置为“无限制”。" ).exists:
                z.toast( "我是小米神隐" )
                d( text='我知道了' ).click( )
            elif d( text='消息' ).exists or d( text='马上绑定' ).exists or d( text='匹配手机通讯录' ).exists:
                if d( text='匹配手机通讯录' ).exists:  # 登陆上后弹出t通讯录的情况
                    d( text='匹配手机通讯录' ).click( )
                    z.sleep( 1.5 )
                    if d( text='取消' ).exists:
                        d( text='取消' ).child( )
                z.toast("卡槽QQ切换成功,继续执行")
            else:
                obj = self.slot.getSlotInfo( slotnum )
                remark = obj['remark']
                remarkArr = remark.split( "_" )
                QQnumber = remarkArr[1]
                if d(text='去安全中心').exists:
                    self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '', '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

                else:
                    self.repo.BackupInfo(cate_id, 'normal', QQnumber, '', '')

                self.slot.clear( slotnum )  # 清空改卡槽,并补登
                z.toast("卡槽QQ状态异常,补登陆卡槽")
                self.action( d, z, args )

        else:  # 有空卡槽的情况
            d.server.adb.cmd( "shell", "pm clear com.tencent.tim" ).communicate( )  # 清除缓存

            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
            # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
            # z.sleep(3)
            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
            # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
            z.heartbeat( )
            # z.toast( "正在ping网络是否通畅" )
            # while True:
            #     ping = d.server.adb.cmd( "shell", "ping -c 3 baidu.com" ).communicate( )
            #     print( ping )
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         break
            #     z.sleep( 2 )

            serialinfo = d.server.adb.device_serial( )
            # print('登陆时的serial%s'%serialinfo)
            z.heartbeat( )
            QQnumber = self.login( d, args, z )
            if QQnumber == 'nothing':
                self.slot.clear( slotnum )  # 清空改卡槽,并补登
                self.action( d, z, args )
            elif QQnumber == 0:
                z.toast( "仓库为空,无法登陆。开始切换卡槽" )
                self.qiehuan( d, z, args )
            elif QQnumber is None:
                return
            else:
                z.heartbeat()
                z.toast("登陆成功")
                featureCodeInfo = z.get_serial("com.tencent.tim")
                self.slot.backup( slotnum, str( slotnum ) + '_' + QQnumber + '_' + cate_id)  # 设备信息,卡槽号,QQ号
                self.repo.BackupInfo( cate_id, 'using', QQnumber, featureCodeInfo, '%s_%s_%s' % (
                    d.server.adb.device_serial( ), self.type, slotnum) )  # 仓库号,使用中,QQ号,设备号_卡槽号


        if (args["time_delay"]):
            time.sleep(int(args["time_delay"]))
예제 #5
0
class QQMailLogin:
    def __init__(self):
        self.repo = Repo()
        self.type = 'qqmail'

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")  # 生成当前时间
        randomNum = random.randint(0, 1000)  # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum)
        uniqueNum = str(nowTime) + str(randomNum)
        return uniqueNum

    def input(self, z, text):
        z.cmd("shell",
              "am broadcast -a ZY_INPUT_TEXT --es text \\\"%s\\\"" % text)

    def palyCode(self, d, z, picObj):
        self.scode = smsCode(d.server.adb.device_serial())
        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
        icode = imageCode()
        im_id = ""
        code = ""
        for i in range(0, 2):  # 打码循环
            if i > 0:
                icode.reportError(im_id)
            obj = picObj.info
            obj = obj['bounds']  # 验证码处的信息
            left = obj["left"]  # 验证码的位置信息
            top = obj['top']
            right = obj['right']
            bottom = obj['bottom']

            d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

            img = Image.open(sourcePng)
            box = (left, top, right, bottom)  # left top right bottom
            region = img.crop(box)  # 截取验证码的图片

            img = Image.new('RGBA', (right - left, bottom - top))
            img.paste(region, (0, 0))

            img.save(codePng)
            im = open(codePng, 'rb')

            codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR, 60)

            code = codeResult["Result"]
            im_id = codeResult["Id"]
            os.remove(sourcePng)
            os.remove(codePng)
            z.heartbeat()
            if code.isalpha() or code.isisdigitv() or code.isalnum():
                break
            else:
                continue

        return code

    def login(self, d, z, args, accounts):
        try:
            d.server.adb.cmd(
                "shell",
                "pm clear com.tencent.androidqqmail").communicate()  # 清除QQ邮箱缓存
            d.server.adb.cmd(
                "shell",
                "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
            ).communicate()  # 拉起QQ邮箱

            z.sleep(8)
            z.heartbeat()

            if args['mail_type'] == '163邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/ee'
                     ).exists:  # 选择163邮箱点击进入登陆页面
                    d(resourceId='com.tencent.androidqqmail:id/ee').click()
                    z.sleep(1)

            if args['mail_type'] == 'QQ邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/ea'
                     ).exists:  # 选择QQ邮箱点击进入登陆页面
                    d(resourceId='com.tencent.androidqqmail:id/ea').click()
                    z.sleep(1)

            if args['mail_type'] == '腾讯企业邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/eb'
                     ).exists:  # 选择腾讯企业邮箱登录点击进入登陆页面
                    d(resourceId='com.tencent.androidqqmail:id/eb').click()
                    z.sleep(1)

            account = accounts[0]['number']
            password = accounts[0]['password']

            if d(text='帐号密码登录').exists:
                d(text='帐号密码登录').click()

            if d(resourceId='com.tencent.androidqqmail:id/bi'
                 ).exists:  # 输入邮箱帐号
                d(resourceId='com.tencent.androidqqmail:id/bi').click()
                # self.input(z,account)
                self.input(z, account)

            if d(resourceId='com.tencent.androidqqmail:id/bs'
                 ).exists:  # 输入邮箱密码
                d(resourceId='com.tencent.androidqqmail:id/bs').click()
                self.input(z, password)

            if d(resourceId='com.tencent.androidqqmail:id/a_'
                 ).exists:  # 点击登录按钮
                d(resourceId='com.tencent.androidqqmail:id/a_').click()

            z.sleep(25)
            while True:
                if d(text="验证中"):
                    time.sleep(3)
                else:
                    break
            if args['mail_type'] == 'QQ邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/h'
                     ).exists:  # 判断是否要填写独立密码
                    self.input(z, "Abc" + account)
                    z.sleep(1)
                    if d(text='确定').exists:
                        d(text='确定').click()
                    z.sleep(5)

                while d(resourceId='com.tencent.androidqqmail:id/a16'
                        ).exists:  # 出现验证码
                    picObj = d(resourceId='com.tencent.androidqqmail:id/a19',
                               index=0)
                    code = self.palyCode(d, z, picObj)
                    if code == "":
                        return False
                    if d(resourceId='com.tencent.androidqqmail:id/a17').exists:
                        d(resourceId='com.tencent.androidqqmail:id/a17').click(
                        )
                    self.input(z, code)
                    if d(resourceId='com.tencent.androidqqmail:id/a_'
                         ).exists:  # 点击登陆
                        d(resourceId='com.tencent.androidqqmail:id/a_').click()
                    z.sleep(8)

                if d(resourceId='com.tencent.androidqqmail:id/h'
                     ).exists:  # 判断是否要填写独立密码
                    self.input(z, "Abc" + account)
                    z.sleep(1)
                    if d(text='确定').exists:
                        d(text='确定').click()

            if args['mail_type'] == '163邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/a_'
                     ).exists:  # 点击登录按钮
                    d(resourceId='com.tencent.androidqqmail:id/a_').click()

                z.sleep(3)
                z.heartbeat()

                d.server.adb.cmd("shell",
                                 "am force-stop com.tencent.androidqqmail"
                                 ).wait()  # 强制停止163邮箱
                d.server.adb.cmd(
                    "shell",
                    "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
                ).communicate()  # 拉起163邮箱

            if args['mail_type'] == '腾讯企业邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/a_'
                     ).exists:  # 点击登录按钮
                    d(resourceId='com.tencent.androidqqmail:id/a_').click()

                z.sleep(3)
                z.heartbeat()

                if d(text='收件箱​').exists:
                    z.toast(u"登录成功。退出模块")
                    d.server.adb.cmd(
                        "shell", "am force-stop com.tencent.androidqqmail"
                    ).wait()  # 强制停止
                    return True
                else:
                    return False
                # d.server.adb.cmd("shell", "am force-stop com.tencent.androidqqmail").wait()  # 强制停止163邮箱
                # d.server.adb.cmd("shell", "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail").communicate()  # 拉起163邮箱

            z.sleep(12)
            z.heartbeat()
            if d(textContains='你有多个应用同时收到').exists:
                d(text='确定').click()
                z.sleep(2)

            if d(text='收件箱​').exists:
                z.toast(u"登录成功。退出模块")
                d.server.adb.cmd(
                    "shell",
                    "am force-stop com.tencent.androidqqmail").wait()  # 强制停止
                return True
            else:
                return False
        except:
            logging.exception("exception")
            z.toast(u"程序出现异常,模块退出")
            d.server.adb.cmd(
                "shell",
                "am force-stop com.tencent.androidqqmail").wait()  # 强制停止
            return False

    def qiehuan(self, d, z, args):
        if args['mail_type'] == '163邮箱登录':
            self.type = '163mail'
        time_limit = int(args['slot_time_limit'])
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽

        slotnum = None
        if not slotObj is None:
            slotnum = slotObj['id']

        while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
            ).communicate()
            z.heartbeat()
            z.sleep(30)
            slotObj = self.slot.getAvailableSlot(time_limit)
            if not slotObj is None:
                slotnum = slotObj['id']
                break

        z.heartbeat()
        d.server.adb.cmd(
            "shell",
            "pm clear com.tencent.androidqqmail").communicate()  # 清除缓存

        obj = self.slot.getSlotInfo(slotnum)
        remark = obj['remark']
        remarkArr = remark.split("_")
        cateId = args['repo_account_id']
        if len(remarkArr) == 3:
            slotInfo = d.server.adb.device_serial(
            ) + '_' + self.type + '_' + slotnum
            cateId = remarkArr[2]
            numbers = self.repo.Getserial(cateId, slotInfo)
            if len(numbers) != 0:
                featureCodeInfo = numbers[0]['imei']
                z.set_serial("com.tencent.androidqqmail", featureCodeInfo)

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
        z.sleep(2)

        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            slotnum + "号\"").communicate()
        z.sleep(2)
        d.server.adb.cmd(
            "shell",
            "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
        ).communicate()  # 拉起QQ邮箱
        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)
        z.sleep(20)

        z.heartbeat()
        d.dump(compressed=False)
        if d(text='密码错误,请重新输入').exists or d(description='QQ邮箱').exists:
            QQnumber = remarkArr[1]
            self.repo.BackupInfo(cateId, 'normal', QQnumber, '',
                                 '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            self.slot.clear(slotnum)  # 清空改卡槽,并补登
            z.toast("卡槽邮箱号状态异常,补登陆卡槽")
            return False

        else:
            z.toast("邮箱登陆状态正常,切换完毕。")
            return True

    def action(self, d, z, args):

        while True:
            # z.toast("正在ping网络是否通畅")
            # i = 0
            # while i < 200:
            #     i += 1
            #     ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
            #     # print(ping)
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         z.toast(u"网络通畅。开始执行:" + args['mail_type'] + u" 有卡槽")
            #         break
            #     z.sleep(2)
            # if i > 200:
            #     z.toast(u"网络不通,请检查网络状态")
            #     return

            z.heartbeat()
            z.generate_serial("com.tencent.androidqqmail")  # 随机生成手机特征码

            if args['mail_type'] == '163邮箱登录':
                self.type = '163mail'

            accounts = self.repo.GetAccount(args['repo_account_id'],
                                            int(args['account_time_limit']),
                                            1)  # 去仓库获取QQ邮箱帐号
            if len(accounts) == 0:
                z.toast(u"帐号库为空")

            serial = d.server.adb.device_serial()
            self.slot = Slot(serial, self.type)
            slotnum = self.slot.getEmpty()  # 取空卡槽
            if slotnum == 0 or len(
                    accounts) == 0:  # 没有空卡槽的话或者仓库没有可登陆的帐号,进行卡槽切换。
                if self.qiehuan(d, z, args):
                    break
                else:
                    continue
            else:  # 有空卡槽的情况

                QQnumber = accounts[0]['number']
                # print QQnumber
                if self.login(d, z, args, accounts):
                    z.heartbeat()
                    featureCodeInfo = z.get_serial("com.tencent.androidqqmail")
                    self.slot.backup(slotnum,
                                     str(slotnum) + '_' + QQnumber + '_' +
                                     args["repo_account_id"])  # 设备信息,卡槽号,QQ号
                    self.repo.BackupInfo(
                        args["repo_account_id"], 'using', QQnumber,
                        featureCodeInfo,
                        '%s_%s_%s' % (d.server.adb.device_serial(), self.type,
                                      slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号
                    break

                else:
                    self.slot.clear(slotnum)  # 清空改卡槽,并补登
                    if d(text='本次登录存在异常,如需帮助请前往安全中心').exists:
                        z.toast(u"登录失败。重新登录")
                        self.repo.BackupInfo(args["repo_account_id"], 'frozen',
                                             QQnumber, '',
                                             '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    elif d(text='帐号或密码错误').exists:
                        z.toast(u"帐号或密码错误")
                        self.repo.BackupInfo(args["repo_account_id"], 'frozen',
                                             QQnumber, '',
                                             '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    else:
                        self.repo.BackupInfo(args["repo_account_id"], 'normal',
                                             QQnumber, '',
                                             '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    continue
예제 #6
0
class QQSafetyCenter:
    def __init__(self):
        self.repo = Repo()
        self.type = 'token'

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        # 生成当前时间
        randomNum = random.randint(0, 1000)
        # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum)
        uniqueNum = str(nowTime) + str(randomNum)
        return uniqueNum

    def LoginPlayCode(self, d, z):
        self.scode = smsCode(d.server.adb.device_serial())
        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
        codeEditTextObj = d(resourceId='com.tencent.mobileqq:id/name',
                            index='2',
                            className="android.widget.EditText")
        if codeEditTextObj.exists:  # 需要验证码的情况
            icode = imageCode()
            im_id = ""
            for i in range(0, 4):  # 打码循环
                if i > 0:
                    icode.reportError(im_id)
                obj = d(resourceId='com.tencent.mobileqq:id/name',
                        className='android.widget.ImageView'
                        )  # 当弹出选择QQ框的时候,定位不到验证码图片
                obj = obj.info
                obj = obj['bounds']  # 验证码处的信息
                left = obj["left"]  # 验证码的位置信息
                top = obj['top']
                right = obj['right']
                bottom = obj['bottom']

                d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

                img = Image.open(sourcePng)
                box = (left, top, right, bottom)  # left top right bottom
                region = img.crop(box)  # 截取验证码的图片

                img = Image.new('RGBA', (right - left, bottom - top))
                img.paste(region, (0, 0))

                img.save(codePng)
                im = open(codePng, 'rb')

                codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR,
                                           60)

                code = codeResult["Result"]
                im_id = codeResult["Id"]
                os.remove(sourcePng)
                os.remove(codePng)

        return code

    def CaseOne(self, d, z, QQNumber,
                QQPassword):  # 登录情况一:手机上有qq登录或提示历史登陆过的帐号直接登陆

        if d(text='切换帐号').exists and d(text='添加帐号').exists:
            if d(resourceId='com.tencent.mobileqq:id/name', index=0).exists:
                obj = d(resourceId='com.tencent.mobileqq:id/name',
                        index=0,
                        className='android.widget.RelativeLayout').child(
                            className='android.widget.LinearLayout',
                            index=1).child(
                                resourceId='com.tencent.mobileqq:id/name',
                                index=0,
                                className='android.widget.LinearLayout').child(
                                    resourceId='com.tencent.mobileqq:id/name',
                                    index=0,
                                    className='android.widget.RelativeLayout')
                Str = obj.info["bounds"]  # 获取该控件大小等信息
                height = int(Str["bottom"]) - int(Str["top"])
                d.swipe(
                    int(Str["right"]) - 10,
                    int(Str["bottom"]) - height / 2,
                    int(Str["left"]) + 10,
                    int(Str["bottom"]) - height / 2, 5)
                z.sleep(1.5)
                if d(text='删除').exists:
                    d(text='删除').click()
                    z.sleep(1)
            d(text='添加帐号').click()

        d(resourceId='com.tencent.mobileqq:id/account').click()
        z.input(QQNumber)

        d(resourceId='com.tencent.mobileqq:id/password').click()
        z.input(QQPassword)

        if d(text='登 录').exists:
            d(text='登 录').click()
            z.sleep(5)

        if d(text='输入验证码').exists:
            code = self.LoginPlayCode(d, z)
            z.input(code)
            z.sleep(1)

            if d(text='完成').exists:
                d(text='完成').click()

    def CaseTwo(self, d, z, QQNumber, QQPassword):  #登录情况二:手机上没有登陆qq也没有登录过安全中心

        d(className='android.view.View', index=1).click()
        z.input(QQNumber)

        d(className='android.view.View', index=2).click()
        z.input(QQPassword)

        if d(description='登 录').exists:
            d(description='登 录').click()

    def Login(self, d, z, args):  #登录方法
        self.scode = smsCode(d.server.adb.device_serial())
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.token").communicate()  # 清除缓存
        if d(text='QQ安全中心').exists:
            d(text='QQ安全中心').click()
            z.sleep(6)
        else:
            z.toast("请返回有QQ安全中心的主页面,再运行")
            d.server.adb.cmd(
                "shell", "pm clear com.tencent.token").communicate()  # 清除缓存
            return
        d.server.adb.cmd("shell",
                         "am start -n com.tencent.token/.ui.LogoActivity"
                         ).communicate()  # 拉起来
        z.sleep(6)

        if d(resourceId='com.tencent.token:id/account_bind_qqface').exists:
            d(resourceId='com.tencent.token:id/account_bind_qqface').click()
            z.sleep(1)

        if d(text='登录').exists:
            d(text='登录').click()
            z.sleep(0.5)

        if d(text='QQ登录').exists:
            d(text='QQ登录').click()
            z.sleep(1)

        cate_id = args["repo_cate_id"]
        time_limit = args['time_limit']
        numbers = self.repo.GetAccount(cate_id, time_limit, 1)
        print(numbers)
        while len(numbers) == 0:
            z.heartbeat()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\""
                % (cate_id, time_limit)).communicate()
            z.sleep(2)
            return "none"

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']
        # QQNumber = '3518608471'
        # QQPassword = '******'
        z.sleep(1)

        if d(text='切换帐号').exists:
            d(text='切换帐号').click()
            z.sleep(1)
            self.CaseOne(d, z, QQNumber, QQPassword)
            z.sleep(5)
        else:
            self.CaseTwo(d, z, QQNumber, QQPassword)
            z.sleep(5)

        if d(description='请向右拖动滑块完成拼图').exists:
            z.toast("遇到安全验证,重新开始")
            return "again"

        if d(text='身份验证').exists:
            d(text='下一步').click()

        if d(text='请填写您收到的短信验证码:').exists:
            info = numbers[0]['qqtoken']
            infoArray = info.split('----')
            number = infoArray[6]
            # number = "14773454349"
            try:
                PhoneNumber = self.scode.GetPhoneNumber(
                    self.scode.QQ_TOKEN_BIND, number)  # 获取接码平台手机号码
            except:
                logging.exception("exception")
                PhoneNumber = None

            if PhoneNumber is None:
                self.repo.BackupInfo(cate_id, 'frozen', QQNumber, '',
                                     '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                z.toast('查不无此号')
                return "again"

            try:
                code = self.scode.GetVertifyCode(
                    PhoneNumber, self.scode.QQ_TOKEN_BIND)  # 获取接码验证码
                self.scode.defriendPhoneNumber(PhoneNumber,
                                               self.scode.QQ_TOKEN_BIND)
            except:
                logging.exception("exception")
                code = ''

            if code == '':
                z.toast(PhoneNumber + '手机号,获取不到验证码')
                self.scode.defriendPhoneNumber(PhoneNumber,
                                               self.scode.QQ_TOKEN_BIND)
                return "again"

            z.input(code)
            if d(resourceId='com.tencent.token:id/sms_code'
                 ).exists:  #点击输入框输入验证码
                d(resourceId='com.tencent.token:id/sms_code').click()
                z.input(code)

            if d(text='下一步').exists:
                d(text='下一步').click()
                z.sleep(5)

            if d(text='开启安全之旅').exists:
                d(text='开启安全之旅').click()

            return QQNumber

            if d(textContains='绑定QQ失败').exists:
                return "again"

        elif d(text='登录失败').exists:
            return "again"

    def QieHuanSolt(self, d, z, args):  # 卡槽切换方法
        time_limit_slot = int(args['time_limit_slot'])
        slotObj = self.slot.getAvailableSlot(
            time_limit_slot)  # 取空卡槽,取2小时没用过的卡槽
        if not slotObj is None:
            slotnum = slotObj['id']
        print(slotnum)
        while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
            ).communicate()
            z.heartbeat()
            z.sleep(10)
            slotObj = self.slot.getAvailableSlot(time_limit_slot)
            if not slotObj is None:
                slotnum = slotObj['id']

        d.server.adb.cmd(
            "shell", "am broadcast -a com.zunyun.zime.toast --es msg \"正在切换到" +
            slotnum + "号卡槽...\"").communicate()
        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            slotnum + "号\"").communicate()

        if d(text='QQ安全中心').exists:
            d(text='QQ安全中心').click()
            z.sleep(6)
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.token").communicate()  # 清除缓存
        d.server.adb.cmd(
            "shell", "am broadcast -a com.zunyun.zime.toast --es msg \"正在切换到" +
            slotnum + "号卡槽...\"").communicate()

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽

        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            slotnum + "号\"").communicate()
        d.server.adb.cmd("shell",
                         "am start -n com.tencent.token/.ui.LogoActivity"
                         ).communicate()  # 拉起来
        z.sleep(10)

        if d(text='欢迎来到安全中心').exists:
            return "fail"

        return "success"

    def action(self, d, z, args):
        z.generate_serial("com.tencent.tim")  # 随机生成手机特征码
        z.toast("随机生成手机特征码")

        serial = d.server.adb.device_serial()
        cate_id = args["repo_cate_id"]
        self.slot = Slot(serial, self.type)
        slotnum = self.slot.getEmpty()  # 取空卡槽

        if slotnum == 0:
            QieHuanSolt_Result = self.QieHuanSolt(d, z, args)
            if QieHuanSolt_Result == "fail":
                obj = self.slot.getSlotInfo(slotnum)
                remark = obj['remark']
                remarkArr = remark.split("_")
                QQnumber = remarkArr[1]
                self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '',
                                     '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                self.slot.clear(slotnum)  # 清空改卡槽,并补登
                z.toast("卡槽恢复失败,进行补登")
                self.action(d, z, args)

            else:
                z.toast("卡槽恢复成功,帐号正常")

        else:
            Login_Result = self.Login(d, z, args)
            if Login_Result == "again":
                self.action(d, z, args)

            elif Login_Result == "none":  # 有空卡槽,单仓库无帐号可登,继续继续切换卡槽
                QieHuanSolt_Result = self.QieHuanSolt(d, z, args)
                if QieHuanSolt_Result == "fail":
                    obj = self.slot.getSlotInfo(slotnum)
                    remark = obj['remark']
                    remarkArr = remark.split("_")
                    QQnumber = remarkArr[1]
                    self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '',
                                         '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    self.slot.clear(slotnum)  # 清空改卡槽,并补登
                    z.toast("卡槽恢复失败,进行补登")
                    self.action(d, z, args)

                else:
                    z.toast("卡槽恢复成功,帐号正常")

            else:
                QQnumber = Login_Result
                self.slot.backup(slotnum,
                                 str(slotnum) + '_' + QQnumber)  # 设备信息,卡槽号,QQ号
                self.repo.BackupInfo(cate_id, 'using', QQnumber, serial,
                                     '%s_%s_%s' %
                                     (d.server.adb.device_serial(), self.type,
                                      slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号
예제 #7
0
class WeiXinRegister:
    def __init__(self):
        self.repo = Repo()
        self.type = 'wechat'

    def GenPassword(self, numOfNum=4, numOfLetter=4):
        # 选中numOfNum个数字
        slcNum = [random.choice(string.digits) for i in range(numOfNum)]
        # 选中numOfLetter个字母
        slcLetter = [
            random.choice(string.lowercase) for i in range(numOfLetter)
        ]
        slcChar = slcLetter + slcNum
        genPwd = ''.join([i for i in slcChar])
        return genPwd

    def RegisterWX(self, d, z, args, slotnum):
        z.generate_serial("com.tencent.mm")  # 随机生成手机特征码
        z.toast("随机生成手机特征码")
        nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 生成当前时间
        saveCate = args['repo_information_id']
        self.scode = smsCode(d.server.adb.device_serial())
        password = self.GenPassword()

        d.press.home()
        d.server.adb.cmd(
            "shell", "pm clear com.tencent.mm").communicate()  # 清除缓存,返回home页面

        if d(text='微信').exists:
            d(text='微信').click()
        else:
            z.toast("该页面没有微信,请翻到有微信页面运行")

        while not d(text='注册').exists:
            z.toast("等待 登录按钮 出现")
            d.dump(compressed=False)
            z.sleep(3)

        if d(text='登录').exists:
            d(text='登录').click()

        z.sleep(2)
        if not d(textContains='中国').exists:
            d(text='国家/地区').click()
            z.sleep(1.5)
            d(resourceId='com.tencent.mm:id/aq').click()
            z.input('中')
            d(text='中国').click()

        information_cate_id = args['repo_information_id']
        numbers = self.repo.GetInformation(information_cate_id)
        if len(numbers) == 0:
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"资料库%s号仓库为空,没有取到手机号\""
                % information_cate_id).communicate()
            z.sleep(10)
            return "notphonenumber"

        z.heartbeat()
        number = numbers[0]['phonenumber']
        try:
            PhoneNumber = self.scode.GetPhoneNumber(self.scode.WECHAT_REGISTER,
                                                    number)  # 获取接码平台手机号码
        except:
            PhoneNumber = None
        # PhoneNumber = self.scode.GetPhoneNumber( self.scode.WECHAT_REGISTER)  # 获取接码平台手机号码

        if PhoneNumber is None:
            self.repo.DeleteInformation(saveCate, number)
            z.toast('讯码查不无此号')
            return "again"

        z.input(PhoneNumber)
        if d(text='下一步').exists:
            d(text='下一步').click()
            z.sleep(1.5)

        d(text='用短信验证码登录').click()
        z.sleep(1.5)

        d(text='获取验证码').click()
        z.sleep(1)

        if d(text='确认手机号码').exists:
            d(text='确定').click()

        z.sleep(3)
        try:
            code = self.scode.GetVertifyCode(
                PhoneNumber, self.scode.WECHAT_REGISTER)  # 获取接码验证码
            self.scode.defriendPhoneNumber(PhoneNumber,
                                           self.scode.WECHAT_REGISTER)
        except:
            self.scode.defriendPhoneNumber(PhoneNumber,
                                           self.scode.WECHAT_REGISTER)
            code = ''
        if code == '':
            self.repo.DeleteInformation(saveCate, PhoneNumber)
            z.toast(PhoneNumber + '手机号,获取不到验证码')
            return "again"

        z.input(code)
        print('手机号码:' + PhoneNumber + '验证码:' + code)

        z.sleep(2)
        d(text='登录', className='android.widget.Button').click()

        z.sleep(5)
        z.heartbeat()
        if d(textContains='看看手机通讯录').exists:
            d(text='是').click()
            z.sleep(15)
            z.heartbeat()
            if d(textContains='如果这不是你本人操作,你的短信内容已经泄露。请检查手机是否被植入木马导致短信被转发。'
                 ).exists:
                d(text='确定').click()

            featureCodeInfo = z.get_serial("com.tencent.mm")
            # 信息入库
            para = {
                "phoneNumber": PhoneNumber,
                'x_02': slotnum,
                'x_03': d.server.adb.device_serial(),
                'x_04': featureCodeInfo,
                'x_05': nowTime,
                'x_19': 'WXRegister'
            }
            self.repo.PostInformation(saveCate, para)

            # 微信号入卡槽
            self.slot.backup(slotnum,
                             str(slotnum) + '_' + PhoneNumber)  # 卡槽号,手机号
            return "success"

        if d(textContains='当前手机号一个月内已成功注册微信号').exists:
            d(text='确定')
            self.repo.DeleteInformation(saveCate, PhoneNumber)
            return "again"

        if d(textContains='操作频率').exists:
            d(text='确定').click()
            return "stop"

        if d(text='该手机号码尚未被注册,是否立即注册微信?').exists:
            d(text='注册').click()
            z.sleep(2)
            if d(text='填写个人信息').exists:
                d(text='昵称').click()
                nicknameList = [
                    random.choice(string.lowercase) for i in range(4)
                ]
                nickname = ''.join([i for i in nicknameList])
                z.input(nickname)
                d(text='注册').click()
                z.sleep(2)

                if d(textContains='相同手机号不可频繁重复注册微信帐号。').exists:
                    self.repo.DeleteInformation(saveCate, PhoneNumber)
                    return "again"

                while not d(text='查找你的微信朋友').exists:
                    d.dump(compressed=False)
                    z.sleep(3)

                featureCodeInfo = z.get_serial("com.tencent.mm")
                # 信息入库
                para = {
                    "phoneNumber": PhoneNumber,
                    'x_02': slotnum,
                    'x_03': d.server.adb.device_serial(),
                    'x_04': featureCodeInfo,
                    'x_05': nowTime,
                    'x_19': 'WXRegister'
                }
                self.repo.PostInformation(saveCate, para)

                # 微信号入卡槽
                self.slot.backup(slotnum,
                                 str(slotnum) + '_' + PhoneNumber)  # 卡槽号,手机号

                if d(text='好').exists:
                    d(text='好').click()
                    z.sleep(10)

                return "success"

        n = 0
        while True:
            z.sleep(5)
            n = n + 1
            if d(text='登录', className='android.widget.Button').exists:
                d(text='登录', className='android.widget.Button').click()
                z.sleep(8)

            if d(textContains='是否立即验证').exists:
                d(text='确定').click()
                z.sleep(8)
            elif d(text='声纹验证').exists:
                d(className='android.widget.ImageView',
                  description='返回').click()
                self.repo.DeleteInformation(saveCate, PhoneNumber)
                break
            elif d(text='系统检测到帐号有被盗风险。为了你的帐号安全,新设备的登录请求会被拒绝。请使用常用设备登录微信。'
                   ).exists:
                d(text='确定').click()
                if n == 1:
                    continue
                else:
                    break
            else:
                self.repo.DeleteInformation(saveCate, PhoneNumber)
                break

            if d(text='确认登录').exists:
                if n == 1:
                    d(className='android.widget.ImageView',
                      description='返回').click()
                    continue
                elif n == 2:
                    self.repo.DeleteInformation(saveCate, PhoneNumber)
                break

            if d(text='设置密码').exists:
                d(className='android.widget.LinearLayout',
                  index=2).child(className='android.widget.EditText',
                                 index=1).click()
                z.input(password)
                z.sleep(2)
                d(className='android.widget.LinearLayout',
                  index=4).child(className='android.widget.EditText',
                                 index=1).click()
                z.input(password)
                d(text='完成').click()
                z.sleep(15)

                z.heartbeat()
                if d(textContains='看看手机通讯录').exists:
                    d(text='是').click()
                    z.sleep(15)
                    z.heartbeat()

                if d(textContains='你的操作频繁过快,请稍后重试').exists:
                    d(text='确定').click()
                    z.sleep(15)
                    z.heartbeat()

                if d(textContains='如果这不是你本人操作,你的短信内容已经泄露。请检查手机是否被植入木马导致短信被转发。'
                     ).exists:
                    d(text='确定').click()
                featureCodeInfo = z.get_serial("com.tencent.mm")
                # 入库信息
                para = {
                    "phoneNumber": PhoneNumber,
                    'x_02': slotnum,
                    'x_03': d.server.adb.device_serial(),
                    'x_04': featureCodeInfo,
                    'x_05': nowTime,
                    'x_06': password,
                    'x_19': 'WXRegister'
                }
                self.repo.PostInformation(saveCate, para)

                # 入卡槽信息
                self.slot.backup(slotnum,
                                 str(slotnum) + '_' + PhoneNumber)  # 卡槽号,手机号
                return "success"

            if d(text='验证身份').exists:
                z.sleep(3)
                if d(description='通过扫码验证身份',
                     className='android.view.View',
                     index=1).exists:
                    featureCodeInfo = z.get_serial("com.tencent.mm")
                    # 入库信息
                    para = {
                        "phoneNumber": PhoneNumber,
                        'x_02': slotnum,
                        'x_03': d.server.adb.device_serial(),
                        'x_04': featureCodeInfo,
                        'x_05': nowTime,
                        'x_19': 'WXRegister'
                    }
                    self.repo.PostInformation(saveCate, para)

                    # 入卡槽信息
                    self.slot.backup(slotnum,
                                     str(slotnum) + '_' +
                                     PhoneNumber)  # 卡槽号,手机号
                    break

                if d(descriptionContains='验证失败',
                     className='android.view.View').exists:
                    d(descriptionContains='关闭页面',
                      className='android.view.View',
                      index=3).click()
                    break

                if d(descriptionContains='验证通过',
                     className='android.view.View').exists:
                    d(descriptionContains='关闭页面',
                      className='android.view.View',
                      index=3).click()
                    featureCodeInfo = z.get_serial("com.tencent.mm")
                    # 入库信息
                    para = {
                        "phoneNumber": PhoneNumber,
                        'x_02': slotnum,
                        'x_03': d.server.adb.device_serial(),
                        'x_04': featureCodeInfo,
                        'x_05': nowTime,
                        'x_19': 'WXRegister'
                    }
                    self.repo.PostInformation(saveCate, para)

                    # 入卡槽信息
                    self.slot.backup(slotnum,
                                     str(slotnum) + '_' +
                                     PhoneNumber)  # 卡槽号,手机号
                    return "success"

                for i in range(1, 6):
                    if i != 1:
                        yibushiObj_HTC = d(
                            className='android.widget.RadioButton',
                            descriptionContains='以上都不是')
                        if not yibushiObj_HTC.exists:
                            break

                    if d(description='请选择你最近一次登录设备的名称').exists:
                        if d(className='android.widget.RadioButton',
                             index=1).exists:
                            number = random.randint(1, 5)
                            if number == 1:
                                d(className='android.widget.RadioButton',
                                  index=1).click()
                                d(className='android.view.View',
                                  descriptionContains='下一步').click()  # 下一步
                                z.sleep(2)
                            if number == 2:
                                d(className='android.widget.RadioButton',
                                  index=2).click()
                                d(className='android.view.View',
                                  descriptionContains='下一步').click()  # 下一步
                                z.sleep(2)
                            if number == 3:
                                d(className='android.widget.RadioButton',
                                  index=3).click()
                                d(className='android.view.View',
                                  descriptionContains='下一步').click()  # 下一步
                                z.sleep(2)
                            if number == 4:
                                d(className='android.widget.RadioButton',
                                  index=4).click()
                                d(className='android.view.View',
                                  descriptionContains='下一步').click()  # 下一步
                                z.sleep(2)
                            if number == 5:
                                d(className='android.widget.RadioButton',
                                  index=5).click()
                                d(className='android.view.View',
                                  descriptionContains='下一步').click()  # 下一步
                                z.sleep(2)
                        else:
                            if d(className='android.widget.RadioButton',
                                 descriptionContains='以上都不是').exists:
                                d(className='android.widget.RadioButton',
                                  descriptionContains='以上都不是').click()
                                d(className='android.view.View',
                                  descriptionContains='下一步').click()  # 下一步
                            else:
                                d.click(410, 540)
                                d.click(410, 640)
                            z.sleep(2)

                    elif d(description='请从下面头像中选出两位你的好友').exists:
                        d(className='android.widget.ImageView',
                          description='返回').click()
                        break
                    else:
                        if d(className='android.widget.RadioButton',
                             descriptionContains='以上都不是').exists:
                            d(className='android.widget.RadioButton',
                              descriptionContains='以上都不是').click()
                            d(className='android.view.View',
                              descriptionContains='下一步').click()  # 下一步
                        else:
                            d.click(410, 540)
                            d.click(410, 640)
                        z.sleep(2)

            z.sleep(5)
            if d(text='确认登录').exists:
                d(className='android.widget.ImageView',
                  description='返回').click()
                continue

            if d(descriptionContains='验证失败',
                 className='android.view.View').exists:
                d(descriptionContains='关闭页面',
                  className='android.view.View',
                  index=3).click()
                continue

            if d(descriptionContains='验证通过',
                 className='android.view.View').exists:
                d(descriptionContains='关闭页面',
                  className='android.view.View',
                  index=3).click()
                continue

        return "again"

    def action(self, d, z, args):
        logger = util.logger
        lock = "YES"
        while True:
            time_limit = 0
            serial = d.server.adb.device_serial()
            self.slot = Slot(serial, self.type)
            if lock == "YES":
                slotnum = self.slot.getEmpty()  # 取空卡槽
            else:
                slotnum = 0
            if slotnum == 0:  # 没有空卡槽的话
                slotObj = self.slot.getAvailableSlot(
                    time_limit)  # 取空卡槽,取2小时没用过的卡槽
                if not slotObj is None:
                    slotnum = slotObj['id']
                print(slotnum)
                while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
                    d.server.adb.cmd(
                        "shell",
                        "am broadcast -a com.zunyun.zime.toast --es msg \"微信卡槽全满,无间隔时间段未用\""
                    ).communicate()
                    z.heartbeat()
                    z.sleep(30)
                    slotObj = self.slot.getAvailableSlot(time_limit)
                    if not slotObj is None:
                        slotnum = slotObj['id']
                z.heartbeat()

                obj = self.slot.getSlotInfo(slotnum)
                remark = obj['remark']
                remarkArr = remark.split("_")
                if len(remarkArr) == 2:

                    phonenumber = remarkArr[1]
                    information_cate_id = args['repo_information_id']
                    numbers = self.repo.GetInformation(information_cate_id,
                                                       phonenumber)
                    featureCodeInfo = numbers[0]['x04']
                    z.set_serial("com.tencent.mm", featureCodeInfo)
                self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
                d.server.adb.cmd(
                    "shell",
                    "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为"
                    + slotnum + "号\"").communicate()
                d.server.adb.cmd(
                    "shell",
                    "am start -n com.tencent.mm/com.tencent.mm.ui.LauncherUI"
                ).communicate()  # 将微信拉起来
                z.sleep(15)
                z.heartbeat()
                if d(text='立刻安装').exists:
                    z.toast("出现更新弹框")
                    d(textContains='取消').click()
                    z.sleep(1.5)
                    d(text='是').click()

                if d(text='发现') and d(text='我') and d(text='通讯录').exists:
                    z.toast("成功切换" + slotnum + "卡槽")
                    break
                else:
                    self.slot.clear(slotnum)  # 清空改卡槽,并补登
                    z.toast("切换失败,开始补登")
                    lock = "YES"
                    self.action(d, z, args)

            else:
                result = self.RegisterWX(d, z, args, slotnum)
                if result == "again":
                    continue
                elif result == "stop":
                    z.toast("操作频繁,模块结束运行")
                    break
                elif result == "notphonenumber":
                    lock = "NO"
                    continue
                else:
                    continue
예제 #8
0
class TIMLogin03:
    def __init__(self):
        self.repo = Repo()
        self.type = 'tim'

    def IPCheckRepitition(self, z, d, args):
        z.toast("正在检测IP...")
        while True:
            # 开关飞行模式
            d.server.adb.cmd(
                "shell",
                "settings put global airplane_mode_on 1").communicate()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true"
            ).communicate()
            z.sleep(3)
            d.server.adb.cmd(
                "shell",
                "settings put global airplane_mode_on 0").communicate()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
            ).communicate()

            t = 0
            while t < 6:
                ping = d.server.adb.cmd("shell",
                                        "ping -c 3 baidu.com").communicate()
                print(ping)
                if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                    break
                z.sleep(10)
                z.heartbeat()
                z.sleep(10)
                t = t + 1
            if t >= 6:
                z.toast("网络无法ping通,重新开关飞行模式")
                continue

            # 获取手机IP
            IPList = d.server.adb.cmd(
                "shell", "curl http://ipecho.net/plain").communicate()
            IP = IPList[0]
            print(IP)

            # IP添加到缓存
            ip = cache.get(IP)
            print(ip)
            if ip is None:
                timeoutStr = args['time_out']
                timeout = int(timeoutStr) * 60
                cache.set(IP, IP, timeout)
                z.toast("IP检测完成")
                break
            else:
                continue

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        # 生成当前时间
        randomNum = random.randint(0, 1000)
        # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum)
        uniqueNum = str(nowTime) + str(randomNum)
        return uniqueNum

    def LoginPlayCode(self, d, z):
        self.scode = smsCode(d.server.adb.device_serial())
        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
        detection_robot = d(index='3', className="android.widget.EditText")
        not_detection_robot = d(resourceId='com.tencent.tim:id/name',
                                index='2',
                                className="android.widget.EditText")
        if detection_robot.exists or not_detection_robot.exists:  # 需要验证码的情况
            icode = imageCode()
            im_id = ""
            for i in range(0, 4):  # 打码循环
                if i > 0:
                    icode.reportError(im_id)
                obj = d(resourceId='com.tencent.tim:id/name',
                        className='android.widget.ImageView'
                        )  # 当弹出选择QQ框的时候,定位不到验证码图片
                if not obj.exists:
                    obj = d(index='2', className='android.widget.Image')
                obj = obj.info
                obj = obj['bounds']  # 验证码处的信息
                left = obj["left"]  # 验证码的位置信息
                top = obj['top']
                right = obj['right']
                bottom = obj['bottom']

                d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

                img = Image.open(sourcePng)
                box = (left, top, right, bottom)  # left top right bottom
                region = img.crop(box)  # 截取验证码的图片

                img = Image.new('RGBA', (right - left, bottom - top))
                img.paste(region, (0, 0))

                img.save(codePng)
                im = open(codePng, 'rb')

                codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR,
                                           60)

                code = codeResult["Result"]
                im_id = codeResult["Id"]
                os.remove(sourcePng)
                os.remove(codePng)
                z.heartbeat()
                z.sleep(5)
                if not_detection_robot.exists:
                    d(resourceId='com.tencent.tim:id/name',
                      index='2',
                      className="android.widget.EditText").set_text(code)
                else:
                    detection_robot.set_text(code)
                z.sleep(3)
                if d(descriptionContains='验证',
                     className='android.view.View').exists:
                    d(descriptionContains='验证',
                      className='android.view.View').click()
                else:
                    d(text='完成',
                      resourceId='com.tencent.tim:id/ivTitleBtnRightText'
                      ).click()
                z.sleep(5)
                z.heartbeat()
                while d(className='android.widget.ProgressBar',
                        index=0).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                    z.sleep(2)
                z.heartbeat()
                if detection_robot.exists or not_detection_robot.exists:
                    continue
                else:
                    break
            z.sleep(5)
            if d(textContains='验证码').exists:
                return "no"
            else:
                return "yes"
        else:
            return "no"

    def login(self, d, args, z):
        z.heartbeat()
        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])
        W_H = width / height
        screenScale = round(W_H, 2)

        cate_id = args["repo_cate_id"]
        time_limit1 = args['time_limit1']
        numbers = self.repo.GetAccount(cate_id, time_limit1, 1)
        while len(numbers) == 0:
            z.heartbeat()
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\""
                % (cate_id, time_limit1)).communicate()
            z.sleep(2)
            return 0

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']
        z.sleep(1)
        z.heartbeat()
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.tim").communicate()  # 清除缓存
        # d.server.adb.cmd("shell",
        #                   "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来
        z.server.adb.run_cmd(
            "shell",
            "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity"
        )
        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)
        z.sleep(3)
        z.server.adb.run_cmd(
            "shell",
            "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity"
        )
        z.heartbeat()
        if d(className='android.widget.ImageView',
             resourceId='com.tencent.tim:id/title',
             index=1).exists:
            for i in range(0, 2):
                d.swipe(width - 20, height / 2, 0, height / 2, 5)
                z.sleep(1.5)
            if d(text='立即体验').exists:
                d(text='立即体验').click()
        z.sleep(2)
        d.dump(compressed=False)
        if d(text='登 录', resourceId='com.tencent.tim:id/btn_login').exists:
            z.toast("控件点击")
            d(text='登 录').click()
        else:
            d(text='QQ号登录').click()
        z.sleep(1)
        # d(className='android.widget.EditText', index=0).set_text(QQNumber)  # 1918697054----xiake1234.  QQNumber
        d(className='android.widget.EditText',
          index=0).click()  # 1918697054----xiake1234.  QQNumber
        z.input(QQNumber)

        z.sleep(1)
        # d(resourceId='com.tencent.mobileqq:id/password').set_text(QQPassword)  # Bn2kJq5l     QQPassword
        d(resourceId='com.tencent.tim:id/password').click(
        )  # Bn2kJq5l     QQPassword
        z.input(QQPassword)
        z.heartbeat()
        logger = util.logger
        print('QQ号:%s,QQ密码:%s' % (QQNumber, QQPassword))
        d.dump(compressed=False)
        d(text='登 录', resourceId='com.tencent.tim:id/login').click()
        z.sleep(1)
        while d(text='登录中').exists:
            z.sleep(2)
        z.sleep(5)
        z.heartbeat()

        detection_robot = d(index='3', className="android.widget.EditText")
        not_detection_robot = d(resourceId='com.tencent.tim:id/name',
                                index='2',
                                className="android.widget.EditText")
        if detection_robot.exists or not_detection_robot.exists:
            playCodeResult = self.LoginPlayCode(d, z)  # 打验证码

        if playCodeResult == "no":
            return "nothing"

        z.sleep(5)
        z.heartbeat()
        if d(text='马上绑定').exists:
            return QQNumber

        if d(text='匹配手机通讯录').exists:  # 登陆上后弹出t通讯录的情况
            d(text='匹配手机通讯录').click()
            z.sleep(1.5)
            if d(text='取消').exists:
                d(text='取消').child()
            return QQNumber

        if d(text='消息').exists and d(description='快捷入口').exists:
            z.toast("卡槽QQ状态正常,继续执行")
            return QQNumber

        if d(text='去安全中心').exists:
            self.repo.BackupInfo(cate_id, 'frozen', QQNumber, '',
                                 '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            z.toast("登陆失败,重新登陆")
            return "nothing"
        else:
            self.repo.BackupInfo(cate_id, 'normal', QQNumber, '',
                                 '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            z.toast("登陆失败,重新登陆")
            return "nothing"

    def qiehuan(self, d, z, args):
        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])
        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽
        while slotObj is None:  # 2小时没有用过的卡槽也为空的情况
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
            ).communicate()
            z.heartbeat()
            z.sleep(10)
            slotObj = self.slot.getAvailableSlot(
                time_limit)  # 没有空卡槽,取2小时没用过的卡槽

        if not slotObj is None:
            slotnum = slotObj['id']
        z.heartbeat()
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.tim").communicate()  # 清除缓存

        # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
        # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
        # z.sleep(6)
        # z.heartbeat()
        # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
        # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
        # z.heartbeat()
        # z.toast( "正在ping网络是否通畅" )
        # while True:
        #     ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
        #     print(ping)
        #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
        #         break
        #     z.sleep(2)

        try:
            self.IPCheckRepitition(z, d, args)
        except:
            z.toast("IP检测出错了,请查找问题")

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽

        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            str(slotnum) + "号\"").communicate()
        z.sleep(2)
        # d.server.adb.cmd("shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity").communicate()  # 拉起来
        z.server.adb.run_cmd(
            "shell",
            "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity"
        )

        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)

        z.sleep(3)
        z.server.adb.run_cmd(
            "shell",
            "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity"
        )
        z.heartbeat()
        if d(className='android.widget.ImageView',
             resourceId='com.tencent.tim:id/title',
             index=1).exists:
            for i in range(0, 2):
                d.swipe(width - 20, height / 2, 0, height / 2, 5)
                z.sleep(1.5)
            if d(text='立即体验').exists:
                d(text='立即体验').click()
        z.sleep(2)

        if d(text='消息').exists or d(text='马上绑定').exists or d(
                text='匹配手机通讯录').exists:
            if d(text='匹配手机通讯录').exists:  # 登陆上后弹出t通讯录的情况
                d(text='匹配手机通讯录').click()
                z.sleep(1.5)
                if d(text='取消').exists:
                    d(text='取消').child()
            z.toast("卡槽QQ切换成功,继续执行")
        else:
            obj = self.slot.getSlotInfo(slotnum)
            remark = obj['remark']
            remarkArr = remark.split("_")
            QQnumber = remarkArr[1]
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '',
                                     '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(cate_id, 'normal', QQnumber, '', '')
            self.slot.clear(slotnum)  # 清空改卡槽,并补登
            z.toast("卡槽QQ状态异常,补登陆卡槽")
            self.action(d, z, args)

    def action(self, d, z, args):
        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])

        z.generate_serial("com.tencent.tim")  # 随机生成手机特征码
        z.toast("随机生成手机特征码")

        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotnum = self.slot.getEmpty()  # 取空卡槽
        if slotnum == 0:  # 没有空卡槽的话
            slotObj = self.slot.getAvailableSlot(time_limit)  # 取空卡槽,取2小时没用过的卡槽
            if not slotObj is None:
                slotnum = slotObj['id']
            print(slotnum)
            while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
                d.server.adb.cmd(
                    "shell",
                    "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
                ).communicate()
                z.heartbeat()
                z.sleep(10)
                slotObj = self.slot.getAvailableSlot(time_limit)
                if not slotObj is None:
                    slotnum = slotObj['id']
            z.heartbeat()
            # d.server.adb.cmd( "shell", "pm clear com.tencent.tim" ).communicate( )  # 清除缓存
            # d.server.adb.cmd( "shell", "am force-stop com.tencent.tim" ).communicate( )  # 强制停止

            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate() #开数据流量
            # d.server.adb.cmd("shell","am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()#开飞行模式
            # z.sleep( 6 )
            # z.heartbeat( )
            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate() # 关数据流量
            # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()#开飞行模式
            #
            # z.heartbeat( )
            # z.toast( "正在ping网络是否通畅" )
            # while True:
            #     ping = d.server.adb.cmd( "shell", "ping -c 3 baidu.com" ).communicate( )
            #     print( ping )
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         break
            #     z.sleep( 2 )

            try:
                self.IPCheckRepitition(z, d, args)
            except:
                z.toast("IP检测出错了,请查找问题")

            self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽

            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
                slotnum + "号\"").communicate()
            z.sleep(2)
            # d.server.adb.cmd( "shell",
            #                   "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来
            z.server.adb.run_cmd(
                "shell",
                "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity"
            )

            z.sleep(5)
            while d(textContains='正在更新数据').exists:
                z.sleep(2)
            z.sleep(3)
            z.server.adb.run_cmd(
                "shell",
                "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity"
            )

            if d(className='android.widget.ImageView',
                 resourceId='com.tencent.tim:id/title',
                 index=1).exists:
                for i in range(0, 2):
                    d.swipe(width - 20, height / 2, 0, height / 2, 5)
                    z.sleep(1.5)
                if d(text='立即体验').exists:
                    d(text='立即体验').click()
            z.sleep(2)
            z.heartbeat()
            if d(text='消息').exists or d(text='马上绑定').exists or d(
                    text='匹配手机通讯录').exists:
                if d(text='匹配手机通讯录').exists:  # 登陆上后弹出t通讯录的情况
                    d(text='匹配手机通讯录').click()
                    z.sleep(1.5)
                    if d(text='取消').exists:
                        d(text='取消').click()
                z.toast("卡槽QQ切换成功,继续执行")
            else:
                obj = self.slot.getSlotInfo(slotnum)
                remark = obj['remark']
                remarkArr = remark.split("_")
                QQnumber = remarkArr[1]
                if d(text='去安全中心').exists:
                    self.repo.BackupInfo(cate_id, 'frozen', QQnumber, '',
                                         '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

                else:
                    self.repo.BackupInfo(cate_id, 'normal', QQnumber, '', '')
                self.slot.clear(slotnum)  # 清空改卡槽,并补登
                z.toast("卡槽QQ状态异常,补登陆卡槽")
                self.action(d, z, args)

        else:  # 有空卡槽的情况
            d.server.adb.cmd("shell",
                             "pm clear com.tencent.tim").communicate()  # 清除缓存

            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
            # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
            # z.sleep(3)
            # d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
            # d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
            # z.heartbeat( )
            # z.toast( "正在ping网络是否通畅" )
            # while True:
            #     ping = d.server.adb.cmd( "shell", "ping -c 3 baidu.com" ).communicate( )
            #     print( ping )
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         break
            #     z.sleep( 2 )

            try:
                self.IPCheckRepitition(z, d, args)
            except:
                logging.exception("exception")
                z.toast("IP检测出错了,请查找问题")

            serialinfo = d.server.adb.device_serial()
            # print('登陆时的serial%s'%serialinfo)
            z.heartbeat()
            QQnumber = self.login(d, args, z)
            if QQnumber == 'nothing':
                self.slot.clear(slotnum)  # 清空改卡槽,并补登
                self.action(d, z, args)
            elif QQnumber == 0:
                z.toast("仓库为空,无法登陆。开始切换卡槽")
                self.qiehuan(d, z, args)
            elif QQnumber is None:
                return
            else:
                z.heartbeat()
                self.slot.backup(slotnum,
                                 str(slotnum) + '_' + QQnumber)  # 设备信息,卡槽号,QQ号
                self.repo.BackupInfo(cate_id, 'using', QQnumber, serialinfo,
                                     '%s_%s_%s' %
                                     (d.server.adb.device_serial(), self.type,
                                      slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号

        if (args["time_delay"]):
            time.sleep(int(args["time_delay"]))
예제 #9
0
class QLLogin:

    def __init__(self):
        self.repo = Repo()
        self.type = 'qqlite'

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S");  # 生成当前时间
        randomNum = random.randint(0, 1000);  # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum);
        uniqueNum = str(nowTime) + str(randomNum);
        return uniqueNum

    def LoginPlayCode(self, d, z):
        self.scode = smsCode( d.server.adb.device_serial( ) )
        base_dir = os.path.abspath( os.path.join( os.path.dirname( __file__ ), os.path.pardir, "tmp" ) )
        if not os.path.isdir( base_dir ):
            os.mkdir( base_dir )
        sourcePng = os.path.join( base_dir, "%s_s.png" % (self.GetUnique( )) )
        codePng = os.path.join( base_dir, "%s_c.png" % (self.GetUnique( )) )
        detection_robot = d( index='3', className="android.widget.EditText" )
        not_detection_robot = d( index='2', className="android.widget.EditText" )
        if detection_robot.exists or not_detection_robot.exists:  # 需要验证码的情况
            icode = imageCode( )
            im_id = ""
            for i in range( 0, 4 ):  # 打码循环
                if i > 0:
                    icode.reportError( im_id )
                obj = d( resourceId='com.tencent.qqlite:id/0',
                         className='android.widget.ImageView' )  # 当弹出选择QQ框的时候,定位不到验证码图片
                if not obj.exists:
                    obj = d( index='2', className='android.widget.Image' )
                obj = obj.info
                obj = obj['bounds']  # 验证码处的信息
                left = obj["left"]  # 验证码的位置信息
                top = obj['top']
                right = obj['right']
                bottom = obj['bottom']

                d.screenshot( sourcePng )  # 截取整个输入验证码时的屏幕

                img = Image.open( sourcePng )
                box = (left, top, right, bottom)  # left top right bottom
                region = img.crop( box )  # 截取验证码的图片

                img = Image.new( 'RGBA', (right - left, bottom - top) )
                img.paste( region, (0, 0) )

                img.save( codePng )
                im = open( codePng, 'rb' )

                codeResult = icode.getCode( im, icode.CODE_TYPE_4_NUMBER_CHAR, 60 )

                code = codeResult["Result"]
                im_id = codeResult["Id"]
                os.remove( sourcePng )
                os.remove( codePng )
                z.heartbeat( )
                z.sleep( 5 )
                if not_detection_robot.exists:
                    d( resourceId='com.tencent.qqlite:id/0', index='2',
                       className="android.widget.EditText" ).set_text( code )
                else:
                    detection_robot.set_text( code )
                z.sleep( 3 )
                if d( descriptionContains='验证', className='android.view.View' ).exists:
                    d( descriptionContains='验证', className='android.view.View' ).click( )
                else:
                    d( text='完成', resourceId='com.tencent.qqlite:id/ivTitleBtnRightText' ).click( )
                z.sleep( 5 )
                z.heartbeat( )
                while d( className='android.widget.ProgressBar', index=0 ).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                    z.sleep( 2 )
                z.heartbeat( )
                if detection_robot.exists or not_detection_robot.exists:
                    continue
                else:
                    break
            z.sleep( 5 )
            if d( textContains='验证码' ).exists:
                return "no"
            else:
                return "yes"
        else:
            return "no"

    def BindAddressBook(self, z, d, args):
        z.toast( "点击启用" )
        self.scode = smsCode( d.server.adb.device_serial( ) )
        d( text='启用' ).click( )
        while d( text='验证手机号码' ).exists:

            PhoneNumber = None
            j = 0
            while PhoneNumber is None:
                j += 1
                if j == 2:
                    z.toast( '取不到手机号码' )
                    if (args["time_delay"]):
                        z.sleep( int( args["time_delay"] ) )
                    return
                PhoneNumber = self.scode.GetPhoneNumber( self.scode.QQ_CONTACT_BIND )  # 获取接码平台手机号码
                z.heartbeat( )


            if not d( textContains='+86' ).exists:
                d( description='点击选择国家和地区' ).click( )
                if d( text='中国' ).exists:
                    d( text='中国' ).click( )
                else:
                    str = d.info  # 获取屏幕大小等信息
                    height = str["displayHeight"]
                    width = str["displayWidth"]
                    d.click(width * 5 / 12, height * 5 / 32)
                    z.sleep(1.5)
                    z.input('中国')
                    z.sleep(2)
                    d(text='+86').click()

            z.input(PhoneNumber)
            z.sleep(1.5)
            if d(text='下一步').exists:
                d(text='下一步').click()
                z.sleep(3)

            while d( text='正在发送请求' ).exists:
                z.sleep( 2 )
            z.sleep(2)
            z.heartbeat( )
            if d( text='确定' ).exists:
                d( text='确定' ).click( )
                z.sleep( 2 )
            code = self.scode.GetVertifyCode( PhoneNumber, self.scode.QQ_CONTACT_BIND, '4' )  # 获取接码验证码
            self.scode.defriendPhoneNumber( PhoneNumber, self.scode.QQ_CONTACT_BIND )
            if code == '':
                z.toast( PhoneNumber + '手机号,获取不到验证码' )
                if d( text='返回' ).exists:
                    d( text='返回' ).click( )
                if not d( textContains='中国' ).exists:
                    if d( text='返回' ).exists:
                        d( text='返回' ).click( )
                if d( className='android.view.View', descriptionContains='删除' ).exists:
                    d( className='android.view.View', descriptionContains='删除' ).click( )
                continue
            z.heartbeat( )
            z.input( code )
            if d( text='下一步' ).exists:
                d( text='下一步' ).click( )
                z.sleep(1.5)
            if d(text='好').exists:
                d(text='好').click()
            z.sleep(5)
            break

    def login(self,d,args,z):
        z.heartbeat()
        Str = d.info  # 获取屏幕大小等信息
        height = float( Str["displayHeight"] )
        width = float( Str["displayWidth"] )
        W_H = width / height
        screenScale = round( W_H, 2 )

        cate_id = args["repo_cate_id"]
        time_limit1 = args['time_limit1']
        numbers = self.repo.GetAccount( cate_id, time_limit1, 1 )
        while len( numbers ) == 0:
            z.heartbeat( )
            d.server.adb.cmd( "shell", "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\"" % (
            cate_id, time_limit1) ).communicate( )
            z.sleep( 2 )
            return 0

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']
        z.sleep( 1 )
        z.heartbeat( )
        d.server.adb.cmd("shell", "pm clear com.tencent.qqlite").communicate( )  # 清除缓存

        # d.server.adb.cmd("shell",
        #                   "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来
        z.server.adb.run_cmd( "shell", "am start -n com.tencent.qqlite/com.tencent.mobileqq.activity.SplashActivity" )
        z.sleep(5)
        while d( textContains='正在更新数据' ).exists:
            z.sleep( 2 )
        z.sleep(3)
        z.heartbeat( )
        d.dump(compressed=False)
        if d(text='登 录',resourceId='com.tencent.qqlite:id/btn_login').exists:
            z.toast("控件点击")
            d( text='登 录' ).click()
        else:
            if screenScale == 0.61:
                d.click(140, 788)
            if screenScale == 0.56:
                d.click(186, 1128)
        z.sleep( 1 )
        # d(className='android.widget.EditText', index=0).set_text(QQNumber)  # 1918697054----xiake1234.  QQNumber
        d(className='android.widget.EditText', index=0).click()  # 1918697054----xiake1234.  QQNumber
        z.input( QQNumber )

        z.sleep( 1 )
        # d(resourceId='com.tencent.mobileqq:id/password').set_text(QQPassword)  # Bn2kJq5l     QQPassword
        d(resourceId='com.tencent.qqlite:id/password').click()  # Bn2kJq5l     QQPassword
        z.input( QQPassword )
        z.heartbeat()
        logger = util.logger
        print('QQ号:%s,QQ密码:%s' % (QQNumber, QQPassword))
        d.dump(compressed=False )
        d( text='登 录', resourceId='com.tencent.qqlite:id/login' ).click( )
        z.sleep(1)
        while d(text='登录中').exists:
            z.sleep(2)
        z.sleep(5)
        z.heartbeat()

        not_detection_robot = d(resourceId='com.tencent.qqlite:id/0',index='2', className="android.widget.EditText" )
        if not_detection_robot.exists:
            playCodeResult = self.LoginPlayCode( d, z )  # 打验证码
        elif d( text='QQ轻聊版', resourceId='com.tencent.qqlite:id/0',className='android.widget.TextView').exists or d( text='启用' ).exists:
            return QQNumber
        else:
            self.repo.BackupInfo( cate_id, 'frozen', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            z.toast( "卡槽QQ状态异常,跳过此模块" )
            return "nothing"

        if playCodeResult == "no":
            return "nothing"

        z.sleep(5)
        z.heartbeat()
        if d( text='启用' ).exists:
            # self.BindAddressBook(z, d, args)
            return QQNumber

        if d(text='QQ轻聊版', resourceId='com.tencent.qqlite:id/0',className='android.widget.TextView').exists:
            z.toast("卡槽QQ状态正常,继续执行")
            return QQNumber
        else:
            self.repo.BackupInfo( cate_id, 'frozen', QQNumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            z.toast( "卡槽QQ状态异常,跳过此模块" )
            return "nothing"


    def qiehuan(self,d,z,args):
        time_limit = int(args['time_limit'])
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial( )
        self.slot = Slot( serial, self.type )
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽
        while slotObj is None:  # 2小时没有用过的卡槽也为空的情况
            d.server.adb.cmd("shell",
                             "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\"").communicate()
            z.heartbeat()
            z.sleep(10)
            slotObj = self.slot.getAvailableSlot( time_limit )  # 没有空卡槽,取2小时没用过的卡槽

        if not slotObj is None:
            slotnum = slotObj['id']
        z.heartbeat()
        d.server.adb.cmd("shell", "pm clear com.tencent.qqlite").communicate()  # 清除缓存

        d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
        d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
        z.sleep(6)
        z.heartbeat()
        d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
        d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
        obj = self.slot.getSlotInfo( slotnum )
        remark = obj['remark']
        remarkArr = remark.split( "_" )
        if len(remarkArr) == 4:
            featureCodeInfo = remarkArr[2]
            z.set_serial( "com.tencent.qqlite", featureCodeInfo )
        self.slot.restore( slotnum )  # 有time_limit分钟没用过的卡槽情况,切换卡槽
        z.heartbeat()
        z.toast( "正在ping网络是否通畅" )
        while True:
            ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
            print(ping)
            if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                break
            z.sleep(2)

        d.server.adb.cmd("shell", "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" + str(slotnum) + "号\"").communicate()
        z.sleep(2)
        # d.server.adb.cmd("shell", "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity").communicate()  # 拉起来
        z.server.adb.run_cmd( "shell", "am start -n com.tencent.qqlite/com.tencent.mobileqq.activity.SplashActivity" )

        z.sleep( 5 )
        while d( textContains='正在更新数据' ).exists:
            z.sleep( 2 )
        z.sleep( 3 )
        z.heartbeat()
        if d(text='QQ轻聊版', resourceId='com.tencent.qqlite:id/0',className='android.widget.TextView').exists.exists or d( text='启用' ).exists:
            z.toast( "卡槽QQ切换成功,继续执行" )
        else:
            obj = self.slot.getSlotInfo( slotnum )
            remark = obj['remark']
            remarkArr = remark.split( "_" )
            QQnumber = remarkArr[1]
            self.repo.BackupInfo( cate_id, 'frozen', QQnumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
            self.slot.clear( slotnum )  # 清空改卡槽,并补登
            z.toast( "卡槽QQ状态异常,补登陆卡槽" )
            self.action( d, z, args )


    def action(self,d,z,args):

        z.generate_serial("com.tencent.qqlite")  # 随机生成手机特征码
        z.toast("随机生成手机特征码")

        time_limit = int( args['time_limit'] )
        cate_id = args["repo_cate_id"]
        serial = d.server.adb.device_serial( )
        self.slot = Slot( serial, self.type )
        slotnum = self.slot.getEmpty( )  # 取空卡槽
        if slotnum == 0:  # 没有空卡槽的话
            slotObj = self.slot.getAvailableSlot( time_limit )  # 取空卡槽,取2小时没用过的卡槽
            if not slotObj is None:
                slotnum = slotObj['id']
            print( slotnum )
            while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
                d.server.adb.cmd( "shell",
                                  "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\"" ).communicate( )
                z.heartbeat( )
                z.sleep( 10 )
                slotObj = self.slot.getAvailableSlot( time_limit )
                if not slotObj is None:
                    slotnum = slotObj['id']
            z.heartbeat()
            d.server.adb.cmd("shell", "pm clear com.tencent.qqlite" ).communicate()  # 清除缓存

            d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate() #开数据流量
            d.server.adb.cmd("shell","am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()#开飞行模式
            z.sleep(6)
            z.heartbeat()
            d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate() # 关数据流量
            d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()#开飞行模式

            obj = self.slot.getSlotInfo( slotnum )
            remark = obj['remark']
            remarkArr = remark.split( "_" )
            if len( remarkArr ) == 4:
                featureCodeInfo = remarkArr[2] + remarkArr[3]
                print( featureCodeInfo )
                z.set_serial( "com.tencent.qqlite", featureCodeInfo )
            z.set_serial( "com.tencent.qqlite", featureCodeInfo )
            self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽

            z.heartbeat()
            z.toast("正在ping网络是否通畅")
            while True:
                ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
                print(ping)
                if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                    break
                z.sleep( 2 )

            d.server.adb.cmd( "shell",
                              "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" + slotnum + "号\"" ).communicate( )

            z.sleep( 2 )
            # d.server.adb.cmd( "shell",
            #                   "am start -n com.tencent.tim/com.tencent.mobileqq.activity.SplashActivity" ).communicate( )  # 拉起来
            z.server.adb.run_cmd( "shell", "am start -n com.tencent.qqlite/com.tencent.mobileqq.activity.SplashActivity" )

            z.sleep(5)
            while d( textContains='正在更新数据' ).exists:
                z.sleep( 2 )
            z.sleep( 3 )
            z.heartbeat()
            if d(text='QQ轻聊版', resourceId='com.tencent.qqlite:id/0',className='android.widget.TextView').exists or d( text='启用' ).exists:
                z.toast("卡槽QQ切换成功,继续执行")
            else:
                obj = self.slot.getSlotInfo( slotnum )
                remark = obj['remark']
                remarkArr = remark.split( "_" )
                QQnumber = remarkArr[1]
                self.repo.BackupInfo( cate_id, 'frozen', QQnumber, '', '' )  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                self.slot.clear( slotnum )  # 清空改卡槽,并补登
                z.toast( "卡槽QQ状态异常,补登陆卡槽" )
                self.action( d, z, args )

        else:  # 有空卡槽的情况
            d.server.adb.cmd( "shell", "pm clear com.tencent.qqlite" ).communicate( )  # 清除缓存

            d.server.adb.cmd("shell", "settings put global airplane_mode_on 1").communicate()
            d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true").communicate()
            z.sleep(3)
            d.server.adb.cmd("shell", "settings put global airplane_mode_on 0").communicate()
            d.server.adb.cmd("shell", "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false").communicate()
            z.heartbeat( )
            z.toast( "正在ping网络是否通畅" )
            while True:
                ping = d.server.adb.cmd( "shell", "ping -c 3 baidu.com" ).communicate( )
                print( ping )
                if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                    break
                z.sleep( 2 )
            serialinfo = d.server.adb.device_serial( )
            # print('登陆时的serial%s'%serialinfo)
            z.heartbeat( )
            QQnumber = self.login( d, args, z )
            if QQnumber == 'nothing':
                self.slot.clear( slotnum )  # 清空改卡槽,并补登
                self.action( d, z, args )
            elif QQnumber == 0:
                z.toast( "仓库为空,无法登陆。开始切换卡槽" )
                self.qiehuan( d, z, args )
            elif QQnumber is None:
                return
            else:
                z.heartbeat()
                featureCodeInfo = z.get_serial( "com.tencent.qqlite" )
                print(featureCodeInfo)
                self.slot.backup( slotnum, str( slotnum ) + '_' + QQnumber + "_" + featureCodeInfo)  # 设备信息,卡槽号,QQ号
                self.repo.BackupInfo( cate_id, 'using', QQnumber, serialinfo, '%s_%s_%s' % (
                    d.server.adb.device_serial( ), self.type, slotnum) )  # 仓库号,使用中,QQ号,设备号_卡槽号


        if (args["time_delay"]):
            time.sleep(int(args["time_delay"]))
예제 #10
0
class QQMailLogin:
    def __init__(self):
        self.repo = Repo()
        self.type = 'qqmail'

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")  # 生成当前时间
        randomNum = random.randint(0, 1000)  # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum)
        uniqueNum = str(nowTime) + str(randomNum)
        return uniqueNum

    def againLogin(self, account, password, d, z, height):
        if d(text="确定", className="android.widget.Button").exists or d(
                text="重新输入", className="android.widget.Button").exists:
            if d(text="确定", className="android.widget.Button").exists:
                d(text="确定", className="android.widget.Button").click()
            else:
                d(text="重新输入", className="android.widget.Button").click()
            time.sleep(1)
            self.input(z, height, password)
            time.sleep(1)
            if d(resourceId="com.tencent.androidqqmail:id/a_").exists:
                d(resourceId="com.tencent.androidqqmail:id/a_").click()
                time.sleep(8)
            while True:
                if d(textContains="验证中"):
                    time.sleep(3)
                else:
                    break
            if d(resourceId='com.tencent.androidqqmail:id/h'
                 ).exists:  # 判断是否要填写独立密码
                self.input(z, height, "Abc" + account)
                z.sleep(1)
                if d(text='确定').exists:
                    d(text='确定').click()
                z.sleep(5)

            while d(resourceId='com.tencent.androidqqmail:id/a16'
                    ).exists:  # 出现验证码
                picObj = d(resourceId='com.tencent.androidqqmail:id/a19',
                           index=0)
                code = self.palyCode(d, z, picObj)
                if code == "":
                    return False
                if d(resourceId='com.tencent.androidqqmail:id/a17').exists:
                    d(resourceId='com.tencent.androidqqmail:id/a17').click()
                self.input(z, height, code)
                if d(resourceId='com.tencent.androidqqmail:id/a_'
                     ).exists:  # 点击登陆
                    d(resourceId='com.tencent.androidqqmail:id/a_').click()
                z.sleep(8)

            if d(resourceId='com.tencent.androidqqmail:id/h'
                 ).exists:  # 判断是否要填写独立密码
                self.input(z, height, "Abc" + account)
                z.sleep(1)
                if d(text='确定').exists:
                    d(text='确定').click()
            while True:
                if d(textContains="验证中"):
                    time.sleep(3)
                else:
                    break
            if d(textContains='你有多个应用同时收到').exists:
                d(text='确定').click()
                z.sleep(2)

            if d(text='收件箱​').exists:
                z.toast(u"登录成功。退出模块")
                # d.server.adb.cmd("shell", "am force-stop com.tencent.androidqqmail").wait()  # 强制停止
                return True
            else:
                if d(textContains='帐号或密码错误').exists:
                    z.toast(u"帐号或密码错误")
                    return False
                elif d(textContains="未开启IMAP服务").exists:
                    z.toast(u"未开启IMAP服务,标记为异常")
                    self.repo.BackupInfo(args["repo_account_id"], 'exception',
                                         account, '',
                                         '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    return False

    def input(self, z, height, text):
        if height > 888:
            z.input(text)
        else:
            z.cmd("shell",
                  "am broadcast -a ZY_INPUT_TEXT --es text \\\"%s\\\"" % text)

    def palyCode(self, d, z, picObj):
        self.scode = smsCode(d.server.adb.device_serial())
        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
        icode = imageCode()
        im_id = ""
        code = ""
        for i in range(0, 2):  # 打码循环
            # if i > 0:
            #     icode.reportError(im_id)
            obj = picObj.info
            obj = obj['bounds']  # 验证码处的信息
            left = obj["left"]  # 验证码的位置信息
            top = obj['top']
            right = obj['right']
            bottom = obj['bottom']

            d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

            img = Image.open(sourcePng)
            box = (left, top, right, bottom)  # left top right bottom
            region = img.crop(box)  # 截取验证码的图片

            img = Image.new('RGBA', (right - left, bottom - top))
            img.paste(region, (0, 0))

            img.save(codePng)
            with open(codePng, 'rb') as f:
                # file = f.read()
                file = "data:image/jpeg;base64," + base64.b64encode(f.read())
                da = {"IMAGES": file}
                path = "/ocr.index"
                headers = {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Connection": "Keep-Alive"
                }
                conn = httplib.HTTPConnection("162626i1w0.51mypc.cn",
                                              10082,
                                              timeout=30)
                params = urllib.urlencode(da)
                conn.request(method="POST",
                             url=path,
                             body=params,
                             headers=headers)
                response = conn.getresponse()
                if response.status == 200:
                    code = response.read()
                else:
                    continue
            os.remove(sourcePng)
            os.remove(codePng)
            z.heartbeat()
            if code.isalpha() or code.isisdigitv() or code.isalnum():
                break
            else:
                continue

        return code

    def login(self, d, z, args, accounts):
        try:
            d.server.adb.cmd(
                "shell",
                "pm clear com.tencent.androidqqmail").communicate()  # 清除QQ邮箱缓存
            d.server.adb.cmd(
                "shell",
                "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
            ).communicate()  # 拉起QQ邮箱
            z.sleep(15)
            z.heartbeat()
            Str = d.info  # 获取屏幕大小等信息
            height = int(Str["displayHeight"])
            width = int(Str["displayWidth"])
            for x in range(2):

                if args['mail_type'] == '163邮箱登录':
                    if d(resourceId='com.tencent.androidqqmail:id/ee'
                         ).exists:  # 选择163邮箱点击进入登陆页面
                        d(resourceId='com.tencent.androidqqmail:id/ee').click()
                        z.sleep(1)
                        break
                    else:
                        d.server.adb.cmd(
                            "shell",
                            "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
                        ).communicate()  # 拉起QQ邮箱
                        z.sleep(25)
                        continue

                if args['mail_type'] == 'QQ邮箱登录':
                    if d(resourceId='com.tencent.androidqqmail:id/ea'
                         ).exists:  # 选择QQ邮箱点击进入登陆页面
                        d(resourceId='com.tencent.androidqqmail:id/ea').click()
                        z.sleep(1)
                        break
                    else:
                        d.server.adb.cmd(
                            "shell",
                            "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
                        ).communicate()  # 拉起QQ邮箱
                        z.sleep(25)
                        continue

                if args['mail_type'] == '腾讯企业邮箱登录':
                    if d(resourceId='com.tencent.androidqqmail:id/eb'
                         ).exists:  # 选择腾讯企业邮箱登录点击进入登陆页面
                        d(resourceId='com.tencent.androidqqmail:id/eb').click()
                        z.sleep(1)
                        break
                    else:
                        d.server.adb.cmd(
                            "shell",
                            "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
                        ).communicate()  # 拉起QQ邮箱
                        z.sleep(25)
                        continue

            account = accounts[0]['number']
            password = accounts[0]['password']

            if d(text='帐号密码登录').exists:
                d(text='帐号密码登录').click()

            if d(resourceId='com.tencent.androidqqmail:id/bi'
                 ).exists:  # 输入邮箱帐号
                d(resourceId='com.tencent.androidqqmail:id/bi').click()
                # self.input(z,height,account)
                self.input(z, height, account)
            else:
                return

            if d(resourceId='com.tencent.androidqqmail:id/bs'
                 ).exists:  # 输入邮箱密码
                d(resourceId='com.tencent.androidqqmail:id/bs').click()
                self.input(z, height, password)

            if d(resourceId='com.tencent.androidqqmail:id/a_'
                 ).exists:  # 点击登录按钮
                d(resourceId='com.tencent.androidqqmail:id/a_').click()

            z.sleep(20)
            while True:
                if d(textContains="验证中"):
                    time.sleep(3)
                else:
                    break
            if args['mail_type'] == 'QQ邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/h'
                     ).exists:  # 判断是否要填写独立密码
                    self.input(z, height, "Abc" + account)
                    z.sleep(1)
                    if d(text='确定').exists:
                        d(text='确定').click()
                    z.sleep(5)

                while d(resourceId='com.tencent.androidqqmail:id/a16'
                        ).exists:  # 出现验证码
                    picObj = d(resourceId='com.tencent.androidqqmail:id/a19',
                               index=0)
                    code = self.palyCode(d, z, picObj)
                    if code == "":
                        return False
                    if d(resourceId='com.tencent.androidqqmail:id/a17').exists:
                        d(resourceId='com.tencent.androidqqmail:id/a17').click(
                        )
                    self.input(z, height, code)
                    if d(resourceId='com.tencent.androidqqmail:id/a_'
                         ).exists:  # 点击登陆
                        d(resourceId='com.tencent.androidqqmail:id/a_').click()
                    z.sleep(8)

                if d(resourceId='com.tencent.androidqqmail:id/h'
                     ).exists:  # 判断是否要填写独立密码
                    self.input(z, height, "Abc" + account)
                    z.sleep(1)
                    if d(text='确定').exists:
                        d(text='确定').click()

            if args['mail_type'] == '163邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/a_'
                     ).exists:  # 点击完成按钮
                    d(resourceId='com.tencent.androidqqmail:id/a_').click()
                    time.sleep(3)
                    d.server.adb.cmd(
                        "shell",
                        "am force-stop com.tencent.androidqqmail").communicate(
                        )  # 强制停止
                    d.server.adb.cmd(
                        "shell",
                        "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
                    ).communicate()  # 拉起QQ邮箱
                    # z.sleep(3)
                    # z.heartbeat()

                # d.server.adb.cmd("shell", "am force-stop com.tencent.androidqqmail").wait()  # 强制停止163邮箱
                # d.server.adb.cmd("shell", "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail").communicate()  # 拉起163邮箱

            if args['mail_type'] == '腾讯企业邮箱登录':
                if d(resourceId='com.tencent.androidqqmail:id/a_'
                     ).exists:  # 点击登录按钮
                    d(resourceId='com.tencent.androidqqmail:id/a_').click()
                    z.sleep(3)
                    z.heartbeat()
                    d.server.adb.cmd(
                        "shell",
                        "am force-stop com.tencent.androidqqmail").communicate(
                        )  # 强制停止
                    d.server.adb.cmd(
                        "shell",
                        "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
                    ).communicate()  # 拉起QQ邮箱

                if d(text='收件箱​').exists:
                    z.toast(u"登录成功。退出模块")
                    # d.server.adb.cmd( "shell", "am force-stop com.tencent.androidqqmail" ).wait( )  # 强制停止
                    return True
                else:
                    return False
                # d.server.adb.cmd("shell", "am force-stop com.tencent.androidqqmail").wait()  # 强制停止163邮箱
                # d.server.adb.cmd("shell", "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail").communicate()  # 拉起163邮箱

            z.sleep(12)
            z.heartbeat()
            if d(textContains='你有多个应用同时收到').exists:
                d(text='确定').click()
                z.sleep(2)

            if d(text='收件箱​').exists:
                z.toast(u"登录成功。退出模块")
                # d.server.adb.cmd("shell", "am force-stop com.tencent.androidqqmail").wait()  # 强制停止
                return True
            else:
                return False
        except:
            logging.exception("exception")
            z.toast(u"程序出现异常,模块退出")
            d.server.adb.cmd(
                "shell",
                "am force-stop com.tencent.androidqqmail").wait()  # 强制停止
            return False

    def qiehuan(self, d, z, args):
        Str = d.info  # 获取屏幕大小等信息
        height = int(Str["displayHeight"])
        width = int(Str["displayWidth"])
        if args['mail_type'] == '163邮箱登录':
            self.type = '163mail'
        time_limit = int(args['slot_time_limit'])
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽

        slotnum = None
        if not slotObj is None:
            slotnum = slotObj['id']

        while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
            ).communicate()
            z.heartbeat()
            z.sleep(30)
            slotObj = self.slot.getAvailableSlot(time_limit)
            if not slotObj is None:
                slotnum = slotObj['id']
                break

        z.heartbeat()
        d.server.adb.cmd(
            "shell",
            "pm clear com.tencent.androidqqmail").communicate()  # 清除缓存

        obj = self.slot.getSlotInfo(slotnum)
        remark = obj['remark']
        remarkArr = remark.split("_")
        cateId = args['repo_account_id']
        if len(remarkArr) == 3:
            slotInfo = d.server.adb.device_serial(
            ) + '_' + self.type + '_' + slotnum
            cateId = remarkArr[2]
            numbers = self.repo.Getserial(cateId, slotInfo)
            if len(numbers) != 0:
                featureCodeInfo = numbers[0]['imei']
                z.set_serial("com.tencent.androidqqmail", featureCodeInfo)

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
        z.sleep(2)

        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            slotnum + "号\"").communicate()
        z.sleep(2)
        d.server.adb.cmd(
            "shell",
            "am start -n com.tencent.androidqqmail/com.tencent.qqmail.LaunchComposeMail"
        ).communicate()  # 拉起QQ邮箱
        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)
        z.sleep(20)

        z.heartbeat()
        d.dump(compressed=False)
        if d(text='密码错误,请重新输入').exists or d(description='QQ邮箱').exists:
            QQnumber = remarkArr[1]
            self.repo.BackupInfo(cateId, 'normal', QQnumber, '',
                                 '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            self.slot.clear(slotnum)  # 清空改卡槽,并补登
            z.toast("卡槽邮箱号状态异常,补登陆卡槽")
            return False

        else:
            z.toast("邮箱登陆状态正常,切换完毕。")
            return True

    def action(self, d, z, args):

        while True:
            # z.toast("正在ping网络是否通畅")
            # i = 0
            # while i < 200:
            #     i += 1
            #     ping = d.server.adb.cmd("shell", "ping -c 3 baidu.com").communicate()
            #     # print(ping)
            #     if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
            #         z.toast(u"网络通畅。开始执行:" + args['mail_type'] + u" 有卡槽")
            #         break
            #     z.sleep(2)
            # if i > 200:
            #     z.toast(u"网络不通,请检查网络状态")
            #     return
            Str = d.info  # 获取屏幕大小等信息
            height = int(Str["displayHeight"])
            width = int(Str["displayWidth"])
            z.heartbeat()
            z.generate_serial("com.tencent.androidqqmail")  # 随机生成手机特征码
            d.server.adb.cmd(
                "shell", "su -c 'rm -r -f /storage/emulated/0/tencent/QQmail'"
            )  # 删除/storage/emulated/0/tencent/QQmail文件夹
            time.sleep(2)
            if args['mail_type'] == '163邮箱登录':
                self.type = '163mail'

            accounts = self.repo.GetAccount(args['repo_account_id'],
                                            int(args['account_time_limit']),
                                            1)  # 去仓库获取QQ邮箱帐号
            if len(accounts) == 0:
                z.toast(u"帐号库为空")

            # self.qiehuan( d, z, args )
            serial = d.server.adb.device_serial()
            self.slot = Slot(serial, self.type)
            slotnum = self.slot.getEmpty()  # 取空卡槽
            if slotnum == 0 or len(
                    accounts) == 0:  # 没有空卡槽的话或者仓库没有可登陆的帐号,进行卡槽切换。
                if self.qiehuan(d, z, args):
                    break
                else:
                    continue
            else:  # 有空卡槽的情况

                QQnumber = accounts[0]['number']
                password = accounts[0]['password']
                # print QQnumber
                if self.login(d, z, args, accounts):
                    z.heartbeat()
                    featureCodeInfo = z.get_serial("com.tencent.androidqqmail")
                    self.slot.backup(slotnum,
                                     str(slotnum) + '_' + QQnumber + '_' +
                                     args["repo_account_id"])  # 设备信息,卡槽号,QQ号
                    self.repo.BackupInfo(
                        args["repo_account_id"], 'using', QQnumber,
                        featureCodeInfo,
                        '%s_%s_%s' % (d.server.adb.device_serial(), self.type,
                                      slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号
                    break

                else:
                    self.slot.clear(slotnum)  # 清空改卡槽,并补登
                    if d(text='本次登录存在异常,如需帮助请前往安全中心').exists:
                        z.toast(u"登录失败。重新登录")
                        self.repo.BackupInfo(args["repo_account_id"], 'frozen',
                                             QQnumber, '',
                                             '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    elif d(textContains='帐号或密码错误').exists:
                        z.toast(u"帐号或密码错误")
                        againCount = int(args["againCount"])
                        for ac in range(againCount):
                            result = self.againLogin(QQnumber, password, d, z,
                                                     height)
                            if result is True:
                                # z.toast( "跳出模块" )
                                return
                        else:
                            z.toast(u"一直登陆出现密码错误,跳出该帐号")
                        # self.repo.BackupInfo(args["repo_account_id"], 'frozen', QQnumber, '', '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

                    elif d(textContains="未开启IMAP服务").exists:
                        z.toast(u"未开启IMAP服务,标记为异常")
                        self.repo.BackupInfo(args["repo_account_id"],
                                             'exception', QQnumber, '',
                                             '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    else:
                        self.repo.BackupInfo(args["repo_account_id"], 'normal',
                                             QQnumber, '',
                                             '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    continue
예제 #11
0
class MobilqqLogin3:
    def __init__(self):
        self.type = 'mobileqq'
        self.repo = Repo()
        self.codedll = codeDLL()

    def GetUnique(self):
        nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        # 生成当前时间
        randomNum = random.randint(0, 1000)
        # 生成的随机整数n,其中0<=n<=100
        if randomNum <= 10:
            randomNum = str(00) + str(randomNum)
        uniqueNum = str(nowTime) + str(randomNum)
        return uniqueNum

    def WebViewBlankPages(self, d, z):
        z.toast("判断是否是滑块")
        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])

        W_H = width / height
        screenScale = round(W_H, 2)

        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))

        if screenScale == 0.56:
            left = 115  # 验证码的位置信息
            top = 670
            right = 185
            bottom = 720
        if screenScale == 0.61:
            left = 115  # 验证码的位置信息
            top = 670
            right = 185
            bottom = 720

        d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕

        img = Image.open(sourcePng)
        box = (left, top, right, bottom)  # left top right bottom
        region = img.crop(box)  # 截取验证码的图片
        # show(region)    #展示资料卡上的信息
        image = region.convert('RGBA')
        # 生成缩略图,减少计算量,减小cpu压力
        image.thumbnail((200, 200))
        max_score = None
        dominant_color = None
        for count, (r, g, b,
                    a) in image.getcolors(image.size[0] * image.size[1]):
            # 跳过纯黑色
            if a == 0:
                continue
            saturation = colorsys.rgb_to_hsv(r / 255.0, g / 255.0,
                                             b / 255.0)[1]
            y = min(
                abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235)
            y = (y - 16.0) / (235 - 16)
            # 忽略高亮色
            if y > 0.9:
                continue

            score = (saturation + 0.1) * count
            if score > max_score:
                max_score = score
                dominant_color = (r, g, b)  # 红绿蓝
        return dominant_color

    def WebViewPlayCode(self, d, z):
        z.toast("非空白页,开始截图打码")

        Str = d.info  # 获取屏幕大小等信息
        height = float(Str["displayHeight"])
        width = float(Str["displayWidth"])
        W_H = width / height
        screenScale = round(W_H, 2)

        base_dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
        if not os.path.isdir(base_dir):
            os.mkdir(base_dir)
        sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
        icode = imageCode()
        im_id = ""
        for i in range(0, 1):  # 打码循环
            if i > 0:
                icode.reportError(im_id)

            d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕
            if screenScale == 0.61:
                p = {
                    "x1": 30 / width,
                    "y1": 200 / height,
                    "x2": 271 / width,
                    "y2": 300 / height
                }
            if screenScale == 0.56:
                p = {
                    "x1": 40 / width,
                    "y1": 270 / height,
                    "x2": 362 / width,
                    "y2": 400 / height
                }
            cropedImg = z.img_crop(sourcePng, p)
            im = open(cropedImg, 'rb')
            codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR, 60)
            code = codeResult["Result"]
            im_id = codeResult["Id"]
            os.remove(sourcePng)
            z.heartbeat()
            z.sleep(5)
            if screenScale == 0.61:
                d.click(360, 240)
            if screenScale == 0.56:
                d.click(500, 350)
            z.input(code)
            z.sleep(2)
            if screenScale == 0.61:
                d.click(270, 450)
            if screenScale == 0.56:
                d.click(360, 600)

            while d(className='android.widget.ProgressBar',
                    index=0).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
                z.sleep(2)
            z.sleep(8)

            if not d(textContains='验证码').exists:
                z.toast("机器人打码跳出--")
                break

    # def playCode(self, codeImgObj, type):
    #     z.toast("非网页视图打码")
    #     self.scode = smsCode(d.server.adb.device_serial())
    #     base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, "tmp"))
    #     if not os.path.isdir(base_dir):
    #         os.mkdir(base_dir)
    #     sourcePng = os.path.join(base_dir, "%s_s.png" % (self.GetUnique()))
    #     codePng = os.path.join(base_dir, "%s_c.png" % (self.GetUnique()))
    #     icode = imageCode()
    #     im_id = ""
    #     for i in range(0, 4):  # 打码循环
    #         if i > 0:
    #             icode.reportError(im_id)
    #         obj = d(resourceId='com.tencent.mobileqq:id/name',
    #                  className='android.widget.ImageView')  # 当弹出选择QQ框的时候,定位不到验证码图片
    #         if not obj.exists:
    #             obj = d(index='2', className='android.widget.Image')
    #         obj = obj.info
    #         obj = obj['bounds']  # 验证码处的信息
    #         left = obj["left"]  # 验证码的位置信息
    #         top = obj['top']
    #         right = obj['right']
    #         bottom = obj['bottom']
    #
    #         d.screenshot(sourcePng)  # 截取整个输入验证码时的屏幕
    #
    #         img = Image.open(sourcePng)
    #         box = (left, top, right, bottom)  # left top right bottom
    #         region = img.crop(box)  # 截取验证码的图片
    #
    #         img = Image.new('RGBA', (right - left, bottom - top))
    #         img.paste(region, (0, 0))
    #
    #         img.save(codePng)
    #
    #         with open(codePng, 'rb') as im:
    #             codeResult = icode.getCode(im, icode.CODE_TYPE_4_NUMBER_CHAR, 60)
    #
    #         code = codeResult["Result"]
    #         im_id = codeResult["Id"]
    #         os.remove(sourcePng)
    #         os.remove(codePng)
    #         z.heartbeat()
    #         z.sleep(5)
    #         if type == 0:
    #             d(resourceId='com.tencent.mobileqq:id/name', index='2',
    #                className="android.widget.EditText").set_text(code)
    #         else:
    #             codeImgObj.set_text(code)
    #         z.sleep(3)
    #         if d(descriptionContains='验证', className='android.view.View').exists:
    #             d(descriptionContains='验证', className='android.view.View').click()
    #         else:
    #             d(text='完成', resourceId='com.tencent.mobileqq:id/ivTitleBtnRightText').click()
    #         z.sleep(6)
    #         z.heartbeat()
    #         while d(className='android.widget.ProgressBar', index=0).exists:  # 网速不给力时,点击完成后仍然在加载时的状态
    #             z.sleep(2)
    #         z.sleep(3)
    #         z.heartbeat()
    #         if codeImgObj.exists:
    #             continue
    #         else:
    #             break
    #     z.sleep(5)
    #     if d(textContains='验证码').exists:
    #         return False
    #     else:
    #         return True

    def login(self, d, args, z, numbers):

        QQNumber = numbers[0]['number']  # 即将登陆的QQ号
        QQPassword = numbers[0]['password']

        z.heartbeat()
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.mobileqq").communicate()  # 清除缓存
        d.server.adb.cmd(
            "shell",
            "am start -n com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity"
        ).communicate()  # 拉起来
        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)

        z.sleep(15)
        z.heartbeat()
        d.dump(compressed=False)
        if d(text='登 录',
             resourceId='com.tencent.mobileqq:id/btn_login').exists:
            d(text='登 录').click()

        z.sleep(1)
        d(className='android.widget.EditText',
          index=0).click()  # 1918697054----xiake1234.  QQNumber
        z.input(QQNumber)

        z.sleep(1)
        d(resourceId='com.tencent.mobileqq:id/password').click(
        )  # Bn2kJq5l     QQPassword
        z.input(QQPassword)

        z.heartbeat()
        print('QQ号:%s,QQ密码:%s' % (QQNumber, QQPassword))
        d.dump(compressed=False)
        d(text='登 录', resourceId='com.tencent.mobileqq:id/login').click()
        z.sleep(3)
        while d(text='登录中').exists:
            z.sleep(2)
        z.sleep(20)

        z.heartbeat()
        detection_robot = d(index='3', className="android.widget.EditText")
        not_detection_robot = d(resourceId='com.tencent.mobileqq:id/name',
                                index='2',
                                className="android.widget.EditText")
        if detection_robot.exists:  # 需要验证码的情况
            if not self.playCode(detection_robot, 1):
                return False

        if not_detection_robot.exists:
            if not self.playCode(not_detection_robot.exists, 0) == "nothing":
                return False

        if d(className='android.webkit.WebView').exists:
            if self.WebViewBlankPages(d, z)[2] < 200:
                self.WebViewPlayCode(d, z)
            else:
                y = 555
                for r in range(1, 3):
                    d.swipe(155, 703, y, 703)
                    z.sleep(2)
                    if not d(text='验证码',
                             resourceId='com.tencent.mobileqq:id/ivTitleName'
                             ).exists:
                        break
                    else:
                        y += 20

                if d(text='验证码',
                     resourceId='com.tencent.mobileqq:id/ivTitleName'
                     ).exists or d(text='去安全中心').exists:
                    self.repo.BackupInfo(args["repo_cate_id"], 'frozen',
                                         QQNumber, '',
                                         '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber
                    return False

        z.sleep(5)
        z.heartbeat()
        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(text='消息').exists and d(text='联系人').exists and d(
                    text='动态').exists:
                loginStatusList = {'success': True}
            elif d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
                z.toast("我是小米神隐")
                d(text='我知道了').click()
            else:
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            z.toast("卡槽QQ状态正常,继续执行")
            return True
        else:
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(args["repo_cate_id"], 'frozen', QQNumber,
                                     '', '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(args["repo_cate_id"], 'normal', QQNumber,
                                     '', '')

            z.toast("卡槽QQ状态异常,跳过此模块")
            return False

        # if d(text='马上绑定').exists:
        #     self.BindAddressBook(z, d, args)

    def qiehuan(self, d, z, args):
        time_limit = int(args['time_limit'])
        serial = d.server.adb.device_serial()
        self.slot = Slot(serial, self.type)
        slotObj = self.slot.getAvailableSlot(time_limit)  # 没有空卡槽,取2小时没用过的卡槽
        slotnum = None
        if not slotObj is None:
            slotnum = slotObj['id']

        while slotObj is None:  # 2小时没用过的卡槽也为没有的情况
            d.server.adb.cmd(
                "shell",
                "am broadcast -a com.zunyun.zime.toast --es msg \"QQ卡槽全满,无间隔时间段未用\""
            ).communicate()
            z.heartbeat()
            z.sleep(30)
            slotObj = self.slot.getAvailableSlot(time_limit)
            if not slotObj is None:
                slotnum = slotObj['id']
                break

        z.heartbeat()
        d.server.adb.cmd("shell",
                         "pm clear com.tencent.mobileqq").communicate()  # 清除缓存

        d.server.adb.cmd(
            "shell",
            "settings put global airplane_mode_on 1").communicate()  # 开飞行模式
        d.server.adb.cmd(
            "shell",
            "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true"
        ).communicate()
        z.sleep(6)
        z.heartbeat()

        d.server.adb.cmd(
            "shell",
            "settings put global airplane_mode_on 0").communicate()  # 关飞行模式
        d.server.adb.cmd(
            "shell",
            "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
        ).communicate()

        z.heartbeat()
        while True:
            ping = d.server.adb.cmd("shell",
                                    "ping -c 3 baidu.com").communicate()
            print(ping)
            if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                break
            z.sleep(2)

        obj = self.slot.getSlotInfo(slotnum)
        remark = obj['remark']
        remarkArr = remark.split("_")
        cateId = ""
        if len(remarkArr) == 3:
            slotInfo = d.server.adb.device_serial(
            ) + '_' + self.type + '_' + slotnum
            cateId = remarkArr[2]
            numbers = self.repo.Getserial(cateId, slotInfo)
            if len(numbers) != 0:
                featureCodeInfo = numbers[0]['imei']
                z.set_serial("com.tencent.mobileqq", featureCodeInfo)

        self.slot.restore(slotnum)  # 有time_limit分钟没用过的卡槽情况,切换卡槽
        z.sleep(2)

        d.server.adb.cmd(
            "shell",
            "am broadcast -a com.zunyun.zime.toast --es msg \"卡槽成功切换为" +
            slotnum + "号\"").communicate()
        z.sleep(2)
        d.server.adb.cmd(
            "shell",
            "am start -n com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity"
        ).communicate()  # 拉起来
        z.sleep(5)
        while d(textContains='正在更新数据').exists:
            z.sleep(2)
        z.sleep(15)

        z.heartbeat()
        loginStatusList = z.qq_getLoginStatus(d)
        if loginStatusList is None:
            if d(text='消息').exists and d(text='联系人').exists and d(
                    text='动态').exists:
                loginStatusList = {'success': True}
            elif d(textContains="请在小米神隐模式中将TIM设置为“无限制”。").exists:
                z.toast("我是小米神隐")
                d(text='我知道了').click()
                loginStatusList = {'success': True}
            else:
                z.toast("登陆新场景,现无法判断登陆状态")
                loginStatusList = {'success': False}

        loginStatus = loginStatusList['success']
        if loginStatus:
            z.toast("卡槽QQ状态正常,继续执行")
            return True
        else:
            QQnumber = remarkArr[1]
            if d(text='去安全中心').exists:
                self.repo.BackupInfo(cateId, 'frozen', QQnumber, '',
                                     '')  # 仓库号,使用中,QQ号,设备号_卡槽号QQNumber

            else:
                self.repo.BackupInfo(cateId, 'normal', QQnumber, '', '')

            self.slot.clear(slotnum)  # 清空改卡槽,并补登
            z.toast("卡槽QQ状态异常,补登陆卡槽")
            return False

    def action(self, d, z, args):
        while True:
            z.toast("正在ping网络是否通畅")
            i = 0
            while i < 200:
                i += 1
                ping = d.server.adb.cmd("shell",
                                        "ping -c 3 baidu.com").communicate()
                print(ping)
                if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                    z.toast("网络通畅。开始执行:普通QQ登录有卡槽")
                    break
                z.sleep(2)
            if i > 200:
                z.toast("网络不通,请检查网络状态")
                if (args["time_delay"]):
                    z.sleep(int(args["time_delay"]))
                return

            z.heartbeat()
            z.generate_serial("com.tencent.mobileqq")  # 随机生成手机特征码
            cate_id = args["repo_cate_id"]

            time_limit1 = args['time_limit1']
            numbers = self.repo.GetAccount(cate_id, time_limit1, 1)
            if len(numbers) == 0:
                d.server.adb.cmd(
                    "shell",
                    "am broadcast -a com.zunyun.zime.toast --es msg \"QQ帐号库%s号仓库无%s分钟未用,开始切换卡槽\""
                    % (cate_id, time_limit1)).communicate()

            serial = d.server.adb.device_serial()
            self.slot = Slot(serial, self.type)
            slotnum = self.slot.getEmpty()  # 取空卡槽
            if slotnum == 0 or len(numbers) == 0:  #没有空卡槽的话
                if self.qiehuan(d, z, args):
                    break

            else:  # 有空卡槽的情况
                d.server.adb.cmd(
                    "shell",
                    "pm clear com.tencent.mobileqq").communicate()  # 清除缓存

                d.server.adb.cmd(
                    "shell",
                    "settings put global airplane_mode_on 1").communicate()
                d.server.adb.cmd(
                    "shell",
                    "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true"
                ).communicate()
                z.sleep(6)
                d.server.adb.cmd(
                    "shell",
                    "settings put global airplane_mode_on 0").communicate()
                d.server.adb.cmd(
                    "shell",
                    "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
                ).communicate()
                z.heartbeat()
                while True:
                    ping = d.server.adb.cmd(
                        "shell", "ping -c 3 baidu.com").communicate()
                    print(ping)
                    if 'icmp_seq' and 'bytes from' and 'time' in ping[0]:
                        break
                    z.sleep(2)

                z.heartbeat()
                if self.login(d, args, z, numbers):
                    z.heartbeat()
                    featureCodeInfo = z.get_serial("com.tencent.mobileqq")
                    self.slot.backup(slotnum,
                                     str(slotnum) + '_' +
                                     numbers[0]['number'] + '_' +
                                     cate_id)  # 设备信息,卡槽号,QQ号
                    self.repo.BackupInfo(
                        cate_id, 'using', numbers[0]['number'],
                        featureCodeInfo,
                        '%s_%s_%s' % (d.server.adb.device_serial(), self.type,
                                      slotnum))  # 仓库号,使用中,QQ号,设备号_卡槽号
                    break

        if args["time_delay"]:
            z.sleep(int(args["time_delay"]))
예제 #12
0
        "x2": 502 / width,
        "y2": 473 / height
    }
    z.img_crop(source, p)

    out = d.server.adb.run_cmd('shell', 'ls')
    z.input("xxx")
    #    d.server.adb.cmd("shell", "ime set com.zunyun.zime/.ZImeService").communicate()
    z.server.install()

    slot = Slot('cda0ae8d', 'mobileqq')
    print(slot.getSlots())
    slot.backup('21', '22221111')

    print(slot.getSlots())
    slot.clear('21')

    z.generateSerial()
    #z.input("6565wv=1027&k=48KHKLm")

    #d.server.adb.cmd("shell", "am", "start", "-a", "zime.clear.contacts").communicate()
    d.server.adb.cmd("shell",
                     "pm clear com.android.providers.contacts").communicate()
    #d.server.adb.cmd("push", filename, "/data/local/tmp/contacts.txt").communicate()
    d.server.adb.cmd("shell", "am", "start", "-n",
                     "com.zunyun.zime/.ImportActivity", "-t", "text/plain",
                     "-d", "/data/local/tmp/contacts.txt").communicate()

    # d.dump(compressed=False)

    args = {