feat: iTunes redirect
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
<div class="entry full">
|
||||
<div>
|
||||
<img src="$IMG">
|
||||
<button onclick="installIpa($IDX)">Install</button>
|
||||
<button onclick="installIPA($IDX)">Install</button>
|
||||
</div>
|
||||
<div class="info">
|
||||
<h4>$TITLE</h4>
|
||||
@@ -71,12 +71,16 @@
|
||||
<div>$IMG</div>
|
||||
<p>$DESCRIPTION</p>
|
||||
</div>
|
||||
<a class="screenshot" href="$URL" target="_blank"><img src="$URL"></a>
|
||||
<a class="screenshot" href="$REF" target="_blank"><img src="$URL"></a>
|
||||
<div class="randomAction">
|
||||
Actions:
|
||||
<button onclick="searchBundle($IDX, '&random=$IDX')">Show all versions</button>
|
||||
<button onclick="randomIPA()">Next Random</button>
|
||||
</div>
|
||||
<div class="no-itunes">
|
||||
<p>iTunes search disabled. No plist server configured.</p>
|
||||
<a onclick="installIPA()">Configure now</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="overlay" hidden>
|
||||
|
||||
29
script.js
29
script.js
@@ -4,7 +4,7 @@ var baseUrls = {};
|
||||
var PER_PAGE = 30;
|
||||
var isInitial = true;
|
||||
var previousSearch = '';
|
||||
var plistGeneratorUrl = ''; // will append ?d=<data>
|
||||
var plistServerUrl = ''; // will append ?d=<data>
|
||||
NodeList.prototype.forEach = Array.prototype.forEach; // fix for < iOS 9.3
|
||||
|
||||
/*
|
||||
@@ -164,11 +164,11 @@ function searchIPA(restorePage) {
|
||||
* Random IPA
|
||||
*/
|
||||
|
||||
function urlsToImgs(list) {
|
||||
function urlsToImgs(redirectUrl, list) {
|
||||
const template = getTemplate('.screenshot');
|
||||
var rv = '<div class="carousel">';
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
rv += renderTemplate(template, { $URL: list[i] });
|
||||
rv += renderTemplate(template, { $REF: list[i], $URL: redirectUrl + list[i] });
|
||||
}
|
||||
return rv + '</div>';
|
||||
}
|
||||
@@ -190,15 +190,20 @@ function randomIPA(specificId) {
|
||||
const entry = entryToDict(DB[idx]);
|
||||
const output = document.getElementById('content');
|
||||
output.innerHTML = '<h3>Random:</h3>' + entriesToStr('.full', [idx]);
|
||||
output.firstElementChild.className += ' single';
|
||||
output.lastElementChild.className += ' single';
|
||||
output.innerHTML += renderTemplate(getTemplate('.randomAction'), { $IDX: idx });
|
||||
|
||||
if (!plistServerUrl) {
|
||||
output.innerHTML += getTemplate('.no-itunes');
|
||||
return;
|
||||
}
|
||||
// Append iTunes info to result
|
||||
const redirectUrl = plistServerUrl + '?r='
|
||||
const iTunesUrl = 'https://itunes.apple.com/lookup?bundleId=' + entry.bundleId;
|
||||
loadFile(iTunesUrl, console.error, function (data) {
|
||||
loadFile(redirectUrl + iTunesUrl, console.error, function (data) {
|
||||
const obj = JSON.parse(data);
|
||||
if (!obj || obj.resultCount < 1) {
|
||||
output.innerHTML += '<p class="no-itunes">No iTunes results.</p>';
|
||||
return;
|
||||
}
|
||||
const info = obj.results[0];
|
||||
@@ -207,10 +212,10 @@ function randomIPA(specificId) {
|
||||
|
||||
var imgStr = '';
|
||||
if (imgs1 && imgs1.length > 0) {
|
||||
imgStr += '<p>iPhone Screenshots:</p>' + urlsToImgs(imgs1);
|
||||
imgStr += '<p>iPhone Screenshots:</p>' + urlsToImgs(redirectUrl, imgs1);
|
||||
}
|
||||
if (imgs2 && imgs2.length > 0) {
|
||||
imgStr += '<p>iPad Screenshots:</p>' + urlsToImgs(imgs2);
|
||||
imgStr += '<p>iPad Screenshots:</p>' + urlsToImgs(redirectUrl, imgs2);
|
||||
}
|
||||
|
||||
output.innerHTML += renderTemplate(getTemplate('.itunes'), {
|
||||
@@ -386,7 +391,7 @@ function setPlistGen() {
|
||||
alert('Server did not respond with a Plist file.');
|
||||
return;
|
||||
}
|
||||
plistGeneratorUrl = testURL;
|
||||
plistServerUrl = testURL;
|
||||
document.getElementById('overlay').hidden = true;
|
||||
saveConfig();
|
||||
});
|
||||
@@ -400,8 +405,8 @@ function utoa(data) {
|
||||
return btoa(unescape(encodeURIComponent(data)));
|
||||
}
|
||||
|
||||
function installIpa(idx) {
|
||||
if (!plistGeneratorUrl) {
|
||||
function installIPA(idx) {
|
||||
if (!plistServerUrl) {
|
||||
document.getElementById('overlay').hidden = false;
|
||||
return;
|
||||
}
|
||||
@@ -423,7 +428,7 @@ function installIpa(idx) {
|
||||
while (b64.slice(-1) === '=') {
|
||||
b64 = b64.slice(0, -1);
|
||||
}
|
||||
// window.open(plistGeneratorUrl + '?d=' + b64);
|
||||
const plistUrl = plistGeneratorUrl + '%3Fd%3D' + b64; // url encoded "?d="
|
||||
// window.open(plistServerUrl + '?d=' + b64);
|
||||
const plistUrl = plistServerUrl + '%3Fd%3D' + b64; // url encoded "?d="
|
||||
window.open('itms-services://?action=download-manifest&url=' + plistUrl);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ h4 {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.itunes {
|
||||
max-width: 600px;
|
||||
max-width: 650px;
|
||||
margin: 40px auto;
|
||||
}
|
||||
.carousel {
|
||||
@@ -99,6 +99,10 @@ h4 {
|
||||
.itunes p {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.no-itunes {
|
||||
color: #777;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.shortpage {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
from urllib.request import urlopen
|
||||
from base64 import b64decode
|
||||
import socket
|
||||
import json
|
||||
@@ -24,20 +25,38 @@ def generatePlist(data: dict) -> str:
|
||||
|
||||
|
||||
class PlistServer(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
try:
|
||||
b64 = self.path.split('?d=')[-1] + '=='
|
||||
data = json.loads(b64decode(b64)) # type: dict
|
||||
rv = generatePlist(data)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
rv = ''
|
||||
def makeHeader(self, contentType):
|
||||
self.send_response(200)
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
if rv:
|
||||
self.send_header('Content-type', 'application/xml')
|
||||
if contentType:
|
||||
self.send_header('Content-type', contentType)
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes(rv, 'utf-8') if rv else b'Parsing error')
|
||||
|
||||
def do_GET(self):
|
||||
try:
|
||||
action, value = self.path.split('?', 1)[-1].split('=', 1)
|
||||
if action == 'r':
|
||||
# http.client.HTTPResponse
|
||||
with urlopen(value) as response:
|
||||
mimeType = response.headers.get('Content-Type')
|
||||
self.makeHeader(mimeType)
|
||||
|
||||
while True:
|
||||
tmp = response.read(8096)
|
||||
if not tmp:
|
||||
break
|
||||
self.wfile.write(tmp)
|
||||
|
||||
elif action == 'd':
|
||||
data = json.loads(b64decode(value + '==')) # type: dict
|
||||
rv = bytes(generatePlist(data), 'utf-8')
|
||||
self.makeHeader('application/xml')
|
||||
self.wfile.write(rv)
|
||||
|
||||
else:
|
||||
return
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
def getLocalIp():
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<?php
|
||||
$X = json_decode(base64_decode($_GET['d']));
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
if ($_GET['r']) {
|
||||
echo stream_get_contents(fopen($_GET['r'], "rb"));
|
||||
} elseif ($_GET['d']) {
|
||||
$X = json_decode(base64_decode($_GET['d']));
|
||||
if ($X->u) {
|
||||
header('Content-Type: application/xml');
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -21,4 +24,7 @@ if ($X->u) {
|
||||
} else {
|
||||
echo 'Parsing error.';
|
||||
}
|
||||
} else {
|
||||
echo 'Error.';
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user