Skip to content

Instantly share code, notes, and snippets.

@MarcosBL
Last active June 13, 2020 22:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save MarcosBL/556ba1d1d833e35de1f7a7d75cb317cc to your computer and use it in GitHub Desktop.
Save MarcosBL/556ba1d1d833e35de1f7a7d75cb317cc to your computer and use it in GitHub Desktop.
Hack rápido para generar un buscador client-side a partir de una cuenta de Google Drive
<?php
$cuenta_rclone = 'conjunto:';
if (php_sapi_name() === 'cli') {
$exclude = ["Trash", "borrar", "Roms", "System "];
$exclude = implode("|", $exclude);
$files = glob("./*.tmp");
foreach ($files as $file) { unlink($file);}
$listing = array_map('ltrim', explode("\n", trim(`rclone lsd $cuenta_rclone`, "\n")) );
$listing = array_map(function($val) { return ltrim(end(explode(' -1 ', $val))); }, $listing);
$colecciones = [];
foreach($listing as $list) {
if ( (strpos($exclude, $list) !== false) ) {
}
else
{
$colecciones[$list] = trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $list));
}
}
foreach($colecciones as $index => $coleccion) {
echo "Procesando ".$index."\n";
$cmd = "rclone lsjson -R --no-mimetype --no-modtime --exclude *.nfo --exclude *.jpg --exclude *.png '".$cuenta_rclone.$index."' > ".$coleccion.".tmp";
$salida = `$cmd`;
$content = json_decode(file_get_contents($coleccion.".tmp"));
file_put_contents($coleccion.'.json',"[\n");
foreach($content as $index => $line) {
$parent = trim(str_replace($line->Name, "", $line->Path), '/');
$parent = ($parent != "") ? $parent : "#";
$sizeGb = ($line->Size > 1) ? ' ('.number_format($line->Size / 1024 / 1024 / 1024, 2).' Gb)' : '';
$newline = json_encode([
"text" => $line->Name.$sizeGb,
"id" => $line->Path,
"parent" => $parent
]);
$coma = ($index +1 == sizeof($content)) ? "" : ",";
file_put_contents($coleccion.'.json', $newline.$coma."\n", FILE_APPEND);
}
file_put_contents($coleccion.'.json',"]", FILE_APPEND);
unlink($coleccion.".tmp");
}
die();
}
?>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>-C-</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.9/jstree.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.9/themes/default/style.min.css" />
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jstree-bootstrap-theme@1.0.1/dist/themes/proton/style.min.css">
<style>
body { font-family: 'Roboto', sans-serif; }
#container { font-size:1.5em; width: 100%; margin:0em auto 0em auto; text-align:center; position:fixed; top:0em; padding:0.5em 0 0 0; background-color: #fff; border-bottom: 2px dashed #ccc; z-index: 1; }
#busca, #coleccion { font-size:1.1em; margin:0em auto 0em auto; display:inline-block; padding:4px; border-radius:4px; background-color:#f5f5f5; border:1px solid silver; text-align:center }
#status { margin:0.5em auto 0.5em auto; color:#888; text-align:center }
#clipboard { width:10px; height:10px; position:absolute; top:-100px; }
#jstree { text-align:left; margin-top:8em; }
.jstree-leaf > .jstree-anchor > .jstree-themeicon { background:url("https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.9/themes/default/32px.png") -100px -68px no-repeat !important; }
.jstree-default .jstree-search {
font-style: normal !important;
color: #00318b !important;
}
@media only screen and (max-width: 768px) {
#jstree { margin-top: 10em; }
}
@media only screen and (max-width: 420px) {
#jstree { margin-top: 12em; }
}
</style>
</head>
<body>
<div id="container">
Buscar en
<select id="coleccion">
<?php
foreach (glob("./*.json") as $file) {
$partes_ruta = pathinfo($file);
if(!isset($first)) { $first = $partes_ruta["basename"]; }
echo "<option value='".$partes_ruta["basename"]."'>".ucwords(str_replace("-", " ", $partes_ruta["filename"]))."</option>";
}
?>
</select>
esto:
<input type="text" id="busca" value="" autofocus>
<div id="status">En espera</div>
<input type="text" id="clipboard" value="" readonly/>
</div>
<div id="jstree"></div>
<script>
var minLength = 4;
var treeInstance = $('#jstree').jstree({
"core" : {
"worker" : false,
"check_callback": true,
"dblclick_toggle": true,
"animation" : 0,
"strings" : {"Loading ..." : "Cargando nodos ..."},
"themes" : {
"name" : "proton",
"responsive" : "true",
"stripes" : "true"
},
'data' : {'url' : '<?php echo $first; ?>' }
},
"search" : {
show_only_matches : true,
show_only_matches_children : true,
case_sensitive : false,
fuzzy : false,
},
"plugins" : [
"search", "sort", "wholerow"
]
});
treeInstance.on("search.jstree", function (e, data) {
$("#status").html("Encontrados " + data.res.length + " elementos para <b>'" + data.str + "'</b>");
});
treeInstance.on("dblclick.jstree", function (event) {
var node = $("#jstree").jstree().get_selected(true);
var data= node[0];
if(data.children_d.length) {
var newText = data.original.text + " - " + data.children_d.length + " elementos";
window.setTimeout( function() {$('#jstree').jstree('rename_node', node, newText); }, 100);
}
var path = '"/' + $("#coleccion option:selected").html() + "/" + data.id + '"';
$("#status").html("Copiado: " + path);
$("#clipboard").val(path).select();
window.setTimeout( function() { document.execCommand("copy"); }, 100);
});
var to = false;
$('#busca').keyup(function () {
var q = $("#busca").val();
$("#status").html("Escribiendo búsqueda, mínimo de " + minLength + " caracteres...");
if(q.length == 0) { $('#jstree').jstree("clear_search"); $("#status").html("En espera"); }
if(to) { clearTimeout(to); }
if(q.length >= minLength) {
to = setTimeout(function () {
$("#status").html("Buscando...");
setTimeout(function() {
$('#jstree').jstree("search", $('#busca').val());
}, 200);
}, 1000);
}
});
$('#coleccion').change(function() {
$('#jstree').jstree(true).settings.core.data = {'url' : $('#coleccion').val() };
$('#jstree').jstree(true).refresh();
$("#busca").val('').focus();
});
</script>
</body>
</html>

