Files

353 lines
14 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Route Explorer Pro</title>
<style>
body { font-family: sans-serif; background: #1a1a1a; color: #e0e0e0; padding: 15px; line-height: 1.4; }
.container { max-width: 900px; margin: auto; background: #2a2a2a; padding: 20px; border-radius: 8px; box-shadow: 0 4px 10px rgba(0,0,0,0.5); }
label { display: block; margin-bottom: 5px; font-weight: bold; color: #4dabf7; font-size: 0.9em; }
select, input[type="text"] { width: 100%; padding: 12px; margin-bottom: 15px; border-radius: 4px; border: 1px solid #444; background: #333; color: white; box-sizing: border-box; }
.checkbox-group { display: flex; gap: 15px; margin-bottom: 15px; }
.checkbox-container { display: flex; align-items: center; background: #383838; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 0.85em; flex: 1; }
.checkbox-container input { margin-right: 8px; }
.breadcrumb { background: #111; padding: 10px; border-radius: 4px; margin-bottom: 1px; font-family: monospace; font-size: 0.85em; color: #888; border-bottom: 1px solid #333; }
.breadcrumb span { color: #4dabf7; cursor: pointer; font-weight: bold; }
#pathList { max-height: 450px; overflow-y: auto; border: 1px solid #444; background: #222; border-radius: 0 0 4px 4px; }
.path-row { display: flex; align-items: center; border-bottom: 1px solid #333; }
.path-row:hover { background: #2d2d2d; }
.path-name { flex-grow: 1; padding: 12px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.9em; }
.btn-target { padding: 12px 18px; cursor: pointer; background: #333; color: #fab005; border: none; border-left: 1px solid #444; font-size: 1.1em; }
.btn-target:hover { background: #fab005; color: #000; }
.is-file { color: #bbb; }
.is-folder { color: #4dabf7; font-weight: 500; }
.output-box { background: #000; border-left: 4px solid #fab005; padding: 15px; margin-top: 15px; word-break: break-all; font-family: monospace; font-size: 0.85em; color: #0f0; }
.hidden { display: none; }
.button-group { display: flex; gap: 10px; margin-top: 10px; }
.btn-ui { padding: 14px; font-weight: bold; border-radius: 4px; text-decoration: none; text-align: center; flex: 1; color: black; font-family: sans-serif; border: none; font-size: 1em; cursor: pointer;}
.btn-copy { background: #a5d8ff; }
.btn-send { background: #fab005; }
#intentLinkContainer { margin-top: 15px; text-align: center; padding: 10px; background: #111; border: 1px dashed #444; border-radius: 4px; }
#intentLink { color: #fab005; font-family: monospace; font-weight: bold; text-decoration: underline; font-size: 1.1em; }
.searching-hint { font-size: 0.7em; color: #fab005; float: right; margin-top: -10px; margin-bottom: 5px; }
</style>
</head>
<body>
<div class="container">
<label>Route Configuration:</label>
<select id="routePicker"><option value="">-- Select Device/Route --</option></select>
<div id="explorerSection" class="hidden">
<input type="text" id="searchBar" placeholder="Search... (waits for you to stop typing)">
<div id="searchHint" class="searching-hint hidden">Typing...</div>
<div class="checkbox-group">
<label class="checkbox-container"><input type="checkbox" id="stripFileToggle" checked> Strip Filename</label>
<label class="checkbox-container"><input type="checkbox" id="urlEncodeToggle"> Tasker Encode</label>
</div>
<div class="breadcrumb" id="breadcrumb">Root</div>
<div id="pathList"></div>
</div>
<div id="outputSection" class="hidden">
<div id="commandOutput" class="output-box"></div>
<div class="button-group">
<button class="btn-ui btn-copy" onclick="copyToClipboard()">COPY ADB</button>
<button id="sendBtn" class="btn-ui btn-send" onclick="handleSendToTasker()">SEND TO TASKER</button>
</div>
<div id="intentLinkContainer" class="hidden">
<a id="intentLink" href="tasker://IntentReceive">IntentSend</a>
</div>
</div>
</div>
<script>
const ROUTES_FILE = 'routes.txt';
let routeData = {};
let masterPathList = [];
let currentDir = "";
let searchTimer;
async function init() {
try {
const res = await fetch(ROUTES_FILE);
const text = await res.text();
const lines = text.split('\n').map(l => l.trim()).filter(l => l !== "");
const picker = document.getElementById('routePicker');
for (let i = 0; i < lines.length; i += 2) {
routeData[lines[i]] = lines[i+1];
picker.add(new Option(lines[i], lines[i]));
}
} catch (e) { console.error("Initialization failed"); }
}
document.getElementById('routePicker').onchange = async (e) => {
if (!e.target.value) return;
const res = await fetch(`${e.target.value}.txt`);
const text = await res.text();
masterPathList = text.split('\n').map(l => l.trim()).filter(l => l !== "");
currentDir = "";
document.getElementById('explorerSection').classList.remove('hidden');
renderExplorer();
};
document.getElementById('searchBar').addEventListener('input', () => {
const hint = document.getElementById('searchHint');
hint.classList.remove('hidden');
clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
hint.classList.add('hidden');
renderExplorer();
}, 400);
});
function renderExplorer() {
const listDiv = document.getElementById('pathList');
const searchTerm = document.getElementById('searchBar').value.toLowerCase();
listDiv.innerHTML = '';
const bc = document.getElementById('breadcrumb');
bc.innerHTML = `<span onclick="navigate('')">Root</span> ${currentDir ? ' / ' + currentDir.split('/').map((seg, i, arr) => `<span onclick="navigate('${arr.slice(0,i+1).join('/')}')">${seg}</span>`).join(' / ') : ''}`;
let itemsToDisplay = [];
if (searchTerm) {
itemsToDisplay = masterPathList
.filter(p => p.toLowerCase().includes(searchTerm))
.slice(0, 200)
.map(p => ({ path: p, isSearch: true }));
} else {
const children = new Set();
masterPathList.forEach(p => {
if (currentDir === "") {
children.add(p.split('/')[0]);
} else if (p.startsWith(currentDir + '/')) {
const relative = p.substring(currentDir.length + 1);
children.add(relative.split('/')[0]);
}
});
itemsToDisplay = Array.from(children).sort().map(name => ({
path: currentDir ? `${currentDir}/${name}` : name,
isSearch: false,
displayName: name
}));
}
const fragment = document.createDocumentFragment();
itemsToDisplay.forEach(item => {
const isFolder = masterPathList.some(p => p.startsWith(item.path + '/'));
const display = item.isSearch ? item.path : item.displayName;
const row = document.createElement('div');
row.className = 'path-row';
const nameSpan = document.createElement('span');
nameSpan.className = `path-name ${isFolder ? 'is-folder' : 'is-file'}`;
nameSpan.textContent = (isFolder ? '📁 ' : '📄 ') + display;
nameSpan.onclick = () => {
if (item.isSearch) {
document.getElementById('searchBar').value = '';
navigate(isFolder ? item.path : item.path.substring(0, item.path.lastIndexOf('/')));
} else {
if (isFolder) navigate(item.path); else selectPath(item.path);
}
};
const targetBtn = document.createElement('button');
targetBtn.className = 'btn-target';
targetBtn.innerHTML = '🎯';
targetBtn.onclick = (e) => {
e.stopPropagation();
selectPath(item.path);
};
row.appendChild(nameSpan);
row.appendChild(targetBtn);
fragment.appendChild(row);
});
listDiv.appendChild(fragment);
}
function navigate(path) {
currentDir = path;
renderExplorer();
}
document.getElementById('stripFileToggle').onchange = () => updateOutput(window.lastPath);
document.getElementById('urlEncodeToggle').onchange = () => updateOutput(window.lastPath);
function selectPath(path) {
window.lastPath = path;
updateOutput(path);
document.getElementById('outputSection').classList.remove('hidden');
}
function updateOutput(path) {
if (!path) return;
let p = path;
if (document.getElementById('stripFileToggle').checked) {
if (p.includes('/') && !masterPathList.some(full => full.startsWith(p + '/'))) {
p = p.substring(0, p.lastIndexOf('/'));
}
}
const routeName = document.getElementById('routePicker').value;
const cmd = routeData[routeName].replace('$path', p);
document.getElementById('commandOutput').textContent = cmd;
// Hide the intent link when path changes so it only appears on press
document.getElementById('intentLinkContainer').classList.add('hidden');
}
async function handleSendToTasker() {
const cmd = document.getElementById('commandOutput').textContent;
if (!cmd) return;
// 1. Copy text to clipboard
try {
await navigator.clipboard.writeText(cmd);
const btn = document.getElementById('sendBtn');
const originalText = btn.textContent;
btn.textContent = "COPIED & SENT!";
setTimeout(() => btn.textContent = originalText, 1500);
} catch (err) { console.error('Clip error', err); }
// 2. Send text to PHP script
const phpUrl = `https://alceawis.de/other/extra/scripts/fakesocialmedia/clip.php?clip=${encodeURIComponent(cmd)}`;
fetch(phpUrl, { mode: 'no-cors' }).catch(e => console.log("PHP Notify Handled"));
// 3. Make IntentSend URL appear
document.getElementById('intentLinkContainer').classList.remove('hidden');
}
function copyToClipboard() {
navigator.clipboard.writeText(document.getElementById('commandOutput').textContent);
const btn = document.querySelector('.btn-copy');
btn.textContent = "COPIED!";
setTimeout(() => btn.textContent = "COPY ADB", 1500);
}
init();
</script>
<details><summary>PrerequisiteForSelfHost</summary><pre>
clip.php
---------
&lt;?php
if (isset($_POST['send'])) {
$content = $_POST['send'];
}
elseif (isset($_GET['clip'])) {
$content = $_GET['clip'];
}
else {
exit("No content provided.");
}
file_put_contents('clip.txt', $content);
echo "Content saved to 'clip.txt'.";
exit;
?&gt;
&lt;?php
if (isset($_POST['send'])) {
$content = $_POST['send'];
file_put_contents('clip.txt', $content);
}
exit;
?&gt;
IntentReceive.xml.tsk
---------------------
&lt;TaskerData sr="" dvi="1" tv="4.9u4m"&gt;
&lt;Task sr="task14"&gt;
&lt;cdate&gt;1767128445686&lt;/cdate&gt;
&lt;edate&gt;1767129026350&lt;/edate&gt;
&lt;id&gt;14&lt;/id&gt;
&lt;nme&gt;IntentReceive&lt;/nme&gt;
&lt;pri&gt;100&lt;/pri&gt;
&lt;Action sr="act0" ve="7"&gt;
&lt;code&gt;123&lt;/code&gt;
&lt;on&gt;false&lt;/on&gt;
&lt;Str sr="arg0" ve="3"&gt;sh /sdcard/exec/intentreceive.sh&lt;/Str&gt;
&lt;Int sr="arg1" val="0"/&gt;
&lt;Int sr="arg2" val="0"/&gt;
&lt;Str sr="arg3" ve="3"/&gt;
&lt;Str sr="arg4" ve="3"/&gt;
&lt;Str sr="arg5" ve="3"/&gt;
&lt;/Action&gt;
&lt;Action sr="act1" ve="7"&gt;
&lt;code&gt;123&lt;/code&gt;
&lt;Str sr="arg0" ve="3"&gt;#!/bin/bash
# URL of the script
SCRIPT_URL="https&#58;//alceawis.de/other/extra/scripts/fakesocialmedia/clip.txt"
# Fetch the script into a variable
SCRIPT=$(curl -fsSL "$SCRIPT_URL")
# Check if the script was successfully downloaded
if [ -n "$SCRIPT" ]; then
echo "Script content (flashed)&#58;"
echo "$SCRIPT" # "Flash" the content directly to the terminal
# Execute the command using su -c (with root privileges)
su -c "$SCRIPT"
else
echo "Failed to download script or script is empty."
fi&lt;/Str&gt;
&lt;Int sr="arg1" val="0"/&gt;
&lt;Int sr="arg2" val="0"/&gt;
&lt;Str sr="arg3" ve="3"/&gt;
&lt;Str sr="arg4" ve="3"/&gt;
&lt;Str sr="arg5" ve="3"/&gt;
&lt;/Action&gt;
&lt;/Task&gt;
&lt;/TaskerData&gt;
apk:
https://m.apkpure.com/tasker-url-launcher/com.aledthomas.taskerurllauncher
https://alceawis.de/other/extra/scripts/fakesocialmedia/commentload.html?number=80000&text=Oh%20nice%20%0D%0Ahttps%3A%2F%2Fm.apkpure.com%2Ftasker-url-launcher%2Fcom.aled
routes.txt
__________
sdcard
am start -a nextapp.fx.intent.action.OPEN_LOCAL -n nextapp.fx/.ui.ExplorerActivity --es "nextapp.fx.intent.extra.PATH" "$path" -f 0x10000000
microsd
am start -a nextapp.fx.intent.action.OPEN_LOCAL -n nextapp.fx/.ui.ExplorerActivity --es "nextapp.fx.intent.extra.PATH" "/storage/4041-393D/$path" -f 0x10000000
alceawis.de
am start -a nextapp.fx.intent.action.OPEN_NETWORK -n nextapp.fx/.ui.ExplorerActivity --es "nextapp.fx.intent.extra.HOST" "27" --es "nextapp.fx.intent.extra.PATH" "/path" -f 0x10000000
m7350
am start -a nextapp.fx.intent.action.OPEN_NETWORK -n nextapp.fx/.ui.ExplorerActivity --es "nextapp.fx.intent.extra.HOST" "25" --es "nextapp.fx.intent.extra.PATH" "/$path" -f 0x10000000
</pre>
</details>
</body>
</html>