2016-11-12

Ikea hacking

Un zapatero para el pasillo construido a base de "estrechar" una estantería "tomnas" (de las pequeñas) hasta que sólo tenga 17cm de profundidad, incorporándole unas puertas "kallax" que, también fue necesario adaptar.

El resultado:




El mueble original, mucho más profundo (35cm):
Y unas puertas de estas:


2016-08-24

2016-08-16

2016-07-13

Raspberry pi como adaptador de wifi a ethernet

O "cómo configurar una raspberry pi para que se conecte a una red wifi (empresarial, en mi caso) a la que redirija el tráfico de su puerto ethernet"

El artículo que lo explica todo es este: WiFi to ethernet adapter for an ethernet-ready TV, yo estoy en una situación similar aunque no lo hice todo exactamente igual.

primero: configurar el fichero /etc/network/interfaces para que la interface eth0 (el puerto ethernet) tenga una ip fija, que será la que nos sirva para crear una mini-red interna con los dispositivos que queramos. En mi caso quedó así:
allow-hotplug eth0
iface eth0 inet static
  address 192.168.2.1
  network 192.168.2.0
  netmask 255.255.255.0
  broadcast 192.168.2.255
  gateway 192.168.2.1

[update 2017-08-24] en las nuevas versiones de raspbian para especificar una ip fija ya no se modifica el fichero /etc/network/interfaces sino que se modifica el fichero /etc/dhcpcd.conf
interface eth0
static ip_address=192.168.2.1/24
static routers=192.168.2.1
static domain_name_servers=192.168.2.1

También hay que deshabilitar los "Predictable Network Interface Names" metiendo net.ifnames=0 en el el /boot/cmdline.txt

Como todo es tan diferente, finalmente optamos por deshabilitar todo este sistema nuevo haciendo
sudo systemctl disable dhcpcd
sudo systemctl enable networking

segundo: conectarse a la wifi. En mi caso es una wifi empresarial, así que hay que configurar el fichero /etc/wpa_supplicant/wpa_supplicant.conf de forma similar a esto:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=ES
eapol_version=1
ap_scan=1
fast_reauth=1
network={
 ssid="unaRRedCualquieRa"
 scan_ssid=1
 key_mgmt=WPA-EAP
 proto=WPA
 eap=TTLS
 pairwise=CCMP
 identity="usuario"
 password="password"
 priority=1
 phase2="auth=PAP"
}

tercero: reiniciar (o usar ifdown e ifup en cada interface) y comprobar que las dos redes están correctamente conectadas usando, por ejemplo, el comando ifconfig. Yo aquí lo que hago es conectarme por el puerto ethernet con una ip fija y demás.

cuarto: conectar una red con otra utilizando "iptables". Primero reseteamos las iptables con este script:
#!/bin/sh
 IPTABLES="$(which iptables)"
# RESET DEFAULT POLICIES
 $IPTABLES -P INPUT ACCEPT
 $IPTABLES -P FORWARD ACCEPT
 $IPTABLES -P OUTPUT ACCEPT
 $IPTABLES -t nat -P PREROUTING ACCEPT
 $IPTABLES -t nat -P POSTROUTING ACCEPT
 $IPTABLES -t nat -P OUTPUT ACCEPT
 $IPTABLES -t mangle -P PREROUTING ACCEPT
 $IPTABLES -t mangle -P OUTPUT ACCEPT
# FLUSH ALL RULES, ERASE NON-DEFAULT CHAINS
 $IPTABLES -F
 $IPTABLES -X
 $IPTABLES -t nat -F
 $IPTABLES -t nat -X
 $IPTABLES -t mangle -F
 $IPTABLES -t mangle -X

quinto: creamos las reglas necesarias para hacer forwarding y NAT desde la red ethernet a la red wifi. En mi caso esto consiste en ejecutar estos dos comandos:
sudo iptables -A FORWARD --in-interface eth0 -j ACCEPT
sudo iptables --table nat -A POSTROUTING --out-interface wlan0 -j MASQUERADE

Ahora nos guardamos las reglas en un fichero llamado "iptables":
sudo iptables-save > /etc/network/iptables