Instalación

Hay que poner el código de este index.php en una ruta accesible por el servidor web, que debe soportar php, obviamente. Si por ejemplo lo metemos en una carpetaa /var/www/html/drive debe ser accesible desde http://tu_dominio_o_ip/drive

Además, necesitaremos una versión bastante reciente de rclone, podemos descargarla de https://rclone.org/downloads/

Estas instrucciones son para Linux, pero cualquiera con manejo suelto en windows podrá hacerlo funcionar sin problema.

Configuración

Lo primero es sustituir conjunto: por el nombre de tu configuración rclone. Se refiere esto al nombre de la misma, no es necesario que la configuración esté montada con rclone mount

Alimentación de datos

Eso en si mismo solo sirve los datos que se hayan cacheado previamente, debemos hacer que lea el contenido de nuestro drive de forma regular corriendo el programa de cache, que es el propio index.php.

Para hacerlo manualmente la primera vez, podemos correr simplemente cd /var/www/html/drive && php index.php

Esto generará unos ficheros carpeta.json, uno por cada carpeta raiz, dentro de la carpeta principal, que nos servirán para filtrar luego el contenido en la interface web. Si queremos excluir alguna carpeta porque tarde demasiado, darle un ojo a la linea $exclude = ["Trash", "borrar", "Roms", "System "]; y añadir ahí carpetas a excluir en ese listado.

Cuando el proceso de indexado termine, ya podremos usar la interface web.

Refresco automático

No querremos estar todo el santo día refrescando los datos manualmente, para evitarlo, programaremos en el crontabde cualquier usuario con acceso a php y permisos de escritura en la carpeta /var/www/html/drive esta linea:

# Actualiza el listado del buscador de gdrive
*/15	*	*	*	*	cd /var/www/html; /usr/bin/php index.php

Y eso es todo, ya podremos usar nuestro buscador:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment