feat: iTunes redirect

This commit is contained in:
relikd
2024-02-29 22:36:35 +01:00
parent a0033f28c5
commit bcdbaaf399
5 changed files with 70 additions and 32 deletions

View File

@@ -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>

View File

@@ -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);
} }

View File

@@ -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 {

View File

@@ -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():

View File

@@ -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.';
} }
?> ?>