const perms = {
friends: [tr("appjs_sperm_friends"), tr("appjs_sperm_friends_desc")],
wall: [tr("appjs_sperm_wall"), tr("appjs_sperm_wall_desc")],
messages: [tr("appjs_sperm_messages"), tr("appjs_sperm_messages_desc")],
groups: [tr("appjs_sperm_groups"), tr("appjs_sperm_groups_desc")],
likes: [tr("appjs_sperm_likes"), tr("appjs_sperm_likes_desc")]
}
function escapeHtml(unsafe)
{
return unsafe
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function toQueryString(obj, prefix) {
var str = [],
p;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p,
v = obj[p];
str.push((v !== null && typeof v === "object") ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
return str.join("&");
}
function handleWallPostRequest(event) {
let mBoxContent = `
${tr("app")} ${window.appTitle} ${tr("appjs_wall_post_desc")}:
${escapeHtml(event.data.text)}
`; MessageBox(tr("appjs_wall_post"), mBoxContent, [tr("appjs_sperm_allow"), tr("appjs_sperm_deny")], [ async () => { let id = await API.Wall.newStatus(event.data.text); event.source.postMessage({ transaction: event.data.transaction, ok: true, post: { id: id, text: event.data.text } }, '*'); }, () => { event.source.postMessage({ transaction: event.data.transaction, ok: false, error: "User cancelled action" }, '*'); } ]); } async function handleVkApiRequest(event) { let method = event.data.method; if(!/^[a-z]+\.[a-z0-9]+$/.test(method)) { event.source.postMessage({ transaction: event.data.transaction, ok: false, error: "API Method name is invalid" }, '*'); return; } let domain = method.split(".")[0]; if(domain === "newsfeed") domain = "wall"; if(!window.appPerms.includes(domain)) { if(typeof perms[domain] === "undefined") { event.source.postMessage({ transaction: event.data.transaction, ok: false, error: "This API method is not supported" }, '*'); return; } let dInfo = perms[domain]; let allowed = false; await (new Promise(r => { MessageBox( tr("appjs_sperm_request"), `${tr("app")} ${window.appTitle} ${tr("appjs_sperm_requests")} ${dInfo[0]}. ${tr("appjs_sperm_can")} ${dInfo[1]}.`, [tr("appjs_sperm_allow"), tr("appjs_sperm_deny")], [ () => { API.Apps.updatePermission(window.appId, domain, "yes").then(() => { window.appPerms.push(domain); allowed = true; r(); }); }, () => { r(); } ] ) })); if(!allowed) { event.source.postMessage({ transaction: event.data.transaction, ok: false, error: "No permission to use this method" }, '*'); return; } } let params = toQueryString(event.data.params); let apiResponse = await (await fetch("/method/" + method + "?auth_mechanism=roaming&" + params)).json(); if(typeof apiResponse.error_code !== "undefined") { event.source.postMessage({ transaction: event.data.transaction, ok: false, error: apiResponse.error_code + ": " + apiResponse.error_msg }, '*'); return; } event.source.postMessage({ transaction: event.data.transaction, ok: true, response: apiResponse.response }, '*'); } function handlePayment(event) { let payload = event.data; if(payload.outSum < 0) { event.source.postMessage({ transaction: payload.transaction, ok: false, error: "negative sum" }, '*'); } MessageBox( tr("appjs_payment"), `
${tr("appjs_payment_intro")} ${window.appTitle}.
${tr("appjs_order_items")}: ${payload.description}
${tr("appjs_payment_total")}: ${payload.outSum} ${tr("points_count")}. `, [tr("appjs_payment_confirm"), tr("cancel")], [ async () => { let sign; try { sign = await API.Apps.pay(window.appId, payload.outSum); } catch(e) { MessageBox(tr("error"), tr("appjs_err_funds"), ["OK"], [Function.noop]); event.source.postMessage({ transaction: payload.transaction, ok: false, error: "Payment error[" + e.code + "]: " + e.message }, '*'); return; } event.source.postMessage({ transaction: payload.transaction, ok: true, outSum: payload.outSum, description: payload.description, signature: sign }, '*'); }, () => { event.source.postMessage({ transaction: payload.transaction, ok: false, error: "User cancelled payment" }, '*'); } ] ) } async function onNewMessage(event) { if(event.source !== appFrame.contentWindow) return; let payload = event.data; switch(payload["@type"]) { case "VkApiRequest": handleVkApiRequest(event); break; case "WallPostRequest": handleWallPostRequest(event); break; case "PaymentRequest": handlePayment(event); break; case "UserInfoRequest": event.source.postMessage({ transaction: payload.transaction, ok: true, user: await API.Apps.getUserInfo() }, '*'); break; default: event.source.postMessage({ transaction: payload.transaction, ok: false, error: "Unknown query type" }, '*'); } } window.addEventListener("message", onNewMessage);