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)
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
2016-01-24
2015-10-31
2014-11-25
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:
Los dos ficheros, a continuación:
2014-07-27
2014-05-10
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:
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
Las asignaciones dinámicas se almacenan (por defecto) en /var/lib/misc/dnsmasq.leases, ahí podemos mirar cómo está la cosa.
- 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
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-11-14
2013-10-14
2013-09-28
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 {} \;
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-15
2013-08-14
Suscribirse a:
Entradas (Atom)