y metemos esto al final del /etc/network/interfaces :
pre-up iptables-restore < /etc/network/iptables

sexto: habilitar el ip forwarding en el kernel descomentando en el fichero /etc/sysctl.conf esta línea:
#net.ipv4.ip_forward=1
luego ejecutamos sudo sysctl --system para que el cambio sea efectivo.

septimo: arreglar la tabla de enrutado del kernel, con este script:
#/etc/init.d/setuproutes
#
### BEGIN INIT INFO
# Provides: default routes for wlan0
# Required-Start: $syslog $network
# Required-Stop: $syslog
# Should-Start:
# Should-Stop:
# X-Start-Before:
# X-Stop-After:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: false
# Short-Description: adjust default routes
# Description: removes default route 192.168.2.1 adds default route 192.168.1.1
### END INIT INFO
sudo route del default gw 192.168.2.1 eth0
# sudo route add default gw 192.168.1.1 wlan0
exit 0
#!/bin/sh

que deberemos copiar en /etc/init.d y activar con este comando:
sudo update-rc.d setuproutes defaults

octavo: añadir un servicio de DHCP para la nueva minired 192.168.2.0
$ sudo apt-get install isc-dhcp-server
$ sudo mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.orig
$ sudo vim /etc/dhcp/dhcpd.conf
y le metemos este contenido
#
# Configuration file for ISC dhcpd for Debian
#
#
ddns-update-style none;
option domain-name "rbn.local";
option domain-name-servers 192.168.1.1;
default-lease-time 600;
max-lease-time 7200;
authoritative;
log-facility local7;

#configure service for network 192.168.2.0 (the ethernet port)
subnet 192.168.2.0 netmask 255.255.255.0 { 
 range 192.168.2.10 192.168.2.50;
 option routers 192.168.2.1;
}
y ejecutamos
$ sudo service isc-dhcp-server restart

2016-06-10

La libertad de expresión, atacada


Esta es una traducción no oficial (y seguramente imperfecta) del artículo "free speech under attack" de The Economist. Si puedes, mejor léelo en su versión original.

Los límites a la libertad de expresión se están intensificando, es hora de manifestarnos.

En cierto sentido, esta es una época dorada para la libertad de expresión. Tu móvil puede contactar con periódicos del otro lado del mundo en segundos. Más de mil millones de tweets, publicaciones en Facebook y actualizaciones de blogs se publican cada día. Cualquiera con acceso a internet puede ser un editor y cualquiera que pueda entrar en la Wikipedia accede a un paraíso digital donde la primera enmienda americana es soberana.

Sin embargo hay guardianes que informan de que manifestarse se está volviendo más peligroso - y tienen razón. Como muestra nuestro informe los límites a la libertad de expresión han aumentado. Sin la libre competencia de ideas el mundo se vuelve tímido e ignorante.

La libertad de expresión está siendo atacada de tres formas. Primero, la represión gubernamental se ha incrementado. Varios países han reinstaurado controles procedentes de la guerra fría o han implantado otros nuevos. Después del colapso de la Unión Soviética, Rusia disfrutó de un período de libres e intensos debates. Bajo el gobierno de Vladimir Putin la mordaza se ha intensificado de nuevo. Todos los canales televisivos de noticias están ahora controlados por el estado o por los secuaces de Putin. A los periodistas que hace preguntas incómodas ya no se les envía a campos de trabajo, pero varios han sido asesinados.

El líder chino, Xi Jinping, emprendió una represión tras su llegada al poder en 2012 reforzando la censura de las redes sociales, arrestando cientos de disidentes y reemplazando el debate liberal en las universidades con Marxismo extra. En Oriente Medio el derrocamiento de déspotas durante la primavera árabe permitió a la gente hablar libremente por primera vez en generaciones. Esto ha durado en Túnez, pero Siria y Libia son más peligrosos para los periodistas de lo que lo eran antes de los levantamientos; y Egipto está gobernado por un hombre que dice, sin inmutarse, "no escuchéis a nadie más que a mí".

Palabras, palos y piedras

