File size: 11,724 Bytes
097ec8a 7b33522 097ec8a 7b33522 097ec8a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
import requests
from urllib.parse import quote
from functools import lru_cache
import os
import json
from functools import lru_cache
apple_device_mapping = {
"Watch1,1": "Apple Watch 38mm case",
"Watch1,2": "Apple Watch 42mm case",
"Watch2,3": "Apple Watch Series 2 38mm case",
"Watch2,4": "Apple Watch Series 2 42mm case",
"Watch2,6": "Apple Watch Series 1 38mm case",
"Watch2,7": "Apple Watch Series 1 42mm case",
"Watch3,1": "Apple Watch Series 3 38mm case",
"Watch3,2": "Apple Watch Series 3 42mm case",
"Watch3,3": "Apple Watch Series 3 38mm case",
"Watch3,4": "Apple Watch Series 3 42mm case",
"Watch4,1": "Apple Watch Series 4 40mm case",
"Watch4,2": "Apple Watch Series 4 44mm case",
"Watch4,3": "Apple Watch Series 4 40mm case",
"Watch4,4": "Apple Watch Series 4 44mm case",
"Watch5,1": "Apple Watch Series 5 40mm case",
"Watch5,10": "Apple Watch SE 44mm case",
"Watch5,11": "Apple Watch SE 40mm case",
"Watch5,12": "Apple Watch SE 44mm case",
"Watch5,2": "Apple Watch Series 5 44mm case",
"Watch5,3": "Apple Watch Series 5 40mm case",
"Watch5,4": "Apple Watch Series 5 44mm case",
"Watch5,9": "Apple Watch SE 40mm case",
"Watch6,1": "Apple Watch Series 6 40mm case",
"Watch6,10": "Apple Watch SE 40mm case",
"Watch6,11": "Apple Watch SE 44mm case",
"Watch6,12": "Apple Watch SE 40mm case",
"Watch6,13": "Apple Watch SE 44mm case",
"Watch6,14": "Apple Watch Series 8 41mm case",
"Watch6,15": "Apple Watch Series 8 45mm case",
"Watch6,16": "Apple Watch Series 8 41mm case",
"Watch6,17": "Apple Watch Series 8 45mm case",
"Watch6,18": "Apple Watch Ultra",
"Watch6,2": "Apple Watch Series 6 44mm case",
"Watch6,3": "Apple Watch Series 6 40mm case",
"Watch6,4": "Apple Watch Series 6 44mm case",
"Watch6,6": "Apple Watch Series 7 41mm case",
"Watch6,7": "Apple Watch Series 7 45mm case",
"Watch6,8": "Apple Watch Series 7 41mm case",
"Watch6,9": "Apple Watch Series 7 45mm case",
"Watch7,1": "Apple Watch Series 9 41mm case",
"Watch7,10": "Apple Watch Series 10 42mm case",
"Watch7,11": "Apple Watch Series 10 46mm",
"Watch7,2": "Apple Watch Series 9 45mm case",
"Watch7,3": "Apple Watch Series 9 41mm case",
"Watch7,4": "Apple Watch Series 9 45mm case",
"Watch7,5": "Apple Watch Ultra 2",
"Watch7,8": "Apple Watch Series 10 42mm case",
"Watch7,9": "Apple Watch Series 10 46mm case (GPS",
"arm64": "iPhone Simulator",
"i386": "iPhone Simulator",
"iPad1,1": "iPad",
"iPad1,2": "iPad 3G",
"iPad11,1": "iPad mini 5th Gen",
"iPad11,2": "iPad mini 5th Gen",
"iPad11,3": "iPad Air 3rd Gen",
"iPad11,4": "iPad Air 3rd Gen",
"iPad11,6": "iPad 8th Gen",
"iPad11,7": "iPad 8th Gen",
"iPad12,1": "iPad 9th Gen",
"iPad12,2": "iPad 9th Gen",
"iPad13,1": "iPad Air 4th Gen",
"iPad13,10": "iPad Pro 12.9 inch 5th Gen",
"iPad13,11": "iPad Pro 12.9 inch 5th Gen",
"iPad13,16": "iPad Air 5th Gen",
"iPad13,17": "iPad Air 5th Gen",
"iPad13,18": "iPad 10th Gen",
"iPad13,19": "iPad 10th Gen",
"iPad13,2": "iPad Air 4th Gen",
"iPad13,4": "iPad Pro 11 inch 5th Gen",
"iPad13,5": "iPad Pro 11 inch 5th Gen",
"iPad13,6": "iPad Pro 11 inch 5th Gen",
"iPad13,7": "iPad Pro 11 inch 5th Gen",
"iPad13,8": "iPad Pro 12.9 inch 5th Gen",
"iPad13,9": "iPad Pro 12.9 inch 5th Gen",
"iPad14,1": "iPad mini 6th Gen",
"iPad14,10": "iPad Air 13 inch 6th Gen",
"iPad14,11": "iPad Air 13 inch 6th Gen",
"iPad14,2": "iPad mini 6th Gen",
"iPad14,3": "iPad Pro 11 inch 4th Gen",
"iPad14,4": "iPad Pro 11 inch 4th Gen",
"iPad14,5": "iPad Pro 12.9 inch 6th Gen",
"iPad14,6": "iPad Pro 12.9 inch 6th Gen",
"iPad14,8": "iPad Air 11 inch 6th Gen",
"iPad14,9": "iPad Air 11 inch 6th Gen",
"iPad15,3": "iPad Air 11-inch 7th Gen",
"iPad15,4": "iPad Air 11-inch 7th Gen",
"iPad15,5": "iPad Air 13-inch 7th Gen",
"iPad15,6": "iPad Air 13-inch 7th Gen",
"iPad15,7": "iPad 11th Gen",
"iPad15,8": "iPad 11th Gen",
"iPad16,1": "iPad mini 7th Gen",
"iPad16,2": "iPad mini 7th Gen",
"iPad16,3": "iPad Pro 11 inch 5th Gen",
"iPad16,4": "iPad Pro 11 inch 5th Gen",
"iPad16,5": "iPad Pro 12.9 inch 7th Gen",
"iPad16,6": "iPad Pro 12.9 inch 7th Gen",
"iPad2,1": "2nd Gen iPad",
"iPad2,2": "2nd Gen iPad",
"iPad2,3": "2nd Gen iPad",
"iPad2,4": "2nd Gen iPad New Revision",
"iPad2,5": "iPad mini",
"iPad2,6": "iPad mini",
"iPad2,7": "iPad mini",
"iPad3,1": "3rd Gen iPad",
"iPad3,2": "3rd Gen iPad",
"iPad3,3": "3rd Gen iPad",
"iPad3,4": "4th Gen iPad",
"iPad3,5": "4th Gen iPad",
"iPad3,6": "4th Gen iPad",
"iPad4,1": "iPad Air",
"iPad4,2": "iPad Air",
"iPad4,3": "1st Gen iPad Air",
"iPad4,4": "iPad mini Retina",
"iPad4,5": "iPad mini Retina",
"iPad4,6": "iPad mini Retina",
"iPad4,7": "iPad mini 3",
"iPad4,8": "iPad mini 3",
"iPad4,9": "iPad Mini 3",
"iPad5,1": "iPad mini 4",
"iPad5,2": "4th Gen iPad mini",
"iPad5,3": "iPad Air 2",
"iPad5,4": "iPad Air 2",
"iPad6,11": "iPad (2017)",
"iPad6,12": "iPad (2017)",
"iPad6,3": "iPad Pro (9.7 inch)",
"iPad6,4": "iPad Pro (9.7 inch)",
"iPad6,7": "iPad Pro (12.9 inch)",
"iPad6,8": "iPad Pro (12.9 inch)",
"iPad7,1": "iPad Pro 2nd Gen",
"iPad7,11": "iPad 7th Gen 10.2-inch",
"iPad7,12": "iPad 7th Gen 10.2-inch",
"iPad7,2": "iPad Pro 2nd Gen",
"iPad7,3": "iPad Pro 10.5-inch 2nd Gen",
"iPad7,4": "iPad Pro 10.5-inch 2nd Gen",
"iPad7,5": "iPad 6th Gen",
"iPad7,6": "iPad 6th Gen",
"iPad8,1": "iPad Pro 11 inch 3rd Gen",
"iPad8,10": "iPad Pro 11 inch 4th Gen",
"iPad8,11": "iPad Pro 12.9 inch 4th Gen",
"iPad8,12": "iPad Pro 12.9 inch 4th Gen",
"iPad8,2": "iPad Pro 11 inch 3rd Gen",
"iPad8,3": "iPad Pro 11 inch 3rd Gen",
"iPad8,4": "iPad Pro 11 inch 3rd Gen",
"iPad8,5": "iPad Pro 12.9 inch 3rd Gen",
"iPad8,6": "iPad Pro 12.9 inch 3rd Gen",
"iPad8,7": "iPad Pro 12.9 inch 3rd Gen",
"iPad8,8": "iPad Pro 12.9 inch 3rd Gen",
"iPad8,9": "iPad Pro 11 inch 4th Gen",
"iPhone1,1": "iPhone",
"iPhone1,2": "iPhone 3G",
"iPhone10,1": "iPhone 8",
"iPhone10,2": "iPhone 8 Plus",
"iPhone10,3": "iPhone X",
"iPhone10,4": "iPhone 8",
"iPhone10,5": "iPhone 8 Plus",
"iPhone10,6": "iPhone X",
"iPhone11,2": "iPhone XS",
"iPhone11,4": "iPhone XS Max",
"iPhone11,6": "iPhone XS Max",
"iPhone11,8": "iPhone XR",
"iPhone12,1": "iPhone 11",
"iPhone12,3": "iPhone 11 Pro",
"iPhone12,5": "iPhone 11 Pro Max",
"iPhone12,8": "iPhone SE 2nd Gen",
"iPhone13,1": "iPhone 12 Mini",
"iPhone13,2": "iPhone 12",
"iPhone13,3": "iPhone 12 Pro",
"iPhone13,4": "iPhone 12 Pro Max",
"iPhone14,2": "iPhone 13 Pro",
"iPhone14,3": "iPhone 13 Pro Max",
"iPhone14,4": "iPhone 13 Mini",
"iPhone14,5": "iPhone 13",
"iPhone14,6": "iPhone SE 3rd Gen",
"iPhone14,7": "iPhone 14",
"iPhone14,8": "iPhone 14 Plus",
"iPhone15,2": "iPhone 14 Pro",
"iPhone15,3": "iPhone 14 Pro Max",
"iPhone15,4": "iPhone 15",
"iPhone15,5": "iPhone 15 Plus",
"iPhone16,1": "iPhone 15 Pro",
"iPhone16,2": "iPhone 15 Pro Max",
"iPhone17,1": "iPhone 16 Pro",
"iPhone17,2": "iPhone 16 Pro Max",
"iPhone17,3": "iPhone 16",
"iPhone17,4": "iPhone 16 Plus",
"iPhone17,5": "iPhone 16e",
"iPhone2,1": "iPhone 3GS",
"iPhone3,1": "iPhone 4",
"iPhone3,2": "iPhone 4",
"iPhone3,3": "iPhone 4",
"iPhone4,1": "iPhone 4S",
"iPhone5,1": "iPhone 5",
"iPhone5,2": "iPhone 5",
"iPhone5,3": "iPhone 5C",
"iPhone5,4": "iPhone 5C",
"iPhone6,1": "iPhone 5S",
"iPhone6,2": "iPhone 5S",
"iPhone7,1": "iPhone 6 Plus",
"iPhone7,2": "iPhone 6",
"iPhone8,1": "iPhone 6s",
"iPhone8,2": "iPhone 6s Plus",
"iPhone8,4": "iPhone SE",
"iPhone9,1": "iPhone 7",
"iPhone9,2": "iPhone 7 Plus",
"iPhone9,3": "iPhone 7",
"iPhone9,4": "iPhone 7 Plus",
"iPod1,1": "1st Gen iPod",
"iPod2,1": "2nd Gen iPod",
"iPod3,1": "3rd Gen iPod",
"iPod4,1": "4th Gen iPod",
"iPod5,1": "5th Gen iPod",
"iPod7,1": "6th Gen iPod",
"iPod9,1": "7th Gen iPod",
"x86_64": "iPhone Simulator",
}
# Cache for Android device names
CACHE_FILE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "android_device_cache.json"
)
android_device_cache = {}
# Load cache from file if it exists
def load_cache():
global android_device_cache
try:
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE, "r") as f:
android_device_cache = json.load(f)
print(f"Loaded {len(android_device_cache)} Android device names from cache")
except Exception as e:
print(f"Error loading Android device cache: {str(e)}")
android_device_cache = {}
# Save cache to file
def save_cache():
try:
with open(CACHE_FILE, "w") as f:
json.dump(android_device_cache, f, indent=2)
except Exception as e:
print(f"Error saving Android device cache: {str(e)}")
# Load cache on module import
load_cache()
@lru_cache(maxsize=1024)
def get_device_name(manufacturer, device_id, default_device_name):
"""
Get the normalized device name from a device ID like iPad16,1
Args:
device_id (str): The device identifier (e.g., iPad16,1)
Returns:
str: The normalized device name without connectivity info
"""
if manufacturer == "Apple":
return apple_device_mapping.get(device_id, default_device_name)
else:
return get_android_model_name(manufacturer, device_id)
def get_android_model_name(manufacturer, model):
"""
Get a user-friendly Android device name from cache or GitHub repository
Args:
manufacturer (str): Device manufacturer
model (str): Device model
Returns:
str: User-friendly device name, or original model if not found
"""
# https://github.com/openhoangnc/android_model_name
# Create a cache key by combining manufacturer and model
cache_key = f"{manufacturer.lower()}:{model.lower()}"
# Check if we already have this device in our cache
if cache_key in android_device_cache:
# Return the cached result
return android_device_cache[cache_key]
# If not in cache, fetch from GitHub
repo_url = "https://raw.githubusercontent.com/openhoangnc/android_model_name/main"
# Prepare the URL path components
if not manufacturer:
# Return the model if manufacturer is empty
return model
first_letter = manufacturer[0].lower()
safe_manufacturer = quote(manufacturer.lower())
safe_model = quote(model.replace("/", "-").lower()) if model else ""
# Build the query URL
query_url = f"{repo_url}/{first_letter}/{safe_manufacturer}/{safe_model}"
try:
# Fetch the device name from the repository
response = requests.get(query_url, timeout=3)
if response.status_code == 200:
device_name = response.text.strip()
# Cache the result
android_device_cache[cache_key] = device_name
# Save cache periodically (every 10 new entries)
if len(android_device_cache) % 10 == 0:
save_cache()
return device_name
return model
except Exception as e:
print(f"Error fetching Android model name: {str(e)}")
return model
# Make sure to save the cache when the program exits
import atexit
atexit.register(save_cache)
|