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