const storageKeyName = "rc_rewrite_ddata"; const jobTitle = "update_rc"; const notificationTitle = "Update RevenueCat JSON" let URL = ""; // URL = 'https://jsonplaceholder.typicode.com/todos/1'; // URL = "https://stackoverflow.com/questions/38708550/difference-between-return-await-promise-and-return-promise" // URL = "http://localhost:8000/rc_rewrite_data.json"; // URL = "https://api.jsonbin.io/v3/qs/651be8b30574da7622b3b246"; URL = "https://git.ykz.app/PorridgePi/json/raw/branch/main/rc_rewrite_data.json"; // URL = "https://porridgepi.github.io/json/rc_rewrite_data.json" requestOpts = { // mode:'no-cors', cache: "no-store", headers: { // "Origin": "https://git.ykz.app/", // "Accept": "application/json" } } const isSurge = typeof $httpClient != "undefined"; const isQuanX = typeof $task != "undefined"; const isLoon = typeof $loon != "undefined"; const isJSBox = typeof $app != "undefined" && typeof $http != "undefined"; const isNode = typeof require == "function" && !isJSBox; function timeout(ms, promise) { return new Promise((resolve, reject) => { const timer = setTimeout(() => { reject(new Error("Timed out after " + String(ms) + "ms")) }, ms) promise .then(value => { clearTimeout(timer) resolve(value) }) .catch(reason => { clearTimeout(timer) reject(reason) }) }) } async function fetchJSON(url, opts = {}) { if (isQuanX) { return fetch(url, { ...opts }) .then(response => { if (false && !response.ok) { console.log("ERROR(fetchJSON): Response not okay, HTTP " + String(response.status) + ' ' + response.statusText); throw new Error("Response not ok"); } return response.text() .then(text => { try { return JSON.parse(text); } catch (err) { console.log("ERROR(fetchJSON): Response body not JSON" + String(err)); console.log(text); throw new Error("Response body not JSON"); } }) }); } if (isNode) { var resp = await $http.get(url, opts); try { return JSON.parse(resp.body); } catch (err) { console.log("ERROR(fetchJSON): Response body not JSON" + String(err)); console.log(text); throw new Error("Response body not JSON"); } } } async function getRewriteItems() { try { let toReturn = JSON.parse($prefs.valueForKey(storageKeyName)); console.log("INFO: Retrieved local copy.") return toReturn; } catch (err) { console.log("ERROR(getRewriteItems): Unable to access local copy - " + err); console.log("INFO: Fetching new copy..."); try { if (isQuanX) return await timeout(1000, fetchJSON(URL, requestOpts)); // add await if using nested try-catch - https://stackoverflow.com/a/42750371 if (isNode) return fetchJSON(URL, requestOpts); } catch (err) { console.log("ERROR(getRewriteItems): " + err); throw new Error("Unable to retrieve rewrite items."); } } } async function onResponse(context, url, request, response) { console.log("INFO: Running..."); let rewriteItems = {} try { rewriteItems = await getRewriteItems(); // console.log(JSON.stringify(rewriteItems)); } catch (err) { console.log("ERROR(onResponse): " + err); } let bundle_id = request.headers["X-Client-Bundle-ID"]; let user_agent = request.headers["User-Agent"]; for (let i = 0; i < rewriteItems.length; i++) { rewriteItem = rewriteItems[i] // console.log(JSON.stringify(rewriteItem)); console.log(rewriteItem.name); let bundleIdMatched = bundle_id != null && bundle_id == rewriteItem.bundle_id let userAgentMatched = user_agent != null && user_agent.includes(rewriteItem.user_agent) if (!bundleIdMatched && !userAgentMatched) { if (i == rewriteItems.length - 1) { // last console.log(String(bundle_id) + " " + String(user_agent)); break; } continue; } console.log("MATCHED!"); body = { ...response.body } if (body.subscriber == undefined) body.subscriber = {} console.log(JSON.stringify(body)); let now = new Date(); let MS_PER_MINUTE = 60000; let timeToUse = new Date(now - 0 * MS_PER_MINUTE); // CAN CHANGE MANUAL DELAY if (body.request_date == undefined) body.request_date = timeToUse.toISOString().split('.')[0] + "Z"; if (body.request_date_ms == undefined) body.request_date_ms = Date.parse(timeToUse); if (body.subscriber.first_seen == undefined) body.subscriber.first_seen = timeToUse.toISOString().split('.')[0] + "Z"; if (body.subscriber.last_seen == undefined) body.subscriber.last_seen = timeToUse.toISOString().split('.')[0] + "Z"; if (body.subscriber.management_url == undefined) body.subscriber.management_url = null; const uuidString = url.slice(-32); console.log(uuidString) const uuid = uuidString.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/g, '$1-$2-$3-$4-$5') console.log(uuid) if (body.subscriber.original_app_user_id == undefined) body.subscriber.original_app_user_id = uuid; if (body.subscriber.original_application_version == undefined) body.subscriber.original_application_version = "0.0"; if (body.subscriber.original_purchase_date == undefined) body.subscriber.original_purchase_date = now.toISOString().split('.')[0] + "Z"; body.subscriber.entitlements = { ...body.subscriber.entitlements }; body.subscriber.subscriptions = { ...body.subscriber.subscriptions }; body.subscriber.non_subscriptions = { ...body.subscriber.non_subscriptions }; body.subscriber.other_purchases = { ...body.subscriber.other_purchases }; let isSubscription = rewriteItem.new_subscriptions.length > 0; let isNonSubscription = rewriteItem.new_non_subscriptions.length > 0; let product_id = "" console.log(isNonSubscription); console.log(isSubscription); console.log(body.subscriber.entitlements); if (isSubscription) { product_id = rewriteItem.new_subscriptions[0]; for (const i of rewriteItem.new_subscriptions) { body.subscriber.subscriptions[i] = { "auto_resume_date": null, "billing_issues_detected_at": null, "expires_date": "2099-12-31T23:59:59Z", "grace_period_expires_date": null, "is_sandbox": false, "original_purchase_date": "2020-01-01T00:00:00Z", "period_type": "normal", "purchase_date": "2020-01-01T00:00:00Z", "refunded_at": null, "store": "app-store", "store_transaction_id": "", "unsubscribe_detected_at": null } } } if (isNonSubscription) { product_id = rewriteItem.new_non_subscriptions[0]; for (const i of rewriteItem.new_non_subscriptions) { body.subscriber.non_subscriptions[i] = { "is_sandbox": false, "store_transaction_id": "", "id": "", "original_purchase_date": "2020-01-01T00:00:00Z", "store": "app_store", "purchase_date": "2020-01-01T00:00:00Z" } } for (const i of rewriteItem.new_other_purchases) { body.subscriber.other_purchases[i] = { purchase_date: "2020-01-01T00:00:00Z" } } } for (const i of rewriteItem.new_entitlements) { body.subscriber.entitlements[i] = { "expires_date": null, "grace_period_expires_date": null, "product_identifier": product_id, "purchase_date": "2020-01-01T00:00:00Z" } } response.body = body; response.statusCode = 200; response.statusPhrase = "OK"; response.headers["Content-Type"] = "application/json"; console.log(response.body); break; } console.log("INFO: Exiting..."); return response; } var $request, $response; async function main() { console.log("Starting..."); if (isSurge || isQuanX) { try { console.log(JSON.stringify($request)); if (typeof $request == 'undefined') $request = { url: "", headers: { // "X-Client-Bundle-ID": "com.benricemccarthy.obscura-2" }, body: "{}" } console.log(JSON.stringify($request)); if (typeof $response == 'undefined') $response = { url: "", headers: {}, body: "{}" } url = $request.url; $request.body = typeof $request.body != "undefined" ? JSON.parse($request.body) : {}; $response.body = typeof $response.body != "undefined" ? JSON.parse($response.body) : {}; } catch (err) { console.log(err); } console.log("starting onResponse"); try { response = await timeout(3000, onResponse(null, url, $request, $response)); } catch (err) { console.log(err); } if (isQuanX) { $request.status = "HTTP/1.1 " + $request.statusCode + " " + $request.statusPhrase; $response.status = "HTTP/1.1 " + $response.statusCode + " " + $response.statusPhrase; $request.body = JSON.stringify($request.body); $response.body = JSON.stringify($response.body); } $done({ status: $response.status, headers: $response.headers, body: $response.body }); } } main();