images: download: Add support for factory images and OTAs

This commit is contained in:
Danny Lin 2021-12-17 14:20:38 -08:00
parent a1d82d9806
commit cd86042e75

View file

@ -3,32 +3,73 @@ import cliProgress from 'cli-progress'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { promises as stream } from 'stream' import { promises as stream } from 'stream'
import path from 'path' import path from 'path'
import _ from 'lodash'
const VENDOR_INDEX_URL = 'https://developers.google.com/android/drivers' const DEV_INDEX_URL = 'https://developers.google.com/android'
const VENDOR_URL_PREFIX = 'https://dl.google.com/dl/android/aosp/google_devices' const DL_URL_PREFIX = 'https://dl.google.com/dl/android/aosp/'
async function getUrl(type: string, buildId: string, device: string) { interface ImageTypeInfo {
if (type == 'vendor') { indexPath: string
let resp = await fetch(VENDOR_INDEX_URL) filePattern: string
cookie?: string
}
export enum ImageType {
Ota = 'ota',
Factory = 'factory',
Vendor = 'vendor',
}
const IMAGE_TYPES: Record<ImageType, ImageTypeInfo> = {
[ImageType.Factory]: {
indexPath: 'images',
filePattern: 'DEVICE-BUILDID',
cookie: 'devsite_wall_acks=nexus-image-tos',
},
[ImageType.Ota]: {
indexPath: 'ota',
filePattern: 'DEVICE-ota-BUILDID',
cookie: 'devsite_wall_acks=nexus-ota-tos',
},
[ImageType.Vendor]: {
indexPath: 'drivers',
filePattern: 'google_devices-DEVICE-BUILDID',
},
}
async function getUrl(type: ImageType, buildId: string, device: string) {
let { indexPath, filePattern, cookie } = IMAGE_TYPES[type]
let resp = await fetch(`${DEV_INDEX_URL}/${indexPath}`, cookie != undefined ? {
headers: {
Cookie: cookie,
},
} : undefined)
let index = await resp.text() let index = await resp.text()
// TODO: parse HTML properly let filePrefix = filePattern.replace('DEVICE', device)
let pattern = new RegExp(`"(${VENDOR_URL_PREFIX}-${device}-${buildId.toLowerCase()}-[a-z9-9.-_]+)">`) .replace('BUILDID', buildId == 'latest' ? '' : buildId.toLowerCase() + '-')
let match = index.match(pattern) let urlPrefix = DL_URL_PREFIX + filePrefix
if (match == null) {
let pattern = new RegExp(`"(${_.escapeRegExp(urlPrefix)}.+?)"`, 'g')
let matches = Array.from(index.matchAll(pattern))
if (matches.length == 0) {
throw new Error(`Image not found: ${type}, ${buildId}, ${device}`) throw new Error(`Image not found: ${type}, ${buildId}, ${device}`)
} }
return match[1] if (buildId == 'latest') {
return matches
.map(m => m[1])
.sort((a, b) => b.localeCompare(a))[0]
} else { } else {
// TODO: implement factory and ota return matches[0][1]
throw new Error(`Unsupported type ${type}`)
} }
} }
export async function downloadFile(type: string, buildId: string, device: string, outDir: string) { export async function downloadFile(type: ImageType, buildId: string, device: string, outDir: string) {
let url = await getUrl(type, buildId, device) let url = await getUrl(type, buildId, device)
console.log(` ${url}`)
let resp = await fetch(url) let resp = await fetch(url)
let name = path.basename(url) let name = path.basename(url)
if (!resp.ok) { if (!resp.ok) {