// Emblem Scanner Library - Utility functions for QR scanning // Self-contained utility functions for camera rules, device detection, and query building var camera_rules = null; /** * Get system information */ function get_system_info() { return wx.getSystemInfoSync(); } /** * Get phone model from system info */ function get_phone_model() { var ret = get_system_info().model; console.log("phone model", ret); return ret; } /** * Match camera rules based on phone model */ function match_camera_rules(model, rules, default_zoom) { console.log(model, "apply zoom rules:", rules); var best_match = null; for (var rule of rules) { if (model.toLowerCase().startsWith(rule.model.toLowerCase())) { if (!best_match || rule.model.length > best_match.model.length) { best_match = rule; } } } if (best_match) { console.log("found best match", best_match); return best_match; } var ret = { zoom: default_zoom, web_view: false }; console.log("using default", ret); return ret; } /** * Get camera rule from API or cache */ function get_camera_rule(max_zoom, cb) { var default_zoom = 4; if (max_zoom && max_zoom >= 60) { /* * 2024.06.01: in some Huawei/Honor models, the scale is different, use 40 * in this case so we don't need to set up rules for each specific model */ console.log(`max zoom is ${max_zoom}, default zoom will be 40`); default_zoom = 40; } if (camera_rules) { let rule = match_camera_rules(get_phone_model(), camera_rules, default_zoom); cb(rule); } else { var url = 'https://themblem.com/api/v1/camera-rules/'; wx.request({ url, complete: (res) => { var rules = res.data; camera_rules = rules; let rule = match_camera_rules(get_phone_model(), rules, default_zoom); cb(rule); } }); } } /** * Build query string for web-view camera */ function make_query(zoom, return_page, real_ip, tenant_id) { var ret = "zoom=" + zoom; var ui = wx.getStorageSync('userinfo') || {}; ret += "&phonemodel=" + encodeURIComponent(get_phone_model()); ret += "&realip=" + (real_ip || ""); ret += "&emblem_id=" + (ui.emblem_id || ""); ret += "&nick_name=" + encodeURIComponent(ui.nickName || ""); ret += "&tenant=" + (tenant_id || ""); ret += "&tk=" + Date.now(); if (return_page) { ret += "&wx_redirect_to=" + encodeURIComponent(return_page); } console.log("Web-view query:", ret); return ret; } /** * Fetch real IP address */ function fetch_real_ip(callback) { wx.request({ url: 'https://themblem.com/api/v1/my-location/', success: (res) => { const ip = res.data.ip || ''; console.log('Real IP fetched:', ip); callback(null, ip); }, fail: (err) => { console.error('Failed to fetch real IP:', err); callback(err, ''); } }); } /** * Get tenant ID from storage */ function get_tenant_id() { const tenant_id = wx.getStorageSync('tenant_id') || ''; console.log('Tenant ID:', tenant_id); return tenant_id; } /** * Check if QR code matches Emblem pattern */ function is_emblem_qr_pattern(p) { if (p.search(/code=[0-9a-zA-Z]+/) >= 0) return true; if (p.search(/id=[0-9a-zA-Z]+/) >= 0) return true; if (p.search(/c=[0-9a-zA-Z]+/) >= 0) return true; if (p.search(/https:\/\/xy.ltd\/v\/[0-9a-zA-Z]+/) >= 0) return true; return false; } /** * Get the current package path for dynamic WASM file loading * This function determines the correct path to WASM files based on the current page location */ function get_current_package_path() { try { // Get current pages stack to determine current page location const pages = getCurrentPages(); if (pages && pages.length > 0) { const currentPage = pages[pages.length - 1]; const route = currentPage.route; // Extract package path from route // For example: "bofen/packages/emblemscanner/emblemscanner" -> "bofen/packages/emblemscanner" const pathParts = route.split('/'); if (pathParts.length >= 2) { // Remove the page file name and return the package path return pathParts.slice(0, -1).join('/'); } } } catch (e) { console.warn('Failed to get current package path:', e); } // Fallback: assume we're in the main pages directory return 'pages/emblemscanner'; } /** * Get the full WASM file path based on current package location */ function get_wasm_file_path(filename) { const packagePath = get_current_package_path(); return `${packagePath}/${filename}`; } /** * Test function to verify path resolution works correctly * This can be called in development to test the path resolution logic */ function test_path_resolution() { console.log('Testing path resolution...'); // Mock getCurrentPages for testing (would normally be available in WeChat miniprogram) const originalGetCurrentPages = global.getCurrentPages; global.getCurrentPages = function() { return [{ route: 'bofen/packages/emblemscanner/emblemscanner' }]; }; try { const packagePath = get_current_package_path(); const wasmPath = get_wasm_file_path('qrtool.wx.wasm.br'); console.log('Expected package path: bofen/packages/emblemscanner'); console.log('Actual package path:', packagePath); console.log('Expected WASM path: bofen/packages/emblemscanner/qrtool.wx.wasm.br'); console.log('Actual WASM path:', wasmPath); if (packagePath === 'bofen/packages/emblemscanner' && wasmPath === 'bofen/packages/emblemscanner/qrtool.wx.wasm.br') { console.log('✅ Path resolution test PASSED'); return true; } else { console.log('❌ Path resolution test FAILED'); return false; } } finally { // Restore original function if (originalGetCurrentPages) { global.getCurrentPages = originalGetCurrentPages; } else { delete global.getCurrentPages; } } } module.exports = { get_system_info, get_phone_model, get_camera_rule, make_query, fetch_real_ip, get_tenant_id, is_emblem_qr_pattern, get_current_package_path, get_wasm_file_path, test_path_resolution };