الإصدار المنشور حزمة: ملف manifest.json واحد وصور PNG التي يسمّيها. تحقّق من كل ملف قبل استخدامه. ولأن الإصدار المنشور لا يتغير أبدًا، يمكنك الاحتفاظ بالحزمة التي اجتازت الفحص مرة واحدة للمدة التي تشاء.
manifest.json
version
manifestUrl
manifestSha256
minEngineVersion
assets
sha256
bytes
يبدو المُدخل في assets على هذا النحو:
{ "assets": { "crown_3f2a91bc.png": { "sha256": "3f2a91bc…", "bytes": 20711 } } }
إذن توجد هذه الصورة على https://…/lenses/8f3c2a10-…/3/crown_3f2a91bc.png، بجوار https://…/lenses/8f3c2a10-…/3/manifest.json.
https://…/lenses/8f3c2a10-…/3/crown_3f2a91bc.png
https://…/lenses/8f3c2a10-…/3/manifest.json
ملف البيان وصوره تنزيلات عادية. لا ترسل مفتاح API معها، ولا تُحتسب طلبات تسليم.
من سطر الأوامر:
curl -s -o manifest.json "$MANIFEST_URL" sha256sum manifest.json # or: shasum -a 256 manifest.json # The hex digest must equal manifestSha256.
في Swift، باستخدام CryptoKit:
import CryptoKit import Foundation enum DownloadError: Error { case hashMismatch } func sha256Hex(_ data: Data) -> String { SHA256.hash(data: data).map { String(format: "%02x", $0) }.joined() } let (bytes, _) = try await URLSession.shared.data(from: manifestURL) guard sha256Hex(bytes) == expectedSha256 else { throw DownloadError.hashMismatch }
في Kotlin:
import java.security.MessageDigest fun sha256Hex(bytes: ByteArray): String = MessageDigest.getInstance("SHA-256").digest(bytes) .joinToString("") { "%02x".format(it) } check(sha256Hex(bytes) == expectedSha256) { "Hash mismatch" }
قد تظهر حقول جديدة في إجابات التسليم في أي وقت. تجاهل الحقول التي لا تعرفها، حتى لا يعطّل حقلٌ جديد تطبيقك أبدًا. وأي إزالة لحقل أو تغيير فيه سيُعلن عنه مسبقًا.
يتجاهل Codable في Swift المفاتيح غير المعروفة افتراضيًا:
Codable
// The "data" object of a face lens answer. struct LensVersion: Decodable { let lensId: String let version: Int let manifestUrl: URL let manifestSha256: String let totalBytes: Int let minEngineVersion: Int let publishedAt: String let previewUrl: URL? }
مع kotlinx.serialization، اضبط ignoreUnknownKeys = true:
kotlinx.serialization
ignoreUnknownKeys = true
val json = Json { ignoreUnknownKeys = true } // The "data" object of a face lens answer. @Serializable data class LensVersion( val lensId: String, val version: Int, val manifestUrl: String, val manifestSha256: String, val totalBytes: Long, val minEngineVersion: Int, val publishedAt: String, val previewUrl: String? = null, )
المرونة مقصورة على إجابات الواجهة. أما ملف البيان نفسه فصارم ومُرقَّم الإصدارات. لا يتغير formatVersion فيه إلا مع تغيير غير متوافق مع ما سبق، ويحدد minEngineVersion محرك العرض القادر على رسمه. تحقّق من كليهما قبل قراءة البقية، وتعامل مع ملف البيان الذي لا يفهمه محرك العرض لديك على أنه ملف يُتخطّى، لا ملف يُخمَّن محتواه.
formatVersion