#!/usr/bin/env python # -*- coding:utf-8 -*- # project: 4月 # author: NinEveN # date: 2021/4/16 import logging from django.db.models import Count, Sum, Q from api.models import AppReleaseInfo, UserInfo from common.base.baseutils import is_valid_phone from common.constants import SignStatus, AppleDeveloperStatus, DeviceClass from common.core.sysconfig import Config, UserConfig from xsign.models import APPSuperSignUsedInfo, UDIDsyncDeveloper, AppUDID, APPToDeveloper, AppIOSDeveloperInfo, \ IosDeveloperPublicPoolBill, IosDeveloperBill, DeveloperDevicesID, AppleDeveloperToAppUse, DeveloperAppID, \ AppleSignMessage, DeviceAbnormalUDID logger = logging.getLogger(__name__) def get_ios_developer_public_num(user_obj): add_number = get_user_public_sign_num(user_obj) if not add_number: add_number = -99 used_number = get_user_public_used_sign_num(user_obj) return add_number - used_number def get_user_public_sign_num(user_obj): add_number = IosDeveloperBill.objects.filter(to_user_id=user_obj, status=2).aggregate( number=Sum('number')) number = add_number.get("number", 0) return number if number else 0 def get_user_public_used_sign_num(user_obj): used_number = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj, udid_sync_info__isnull=False).exclude( udid_sync_info__developerid__user_id=user_obj).values('number', 'udid_sync_info_id').annotate( counts=Count('udid_sync_info_id')).aggregate(number=Sum('number')) number = used_number.get("number", 0) return number if number else 0 # def get_developer_can_used_from_public_sign(user_obj): # o_number_info = IosDeveloperBill.objects.filter(to_user_id__isnull=False, user_id=user_obj).values( # 'number').aggregate(number=Sum('number')) # o_number = o_number_info.get("number", 0) # if o_number is None: # o_number = 0 # u_number_info = IosDeveloperPublicPoolBill.objects.filter( # user_id_id__in=IosDeveloperBill.objects.filter(user_id=user_obj).values('to_user_id_id')).values( # 'number', # 'udid_sync_info_id').annotate( # counts=Count('udid_sync_info_id')).aggregate(number=Sum('number')) # u_number = u_number_info.get("number", 0) # if u_number is None: # u_number = 0 # return o_number - u_number def check_super_sign_permission(user_obj): if not user_obj.supersign_active: return False developer_count = AppIOSDeveloperInfo.objects.filter(user_id=user_obj).count() if developer_count == 0 and get_ios_developer_public_num(user_obj) < 0: return False return True def check_ipa_is_latest_sign(app_obj, developer_obj=None, app_udid_obj=None): if not app_udid_obj and AppUDID.objects.filter(app_id=app_obj, udid__developerid=developer_obj, sign_status__lt=SignStatus.SIGNATURE_PACKAGE_COMPLETE).first(): return release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first() all_app_to_dev = APPToDeveloper.objects.filter(app_id=app_obj) if developer_obj: all_app_to_dev = all_app_to_dev.filter(developerid=developer_obj) all_app_to_dev = all_app_to_dev.all() t_count = 0 for apptodev_obj in all_app_to_dev: if release_obj.release_id == apptodev_obj.release_file: t_count += 1 if t_count == all_app_to_dev.count(): return True def get_developer_udided(developer_obj): super_sing_used_obj = APPSuperSignUsedInfo.objects.filter(developerid=developer_obj).all() udid_sync_developer_obj = UDIDsyncDeveloper.objects.filter(developerid=developer_obj).all() developer_udid_lists = [] super_sign_udid_lists = [] if udid_sync_developer_obj: developer_udid_lists = list(udid_sync_developer_obj.values_list("udid")) if super_sing_used_obj: super_sign_udid_lists = list(super_sing_used_obj.values_list("udid__udid__udid")) return len(set(developer_udid_lists) - set(super_sign_udid_lists)), len(set(super_sign_udid_lists)), len( set(developer_udid_lists)) def update_or_create_developer_udid_info(device_obj, developer_obj): device = { "serial": device_obj.id, "product": device_obj.name, "udid": device_obj.udid, "version": device_obj.model, "status": device_obj.status, "device_class": device_obj.deviceClass } return UDIDsyncDeveloper.objects.update_or_create(developerid=developer_obj, udid=device_obj.udid, defaults=device) def check_uid_has_relevant(user_uid, to_user_uid): if user_uid and to_user_uid: return IosDeveloperBill.objects.filter(user_id__uid=user_uid, to_user_id__uid=to_user_uid, status=2).first() def usable_number(developer_obj): d_count = UDIDsyncDeveloper.objects.filter(developerid=developer_obj, device_class=DeviceClass.IPHONE).count() u_count = developer_obj.usable_number return d_count if d_count > u_count else u_count def get_use_number(developer_obj): return DeveloperDevicesID.objects.filter(developerid=developer_obj).values('udid').distinct().count() def get_developer_devices(developer_obj_lists, user_obj): developer_obj_lists = developer_obj_lists.filter(status__in=Config.DEVELOPER_USE_STATUS).all() result_info = [] for dev_obj in developer_obj_lists: other_used, flyapp_used, _ = get_developer_udided(dev_obj) device_class_count = UDIDsyncDeveloper.objects.filter(developerid=dev_obj).exclude( device_class=DeviceClass.IPHONE).count() result_info.append({ 'other_used': other_used, 'flyapp_used': flyapp_used, 'usable_number': usable_number(dev_obj), 'use_number': get_use_number(dev_obj), 'status': dev_obj.status, 'abnormal_register': dev_obj.abnormal_register, 'device_class_count': device_class_count }) use_num = { "all_usable_number": 0, # 可用的设备数 "all_use_number": 0, # 已经使用的设备数 【通过设备ID】 "other_used_sum": 0, # 开发者已经使用,但是平台未使用设备数 "flyapp_used_sum": 0, # 平台已经使用的设备数【通过设备安装详情】 "can_sign_number": 0, # 可以被用来签名数【状态为1】 "used_sign_number": 0, # 已被用来签名数【状态为1】 "may_sign_number": 0, # 可以被用来签名数 "can_other_used": 0, # 开发者已经使用,但是平台未使用设备数【状态为1】 "used_number": 0, # 可用的设备数【状态为1】 "max_total": 100 * len(result_info), "device_class_count": 0 # 除了IPHONE其他设备状态 } developer_status = Config.DEVELOPER_SIGN_STATUS if UserConfig(user_obj).DEVELOPER_WAIT_ABNORMAL_DEVICE and UserConfig(user_obj).DEVELOPER_ABNORMAL_DEVICE_WRITE: developer_status.append(AppleDeveloperStatus.DEVICE_ABNORMAL) for info in result_info: use_num['other_used_sum'] += info['other_used'] use_num['flyapp_used_sum'] += info['flyapp_used'] use_num['all_usable_number'] += info['usable_number'] use_num['all_use_number'] += info['use_number'] if info['status'] in Config.DEVELOPER_SIGN_STATUS or ( info['status'] in developer_status and info['abnormal_register']): use_num['can_sign_number'] += (info['usable_number'] - info['flyapp_used'] - info['other_used']) use_num['used_sign_number'] += info['usable_number'] use_num['can_other_used'] += info['other_used'] use_num['used_number'] += info['use_number'] use_num['may_sign_number'] += (info['usable_number'] - info['flyapp_used'] - info['other_used']) use_num['device_class_count'] += info['device_class_count'] return use_num def get_user_obj_from_epu(user_id): if is_valid_phone(user_id): user_obj = UserInfo.objects.filter(mobile=user_id).first() else: user_obj = UserInfo.objects.filter(Q(email=user_id) | Q(uid=user_id)).first() return user_obj def get_app_sign_info(app_obj): return { 'count': APPToDeveloper.objects.filter(app_id=app_obj).count(), 'private_developer_number': AppleDeveloperToAppUse.objects.filter(app_id=app_obj).count(), 'supersign_used_number': APPSuperSignUsedInfo.objects.filter(app_id=app_obj).all().count(), 'developer_used_count': DeveloperAppID.objects.filter(app_id=app_obj).all().count(), 'private_developer_used_number': DeveloperDevicesID.objects.filter(app_id=app_obj, developerid__appledevelopertoappuse__app_id=app_obj).distinct().count() } def get_filename_form_file(filename): file_id_list = filename.split('.') check = False if file_id_list[-1] in ['ipa']: app_to_obj = APPToDeveloper.objects.filter(binary_file='.'.join(file_id_list[0:-1])).first() if app_to_obj: app_obj = app_to_obj.app_id if app_obj.type == 0: f_type = '.apk' else: f_type = '.ipa' filename = f"{app_obj.name}-sign-{app_obj.short}{f_type}" check = True return check, filename def add_sign_message(user_obj, developer_obj, app_obj, title, message, is_success): if app_obj: title = f'应用【{app_obj.name}】 {title}' AppleSignMessage.objects.create(user_id=user_obj, developerid=developer_obj, app_id=app_obj, title=title, message=message, operate_status=is_success) def sync_abnormal_device(developer_obj, udid): DeviceAbnormalUDID.objects.filter(auto_remove=True, udid__udid=udid, udid__developerid=developer_obj).delete() def update_or_create_abnormal_device(sync_device_obj, user_obj, app_obj, client_ip): defaults = { "description": f"签名应用【{app_obj.name}】 客户端IP地址:【{client_ip}】", } return DeviceAbnormalUDID.objects.update_or_create(user_id=user_obj, udid=sync_device_obj, defaults=defaults)