En segundo lugar, un preocupante número de actores no gubernamentales están aplicando la censura mediante el homicidio. Reporteros en México que investigan crímenes o corrupción a menudo son asesinados, en ocasiones tras ser torturados. Los Yihadistas sacrifican a aquellos que a su juicio han insultado su fé. Cuando los autores y artistas dicen cualquier cosa que pueda ser considerada irrespetuosa con el Islam, están poniéndose en riesgo. Los blogueros laicos de Bangladesh son atacados a machetazos en la calle (ver artículo). Dibujantes franceses son tiroteados en sus oficinas. Los yihadistas atacan a los musulmanes más que a cualquier otro, en particular para ponerles más difícil entablar una discusión honesta sobre cómo organizar su sociedad.

En tercer lugar, se ha extendido la idea de que las personas y los grupos tienen derecho a no ser ofendidos. Esto puede sonar inocuo: la educación es una virtud, después de todo, pero si yo tengo derecho a no ser ofendido eso significa que alguien debe controlar lo que dices sobre mí, o sobre las cosas que yo estimo, como mi grupo étnico, religión o incluso mis ideas políticas. Dado que la ofensa es subjetiva, el poder del que controla es tanto amplio como arbitrario.

No obstante, muchos estudiantes en América y Europa creen que alguien debería ejercerlo. Algunos se rinden ante el absolutismo de las políticas identitarias argumentando que los hombres no tienen derecho a hablar de feminismo o que los blancos no pueden hablar sobre la esclavitud. Otros han impedido a oradores reflexivos y bien conocidos como Condoleezza Rice y Ayaan Hirsi Ali que hablaran en la universidad (ver artículo).

La preocupación por las víctimas de la discriminación es loable. Y las protestas estudiantiles son, a menudo un acto de libertad de expresión en sí mismas, pero la universidad es un lugar donde los estudiantes debe, supuestamente, aprender a pensar. Esa misión es imposible si las ideas poco cómodas están prohibidas. Y las protestas pueden derivar fácilmente en el preciosismo: la universidad de California, por ejemplo, sugiere que es una "micro-agresión" racista decir que "América es una tierra de oportunidad", porque se podría considerar que implica que los que no tienen éxito sólo se pueden culpar a sí mismos.

La verdad incómoda

La intolerancia entre los liberales occidentales también tiene consecuencias completamente imprevistas. Incluso los déspotas saben que está mal visto encerrar a los disidentes bocazas pero no violentos. Casi todos los países tienen leyes que protegen la libertad de expresión, así que los gobiernos autoritarios están siempre buscando excusas de apariencia respetable para pisotearlas. La seguridad nacional es una de ellas. Rusia recientemente sentenció a Vadim Tyumentsev, un bloguero, a cinco años de prisión por promover el "extremismo", después de que criticara las políticas rusas en Ucrania. La "incitación al odio" es otra de ellas: China encierra a los partidarios de la independencia del Tibet por "incitar al odio étnico", Arabia Saudita azota a los blasfemos, los indios pueden ser encerrados en prisión durante tres años por promover la discordia de carácter religioso, raza, casta... o cualquier otro carácter cualquiera.

La amenaza a la libertad de expresión en las universidades occidentales es muy diferente de aquella a la que se enfrentan los ateos en Afganistán o los demócratas en China, pero cuando los intelectuales progresistas acuerdan que las palabras ofensivas deben ser censuradas eso ayuda a los regímenes autoritarios a justificar sus propias, aunque más duras, restricciones y a los grupos religiosos intolerantes su violencia. Cuando los defensores de los derechos humanos se quejan de lo que pasa bajo esos gobiernos opresores los déspotas señalan que las democracias liberales como Francia o España también criminalidad aquellos que "glorifican" o "defienden" el terrorismo, y que muchos países occidentales consideran un delito insultar una religión o incitar a la violencia racista.

Un dictador que ha sido capaz de usar a su conveniencia la hipocresía occidental es Recep Tayyip Erdogan, presidente de Turquía. En su país no tolera insultos a su persona, religión o políticas. En el extranjero exige el mismo tratamiento, y en Alemania ha visto satisfechas sus demandas. En marzo un humorista alemán recitó un poema satírico sobre él "tirándose a cabras y oprimiendo minorías" (sólo los cargos más serios son ciertos). El señor Erdogan se acogió a una antigua y abandonada ley alemana que prohíbe insultar a jefes de estado extranjeros. Sorprendentemente la canciller alemana Angela Merkel ha permitido que el proceso judicial continúe. Aún más sorprendente es que nueve países europeos más aún tienen leyes similares, y 13 prohíben los insultos contra su propio jefe de estado.

Las encuestas revelan que en muchos países el apoyo a la libertad de expresión es tibio y condicional. Si las palabras generan enfado, la gente prefiere que el gobierno o alguna otra autoridad haga callar al que habla. Un grupo de países islámicos forman un lobby para conseguir que insultar a la religión sea un crimen según la legislación internacional. Tienen motivos para esperar tener éxito.

Por todo esto vale la pena señalar por qué la libertad de expresión es la piedra angular de todas las libertades. La libertad de expresión es la mejor defensa ante un mal gobierno. Los políticos que se equivocan (o sea, todos) deberían estar sometidos a la crítica sin restricciones. Aquellos que las oyen puede que las respondan, los que las silencian puede que nunca sepan cómo sus políticas salieron mal. Como la premio Nobel Amartya Sen ha señalado, ninguna democracia con libertad de prensa ha sido víctima de la hambruna jamás.

En todas las áreas de la vida el debate libre permite separar las buenas ideas de las malas. La ciencia no puede desarrollarse a menos que las viejas creencias sean puestas a prueba. Los tabúes son los enemigos del conocimiento. Cuando el gobierno chino ordena a los economistas ofrecer previsiones optimistas garantiza que sus propias políticas estén mal informadas. Cuando las facultades de ciencias sociales americanas contratan únicamente profesores de izquierdas sus investigaciones merecen ser tomadas menos en serio.

Las leyes contra la blasfemia son un anacronismo. La religion debería estar abierta a debate. Las leyes contra la incitación al odio son inevitablemente subjetivas y objeto de abuso. Prohibir palabras o argumentos que un grupo considera ofensivas no conduce a la armonía social; al contrario, le da a todo el mundo un incentivo para ofenderse -un hecho que los políticos oportunistas con apoyo étnico aprovechan rápidamente.

La incitación a la violencia debería ser prohibida. Sin embargo, debería ser bien definida de forma precisa como aquella en la que el orador pretende incitar a aquellos que están de acuerdo con él a cometer violencia, y cuando sus palabras tengan un probable efecto inmediato. Gritar "matemos a los judíos" a una multitud enfadada en el exterior de una sinagoga es un ejemplo válido. Publicar, estando borracho, "ojalá se murieran todos los judíos" en una escondida página de Facebook probablemente no lo sea. Decir algo ofensivo acerca de un grupo cuyos miembros, a continuación, inician disturbios violentos ciertamente no cuenta; hubieran debido contestar con palabras o simplemente ignorar al tonto que los ha insultado.

En países inestables como Ruanda o Burundi las palabras que incitan a la violencia diferirán de aquellas que lo harían en democracias estables, pero los principios son los mismos. La policía debería ocuparse de amenazas serias e inminentes, no arrestar a cada fanático con un portátil o un megáfono (los gobiernos de Ruanda y Burundi, por cierto, no muestran dicho autocontrol).

Areopagitica online

Facebook, Twitter y otros gigantes digitales deberían, como organizaciones privadas, ser libres de decidir qué permiten publicar en sus plataformas. Usando la misma lógica, una universidad privada debería tener libertad, hasta donde la ley lo permite, para implantar un código de expresión en sus estudiantes. Si no te gustan las normas de una universidad católica que prohíben las palabras malsonantes, la pornografía o expresar la no creencia en dios puedes ir a otro sitio cualquiera. Sin embargo cualquier universidad pública o cualquier universidad que aspire a ayudar a sus estudiantes a crecer intelectualmente debería tener como objetivo exponerlos a ideas retadoras. El mundo fuera del campus a menudo les ofenderá, deben aprender a responder usando protestas pacíficas, la retórica y la razón.

Estas son buenas reglas para cualquiera. Nunca intentar silenciar la visión con la que no estás de acuerdo. Contesta al discurso desagradable con más discurso. Gana la discusión sin recurrir a la fuerza. Y haz que tu piel sea más dura.




2016-03-19

2016-02-14

2016-02-06

usborne have made their 1980s computer programming books available as free downloads

Mike Atherton (@MikeAtherton) twitteó a las 6:35 p. m. on vie., feb. 05, 2016:
Wow. @usborne have made their 1980s computer programming books available as free downloads. https://t.co/PiBxpAyXZo https://t.co/cqaGTteCfG
(https://twitter.com/MikeAtherton/status/695662160261865472?s=09)

Obtén la aplicación oficial de Twitter en https://twitter.com/download?s=13

2015-10-31

Dando el paseito



Enviado desde mi smartphone BlackBerry 10.

2014-10-15

2014-08-15

Plex: Bajar subtítulos de los episodios "on deck"


El script con el que me bajo los subtítulos de los episodios "on deck" es este (yo lo llamo "subtitulosOnDeck.sh"):


# ruta de la b.d. de Plex Media Server
RUTABD="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db"

# ejecucion de la query en sqlite
cat queryFicherosOnDeckSubs.sql | sqlite3 "$RUTABD" 


# me bajo los subtitulos de todos los ficheros de la lista
while read unfichero; do

  # borro los subtitulos que haya...
  sinextension=${unfichero%.*}
  rm "$sinextension"*srt 

  subliminal -l en es -- "$unfichero"

done < "ficherosondecksubs.txt"


Explicación: la primera línea mete en la variable "RUTABD" la ruta de la b.d. de plex, que no es más que un fichero. Como es tan complicada la meto en una variable porque si no luego el comando no hay quien lo entienda.

La segunda línea ejecuta la query, que está en el fichero "queryFicherosOnDeckSubs.sql" enchufándosela al "sqlite3", que es el motor de base de datos que usa plex. La query genera un fichero que se llama "ficherosondecksubs.txt". Luego para cada línea de ese fichero, ejecuta "subliminal".

En la query aparecen las secciones que se tienen en cuenta en la línea 19. Si quieres que las tenga en cuenta todas, pues bastaría con eliminar las líneas 18 y 19. Si quieres tener en cuenta más secciones, basta con separarlas por comas, por ejemplo ("03 TVShows", "01 Series", "02 Peliculas")

Los dos ficheros, a continuación:




2014-07-27

2014-05-10

Popcorn Time

Para ver pelis en inglés.... muy bueno:

Popcorn Time - Download

2014-03-22

2013-12-19

Servidor casero (linux) de DNS y DHCP

Si tu router es una mierda, como el mío, aunque tenga DHCP no podrás hacer cosas como:

  • asignarle (centralizadamente) a cada máquina de la red la IP que me de la gana
  • asignarle a cada IP el nombre que me de la gana, porque no tiene DNS

Sin embargo, con un servidor linux y dnsmasq no puede ser más fácil:

Instalamos dnsmasq:

$ sudo apt-get install dnsmasq


Modificamos el fichero /etc/dnsmasq.conf (pongo sólo las líneas interesantes y sus comentarios correspondients):

# If you don't want dnsmasq to read /etc/resolv.conf or any other
# file, getting its servers from this file instead (see below), then
# uncomment this.
#
# Como prefiero tener cuantos menos ficheros mejor, configuraré los servidores
# DNS en este mismo fichero (los de Google, los de R, etc...)
no-resolv

# Add other name servers here, with domain specs if they are for
# non-public domains.
#server=/localnet/192.168.0.1
server=213.60.205.175
server=213.60.205.173
server=212.51.32.254
server=8.8.8.8

server=8.8.4.4

# Set this (and domain: see below) if you want to have a domain
# automatically added to simple names in a hosts-file.
# Creo que no hay otra forma de indicarle los nombres, cuando me interesa
# dárselos yo, van a ir en el fichero /etc/hosts

expand-hosts

# Set the domain for dnsmasq. this is optional, but if it is set, it
# does the following things.
# 1) Allows DHCP hosts to have fully qualified domain names, as long
#     as the domain part matches this setting.
# 2) Sets the "domain" DHCP option thereby potentially setting the
#    domain of all systems configured by DHCP
# 3) Provides the domain part for "expand-hosts"
# Los PCs de mi red local se van a llamar xxxx.LAN.local

domain=LAN.local

# Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and optionally
# a lease time. If you have more than one network, you will need to
# repeat this for each network on which you want to supply DHCP
# service.
# Este es el rango de IPs que el servidor va a asignar de forma dinámica

dhcp-range=10.0.1.11,10.0.1.99,12h

# Always allocate the host with Ethernet address 11:22:33:44:55:66
# The IP address 192.168.0.60
# Esta máquina va a tener siempre esta IP, por narices

dhcp-host=00:1F:F3:42:33:FF,10.0.1.2

# Override the default route supplied by dnsmasq, which assumes the
# router is the same machine as the one running dnsmasq.
# La ip de mi router (default gateway) es 10.0.1.1

dhcp-option=3,10.0.1.1


El fichero tiene millones de opciones, pero creo que con estas llega.

Luego sólo falta modificar el fichero /etc/hosts para forzar un nombre a aquellas máquinas que no lo tienen, o nos interesa darle uno por cualquier motivo. Por ejemplo:

127.0.0.1       localhost
10.0.1.10       miservidor
10.0.1.1        cablemodem


Las asignaciones dinámicas se almacenan (por defecto) en /var/lib/misc/dnsmasq.leases, ahí podemos mirar cómo está la cosa.









2013-12-04

2013-11-19

Actualizar Microserver a la ultima version de Ubuntu


No tuve muchos problemas. Así de memoria:

 - Para actualizar (a una ubuntu que no es LTS), las instrucciones están aquí: https://help.ubuntu.com/community/QuantalUpgrades
 - Luego ya te va diciendo él solito que hay versiones posteriores, y que tienes que ejecutar "do-release-upgrade"
 - al actualizar él solito quita el plex de /etc/apt/sources.lst, con lo que se desinstala (de todas formas, no está actualizado... fue volver a bajar el .deb y volverlo a instalar, no se perdió la configuración ni nada), a ver si lo arreglan algún día 
 - me encontré con este problema: http://askubuntu.com/questions/202027/unable-to-configure-a-service-to-run-at-startup-with-update-rc-d (hay un pequeño bug en la configuración del transmission, y no arranca automáticamente al reiniciar, pero es fácil de corregir)
 - tenía conectada una unidad de red (configurada en el /etc/fstab) y dejó de funcionar, pero creo que el problema es bastante específico de la airport extreme actuando como servidor samba, lo arreglé poniendo sec=ntlm en los parametros

Eso es todo. Ahora estoy con el ubuntu 13.10, que incluye transmission-daemon 2.82 (que es lo que yo quería). Sickbeard, subliminal, etc... ni se enteraron


2013-09-28

La cosecha de este a año

Un poco escasa....

2013-08-29

Sacarle más partido a Plex con un poco de SQL

Si no conoces Plex, échale un ojo: http://www.plexapp.com, además de las aplicaciones para Windows y Mac (gratuitas) tienen unos excelentes clientes (baratillos) para iOS y Android que, en sus versiones "premium" (plexpass) tienen una funcionalidad interesante, llamada PlexSync.

Resumidamente, plexsync premite sincronizar automáticamente ciertos contenidos en nuestros dispositivos móviles para, por ejemplo, llevar siempre los episodios que no hemos visto de nuestra serie favorita en el tablet o el móvil.

Como Plex almacena el catálogo de contenidos en una base de datos (SQLite 3) podemos montarnos un plexsync casero con un poco de SQL... le pongo muchos comentarios para que se entienda:

--
--  solo me interesa la ruta del fichero, para llegar a ella
--  tengo que enlazar las tablas 
--  METADATA_ITEMS, MEDIA_ITEMS y MEDIA_PARTS 
--  METADATA_ITEMS es la tabla principal, por asi decirlo
select distinct P.file  
  from METADATA_ITEMS I
           --

           -- tengo varias secciones (musica, peliculas en ingles, etc...)
           -- y no me interesan todas, asi que enlazo la tabla LIBRARY_SECTIONS
           -- para poder filtrar  
           inner join LIBRARY_SECTIONS L       
              on I.library_section_id = L.id
           --

           -- la tabla METADATA_ITEM_SETTINGS me interesa porque es ahí
           -- donde plex almacena si has visto o no el item 
           left outer join METADATA_ITEM_SETTINGS S
              on I.guid = S.guid

           --
           -- ahora vienen las dos tablas que necesito para llegar al
           -- nombre del fichero
           inner join MEDIA_ITEMS M            
              on I.id = M.metadata_item_id
           inner join MEDIA_PARTS P            
              on M.id = P.media_item_id

           --
           -- los episodios de una serie se agrupan en temporadas (el
           -- item "padre") y, a su vez, en series (el "abuelo")        
           left outer join METADATA_ITEMS IPadre
              on I.parent_id = IPadre.id
           left outer join METADATA_ITEMS IAbuelo
              on IPadre.parent_id = IAbuelo.id
 where 

   --
   -- los "no vistos":
   ( S.view_count = 0 or S.view_count is null)
   --

   -- las secciones que me interesan:
   and L.name in
          ("01 Series",
           "02 Peliculas",
           "03 TVShows")

   --
   -- y, ahora viene lo chulo: me interesan los 3 siguientes episodios
   -- de cada serie, así que para cada fila que me devuelve la query 
   -- compruebo si el episodio es uno de los tres primeros que me devuelve
   -- esta subquery. no es muy eficiente, pero tampoco es que tenga prisa...
   and (
          IPadre.[index]*100 + I.[index] in
          (
            select IPadre2.[index] * 100 + I2.[index]
              from METADATA_ITEMS I2
                 inner join LIBRARY_SECTIONS L2       
                    on I2.library_section_id = L2.id
                 left outer join METADATA_ITEMS IPadre2
                    on I2.parent_id = IPadre2.id
                 left outer join METADATA_ITEMS IAbuelo2
                    on IPadre2.parent_id = IAbuelo2.id
              where IAbuelo.id = IAbuelo2.id

                and ( S2.view_count = 0 or S2.view_count is null)
              order by 1
              limit 3            
          )
          or

          --
          -- las peliculas no tienen abuelo
          IAbuelo.id is null
       ) 


Esta query devuelve una lista con las rutas de los ficheros que me interesa tener copiados en, digamos, un pen drive que me llevo por ahí. Sólo falta automatizar la copia:

Metemos la query en un fichero (query.sql) al que le metemos, al principio, estas dos líneas adicionales:

.headers OFF
.output ficheros.txt


y, al final, esta:

.quit

para que cuando ejecutemos la query el sqlite3 no nos devuelva el nombre de la columna y para que el resultado lo guarde en un ficherito llamado "ficheros.txt".

Finalmente, un pequeño script, y listo:

# query para obtener los ficheros ondeck
#   - la query esta en query.sql
#   - deja los resultados en "ficheros.txt"

# ruta de la b.d. de Plex Media Server
RUTABD="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db"
# ejecucion de la query en sqlite
cat query.sql | sqlite3 "$RUTABD"

# copiamos los ficheros al disco usb, asegurandonos de modificar fecha
while read unfichero; do
  sinextension=${unfichero%.*}
  # echo $sinextension
  nombrefichero=$(basename "$unfichero")
  # echo $nombrefichero
  cp -u "$sinextension".* /media/usb0/series
  touch "/media/usb0/series/${nombrefichero%.*}".*
done < "ficheros.txt"


# borramos ficheros viejos
find /media/usb0/series/* -mtime +1 -exec rm {} \;


2013-08-10

National Geographic III

Hoy ha aparecido un nuevo habitante del jardín. Estaba asomando la cabeza y tuve que hacerle una foto. Que menos.

2013-06-02

2013-05-18

Este año nueva estrategia para los tomates

Como el año pasado les faltó algo de sol, este año vamos a probar algo diferente...

2013-05-05

2 LEDs para la Raspberry pi

Ya está hecho. Ahora no puedo controlar el xbmc con el mando de la tele. Qué frágil es este chisme.