Initial commit

This commit is contained in:
drymer 2018-08-22 22:37:33 +02:00
commit 8ee84f8031
195 changed files with 22739 additions and 0 deletions

31
.drone.yml Normal file
View File

@ -0,0 +1,31 @@
---
pipeline:
build-web:
image: registry.daemons.it/hugo:latest
build-docker:
image: plugins/docker
repo: r.daemons.it/baddaemons
registry: r.daemons.it
secrets: [docker_username, docker_password]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
when:
event: push
ssh:
image: appleboy/drone-ssh
host: daemons.it
username: drone
port: 6699
secrets: [ssh_key]
script:
- sudo docker pull registry.daemons.it/baddaemons:latest
- sudo systemctl restart docker-hugo
when:
event: push
notify:
image: registry.daemons.it/drone-xmpp
secrets: [xmpp_user, xmpp_password, xmpp_room]
when:
status: [success, failure]
event: push
branch: master

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
content-org/articulos.org
content-org/otros.org
resources
public

7
.gitmodules vendored Normal file
View File

@ -0,0 +1,7 @@
[submodule "after-dark"]
path = themes/after-dark
url = https://git.habd.as/comfusion/after-dark
[submodule "LFS201"]
path = static/LFS201
url = https://git.daemons.it/drymer/apuntes-LFS201

5
Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html
COPY public /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]

63
config.yaml Normal file
View File

@ -0,0 +1,63 @@
---
title: "Bad Daemons"
baseURL: "https://daemons.it/"
paginate: 10
theme:
- "after-dark"
enableRobotsTXT: true
pygmentsUseClasses: true
pygmentsCodeFences: true
pygmentsStyle: "monokai"
postNavigation: true
permalinks:
posts: "/posts/:title/"
rssLimit: 20
menu:
main:
- name: "Casa"
weight: 1
identifier: "home"
url: "/"
- name: "Articulos"
weight: 2
identifier: "posts"
url: "/posts/"
- name: "Microblogging"
weight: 3
identifier: "microblogging"
url: "https://pl.daemons.it/users/1"
- name: "Código"
weight: 4
identifier: "git"
url: "https://git.daemons.it/drymer/"
- name: "RSS"
weight: 5
identifier: "rss"
url: "/rss.xml"
- name: "Buscar"
weight: 6
identifier: "search"
url: "/search/"
outputs:
home: ["HTML", "RSS"]
outputFormats:
RSS:
baseName: "rss"
toc: true
params:
description: "Un blog de emacs, sysadmins, contenedores, programacion y otras fuzzwords."
author: "drymer"
hide_author: false
show_menu: true
powered_by: false
hackcss:
disabled: false
mode: "hack"
palette: "dark-grey"

File diff suppressed because it is too large Load Diff

3427
content-org/emacs-conf.org Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
+++
title = "Abrir un fichero con sudo automáticamente en emacs"
author = ["drymer"]
date = 2017-04-25T18:00:00+02:00
tags = ["emacs"]
draft = false
+++
Es una de estas cosas que a primera vista parece que deba ser algo simple, pero es algo más complejo cuando empiezas a mirarlo. Ya hace tiempo que encontré una función para hacerlo en local en la fantástica web de [emacsredux](http://emacsredux.com/blog/2013/04/21/edit-files-as-root/):
```emacs-lisp
(defun sudo-edit (&optional arg)
"Edit currently visited file as root.
With a prefix ARG prompt for a file to visit.
Will also prompt for a file to visit if current
buffer is not visiting a file."
(interactive "P")
(if (or arg (not buffer-file-name))
(find-file (concat "/sudo:root@localhost:"
(ido-read-file-name "Find file(as root): ")))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
```
El funcionamiento es: abrir un fichero y luego ejecutar `M-x sudo-edit RET`. No es la fiesta, pero funciona bien. El problema es que yo suelo editar muchos ficheros en remoto y por desgracia esta función no funciona, ya que tiene hardcodeado el hostname localhost. Intentando arreglar esto, me fié en que el sitio del que habia sacado esta función tenia una segunda opción que deseché simplemente por que no la entendía:
```emacs-lisp
(defadvice find-file (after find-file-sudo activate)
"Find file as root if necessary."
(unless (and buffer-file-name
(file-writable-p buffer-file-name))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
```
Ahora que ya entiendo un poco más de emacs lisp, se que `defadvice` sirve para añadir la ejecución de una función o macro antes de otra, una suerte de `before-hook`. Y en este caso, esta función hace que `find-file` intente abrir el fichero con sudo si detecta que no tiene permisos para modificarlo. Es posible que esto diese problemas si se tiene la costumbre de modificar los atributos de los ficheros, pero es muy poco habitual.
Como eso no me servía para editar ficheros en máquinas remotas, he modificado la función anterior para que detecte automáticamente si se intenta abrir un fichero en la máquina local o en una remota y si es lo segundo, que modifique la ruta para que pueda hacerlo:
```emacs-lisp
(defadvice purpose-find-file-overload (after find-file-sudo activate)
"Find file as root if necessary."
(unless (and buffer-file-name
(file-writable-p buffer-file-name))
(let* ((buffer-file (buffer-file-name))
(coincidence (string-match-p "@" buffer-file))
(hostname)
(buffer-name))
(if coincidence
(progn
(setq hostname (substring buffer-file (+ coincidence 1)
(string-match-p ":" buffer-file (+ coincidence 1))))
(setq buffer-name
(concat
(substring buffer-file 0 coincidence) "@"
(replace-regexp-in-string ":" (concat "|sudo:" hostname ":")
buffer-file nil nil nil (+ coincidence 1))))
(find-alternate-file buffer-name))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file))))))
(defadvice counsel-find-file (after find-file-sudo activate)
"Find file as root if necessary."
(unless (and buffer-file-name
(file-writable-p buffer-file-name))
(let* ((buffer-file (buffer-file-name))
(coincidence (string-match-p "@" buffer-file))
(hostname)
(buffer-name))
(if coincidence
(progn
(setq hostname (substring buffer-file (+ coincidence 1)
(string-match-p ":" buffer-file (+ coincidence 1))))
(setq buffer-name
(concat
(substring buffer-file 0 coincidence) "@"
(replace-regexp-in-string ":" (concat "|sudo:" hostname ":")
buffer-file nil nil nil (+ coincidence 1))))
(find-alternate-file buffer-name))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file))))))
(defadvice find-file (after find-file-sudo activate)
"Find file as root if necessary."
(unless (and buffer-file-name
(file-writable-p buffer-file-name))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
```
En mi caso se modifica la función `purpose-find-file-overload`, que es la que tengo asignada a `C-x C-f`, pero se puede cambiar por `ido-find-file`, `find-file` o la que sea.
La ruta correcta para abrir un fichero remoto con permiso de superusuario seria así: `/ssh:drymer@daemons.it|sudo:root@daemons.it:/`. Esto último lo he sacado de este post de [Stack Overflow](http://stackoverflow.com/questions/2177687/open-file-via-ssh-and-sudo-with-emacs/16408592#16408592).

View File

@ -0,0 +1,36 @@
+++
title = "ace-isearch ahora soporta swipper"
author = ["drymer"]
date = 2017-05-07T15:01:00+02:00
draft = false
+++
Hace un tiempo [escribí sobre ace-isearch](https://daemons.it/posts/cosillas-de-emacs-buscar-en-el-buffer/), una manera cuanto menos curiosa de moverse por el buffer. Para quien no lo sepa, es una manera simple de usar a la vez `avy`, `isearch` y `helm-swoop`.
Como se pudo ver en el articulo de como [migrar de Helm a Ivy](https://daemons.it/posts/migrar-de-helm-a-ivy/), yo ahora uso Ivy, por lo que abandoné el uso de ace-isearch. Prefiero no mezclar el uso de ambos frameworks, que luego vienen los líos y los bugs raros. Pero hace poco caí en que swipper y helm-swoop eran muy similares y de hecho hasta tenían la misma pinta cuando los ejecutas, así que pensé en añadirle soporte a swipper a ace-isearch. Dicho y hecho, esta semana anterior me aceptaron el Pull Request en Github (buuuu), por lo que ace-isearch permite escoger entre avy y ace y entre helm-swoop y swipper. Para más información, se puede ver la sección correspondiente de mi archivo de configuración de emacs:
```emacs-lisp
(use-package ace-isearch
:ensure t
:init
;; Dependencias
;; (use-package helm-swoop :ensure t)
(use-package avy
:ensure t
:config
(setq avy-all-windows t))
;; (use-package ace-jump-mode :ensure t)
:config
(setq avy-background t)
(setq ace-isearch-function 'avy-goto-char)
(setq ace-isearch-input-length 5)
(setq ace-isearch-jump-delay 0.30)
(setq ace-isearch-use-jump 'printing-char)
(setq ace-isearch-function-from-isearch 'ace-isearch-swiper-from-isearch)
(global-ace-isearch-mode +1)
(global-ace-isearch-mode -1)
(global-ace-isearch-mode +1)
:bind (:map isearch-mode-map
("C-'" . avy-isearch))
:diminish ace-isearch-mode)
```

View File

@ -0,0 +1,48 @@
+++
title = "Actualizar el contenido de una web mediante un hook de git"
author = ["drymer"]
date = 2016-05-21T15:31:00+02:00
tags = ["git"]
draft = false
+++
`git` mola mucho. Tiene mucha más potencia que la de compartir archivos, y lo de ahora apenas será rascar la superficie. Hoy veremos los llamados **hooks** de `git`, uno en concreto llamado **post-update**.
Primero un resumen, que son los hooks de `git`? Son scripts que se ejecutan en función a eventos. Unos ejemplos son el **pre-commit**, **pre-receive**, **post-commit** o **post-update**. Los nombres son bastante lógicos, no tiene sentido dedicarle más tiempo.
Entonces, la ideal de manual es enseñar cómo actualizar el contenido de una web, por ejemplo, haciendo solamente un push a un repositorio `git`. El escenario es el siguiente:
- Repositorio git (llamado **~/web** en el ejemplo)
- Directorio de la web (llamado **/var/www/web**)
- Cliente
Por lo tanto, desde el cliente se pushea al repositorio git, y este automáticamente se irá al directorio de la web y hará un git pull. Todo esto sin tener que lidiar con `ssh`, `ftp` ni nada similar. Al lío.
En el servidor se creará un usuario llamado git, en el home de este se creará el repositorio, luego se pondrá la clave ssh del cliente en **authorized\_keys** (para no tener que estar poniendo la contraseña del usuario git del servidor) y luego se creará el hook.
```sh
# Desde el servidor
su -c "adduser git"
su -c "su git"
cd ~
git init --bare web
# Desde el cliente
cat ~/.ssh/id_rsa.pub
# lo que devuelva se copia en una sola linea en el siguiente fichero del servidor
nano ~/.ssh/authorized_keys
# creamos el hook
nano ~/web/hooks/post-update
# y insertamos...
#!/bin/bash
cd /var/www/web
umask 0022
echo "Updating remote folder..."
env -i git pull 1> /dev/null
```
El anterior script es bastante chustero, pero hace su función. Lo suyo seria usar las variables GIT\_REPO y GIT\_WORKDIR, pero no tenia ganas y para lo poco que lo uso me vale. Lo que hace, por cierto, es entrar en el directorio de la web, establecer una máscara que se adecúe a los permisos que hay, informar de que se procede a actualizar la rama y a ejecutar un pull del repositorio sin variables de entorno (como las ya mencionadas GIT\_REPO y GIT\_WORKDIR).
Se ejecuta `chmod +x post_update` y si los permisos son correctos, ese repositorio se actualizará cada vez que se haga un push.

View File

@ -0,0 +1,47 @@
+++
title = "Alternativas a grep"
author = ["drymer"]
date = 2017-08-28T08:30:00+02:00
tags = ["cli"]
draft = false
+++
Desde hace un tiempo me he ido encontrando con la necesidad de buscar cadenas de texto (sin regex, solo palabras simples) en ficheros muy grandes o muchos ficheros pequeños. Para ello, siempre habia usado `grep`, pero a la fueron subiendo los GB en los que buscar, fue subiendo el tiempo que tenia que esperar, hasta niveles absurdos. Y de casualidad me encontré con un par de alternativas a `grep` mucho más rápidas.
La primera fue [The Silver Search](https://github.com/ggreer/the%5Fsilver%5Fsearcher). En su gitsux lo comparan con `ack`, siendo `ag` una orden de magnitud más rápido. Está en los repositorios de casi todas las distros, el paquete se llama `the_silver_searcher` menos en Debian y derivados, que se llama `silversearcher-ag`. Este paquete me sirvió un tiempo, pero a medida que fue subiendo la cantidad de datos en los que necesitaba bucear, hasta `ag` se quedaba corto, por lo que terminé usando [ripgrep](https://github.com/BurntSushi/ripgrep).
Veamos una cutre-demostración de las tres alternativas. Primero, la fuente en la que bucear:
```bash
du -sh ~/.owncloud
```
```text
36G /home/drymer/.owncloud
```
Ahí tengo 36GB de datos, como se puede ver. Veamos cuanto tarda en buscar `grep` la palabra **documentos**, cuanto `ag` y cuanto `ripgrep`:
```bash
time grep -ri documentos ~/.owncloud
time ag documentos ~/.owncloud
time rg documentos ~/.owncloud
```
```text
grep --color -ri documentos ~/.owncloud > /dev/null 42,48s user 59,08s system 12% cpu 14:03,23 total
ag documentos ~/.owncloud > /dev/null 2,98s user 10,81s system 2% cpu 8:01,56 total:
rg documentos ~/.owncloud > /dev/null 1,64s user 1,30s system 20% cpu 14,534 total
```
Como se puede ver, `grep` tarda 14 minutos con un uso de la CPU de un 12%, `ag` tarda 8 minutos con un uso de la CPU del 2% y por último `ripgrep`, que tarda la friolera de 14 segundos, a costa de un mayor uso de la CPU, aunque es más que razonable. Para quien sienta curiosidad de ver por que es tan absurdamente rápido, en el repositorio lo explican, además de enlazar a un blog en el que hacen distintos benchmarks mucho más trabajados que el mío.
Ya solo queda instalar `ripgrep`. Por desgracia, no está en el repositorio de Debian, aunque si en muchos otras distros. Por ello, habrá que compilar o tirar de binario. Como está hecho en Rust y paso de meterme en ese mundo, he tirado de binario, que se puede instalar así:
```bash
wget https://github.com/BurntSushi/ripgrep/releases/download/0.5.2/ripgrep-0.5.2-i686-unknown-linux-musl.tar.gz -O /tmp/ripgrep.tar.gz
cd /tmp/
tar xzf /tmp/ripgrep.tar.gz
cd ripgrep-*
sudo mv rg /usr/local/bin
```

View File

@ -0,0 +1,44 @@
+++
title = "Ansible en emacs"
author = ["drymer"]
date = 2017-06-06T20:16:00+02:00
tags = ["emacs", "ansible"]
draft = false
+++
Últimamente he estado toqueteando bastante Ansible. Para quien no lo conozca, Ansible es un gestor de configuraciones. Permite instalar y configurar programas y configuraciones en un ordenador o en 1.000. Por eso se usa en el ámbito de la Integración Continua. Pero bueno, ya hablaré más en profundidad de ello en otro articulo.
Por ahora hablaré de lo que uso para editar playbooks. Uso `yaml-mode`, `ansible-doc` y `ansible-vale-mode`. Por suerte los playbooks de Ansible se escriben en el maravilloso formato Yaml, muy cómodo para editarlo. El modo no ofrece mucho más que la identación y los colores, pero tampoco hace falta mucho más:
```emacs-lisp
(use-package yaml-mode
:ensure t)
```
`ansible-doc` lo que hace es ofrecer el comando de línea `ansible-doc` pero desde emacs, con [helm](https://daemons.it/categories/helm/) o [ivy](https://daemons.it/categories/ivy/) si se usa alguno. La primera linea de la sección **config** enlaza el `ansible-doc-mode` al `yaml-mode`, por lo que cuando se edite yaml, solo hay que ejecutar `C-?` y se accederá a los docs. Por defecto la primera vez que se lo llama tarda bastante en responder, por que guarda la respuesta para que las siguientes veces sea más rápido. Yo lo que he hecho es añadir la segunda línea, que hace que este cacheo se produzca al iniciar emacs. Tarda más en arrancar emacs, pero dado que solo lo arranco una vez cada muchas semanas, no me resulta un problema.
```emacs-lisp
(use-package ansible-doc
:ensure t
:config
(add-hook 'yaml-mode-hook #'ansible-doc-mode))
```
Y por último, `ansible-vault`. Este paquete es otro wrapper de su [equivalente de terminal](http://docs.ansible.com/ansible/playbooks%5Fvault.html). Para quién no lo sepa, vault es la forma de gestionar variables sensibles en ansible. Se puede usar de dos formas, con una contraseña genérica o una por proyecto. Para lo primero, solo hay que crear un fichero `~/.vault_pass`. Para lo segundo, hay que hacer uso del fichero `.dir-locals.el`. Este fichero permite concretar variables por directorio, como su nombre indica. Es algo propio de emacs, no de `ansible-vault`. Por lo tanto, en ese fichero habría que poner algo como esto:
```emacs-lisp
((yaml-mode
(ansible-vault-pass-file . "~/.ansible-vault/custom_vault_pass")))
```
```emacs-lisp
(use-package ansible-vault
:ensure t
:config
(defun ansible-vault-mode-maybe ()
(when (ansible-vault--is-vault-file)
(ansible-vault-mode 1)))
(add-hook 'yaml-mode-hook 'ansible-vault-mode-maybe))
```
Con esto, se hace mucho más fácil y cómodo editar playbooks de Ansible. Y si además queremos visitar la página de la documentación oficial, siempre se puede usar [counsel-dash](https://daemons.it/posts/ver-documentacin-usando-ivy/).

View File

@ -0,0 +1,170 @@
+++
title = "Aplicaciones web simples con flask, uwsgi y nginx"
author = ["drymer"]
date = 2017-07-05T08:30:00+02:00
tags = ["python", "sysadmin", "nginx", "git"]
draft = false
+++
Lo primero que tengo que dear claro sobre el tema es que odio el desarrollo web. Solo hay que ver el estado de esta página web, si fuese más viejuna tendría que meterle gifs de bebes satánicos bailando. Supongo que es por que las veces que me he tenido que pelear con el tema, he tenido que tocar mucho de la parte visual, lo que seria el diseño y el CSS. Y yo tengo un gusto horrible.
Por ello, cuando quise hacer uso de los webhooks que ofrece gitea pensé que odiaría hacerlo posible. Por suerte me encontré con Flask, que viene a ser un django usable por gente que no quiere dedicarle mucho tiempo al desarrollo. Una vez instalado el paquete mediante un `pip install flask`, hacer un "Hola Mundo!" es tan simple como esto:
```python
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hola Mundo!"
```
Cuando se ejecute el anterior script, dirá que hay un servidor web activo en el puerto 5000, si le hacemos un curl nos devolverá el querido "Hola Mundo".
La aplicación que hice es la siguiente. Está en python 2 por que quería usar xmpppy, que es más simple de usar que Sleekxmpp o Slixmpp. Estas librerías son mucho más robustas, pero mantener la conexión asíncrona era complicarse más de lo que quería. Así que una conexión por visita y ale:
```python
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import xmpp
import json
from flask import Flask, request
import ConfigParser
app = Flask(__name__)
@app.route('/')
def root():
return redirect("/webhook", code=302)
@app.route("/webhook", methods=['POST'])
def webhook():
# read config file
config = ConfigParser.ConfigParser()
config.read('config.ini')
username = config.get('xmpp', 'username', 0)
password = config.get('xmpp', 'password', 0)
server = config.get('xmpp', 'server', 0)
room = config.get('xmpp', 'room', 0)
nick = config.get('xmpp', 'nick', 0)
secret = config.get('gitea', 'secret', 0)
# TODO: comprobar si funciona sin secret
if not secret:
secret = ''
if request.json['secret'] == secret:
data = json.loads(request.data.decode('utf-8'))
message = ''
print(data)
# commit
if 'compare_url' in data.keys():
message = data['pusher']['username'] + ' has pushed some changes:'\
+ ' ' + data['compare_url']
# pull request open
elif data['action'] == 'opened':
message = data['sender']['username'] + ' opened a new pull reques'\
+ 't: ' + data['pull_request']['html_url']
# close pull request
elif data['action'] == 'closed':
message = data['sender']['username'] + ' closed a pull request: ' \
+ data['pull_request']['html_url']
# reopen pull request
elif data['action'] == 'reopened':
message = data['sender']['username'] + ' reopened a pull request:'\
+ ' ' + data['pull_request']['html_url']
# add label
elif data['action'] == 'label_updated':
f_tag = ""
for tag in data['pull_request']['labels']:
f_tag += '[' + tag['name'] + '] '
message = data['sender']['username'] + ' changed the labels ' \
'of a pull request: ' + f_tag + \
data['pull_request']['html_url']
# delete label
elif data['action'] == 'label_cleared':
message = data['sender']['username'] + ' deleted all the labels ' \
'of a pull request: ' + data['pull_request']['html_url']
if message:
client = xmpp.Client(server, debug=[])
client.connect()
client.auth(username, password, 'gitea')
# send join
client.send(xmpp.Presence(to="%s/%s" % (room, nick)))
msg = xmpp.protocol.Message(body=message)
msg.setTo(room)
msg.setType('groupchat')
client.send(msg)
presence = xmpp.Presence(to=room)
presence.setAttr('type', 'unjavailable')
client.send(presence)
return ":)"
if __name__ == "__main__":
app.run()
```
Este fichero debería guardarse como `gitea-sendxmpp.py`. No hay mucho que comentar. Las peticiones que se hagan a la raíz se re-envían a `/webhook`, por lo que se puede apuntar directamente ahí. Leerá el archivo de configuración (que veremos a continuación), y si el secreto cuadra con el de la configuración pardeará el mensaje y enviará un mensaje a la sala de jabber que se le diga.
El archivo de configuración a rellenar es el siguiente:
```ini
[xmpp]
username =
password =
server =
room =
nick =
[gitea]
secret =
```
Y por último, la forma correcta de ejecutar aplicaciones web en python es usar `uwsgi`. Un ejemplo simple de configuración es el siguiente:
```ini
[uwsgi]
chdir = /var/www/gitea-sendxmpp/
module = gitea-sendxmpp:app
master = true
processes = 1
threads = 2
uid = www-data
gid = www-data
socket = /tmp/gitea-sendxmpp.sock
chmod-socket = 777
die-on-term = true
```
Ya solo queda configurar nginx para que actué como un proxy inverso (algo sumamente recomendable por temas de codificación, eficiencia, seguridad, ...) del siguiente modo:
```nginx
server {
listen 80;
server_name daemons.it;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/gitea-sendxmpp.sock;
}
}
```
Lo más importante es que el socket `uwsgi_pass` sea el mismo tanto en la configuración de `uwsgi` como de nginx.
Para ver la versión más reciente, en caso de que la modifique, se puede visitar [el repositorio](https://git.daemons.it/drymer/gists#org037c36d).

View File

@ -0,0 +1,15 @@
+++
title = "Arreglar completado de texto en elpy-doc"
author = ["drymer"]
date = 2017-02-28T08:30:00+01:00
tags = ["ivy", "python", "elpy", "helm"]
draft = false
+++
Quien leyese el articulo de como [convertir emacs en un IDE de python](https://daemons.cf/posts/programando-en-python-en-emacs/), tal vez se fió en lo útil de `elpy-doc`. Es una orden muy útil, pero usada con el auto-completado que ofrece [ivy](https://daemons.cf/categories/ivy/), da problemas. Solo ofrece el auto-completado de la primera parte del paquete.
Es decir, si queremos ver la documentación de `datetime.datetime`, ivy solo ofrecerá hasta el primer `datetime`. Esto es debido a la forma de ofrecer completados de elpy. Sin entrar en si es correcto o no, su desarrollador [no quiere](https://github.com/jorgenschaefer/elpy/issues/1084) hacerlo compatible con ivy o helm. Por ello, el desarrollador de ivy [ha añadido](https://github.com/abo-abo/swiper/issues/892) una variable en la que se puede concretar funciones en las que no queremos que el completado funcione. Es un apaño cutre, pero dado que los desarrolladores no han podido llegar a un acuerdo, al menos podemos usar `elpy-doc` correctamente con ivy. La variable se llama `ivy-completing-read-handlers-alist` y el equivalente en helm es `helm-completing-read-handlers-alist`. Añadimos la siguiente línea (cambiando ivy por helm si se usa este) en nuestra configuración y ale, a correr.
```emacs-lisp
(add-to-list 'ivy-completing-read-handlers-alist '(elpy-doc . completing-read-default))
```

View File

@ -0,0 +1,25 @@
+++
title = "Publicada la auditoria de Truecrypt"
author = ["drymer"]
date = 2015-04-03T19:15:00+02:00
draft = false
tags = ["privacidad", "elbinario"]
+++
En un bonito PDF. Lo tienen todo bastante dividido, explicando cómo han procedido con la auditoria, con qué métodos, que funciones han auditado, etc.
DISCLAIMER
A continuación escribo un pequeño resumen. Aviso que no me acerco ni de lejos a ser un experto en nada, y menos en criptografia. Por lo que perfectamente me podria equivocar en lo que interpreto del texto. Cualquier apunte o crítica es bien recibida.
Las vulnerabilidades encontradas son pocas, aunque algunas críticas. Concretamente son cuatro, dos de ellas catalogadas cómo de criticidad "alta", una "baja" y otra indeterminada.
* CryptAquireContext puede fallar silenciosamente: esta función, que parece ser la encargada de conseguir entropia en los sistemas Windows, puede fallar sin avisar. Un escenario planteado es el de una usuaria creando un Volumen Cifrado en un entorno empresarial con políticas de grupo que delimita el acceso al servicio proveedor de criptografia, provocando así que se pase a usar otros métodos más inseguros. Esto permitiria a un atacante, de conocer la fuente insegura, un ataque de fuerza bruta. Esta vulnerabilidad se cataloga cómo crítica y de dificultad de abuso indeterminada. Apunte: el proveedor de entropia es el encargado de conseguir aleatoriedad para que esta pueda ser usada por los programas que lo necesitan.
* La implementación de AES es susceptible al ataque cache-timing: AES usa tablas muy grandes, que a veces no caben en la caché de las CPU. Un atacante podría ejecutar código de manera remota para calcular el tiempo de descifrado de la clave, hacer un análisis estadístico y conseguir así la clave privada AES. Hay que hacer constar que este ataque no es propio de TrueCrypt sinó de el propio concepto de cifrado de AES. Para que un atacante lograse este ataque, tendría que tener acceso a este ordenador y la capacidad de ejecutar código nativo en la máquina. Este tipo de ataque, cómo muchos side-attacks, no se pueden erradicar. Lo único que se puede hacer es dificultar su explotación. Esta vulnerabilidad se cataloga como crítica y de dificultad de abuso alta.
* La mezcla de keyfiles no es optima: TrueCrypt coge las keyfiles y las mezcla con la contraseña del usuario tal cual, sin hashearlas. Esto, más que una vulnerabilidad se considera una mala práctica. El motivo es que al manejar diferentes fuentes de entropia, las claves en este caso, aunque un atacante controlase una no no será capaz de deducir la contraseña de desbloqueo. Lo que si podría hacer es manipular una de las claves no controladas y provocar que, al meter la contraseña, fuése cómo si no se estuviesen usando estas llaves. Esta vulnerabilidad se cataloga cómo crítica y de dificultad de abuso alta.
* Texto cifrado en las cabeceras del volumen: Hay algo de metadatos en estas cabeceras. La cabecera y el volumen están cifrados con una clave distinta. La cabecera está cifrada con la contrasñea del usuario y el volumen con una keyfile que está en la cabecera. Garantizar la integridad y la autenticidad es algo de lo que el cifrado de disco completo no pretende hacerse cargo, ya que incurriria en un rendimiento del disco más bajo. Sin embargo, este cifrado si puede tratar la integridad de la cabecera, que al fin y al cabo contiene la llave que abre el volumen. TrueCrypt intenta solucionarlo incluyendo en la cabecera un string TRUE, un CRC32 (Cyclic Redundancy Check (Comprobación Cíclica Redundante)) de la clave y otro CRC32 del resto del volumen. EL CRC32 es un método de hasheo inseguro. De no estar cifrada la cabecera, esto podría permitir el acceso a la clave maestra y por tanto al volumen cifrado.
Y esto es. Este es el análisis final de la segunda fase de la auditoria. Este es la auditoria final, aunque queda pendiente un sumario ejecutivo. Pronto saldran otra vez las teorías sobre el abandono de esta herramienta. O, más vien, se descartan algunas, tales cómo que los de TrueCrypt abandonaron por miedo a que la auditoria encontráse algo comprometido. Solo se me ocurre esa teoría en la que se vieron obligados a abandonar ante las presiones de distintos gobiernos, presumiblemente el de EEUU.
Recomiendo la lectura de la [https://opencryptoaudit.org/reports/TrueCrypt_Phase_II_NCC_OCAP_final.pdf](fuente), ya que será mucho más fiable que esto que he escrito.

35
content/posts/bashblog.md Normal file
View File

@ -0,0 +1,35 @@
+++
title = "Bashblog - Un blog com bash"
author = ["drymer"]
date = 2015-06-26T19:15:00+02:00
draft = false
tags = ["bash", "elbinario"]
+++
Cuando se trata de hacer blogs o incluso webs sencillas, Wordpress es el CMS más usado. Pero no es la unica alternativa, ni mucho menos. Sobretodo si buscas al sencillo. Wordpress está bien si quieres tener cierta moduralidad y funcionalidades. Pero si buscas algo más sencillo, Bash Blog es la solución.
Podemos instalarlo y empezar a usarlo tal que así:
```bash
git clone https://github.com/cfenollosa/bashblog.git
cd bashblog
bash bb.sh
```
Puede que al ejecutarlo nos pida que definamos la variable $EDITOR. En el prompt debemos poner **EDITOR=$editor", siendo $editor el editor que queramos, tal cómo vim, emacs, nano, etc. También podremos crear los articulos con markdown o con html. Por defecto, busca Markdwon.pl y sinó, fuerza el html. Dado que la única necesidad real del programa que use markdown es que acepte el formato \*markdown in.md > out.html**, podemos usar cualquiera que acepte este formato. Lo único que tenemos que hacer es cambiar la línea 146 en la que se define la variable **markdown\_bin**. Con poner el nombre del binario valdrá. En mi caso, queda así.
```bash
markdown_bin="$(which markdown || which markdown)"
```
Ahora, podemos empezar con la edición. Lo haremos pasándole el argumento **post** al ejecutar el script. Y nos saldrá un texto cómo este:
```text
Title on this line
<p>The rest of the text file is an <b>html</b> blog post. The process will continue as soon
as you exit your editor.</p>
<p>Tags: keep-this-tag-format, tags-are-optional, example</p>
```
Quien sepa un poquito de inglés, no tendrá problema. No tiene mucho misterio. Instertamos título, cuerpo del artículo y por último tags, de tenerlos. Este articulo se veria [así](http://elbinario.net/bashblog/index.html), si usásemos ese programa. Y poco más hay que añadir. La gracia de esto es precisamente el minimalismo y la facilidad que ofrece.

View File

@ -0,0 +1,70 @@
+++
title = "Botón de los cojones para compartir en GNU Social"
author = ["drymer"]
date = 2015-11-05T19:34:00+01:00
tags = ["gnusocial"]
draft = false
+++
Pues eso, he visto por GNU Social en varias ocasiones la discusión sobre el botoncito, así que ahí va un pequeño tutorial.
Aviso de que hace falta tener acceso por terminal al servidor en cuestión. Funciona con cualquier tipo de web, no es un plugin de wordpress ni nada. Así que al lío. Nos metemos en el servidor por ssh y vamos al directorio en el que queremos el plugin. De ser un wordpress, tiene sentido ponerlo en wp-content/plugins. Una vez en ese directorio:
```sh
git clone https://github.com/chimo/gs-share.git
cd gs-share
# Dado que ese plugin hace mucho que no se actualiza, nos podemos cargar el .git
rm -rf .git*
```
Ahora vamos a modificar un comportamiento que tiene por defecto. Si miráis en el botón de este mismo articulo, hacia el final, veréis que hay un tick que dice **bookmark**. Ni sé que hace exactamente el bookmark en GNU Social, pero si que evita que se comparta el articulo correctamente. Y la cosa es que por defecto sale clicado. Así que vamos a modificar el plugin para que no salga clicado. Estas son las lineas de 93 a 96 del archivo s/gs-share.s
```s
frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
'<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
'<input type="checkbox" checked id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
'<input type="submit" value=\''+ i18n.submit + '\'/>';
```
Ahora hay que quitar la palabra **checked** de la linea 95, tal que así:
```s
frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
'<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
'<input type="checkbox" id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
'<input type="submit" value=\''+ i18n.submit + '\'/>';
```
Ahora ya estamos listos para proceder a insertarlo. Ahora tenéis que encontrar la manera de insertar cierto código de manera automática, o no. Yo es que soy muy vago. Esto dependerá bastante según el sitio web que uséis. El siguiente método ha funcionado en un wordpress (el de [Jess](http://diariodeunalinuxera.com), por cierto), pero en el mío no y tuve que usar otro método, luego explico por qué.
En cada articulo hay que meter el siguiente código, a mano. Lo suyo seria tener un plugin que lo agregue a cada uno de manera automático, pero no he encontrado ninguno.
```text
<!-- Ejemplo funcional de su blog-->
<script src="http://diariodeunalinuxera.com/wp-content/plugins/gs-share/s/gs-share.s"></script>
<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>
```
A mi no me ha funcionado por un motivo muy simple. El archivo script tiene que estar una sola vez por página y en mi web se carga todo el cuerpo de los articulos, por lo que ese archivo sale varias veces. Por suerte, con nikola sólo he tenido que meter en la sección del header esa primera línea, y en el script del deploy un pequeño if que compruebe cada vez si ese articulo tiene el botóncito de los cojones.
```python
# Linea 889 en mi conf.py
EXTRA_HEAD_DATA = '<link rel="stylesheet" href="http://daemons.it/gs-share/css/styles.css" />'
```
Y en el script concretado en el deploy:
```sh
for i in $(ls posts | grep .wp)
do
filtro=$(grep "s-gs-share" posts/$i)
if [[ -z $filtro ]]
then
echo '<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>' >> "posts/$i"
fi
done
```
A lo cutre. Pero si funciona, que más da que sea cutre.
PD: Es tan cutre, que al hablar de ello en este articulo, ha detectado que el botón "ya estaba" y no lo ha añadido.

View File

@ -0,0 +1,70 @@
+++
title = "Botón de los coones para compartir en GNU Social"
author = ["drymer"]
date = 2015-11-05T19:34:00+01:00
tags = ["gnusocial"]
draft = false
+++
Pues eso, he visto por GNU Social en varias ocasiones la discusión sobre el botoncito, así que ahí va un pequeño tutorial.
Aviso de que hace falta tener acceso por terminal al servidor en cuestión. Funciona con cualquier tipo de web, no es un plugin de wordpress ni nada. Así que al lío. Nos metemos en el servidor por ssh y vamos al directorio en el que queremos el plugin. De ser un wordpress, tiene sentido ponerlo en wp-content/plugins. Una vez en ese directorio:
```sh
git clone https://github.com/chimo/gs-share.git
cd gs-share
# Dado que ese plugin hace mucho que no se actualiza, nos podemos cargar el .git
rm -rf .git*
```
Ahora vamos a modificar un comportamiento que tiene por defecto. Si mirais en el botón de este mismo articulo, hacia el final, veréis que hay un tick que dice **bookmark**. Ni sé que hace exactamente el bookmark en GNU Social, pero si que evita que se comparta el articulo correctamente. Y la cosa es que por defecto sale clicado. Así que vamos a modificar el plugin para que no salga clicado. Estas son las lineas de 93 a 96 del archivo s/gs-share.s
```s
frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
'<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
'<input type="checkbox" checked id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
'<input type="submit" value=\''+ i18n.submit + '\'/>';
```
Ahora hay que quitar la palabra **checked** de la linea 95, tal que así:
```s
frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
'<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
'<input type="checkbox" id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
'<input type="submit" value=\''+ i18n.submit + '\'/>';
```
Ahora ya estamos listos para proceder a insertarlo. Ahora tenéis que encontrar la manera de insertar cierto código de manera automática, o no. Yo es que soy muy vago. Esto dependerá bastante según el sitio web que uséis. El siguiente método ha funcionado en un wordpress (el de [ess](http://diariodeunalinuxera.com), por cierto), pero en el mío no y tuve que usar otro método, luego explico por qué.
En cada articulo hay que meter el siguiente código, a mano. Lo suyo seria tener un plugin que lo agregue a cada uno de manera automático, pero no he encontrado ninguno.
```text
<!-- Eemplo funcional de su blog-->
<script src="http://diariodeunalinuxera.com/wp-content/plugins/gs-share/s/gs-share.s"></script>
<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>
```
A mi no me ha funcionado por un motivo muy simple. El archivo script tiene que estar una sola vez por página y en mi web se carga todo el cuerpo de los articulos, por lo que ese archivo sale varias veces. Por suerte, con nikola sólo he tenido que meter en la sección del header esa primera línea, y en el script del deploy un pequeño if que compruebe cada vez si ese articulo tiene el botóncito de los coones.
```python
# Linea 889 en mi conf.py
EXTRA_HEAD_DATA = '<link rel="stylesheet" href="http://daemons.it/gs-share/css/styles.css" />'
```
Y en el script concretado en el deploy:
```sh
for i in $(ls posts | grep .wp)
do
filtro=$(grep "s-gs-share" posts/$i)
if [[ -z $filtro ]]
then
echo '<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>' >> "posts/$i"
fi
done
```
A lo cutre. Pero si funciona, que más da que sea cutre.
PD: Es tan cutre, que al hablar de ello en este articulo, ha detectado que el botón "ya estaba" y no lo ha añadido.

View File

@ -0,0 +1,66 @@
+++
title = "Calfw: ver la agenda en modo calendario"
author = ["drymer"]
date = 2016-12-11T08:30:00+01:00
tags = ["orgmode", "emacs"]
draft = false
+++
Esto fue lo primero que busqué cuando empecé a usar la agenda hasta que me di cuenta de que no tenia. Me sorprendió bastante al principio, hasta que entendí que `org-mode` está pensado para gestionar listas y hacer búsquedas, no dar una visión general. Que ojo, eso va muy bien, pero hay veces que se prefiere el formato clásico del calendario. Y buscando, encontré `calfw`.
Este paquete muestra un calendario simple, sin misterio. Permite 4 tipos de fuentes:
- [howm](http://howm.osdn.jp/index.html)
- ical
- org-mode
- diary-mode
Solo veremos como usar el de `org-mode`, que es el que uso yo. La configuración necesaria es mínima:
```emacs-lisp
(if (not (el-get-package-installed-p 'calfw))
(el-get 'sync 'calfw))
(use-package calfw
:load-path "el-get/calfw"
:config
(require 'calfw-org)
(setq cfw:org-overwrite-default-keybinding t)
(setq calendar-week-start-day 1)
(setq calendar-month-name-array
["Gener" "Febrer" "Març" "Abril" "Maig" "Juny" "Juliol" "Agost" "Septembre" "Octubre" "Novembre" "Desembre"])
(setq calendar-day-name-array
["Diumenge" "Dilluns" "Dimarts" "Dimecres" "Dijous" "Divendres" "Dissabte"])
:bind ("C-c f" . cfw:open-org-calendar))
```
Como se puede ver, lo he instalado mediante [el-get](https://daemons.cf/posts/el-get-otro-instalador-de-paquetes). Se puede instalar mediante `package.el`, por eso. Respecto al resto de la configuración:
- `cfw:org-overwrite-default-keybinding`: establece los atajos de teclado de la agenda de `org-mode`, bastante práctico si es la que se suele usar.
- `calendar-week-start-day`: al establecerla en 1, la semana empieza el lunes.
- `calendar-month-name-array`: la traducción de los meses al catalan.
- `calendar-day-name-array`: la traducción de los días al catalan.
Y ya. Respecto a los atajos de teclado, al activar los de `org-mode` pasan a ser los siguiente:
| Tecla | Función |
|-------|------------------------|
| g | Actualiza la agenda |
| | Salta a fecha indicada |
| k | org-capture |
| x | Cierra calfw |
| v d | Vista diaria |
| v w | Vista semanal |
| v m | Vista mensual |
Para abrir el buffer del calendario, hay que ejecutar `cfw:org-calendar-buffer` o, si se usa el bind que tengo establecido, C-c f. Se ve así:
{{< figure src="/img/calfw.png" >}}
Más información en el [repositorio git](https://github.com/kiwanami/emacs-calfw) del proyecto.

View File

@ -0,0 +1,78 @@
+++
title = "Catalunya: los datos de los pacientes en manos de terceros"
author = ["drymer"]
date = 2015-04-04T19:15:00+02:00
draft = false
tags = ["privacidad", "elbinario"]
+++
DISCLAIMER: Tocho-post incoming.
En España se lleva el amarillo y el rojo. Algunas personas lo adornan con un aguilucho de estos ilegales. Otras personas le meten una estrella con cuatro rallitas. También se comenta que esta es ilegal. Pero los adornos que se le pongan a una bandera no son importante, sigue siendo una **puta** bandera.
Mientras el partido gobernante de esta comunidad autonómica sigue pasándose por el forro la legalidad de sus acciones, tales cómo el [ab]uso de la fuerza en el caso de los Mosssos, hay gente que aún piensa que nada es más importante tener una bandera con más barras rojas que preocuparse por los actos de sus gobernantes. Ahora llega un nuevo(?) atropello (no sólo típico de dónde se hace la butifarra, en Madrid y otras comunidades hacen cosas similares), que no está teniendo demasiada repercusión mediática. Será por que si les toques al señor Menos te lapidan. Que hay que ver lo anti-catalan que es alguien por ser crítico.
Se ha aprobado[^1] el proyecto llamado Visc+. Les gusta mucho eso de poner nombres modernos y que atraigan a los jóvenes, se ve. La siguiente cita, que es más bien un resumen traducido de la página del Govern[^2], dice tal que así:
### Que es VISC+?
Este proyecto permitirá poner en manos de la comunidad científica información relacionada con el sistema sanitario catalan. Previamente anonimizado, claro. Todo esto con el fin de facilitar la investigación, la innovación y la evaluación en el campo de la biomedicina.
### Con que finalidad se podran usar estos datos?
"Sólo" podrán acceder por investigadores que justifiquen que su uso se corresponde a una finalidad médica. Su finalidad será analizada tanto éticamente cómo científicamente. Esto permite la mejora en el ámbito asistencial pero también en el diagnóstico.
### Que datos se investigan?
[No para de repetirse que están previamente anonimizados] Información de atención primaria, hospitalária, imagen médica digital o información sobre la receta electrónica. Entre otros. El proyecto no accederá directamente al historial médico de un paciente.
### Esta información se ha usado antes para investigar?
Si. [Pues que gilipollez de ley, si ya se podía hacer, no?] Tendrá acceso a esta incluso organizaciones con animo de lucro.
### Beneficios
* Aumentar la calidad de la asistencia recibida.
* Beneficios para los investigadores, que tendrán acceso a muchos datos.
* Beneficios del sistema sanitario, por que obtendran los resultados de los analisis.
### Cómo se garantiza la Integridad de los datos en este proyecto?
[Esta sección existe y está en blanco...]
### Será público quien accede a estos datos y que utiliza?
Si.
### Puedo excluir mis datos de este proyecto?
Si. [En vez de pedirte si pueden darlos, tienes que decir que no pueden.]
### Algun proyecto similar en el resto del mundo?
Si. En Inglaterra, Holanda, EEUU y, sorpresa, Catalunya.
### Por qué AQuAS(Agència de Qualitat i Avaluació Sanitàries de Catalunya) tira adelante este proyecto?
Por que son buena gente y quieren mejorar la investigación y los Centros de Atención Primaria. Catalunya es muy moderna porqué hace uso del Big Data.
### Cuales son nuestros derechos respecto con nuestros datos personales?
Se aplican los llamados derechos ARCO. Acceso, rectificacion, cancelación y oposición.
Qué diferencia hay con este proyecto, respecto a anteriores tales cómo SIDIAP[^3]? Técnicismos. Poco más.
Esta es la parte bonita, en la que se habla de lo beneficioso que es el Big Data y lo moderna que es Catalunya, que está muy avanzada para la edad que tiene. Sólo les falta decir que también tiene las tetas grandes. Luego vienen las cosas de las que no hablan u obvian. Por ejemplo, este proyecto ha sido aprobado por el propi Govern, sin pasar por el Parlament. Tiene relación, o directamente han participado, con diferentes empresas cuya ética es, cómo mínimo, preocupante. Un par de ellas son PWC y IMS Health. La primera, una consultora, ha llegado a proponer los cambios necesarios al ICS para que los hospitales públicos sean fácilmente absorbibles por entidades privadas. [^4]
Evidentemente, un proyecto de este tipo puede ser muy beneficioso para la sanidad pública. Lo preocupante es lo mencionado en el anterior parágrafo, entre otras cosas. Incurren en demasiadas contradicciones. Por ejemplo, en el FAQ aparece que se puede pedir que no se incluyan tus datos en las cesiones cómo única medida para contrarestrar esta apropiación. En el Diario Oficialde Catalunya dice, sin embargo *Cession a terceros de informacion personal [...] siempre que haya consentimiento previo*. Pero el tema más preocupante es el de la anonimización de estos datos. El Govern no es conocido por sus grandes dotes en ámbitos informáticos. Su web da bastante asco y está llena de links rotos. Si un organismo cómo el CESICAT, que se dedican a la seguridad y uso de nuevas tecnologias, la cagó cómo la cagó[^5], qué nos garantiza que no lo hagan tres veces peor los de AQuAS?
Porqué, de hecho, ya se tiene en cuenta la posibilidad de des-anonimizar estos datos. En el anexo 2 de la resolución SLT/570/2015, el punto 8, habla de algo interesante. *Reidentificación de los datos anonimizados en caso de peligro*: Esto no es malo en si, pueden salvar a alguien. Lo preocupante es que realmente se puede reidentificar a alguien. Entonces, que tipo de anonimización de datos es esta? Será que con un tipo concreto de información sobre una persona, se le puede identificar fácilmente? De ser así, en que situación nos encontrariamos si las empresas que pueden contratarnos saben nuestro historial? Por no hablar de lo que podrían hacer las aseguradoras. De esto último, se hizo un documental muy interesante hace años, de Michael Moore. Recomiendo su visionado o incluso re-visionado. Las cosas se ven un poco distintas con el tiempo. Sobretodo sabiendo que algunas personas quieren dirigirnos al tipo de Sanidad que muestran en ese documental.
Cómo mencionaba arriba, aquí si se crítica al Govern es que eres anti-catalan. Entre eso y las presiones que probablemente hacen distintas empresas junto con el Govern a los medios de comunicación, no se está tratando este tema. En el Parlament poco pueden hacer (los pocos que quieren), ya que les han pasado por encima. Sólo queda la concienciación y la acción ciutadana.
Y si te piensas que por estar fuera de Catalunya esto no te afecta, estás equivocada. En el caso que esto tire adelante y empiecen a sacar pasta, crees que el resto del país no querrá sacar tajada también?
[^1]: [Fuente][1]
[^2]: [Fuente][2]
[^3]: Sidiap es un proyecto que ya existe desde el 2010 en Catalunya. Desde entonces ya tenia acceso a estos datos. Empezó cómo XIIAP (Xarxa Informatizada d'Investigació a l'AP) en el 2000, hasta 2007 que pasó a ser UNIDAP (Unitat de Dades Informatitzades de l'AP), y en 2010 pasó a ser SIDIAP (Sistema dInformació pel Desenvolupament de la Investigació a lAtenció Primària). Su web: [http://www.sidiap.org/](http://www.sidiap.org/)
[^4]: [Fuente][4]
[^5]: [Fuente][5]
[^6]: [Fuente][6]
[1]: http://www.20minutos.es/noticia/2421621/0/generalitat-aprueba/venta-datos-sanitarios/gestion-privada/
[2]: http://aquas.gencat.cat/ca/projectes/visc/preguntes-frequeents/#FW_bloc_dfc09e8f-85cd-11e4-8517-005056924a59_1
[3]: http://www.sidiap.org/index.php?option=com_content&view=article&id=46&Itemid=34&lang=ca
[4]: http://www.catacctsiac.cat/docs_observatori/model/empreses_publiques/20121212_document_pwc.pdf
[5]: http://www.sindicatperiodistes.cat/es/content/m%C3%A1s-filtraciones-de-seguimientos-periodistas

View File

@ -0,0 +1,10 @@
+++
title = "Charla: Emacs no necesita esteroides"
author = ["drymer"]
date = 2018-04-21T22:42:00+02:00
tags = ["charlas", "emacs"]
draft = false
+++
Este miércoles 25 de abril, a las 20:00, daré una charla sobre emacs en la Brecha Digital. Veremos, a grandes rasgos, qué es exactamente emacs, sus orígenes, comparación con vim para darle emoción, que posibilidades de uso tiene y cómo empezar a usarlo.
El nivel de la charla será introductorio, pero si ya conoces emacs siempre puedes aprovechar la ocasión para ver la Brecha Digital, un grupo que se reúne en La Brecha, un centro social alquilado, en el que nos untamos habitualmente para dar charlas y aprender tecnologías molonas en común. Más información de La Brecha Digital [aquí](https://labrecha.digital), echadle un ojo para ver como llegar a La Brecha.

View File

@ -0,0 +1,65 @@
+++
title = "Cliente de GNU social para emacs"
author = ["drymer"]
date = 2016-10-04T08:30:00+02:00
tags = ["emacs", "gnusocial"]
draft = false
+++
En un [articulo](https://daemons.cf/posts/gnu-social-en-emacs/) de [@maxxcan](https://gnusocial.net/maxxcan) ya vimos como usar `identica-mode` como cliente de emacs. Como su propio nombre indica, está pensado para el entonces centralizado servicio que era Statusnet, cuyo servidor principal era identi.ca. Sin embargo [@bob](https://primatemind.info/bob), alias [@bashrc](https://github.com/bashrc/gnu-social-mode), lo ha actualizado, cambiando nombres de funciones y creando otras.
Así que procedemos a instalarlo. De momento está en github. igual en un tiempo se anima a meterlo en Elpa.
```sh
mkdir -p ~/.emacs.d/lisp/
git clone https://github.com/bashrc/gnu-social-mode ~/.emacs.d/lisp/gnu-social-mode/
```
Ahora lo configuramos. Añadimos el directorio a la ruta de ejecución y luego establecemos las variables mínimas.
```emacs-lisp
(add-to-list 'el-get-sources '(:name gnu-social-mode
:description "gnu-social client"
:type github
:pkgname "bashrc/gnu-social-mode"))
(if (not (el-get-package-installed-p 'gnu-social-mode))
(el-get 'sync 'gnu-social-mode))
(use-package gnu-social-mode
:load-path "el-get/gnu-social-mode/"
:init
(setq gnu-social-server-textlimit 140
gnu-social-server "quitter.se"
gnu-social-username "drymer"
gnu-social-password "lolazing"
gnu-social-new-dents-count 1
gnu-social-status-format "%i %s, %@:\n %h%t\n\n"
gnu-social-statuses-count 200))
```
La primera variable, `gnu-social-server-textlimit`, establece el máximo de caracteres que nos permitirá enviar emacs. Debería ser el mismo que el que usa el servidor, en mi caso uso [https://quitter.se/](https://quitter.se/) así que son 140. Las variables `*-server`, `*-username` y `*-password` son obvias. La de `gnu-social-status-format` estable el formato de las noticias. Sin entrar en detalles, así queda mejor que como viene por defecto. Si queréis saber más, `C-h v gnu-social-status-format RET`. Y la última, `gnu-social-statuses-count`. Son las noticias que mostrará cada vez que carguemos una linea temporal. Por defecto son 20, lo que a mi me parece poco.
Gestionar GS desde emacs es bastante sencillo, a continuación una tabla con las funciones más habituales con atajos de teclado pre-establecidos.
| Atajo de teclado | Función |
|------------------|------------------------------------------------|
| / k | Moverse una noticia arriba / abajo |
| A | Responder a todas |
| r | Repostear |
| F | Añadir a favorito |
| R | Responder a la persona que postea |
| C-c C-s | Publicar una noticia |
| C-c C-r | Ir a la linea temporal de respuestas |
| C-c C-f | Ir a la linea temporal de amigos (por defecto) |
| C-c C-v | Ir a tu perfil |
| C-c C-a | Ir a linea temporal pública |
| C-c C-g | Ir a linea temporal de grupo |
| C-c C-u | Ir a linea temporal propia |
| C-c C-o | Ir a linea temporal de usuario concreto |
Recordemos que estos atajos son opcionales. Siempre podemos ejecutarlos usando M-x.
Aquí una captura de cómo se ve.
{{< figure src="/img/2016-10-03-112112_1024x768_scrot.png" >}}

View File

@ -0,0 +1,52 @@
+++
title = "Cómo montar un planet"
author = ["drymer"]
date = 2016-07-14T22:26:00+02:00
tags = ["sysadmin"]
draft = false
+++
Primero de todo, que es un planet? La definición aproximada que nos da **Planet Venus**, que es el programa que usaremos, es un increíble rio de noticias. En sinsillo, lo que hace este programa es coger una cantidad indefinida de feeds y crear uno único. También se le podría llamar agregador de noticias. La cosa es que, en este caso, se suele usar con blogs o webs con una temática concreta, pero bueno, eso ya queda a elección de quien lo use. Un ejemplo es [http://planet.emacsen.org](http://planet.emacses.org), [http://planet.emacs-es.org/](http://planet.emacs-es.org/) o [http://planetlibre.es](http://planetlibre.es).
Así que al lío. Primero de todo, hay que clonar el repositorio de Venus. Lo suyo seria hacerlo directamente en lo que queremos que sea la raíz del servidor web, por ejemplo en `/var/www/planet/`:
```sh
su www-data
cd /var/www/
git clone https://github.com/rubys/venus planet
cd planet
```
Una vez hecho, se tiene que crear un archivo de configuración. Para ello disponemos del directorio `examples/`. Para no liarnos, copiamos uno de esos archivos a la raíz con `cp examples/planet-schmanet.ini $nombreDePlanet.ini` y editamos el archivo llamado que hayamos copiado. Se puede observar que hay dos secciones, que son `[Planet]` y `[DEFAULT]`. Todas las secciones son bastante obvias, así que simplemente pegaré el de `emacs-es.ini`.
```ini
[Planet]
name = Planet Emacses
link = http://planet.emacs-es.org
owner_name = Nobody
owner_email = contacto@emacs-es.org
cache_directory = /var/www/emacs-es.org/cache
log_level = DEBUG
feed_timeout = 20
output_theme = emacsen
output_dir = /var/www/emacs-es.org/output/
items_per_page = 60
bill_of_materials:
images/#{face}
activity_threshold = 90
new_feed_items = 5
locale = "es_ES"
[DEFAULT]
[http://daemons.it/categories/emacs.xml]
name = Bad Daemons
[http://www.maxxcan.com/category/emacs/feed/]
name = Maxxcan's Site
```
Todo queda bastante claro, hay que adaptar rutas, RSS y el tema. Sólo un par de cosas a comentar. En la sección `[DEFAULT]` van los feeds que queremos que salgan en la web y el parámetro `output_theme` es el tema del planet. Hay unos pocos y son muy feos, por eso decidimos copiar el de [http://planet.emacsen.org](http://planet.emacsen.org). A título de curiosidad diré que me pasé dos o tres horas copiando el tema de la web del planet, examinando el css, entendiendo cómo funcionan las plantillas, adaptándolo y todo eso, y resulta que tienen tanto la plantilla cómo los css en su puto repositorio. Me reí tanto que escupí sangre. Pero bueno, al menos modifiqué un par de cosillas que no me gustaban del que tenían y aprendí como funcionan las plantillas, que diría que cuadra bastante con el [Modelo Vista Controlador (MVC)](https://es.wikipedia.org/wiki/Modelo%25E2%2580%2593vista%25E2%2580%2593controlador), aunque yo de eso no se mucho.
Pues nada, ya tenemos un planet en funcionamiento. Para ejecutarlo, hay que ejecutar en el directorio `python2 planet.py emacs-es.ini` y ya esta (lo suyo seria ponerlo en el `crontab`). En el servidor web que se use, siguiendo el ejemplo, se tiene que poner la raíz en `/var/www/emacs-es.org/output/`. Con esto, ya se tiene lo básico. Para más información, se puede mirar en la [documentación de Venus](http://intertwingly.net/code/venus/docs/index.html) y se puede ver el repositorio de nuestro planet.
PD: El repositorio de la web está en [mi git](http://daemons.cf/cgit/planet.emacs-es.org), incluido el css de la web.

View File

@ -0,0 +1,55 @@
+++
title = "Como replicar una web de HTML estático en ZeroNet"
author = ["drymer"]
date = 2016-08-19T23:43:00+02:00
tags = ["zeronet"]
draft = false
+++
Leyendo [el articulo](https://elzorrolibre.noblogs.org/2016/07/navegando-por-zeronet/) de [@zorro](https://quitter.se/zorrito) acerca de ZeroNet me dio curiosidad por esa plataforma y me puse a probar y leer un poco sobre el tema. Para quien no lo sepa, ZeroNet es una darknet estricta que permite tener webs (y otros servicios) resistentes a la censura, ya que se distribuyen en todos los ordenadores que visitan esas webs. Funciona con la tecnología de Bitcoin (los blockchains) para firmar las webs y la red BitTorrent para distribuirlas. Al usar P2P es casi imposible hacer desaparecer una web, ya que esta estará en cualquier usuaria que la haya visitado. Es obvio por que este tipo de tecnología es tan interesante, sobretodo en los tiempos tan precarios que corren. En España mismo estamos sueltos a una vigilancia y censura cada vez más evidente.
No es la primera red de este tipo que existe, también está i2p o freenet, que de hecho son proyectos mucho más maduros, ya que al fin y al cabo ZeroNet tiene apenas un año de vida. Pero aún así hay algo que para mi lo hace un claro vencedor y es que no está hecho en puto java de los cojones, sino python. Hasta hace poco, para mi usar java era una mierda por que era usar java, pero ahora ya me resultaría imposible del todo, con el ordenador tan justo de recursos que tengo. Por lo que una red de este tipo es una bendición (Si, i2p tiene una versión en c++ en desarrollo, pero la última vez que la probé fallaba más que una escopeta de feria).
Lo que menos me gusta de la ZeroNet es la documentación, que es más bien pobre. Te dicen cómo instalarlo y como crear una web, pero todo lo demás lo tienes que averiguar tu mismo.
Pero bueno, el tema es como meter tu web de HTML estático en ZeroNet. No hay que hacer mucho, la verdad. El único tema es el de los comentarios, sea lo que sea que uses, en zeronet no funcionará, ni los comentarios de ZeroNet se postearán en la web. Yo lo que he hecho es poner un simple aviso para los usuarios de ZeroNet diciendo que si quieren comentar, que vayan a la dirección de la clearnet o la del onion. En otro articulo explicaré como lo he hecho.
Primero de todo, hay que instalar ZeroNet, lógicamente. Recomiendo para ello visitar el enlace del [articulo de @zorro](https://elzorrolibre.noblogs.org/2016/07/navegando-por-zeronet/articulo).
Una vez instalado, en el directorio en el que esté instalado, se ejecuta lo siguiente para crear la web cómo tal:
```sh
./zeronet.py siteCreate
```
Devolverá la clave pública y la clave privada. Muy importante: **hay que guardar la clave privada**. Si se pierde, la web se va a la mierda. Cuando termine de ejecutarse, se habrá creado el directorio `$RUTA_A_ZERONET/data/[Clave Pública]`. En mi caso se creó el directorio `$RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5/`. Dentro de este directorio se crea un archivo llamado `index.html` y el importante, que es `content.son`. Este archivo es una especie de sitemap de la web, cada vez que alguien visite la web, lo primero que descargará es ese archivo, en el que se listan todos los archivos que forman parte de la web unto a algún dato más.
Suponiendo que ya tengamos el HTML generado, que en mi caso está en el directorio `/home/drymer/Documentos/blog/output/`, solo hay que copiar el ya mencionado `content.son` en el directorio anterior, borrar el directorio `$RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5/` y crear un enlace simbólico del directorio del HTML al directorio `data` de ZeroNet con el nombre del directorio borrado. Igual queda más claro visto en comandos:
```sh
cp $RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5/content.son /home/drymer/Documentos/blog/output/
rm -rf $RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5/
ln -s /home/drymer/Documentos/blog/output/ $RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5
```
De este modo, sin tener que estar copiando de un lado a otro, ZeroNet ya accede a la web existente. Ahora solo queda firmarla y distribuirla.
```sh
# si se quiere automatizar, la clave privada se puede poner usto detrás de la clave pública, sino preguntará por ella
./zeronet.py siteSign $clave_publica [$clave_privada]
./zeronet.py --tor always sitePublish $clave_publica
```
Es posible que la primera vez no funcione el `sitePublish`. No he sabido encontrar un motivo claro, pero a mi me pasó. Lo que tuve que hacer es ver yo mismo la web desde el navegador y pasársela a otra persona. No se si fue lo anterior o simplemente que pasaron unos minutos, pero después ya pude publicarla sin problemas.
Y con esto ya estamos, una manera muy sencilla de replicar contenido. Mi web, por si alguien usa ya ZeroNet, está [aquí](http://127.0.0.1:43110/1M8FhYZe1j1wWGgCAf8X13eEtQxeyWmgL5/).
De regalo unos cuantos enlaces de ZeroNet que me parecen interesantes:
- [ZeroMe con un tema oscuro](http://127.0.0.1:43110/1HmJ7GadjdiQUPevaK7QXVrK4nhyCp1fSj/)
- [Un mirror de Privacy Tools](http://127.0.0.1:43110/1J625kWnshbcBk9gE9BdPr4peTeXusRzU8/)
- [Un foro en castellano](http://127.0.0.1:43110/165eqHdoQfyf7CVGqtVCGNDvMBZhwVSJBL/)
- [Una wiki en castellano](http://127.0.0.1:43110/1FwbupJhHcnFWGXuu3bn5VxcRVW9tx2tDQ/)

View File

@ -0,0 +1,138 @@
+++
title = "Cómo sacar el código de un apk"
author = ["drymer"]
date = 2016-06-05T10:11:00+02:00
tags = ["android", "docker"]
draft = false
+++
Una de las cosas buenas que tienen las aplicaciones para android, es que permiten que se examine el código fuente, sin que la licencia que tiene importe demasiado. Evidentemente, de hacerlo y querer modificarlas, no se podrían distribuir (supuestamente), ya que esto iría, de ser privativas, en contra del copyright. Es posible que ni siquiera sea legal examinarlo, ya se sabe cómo son con estas cosas. Pero cómo no pueden evitarlo, al lío.
Las órdenes estarán pensadas para usar en Ubuntu 16.04. "Oh dios mío, Ubuntu, que te ha pasado, tu antes molabas." La vida. El motivo de usarla es que encontré la manera de hacerlo apuntando a Ubuntu concretamente, y dado que lo he hecho usando docker, me da bastante igual la distribución. En teoría debería ir con cualquier distro, adaptando los paquetes a cómo se llamen en esa. Por cierto, [aquí](http://daemons.cf/cgit/dockerfiles/) está el link al repositorio git en el que tengo el Dockerfile para poder construir esa imagen. Si os da igual el cómo, podéis seguir el README y en 10 minutos estar descompilando apk. Para las que tienen curiosidad en la vida, ahí va.
Desde el propio Ubuntu, primero de todo actualizar e instalar todos los paquetes que serán necesarios. Es posible que varios ya lo estén:
```sh
su -c "apt-get update; apt-get install --no-install-recommends ca-certificates net-tools openssh-server unzip opendk-8-dk mercurial gradle patch wget"
```
Ahora, se descargaran dos herramientas básicas para darle al tema. La primera, `dex2jar`. Se descarga, descomprime, enlace simbólico y permisos de ejecución.
```sh
cd ~/
wget https://sourceforge.net/projects/dex2ar/files/dex2ar-2.0.zip/download -O dex2jar.zip
unzip dex2jar.zip
rm dex2jar.zip
```
Ahí va la primera. Esta herramienta lo que hace es pasar del formato `.dex`, que es lo que usa la máquina virtual java de Android (Dalvik) y lo pasa a un formato `jar`, lo que permite que se ejecute o se manipule con `opendk`.
La segunda herramienta es `procyon` (luego me quejo de los nombres de mis programas), que es un conjunto de herramientas de metaprogramación (su definición). Tiene un montón de cosas que nos dan muy igual, sólo nos interesa una de ellas, el `decompiler`. Ahora se clona el repositorio.
```sh
cd ~/
hg clone https://bitbucket.org/mstrobel/procyon
cd procyon
```
Un pequeño parón aquí. Hay que quitar todas las líneas en las que salga "sign" del archivo **build.gradle**. Lo podéis hacer a mano o podéis guardar el siguiente bloque de código con el nombre de parche en el directorio `procyon` y aplicarlo con `patch < parche` en el directorio del programa.
```diff
diff -r 1aa0bd29339b build.gradle
--- a/build.gradle Sat May 21 11:20:43 2016 -0400
+++ b/build.gradle Tue May 31 12:11:49 2016 +0000
@@ -59,7 +59,6 @@
subprojects {
apply plugin: 'maven'
- apply plugin: 'signing'
archivesBaseName = 'procyon-' + it.name.split("\\.")[1].toLowerCase()
@@ -91,10 +90,6 @@
archives sourcesar
}
- signing {
- sign configurations.archives
- }
-
uploadArchives {
repositories.mavenDeployer {
beforeDeployment { MavenDeployment deployment ->
```
Solo queda compilar el programa. Puede que de algún warning, es un poco quejica. Pero si no es más que eso, debería funcionar correctamente:
```sh
gradle fatar
```
Y con esto, ya podemos empezar a descompilar `apk`. El proceso viene a ser, pasar los `.dex` a `.jar` y descompilarlo sin más. Las órdenes serian:
```sh
# aquí tenemos el apk, por ejemplo
cd ~/apk
mv com.ejemplo.apk com.ejemplo.apk.zip
unzip com.ejemplo.apk.zip
dex2jar classes.dex
mkdir ~/src
java -jar ~/procyon/build/Procyon.Decompiler/libs/procyon-decompiler-0.5.32.ar -jar classes-dex2jar.jar -o ~/src
```
Y con esto ya esta. Es bastante sencillo. Pero un poco coñazo, sobretodo si se piensa que esto no se hace de manera habitual (yo no tengo por costumbre descomprimir apk). Si se hace muy de vez en cuando, cada vez que se haga habrá que remirar este articulo, o unos apuntes o lo que sea. Por ello, vamos a dejarlo bonico der to con un par de enlaces simbólicos y algunos scripts.
```sh
ln -s ~/dex2ar-2.0/d2-dex2ar.sh /usr/local/bin/dex2ar
chmod +s ~/dex2ar-2.0/d2-dex2ar.sh ~/dex2ar-2.0/d2_invoke.sh
```
El siguiente script, se meterá en `/usr/local/bin/decompiler` y se le dará permisos de ejecución con `chmod +x /usr/local/bin/decompiler`. **Aviso**: hay que tener en cuenta que en ambos scripts se da por supuesto que los programas están en la raíz de `/home/$USER`. Si no está ahí, debería adaptarse.
```sh
#!/bin/bash
if [ -z "$1" ] || [ -z "$2"]
then
echo "You need to pass the apk path and the output path as an argument. Exiting..."
exit
fi
java -jar ~/procyon/build/Procyon.Decompiler/libs/procyon-decompiler-0.5.32.ar -jar "$1" -o "$2"
```
Lo mismo con el siguiente, pero con el nombre de `/usr/local/bin/automatic-decompile` y se le dará permisos de ejecución con `chmod +x /usr/local/bin/automatic-decompile`. Este nombre no tiene por que ser así, pero el anterior si que debe llamarse `decompiler`, ya que está hardcodeado en el siguiente.
```sh
#!/bin/bash
if [ -z "$1" ]
then
echo "You need to pass the apk path as an argument. Exiting..."
exit
fi
mkdir -p ~/tmp/"$1"
cp "$1" ~/tmp/"$1"/"$1".zip
cd ~/tmp/"$1"/
echo "Unziping apk..."
unzip "$1".zip > /dev/null
echo "Executing dex2jar..."
dex2ar classes.dex 2> /dev/null
echo "Decompiling ar..."
mkdir -p ~/src/"$1"
decompiler classes-dex2ar.ar ~/src/"$1" > /dev/null
echo "Done. The source code is under ~/src/$1/. You can delete ~/tmp."
```
Y ale. De este modo, para descomprimir un `apk` sólo habrá que ejecutar:
```sh
automatic-decompile /ruta/al/apk
```
Entonces, se crearán dos directorios, `~/tmp/` `~/src/`. El código estará disponible en el segundo, el primero, cómo su nombre indica, se podrá borrar. Más sencillo de recordar entre uso y uso, creo yo.

View File

@ -0,0 +1,28 @@
+++
title = "Como crear subdominios en los servicios ocultos de Tor"
author = ["drymer"]
date = 2016-11-03T08:30:00+01:00
tags = ["tor"]
draft = false
+++
Es estúpidamente sencillo. No sé cuanto tiempo lleva esta opción activa, por que no la he visto anunciada en ningún sitio, simplemente he visto que que la gente lo ha empezado a usar sin más. El tema de los subdominios curiosamente no lo gestiona Tor como tal, sino los virtual hosts de los servicios. Si aún no sabéis como configurar un servicio oculto de Tor, podéis leer [este articulo](https://daemons.cf/posts/crear-un-hidden-service-con-tor/).
Un ejemplo tonto, redirigir el subdominio www de daemon4idu2oig6.onion al propio daemon4idu2oig6.onion.
```nginx
server {
listen 127.0.0.1:80;
server_name www.daemon4idu2oig6.onion;
return 301 http://daemon4idu2oig6.onion$request_uri;
}
```
Esto ya debería pasar si se han tomado las precauciones mínimas que es establecer un default\_server en el virtual\_host general, pero bueno. En el caso de prosody, para añadir salas de chat:
```lua
Component "salas.daemon4idu2oig6.onion" "muc"
name = "Salas de Bad Daemons"
```
Y ale, a correr. Según parece, todos los subdominios apuntan a donde apunte el tld principal, si el servidor sabe gestionar ese nombre, lo hará.

View File

@ -0,0 +1,139 @@
+++
title = "Como gestionar las configuraciones y programas de tu ordenador con Ansible"
author = ["drymer"]
date = 2018-01-08T08:30:00+01:00
tags = ["ansible"]
draft = false
+++
Hace relativamente poco abandoné Slackware por Debian por dos motivos. Uno fue que mi ordenador no tenia mucha potencia y me cansé de compilar y el segundo que quería automatizar la gestión de todo lo que tuviese que ver con mi ordenador, tanto la instalación de paquetes del sistema operativo, paquetes pip y paquetes compilados, como la configuración de ciertos programas. Así que me puse a ello y creé unos cuantos roles. Algunos se pueden reutilizar, los veremos a continuación mientras explico por encima como funciona Ansible y que tiene de genial.
La lista de roles que he hecho y que pueden utilizarse son los siguientes:
- [virtualenvwrapper](https://git.daemons.it/ansible-roles/virtualenvwrapper/commits/master)
- [syncthing](https://git.daemons.it/ansible-roles/syncthing)
- [emacs](https://git.daemons.it/ansible-roles/emacs)
- [virtualbox](https://git.daemons.it/ansible-roles/virtualbox)
- [qutebrowser](https://git.daemons.it/ansible-roles/qutebrowser)
- [termite](https://git.daemons.it/ansible-roles/termite)
- [slim](https://git.daemons.it/ansible-roles/slim)
- [i3-gaps](https://git.daemons.it/ansible-roles/i3-gaps)
- [fonts](https://git.daemons.it/ansible-roles/fonts)
- [docker](https://git.daemons.it/ansible-roles/docker)
Al crear roles hay que intentar seguir la filosofía de roles atómicos, que significa crear roles con una función muy específica de modo que sean muy manejables, fáciles de mantener y de reutilizar. Veamos la estructura de uno de ellos, por ejemplo el rol de instalación de [slim](https://wiki.archlinux.org/index.php/SLiM%5F(Espa%25C3%25B1ol)):
```text
~/Documentos/ansible/roles/desktop/slim
├── defaults
│   └── main.yml
├── files
│   ├── slim.service
│   └── xinitrc
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
└── tasks
└── main.yml
```
Están los directorios:
- **defaults**: Para definición de variables.
- **files**: Para ficheros externos al rol.
- **handlers**: Para el maneo de servicios.
- **meta**: Para manear metadatos del rol.
- **tasks**: Para dotar al rol de funcionalidad.
En **defaults** se define la variable `session_manager`, que define un gestor de sesiones que será desactivado. En **files** está el servicio de systemd de `slim` y el fichero `xinitrc`, en el que se arranca i3-wm. En **handlers** se deshabilita el gestor de sesiones de `session_manager` y se habilita `slim`. En **meta** se concretan los metadatos del rol, como ya he comentado. En la práctica no es demasiado relevante, pero cuando se instala un rol con `ansible-galaxy` se queja si no existe (ya comentaremos este programa). Y por último, las tareas:
```yaml
---
# tasks file for slim
- name: Install slim in debian or derivates
become: yes
apt:
name: slim
state: present
update_cache: yes
- name: Modify /etc/slim.conf
become: yes
lineinfile:
path: /etc/slim.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
with_items:
- { regexp: "#? ?numlock", line: "numlock on" }
- { regexp: "#? ?hidecursor", line: "hidecursor true" }
- { regexp: "^login_cmd", line: "login_cmd exec /bin/sh - ~/.xinitrc" }
- name: Copy slim systemd service
become: yes
copy:
src: "{{ role_path }}/files/slim.service"
dest: /lib/systemd/system/slim.service
force: yes
when:
ansible_connection != 'docker'
or
force_docker == 'yes'
notify:
- disable session manager
- enable slim
```
Ansible usa el formato yaml para sus ficheros. Esto mola mucho por que es muy legible. Sin saber nada de Ansible se puede entender bastante lo que hace. Analicemos la primera tarea:
- `name`: Es el nombre de la tarea, para poder identificarla cuando se ejecute el rol.
- `become`: Se usa para escalar privilegios. Por defecto uso `sudo`, pero puede usarse `su`.
- `apt`: Es el módulo de apt. Los módulos son el fuerte de Ansible, permiten ejecutar tareas concretas (si están bien hechos) de forma idempotente. Esto significa que una tarea puede ejecutarse **n** veces pero solo provocará cambios si es necesario. En el caso de este módulo, solo instala un paquete si este no está instalado. El equivalente de esta tarea seria el siguiente:
```bash
sudo apt update
sudo apt install slim -y
```
La siguiente tarea usa el módulo `lineinfile`, que sirve para modificar ficheros. Se le pasa la variable `path` para determinar la ruta del fichero a modificar, la variable `regexp` para la expresión regular que queremos cambiar y la variable `line` para lo que se quiere que substituya lo que encaje con la expresión regular. Además, aquí se puede ver como se usa un bucle en Ansible.
En la última tarea vemos el módulo `copy`, que sirve para copiar un fichero local con la variable `src` al destino de la variable `dest`. Y además podemos ver la palabra clave `when`, que sirve para gestionar condicionales. En este caso, se copia ese fichero cuando la variable `ansible_connection` es diferente a **docker** o la variable `force_docker` es `yes`.
Hasta aquí hemos visto lo que es un rol de Ansible. Al principio he puesto la lista de los que pueden ser relevantes para otras personas. Para utilizar alguno de ellos, hay que crear un playbook. Si solo quisiésemos usar el rol de `slim`, seria así:
```yaml
- hosts: localhost
connection: local
vars:
install_dir: ~/Instalados/
roles:
- slim
```
La palabra clave `hosts` apunta al host **localhost**, valga la redundancia. `connection` por defecto usa ssh, pero como es una conexión al propio ordenador, es mejor usar el valor `local`, que es más rápido. Con `vars` definimos variables a usar en los roles y `roles` para los roles. Como dije, lo bueno que tiene el lenguaje de Ansible es que es muy claro si sabes inglés.
Ahora tocará ver como gestionar las dependencias de roles. Se podría tirar de submódulos de git, pero por suerte Ansible provee de una herramienta para esto, `ansible-galaxy`. Por defecto instala del [hub de ansible-galaxy](https://galaxy.ansible.com/explore), un repositorio centralizado de roles. Por lo tanto no tengo mayor interés en usarlo. Por ello tengo la costumbre de usar `ansible-galaxy` con repositorios git sin más. Para instalar roles, hay que crear un fichero llamado `requirements.txt` y llenarlo de roles en un formato como este:
```text
- src: git+https://git.daemons.it/ansible-roles/slim
```
Una vez creado el fichero, solo hay que ejecutar `ansible-galaxy install -r requirements.txt -p roles`. Y a reusar roles a dos manos.
Para ver un ejemplo más completo de como hacerse un playbook que gestione todos los roles que hagan falta, se puede ver [mi repositorio principal de dotfiles](https://git.daemons.it/drymer/dotfiles).
Por último solo queda hablar de la documentación. En la [documentación oficial](http://docs.ansible.com/ansible/latest/index.html) de Ansible se puede encontrar mucha información relevante, pero la herramienta más útil para mi es `ansible-doc`. Viene por defecto al instalar Ansible y permite ver la documentación completa de un módulo concreto.
Lyz ha dado varias charlas en La Brecha Digital sobre Ansible y tiene los índices en el [repositorio de charlas de La Brecha Digital](https://git.digitales.cslabrecha.org/La%5FBrecha%5FDigital/charlas-y-talleres/src/master/20171108-basic-ansible-Lyz), por si alguien le quiere echar un ojo. Cualquier duda sólo hay que preguntarla ya sea en los comentarios o en la sala XMPP de [La Brecha Digital](https://www.suchat.org/jappix/?r=brechadigital%5Fgestion@sala.chat.cslabrecha.org&n=daemonita).

View File

@ -0,0 +1,21 @@
+++
title = "Añadir automáticamente símbolos de marcado en org-mode"
author = ["drymer"]
date = 2016-09-27T09:33:00+02:00
tags = ["orgmode", "emacs"]
draft = false
+++
Quien use [org-mode](https://daemons.cf/categories/orgmode/) sabrá de la existencia de los símbolos de marcado. Me refiero la _cursiva_, el <span class="underline">subrayado</span>, **negrita** y el `resaltado`. Yo, como soy muy vago, he buscado la forma de que al presionar una vez cualquiera de los carácteres de marcado anteriores se inserte el segundo, del mismo modo que `electric-pair-mode` cierra los paréntesis o los corchetes.
Para ello hay que modificar la tabla de sintaxis de **org-mode**:
```emacs-lisp
(with-eval-after-load 'org
(modify-syntax-entry ?/ "(/" org-mode-syntax-table)
(modify-syntax-entry ?* "(*" org-mode-syntax-table)
(modify-syntax-entry ?_ "(_" org-mode-syntax-table)
(modify-syntax-entry ?= "(=" org-mode-syntax-table))
```
Si hacéis cómo yo, que lo primero que hacéis es cargar **org-mode**, el `with-eval-after-load` no hace falta.

View File

@ -0,0 +1,39 @@
+++
title = "Buscar en el buffer de emacs"
author = ["drymer"]
date = 2016-05-18T19:18:00+02:00
tags = ["emacs", "helm"]
draft = false
+++
El siguiente paquete es de los buenos. Para buscar en un buffer, se suele usar `isearch`, que se ejecuta con `C-s`. Con esto se puede buscar una palabra o varias siempre que estén en orden. Yo echaba en falta el poder buscar mediante expresiones regulares, cómo hace `helm`. Entonces encontré `helm-swoop`. Este permitía hacer justo lo que andaba buscando, sólo habia que bindejarlo a `C-s` y a volar. Pero entonces perdía el comportamiento por defecto de `isearch`, lo cual no quería hacer, de poder evitarlo. Y el siguiente paquete fue la clave `ace-isearch-mode`.
Este paquete tiene tres dependencias,que son `isearch`, `avy` o `ace-jump` y `helm-swoop`. `ace-jump` y `avy` lo que hacen es pedir un carácter y luego mostrar las coincidencias en el buffer y asociar una letra a cada coincidencia. Al escribir esa letra asociada, mueve el cursor a esa posición. Hacen lo mismo sólo que de manera distinta, por lo que se puede escoger cualquiera de los dos.
{{< figure src="/img/avy.gif" caption="Figura 1: avy" >}}
Al ejecutar la función de búsqueda, se presiona `e a a` y lleva a la primera `e` del buffer, que es la de el primer parágrafo.
{{< figure src="/img/ace.gif" caption="Figura 2: ace" >}}
Al ejecutar la función de búsqueda, se presiona `e a a` y lleva a la primera `e` del buffer, que es la de el primer parágrafo.
Entonces, de que modo se combinan las tres funciones? Se presiona `C-s` y al escribir un carácter, se usa `ace-jump`. Al escribir cuatro más, osea cinco carácteres, se usa `isearch`, y al llegar a las seis o más, se usa `helm-swoop`. Muy versátil.
Ahora al lío. Se instalan los paquetes `M-x package-install RET ace-jump`, `M-x package-install RET helm-swoop` y `M-x package-install RET ace-isearch`.
Se configura con las siguientes lineas:
```emacs-lisp
(custom-set-variables
'(ace-isearch-input-length 7)
'(ace-isearch-jump-delay 0.25)
'(ace-isearch-function 'avy-goto-char)
'(ace-isearch-use-jump 'printing-char))
```
Y a buscar más eficientemente.
Más información en su [repositorio git](https://github.com/tam17aki/ace-isearch).
[La sección](https://daemons.cf/stories/mi-configuracin-de-emacs/#Buscar más eficazmente en Helm) pertinente en mi configuración.

View File

@ -0,0 +1,53 @@
+++
title = "Escapar símbolos al usar marcado en org-mode"
author = ["drymer"]
date = 2016-05-30T09:34:00+02:00
tags = ["orgmode", "emacs"]
draft = false
+++
Un caso que puede sonarle a alguien, es usar rutas. Si se escribe en org-mode las palabras /home/drymer/, por ejemplo, pasará que al exportar o en el mismo buffer si tenemos activado `org-hide-emphasis-markers`, veremos que /home/drymer/ pasa a ser _home/drymer_, en cursiva y sin la primera y última barra. Por suerte, hay una manera sencilla de escapar estos carácteres usando entidades org (`org-entities`).
Las entidades de org son parecidas al latex. En vuestro editor con un buffer en `org-mode`, escribid `\ast{}`. Se ve igual? De ser así, ejecutad `M-x org-toggle-pretty-entities` y voila, el `\ast{}` pasa a ser un &lowast;.
Ahora, alguien se podría dar cuenta de que cada símbolo que se quiera usar tiene su "código" asociado, por lo que memorizarlo debe ser acojonante. Pero llega al recate el conocimiento en común. Hay un humano que soluciona este problema, cómo se puede ver en [Stack Overflow](http://emacs.stackexchange.com/questions/16688/how-can-i-escape-the-in-org-mode-to-prevent-bold-fontification/16746#16746). Cómo ahí se cuenta, hubo un debate de la mejor manera de escapar símbolos y acabó sacando ese par de funciones. Aún así, estaba hecha para funcionar en emacs 25, en las 24.&lowast; no funcionaba. Pero, después de un [intercambio de correos](http://lists.gnu.org/archive/html/emacs-orgmode/2016-05/msg00135.html) en la lista pudo arreglarlo y actualizo la función que aparece en Stack Overflow. Ahora, es tan sencillo cómo presionar `C-u SIMBOLO`, siendo SIMBOLO el símbolo que queremos que aparezca. Bien sencillo. Y ahora, el código.
```emacs-lisp
(setq org-pretty-entities t)
(defun modi/org-entity-get-name (char)
"Return the entity name for CHAR. For example, return \"ast\" for *."
(let ((ll (append org-entities-user
org-entities))
e name utf8)
(catch 'break
(while ll
(setq e (pop ll))
(when (not (stringp e))
(setq utf8 (nth 6 e))
(when (string= char utf8)
(setq name (car e))
(throw 'break name)))))))
(defun modi/org-insert-org-entity-maybe (orig-fun &rest args)
"When the universal prefix C-u is used before entering any character,
insert the character's `org-entity' name if javailable."
(let ((pressed-key (char-to-string (elt (this-single-command-keys) 0)))
entity-name)
(when (and (listp args) (eq 4 (car args)))
(setq entity-name (modi/org-entity-get-name pressed-key))
(when entity-name
(setq entity-name (concat "\\" entity-name "{}"))
(insert entity-name)
(message (concat "Inserted `org-entity' "
(propertize entity-name
'face 'font-lock-function-name-face)
" for the symbol "
(propertize pressed-key
'face 'font-lock-function-name-face)
"."))))
(when (null entity-name)
(apply orig-fun args))))
(advice-add 'org-self-insert-command :around #'modi/org-insert-org-entity-maybe)
```

View File

@ -0,0 +1,68 @@
+++
title = "Escribir prosa en emacs"
author = ["drymer"]
date = 2016-03-19T02:00:00+01:00
tags = ["orgmode", "emacs"]
draft = false
+++
Hoy inauguro una sección del blog que se llamará cómo el título, "Cosillas de emacs" seguido de un guión y un nombre descriptivo de lo que sea de lo que se habla. A título de curiosidad, [nikola](http://daemons.cf/posts/nikola-emacs-gestionar-un-blog-de-contenido-esttico/) crea RSS de las diferentes etiquetas que se usan en el sitio, por lo que si sólo interesa subscribir se a, por ejemplo, la etiqueta **emacs**, se va abajo del todo, etiquetas, emacs y se verá un índice con todos los articulos y el link al RSS. Mola.
Hay un motivo muy fuerte para escoger org-mode delante de cualquier otro lenguaje de marcado, y es la opción de la exportación. A continuación una lista de los formatos a los que se puede exportar **por defecto**: ascii, beamer, html, icalendar, latex, man, md, odt, texinfo. Y en [contribuciones](http://orgmode.org/worg/org-contrib/#orgheadline2) unos cuantos más: bibtex, confluence, freemind, rss, entre otros.
Si por lo que sea se odia org-mode, se puede usar **markdown**, **ReST**, **LaTeX** con sus respectivos modos markdown-mode, rst-mode y latex-mode. Algunos modos o paquetes complementarios:
- Markdown: [markdown-toc](https://github.com/ardumont/markdown-toc) y [markdown-preview-mode](https://github.com/ancane/markdown-preview-mode)
- LaTeX: [latex-preview-pane](https://www.emacswiki.org/emacs/LaTeXPreviewPane)
Y hasta aquí las cosas aburridas, ahora **org-mode** y la diversión (sin banderas). Primero unas pocas líneas de código lisp que a mi me van bien.
Por defecto emacs trunca las líneas largas, con la siguiente línea esto se evita.
```lisp
;; No truncar
(setq toggle-truncate-lines t)
```
Seguir los hipervínculos apretando RET.
```lisp
;; RET or TAB to follow a link
(setq org-return-follows-link t)
(setq org-tab-follows-link t)
```
Una función que ayuda en la creación de bloques de código. Se evalúa lo siguiente y al ejecutarla (`M-x org-insert-src-block`) se escogerá el lenguaje del código y se abrirá un buffer en el que se podrá editar el código.
```lisp
;; insert source block
(defun org-insert-src-block (src-code-type)
"Insert a `SRC-CODE-TYPE' type source code block in org-mode."
(interactive
(let ((src-code-types
'("emacs-lisp" "python" "C" "sh" "java" "s" "clojure" "C++" "css"
"calc" "asymptote" "dot" "gnuplot" "ledger" "lilypond" "mscgen"
"octave" "oz" "plantuml" "R" "sass" "screen" "sql" "awk" "ditaa"
"haskell" "latex" "lisp" "matlab" "ocaml" "org" "perl" "ruby"
"scheme" "sqlite")))
(list (ido-completing-read "Source code type: " src-code-types))))
(progn
(newline-and-indent)
(insert (format "#+BEGIN_SRC %s\n" src-code-type))
(newline-and-indent)
(insert "#+END_SRC\n")
(previous-line 2)
(org-edit-src-code)))
```
Resaltar la sintaxis de dentro de los bloques de código.
```lisp
(setq org-src-fontify-natively t)
'(org-fontify-inline-src-block)
```
Con esto se cubre lo básico. Para la corrección ortográfica se puede usar `ispell`, que viene instalado por defecto. Se ejecuta con `M-x ispell-buffer`, por ejemplo.
Aún quedan pequeñas cosas, pero ya irán saliendo. El último par de cosas son una chorrada (sobretodo la segunda), pero nunca se sabe. [olivetti-mode](https://github.com/rnkn/olivetti) centra el texto en medio de la pantalla dejando laterales, permitiendo así poder concentrarse en la escritura. Y la última gilipollez, [selectric-mode](https://github.com/rbanffy/selectric-mode) que imita el ruido de una máquina de escribir. Por lo de los teclados silenciosos y eso. En próximas entregas se verá cómo sacarle más provecho aún a **org-mode**.

View File

@ -0,0 +1,93 @@
+++
title = "Un par de funciones útiles de emacs"
author = ["drymer"]
date = 2016-05-01T01:35:00+02:00
tags = ["emacs", "snippets", "orgmode"]
draft = false
+++
No tengo ni idea de elisp, pero aún así me las he apañado para hacer un par de snippets medio útiles para un par de cosas que me hacían falta. Las he hecho basándome en dos articulos, [este](http://pragmaticemacs.com/emacs/wrap-text-in-an-org-mode-block/) y [este](http://wenshanren.org/?p=334). Seguro que se pueden optimizar.
La primera de ellas sirve para insertar cabeceras típicas en `org-mode`. Le he puesto sólo tres tipos, ya que son los que uso para exportar. Después de evaluar el código y ejecutar la función, mediante `ido` aparecerá una pregunta que nos dará a escoger entre los distintos tipos. Sólo hay que escogerlo y se insertará (en la posición del buffer en la que se esté) la cabecera. El código es el siguiente:
```emacs-lisp
(defun org-mode-insert-header (language)
"Make a template at point."
(interactive
(let ((languages '("Generic" "HTML" "LaTeX" )))
(list (ido-completing-read "To which export: " languages))
)
)
(when (string= language "Generic")
(progn
(insert (format "#+TITLE:\n"))
(insert (format "#+AUTHOR:\n"))
(insert (format "#+LANGUAGE: es \n"))
(insert (format "#+OPTIONS: toc:1\n"))
(insert (format "#+TOC: headlines 3\n"))
(insert (format "#+STARTUP: indent\n\n"))
)
)
(when (string= language "HTML")
(progn
(insert (format "#+TITLE:\n"))
(insert (format "#+AUTHOR:\n"))
(insert (format "#+LANGUAGE: ca\n"))
(insert (format "#+OPTIONS: toc:1\n"))
(insert (format "#+TOC: headlines 3\n"))
(insert (format (concat "#+SETUPFILE: " user-emacs-directory "/css/org-html-themes/setup/theme-readtheorg.setup\n\n")))
)
)
(when (string= language "LaTeX")
(progn
(insert (format "#+Title:\n"))
(insert (format "#+Author:\n"))
(insert (format "#+LANGUAGE: es\n"))
(insert (format "#+LATEX_CLASS: article\n"))
(insert (format "#+LATEX_CLASS_OPTIONS: [spanish,a4paper]\n"))
(insert (format "#+LATEX_HEADER: \\usepackage{color}\n"))
(insert (format "#+LATEX_HEADER: \\usepackage[spanish]{babel}\n\n"))
)
)
)
```
Lo suyo es modificar el código para que se adecue a las necesidades de quien lo usa.
El siguiente snippet de código sirve para insertar bloques de código. Se puede usar tanto de manera normal cómo al resaltar un trozo de código o letras. Es un poco dificil de explicar, por lo que he hecho un gif para mostrarlo.
{{< figure src="/img/insert-src.gif" >}}
El código es:
```emacs-lisp
(defun org-src-insert (choice)
"Insert src code blocks."
(interactive
(if (org-at-table-p)
(call-interactively 'org-table-rotate-recalc-marks)
(let ((choices '("emacs-lisp" "python" "shell" "css" "ledger" "latex" "lisp" "sqlite")))
(list (ido-completing-read "Source code type: " choices)))))
(cond
((region-active-p)
(let ((start (region-beginning))
(end (region-end)))
(progn
(goto-char end)
(insert "\n#+END_SRC\n")
(goto-char start)
(insert (format "#+BEGIN_SRC %s\n" choice)))
)
)
(t
(insert (format "#+BEGIN_SRC %s\n" choice))
(save-excursion (insert "\n#+END_SRC")))))
```

View File

@ -0,0 +1,28 @@
+++
title = "Curso completo LFS201"
author = ["drymer"]
draft = true
+++
Durante el año anterior estuve publicando en GNU social los apuntes que iba haciendo del curso [Essentials of System Administration](https://training.linuxfoundation.org/linux-courses/system-administration-training/essentials-of-system-administration) de la Linux Foundation. En un principio eso iba a ser todo, mis apuntes, por que copiar todo el curso iba a ser complicado. Pero hubo suerte, por haber publicado los apuntes y alguna queja sobre el curso (se puede ver en el [README](https://daemons.cf/cgit/apuntes-LFS201/about/) del repositorio git) me contactó una persona con la que he ido manteniendo el contacto, que me confirmó que el curso era bastante mierdoso y que ella había conseguido sacar el código HTML de este. Esta persona prefiere quedar en el anonimato, pero a quien le sirva el curso que le mande muchos besitos imaginarios.
Al final he desde mis apuntes, ya que pueden servir de algo a alguien, pero el curso es la fuente oficial, así que vosotros veréis. Hay varias cosas del examen que deberian saberse, recomiendo leer el README detenidamente y sobretodo la página de la certificación.
Este curso te prepara para ser un sysadmin del ñú, al examinarse hay que escoger entre Ubuntu, openSUSE y Red Hat. El curso varia en precio, yo lo cogí por unos 200€ y ahora está en 400€. Lo que si es cierto es que suele haber al menos 200€ entre el precio del curso y el del examen solamente.
Se puede acceder de distintos modos al curso:
- Clonar el repositorio
```sh
git clone https://daemons.it/drymer/apuntes-LFS201/
```
- Verlo online
- [Apuntes HTML](https://daemons.cf/LFS201/apuntes.html)
- [Apuntes PDF](https://daemons.cf/LFS201/apuntes.pdf)
- [Curso HTML](https://daemons.cf/LFS201/curso-completo.html)
Probablemente haya alguna falta o esté mal formateado, de ser así agradeceré un correo o un comentario.

View File

@ -0,0 +1,35 @@
+++
title = "Cutrescript para mostrar posts de tags de GNU social"
author = ["drymer"]
date = 2017-10-29T17:51:00+01:00
tags = ["python", "gnusocial"]
draft = false
+++
A este cutrescript, que no merece ni estar en un repositorio de git, se le pasa el parámetro del servidor y el parámetro del tag y imprime todas las noticias de ese servidor que tengan ese tag:
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import son
import sys
server = sys.argv[1]
tag = sys.argv[2]
nota = 1
posts = requests.get('https://' + server + '/api/statusnet/tags/timeline/' +
tag + '.son?count=200').text
posts = son.loads(posts)
for post in reversed(posts):
print("Nota " + str(nota) + ': ' + post['text'].replace(
' #' + tag, ''))
nota += 1
```
Quien me siga en GS habrá visto que estaba muy pesado con el tag #learningdocker. Lo que he estado haciendo es leer un libro, del cual ya hablaré en otro articulo, y de mientras usar GNU social como libreta de apuntes. Es mejor que usar el propio programa de apuntes del e-book e infinitamente mejor que usar una libreta de papel. Odio escribir en papel. Y GNU social me parece útil para esto, por que como es algo que puedo estar un tiempo largo haciendo, siempre puedo recuperarlo de forma fiable, además de que creo que puede ser útil leer a trocitos.

View File

@ -0,0 +1,34 @@
+++
title = "Editar archivos de un contenedor docker desde emacs"
author = ["drymer"]
date = 2016-06-19T23:12:00+02:00
tags = ["docker", "emacs"]
draft = false
+++
Fiate tu la cosa más tonta que es, y yo iba tirando de `ssh` y `tramp`, lo que es muy incoḿodo. Pero de casualidad, buscando otra cosa en la [wiki de emacs](http://wikiemacs.org), encontré un [pequeño snippet](https://www.emacswiki.org/emacs/TrampAndDocker) que facilita las cosas.
```emacs-lisp
(push
(cons
"docker"
'((tramp-login-program "docker")
(tramp-login-args (("exec" "-it") ("%h") ("/bin/sh")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-i") ("-c"))))
tramp-methods)
(defadvice tramp-completion-handle-file-name-all-completions
(around dotemacs-completion-docker activate)
"(tramp-completion-handle-file-name-all-completions \"\" \"/docker:\" returns
a list of active Docker container names, followed by colons."
(if (equal (ad-get-arg 1) "/docker:")
(let* ((dockernames-raw (shell-command-to-string "docker ps | awk '$NF != \"NAMES\" { print $NF \":\" }'"))
(dockernames (cl-remove-if-not
#'(lambda (dockerline) (string-match ":$" dockerline))
(split-string dockernames-raw "\n"))))
(setq ad-return-value dockernames))
ad-do-it))
```
Como podéis observar, se añade un tercer modo a `tramp` que no es `ssh` ni `scp`. Lo que hace es conectarse usando la propia shell de docker. Muy cómodo, más que estarse preocupando de si el `ssh` del contenedor está en marcha o no. La segunda función, además, nos mostrará los nombres de los contenedores en funcionamiento, teniendo sólo que escoger el que se quiera editar. Se evalua el anterior snippet y se usa del siguiente modo: `C-x C-f /docker:$nombreDelContenedor:$rutaDelArchivo`. Y a ser felices.

View File

@ -0,0 +1,35 @@
+++
title = "Ejecución asíncrona de bloques babel en org-mode"
author = ["drymer"]
date = 2017-05-28T11:23:00+02:00
tags = ["emacs"]
draft = false
+++
En el articulo sobre la [programación literaria para sysadmins](https://daemons.it/posts/programacin-literaria-para-sysadminsdevops/) se pudo ver que los bloques de babel en org-mode son muy útiles. Lo malo que tiene ejecutar estos bloques es que se bloquea emacs. El dichoso tema de la concurrencia de nueva. Pero como siempre, se puede trampear.
Se puede abrir un proceso paralelo de emacs para que ejecute el bloque sin que bloquee el proceso de emacs principal. Me estaba pegando con ello justo cuando descubrí que alguien ya lo habia hecho mejor. Veamos un ejemplo. Primero un ejemplo síncrono, que no tiene mucho sentido pero es gratis:
<a id="org3b6e1ac"></a>
{{< figure src="/img/no-async-babel.gif" >}}
<a id="org24a915c"></a>
{{< figure src="/img/async-babel.gif" >}}
Muy fácil de usar, como se puede ver. Lo único malo que tiene es que no se puede usar la variable `:session`, por lo tanto se pierde la idempotencia. Se puede usar `:noweb`, pero cada bloque ejecutará todo lo anterior, lógicamente. Pero bueno, no me suele afectar demasiado para lo que uso. Para instalar el paquete que habilita este parámetro hay que añadir esto al archivo de configuración de emacs:
```emacs-lisp
(add-to-list 'el-get-sources '(:name ob-async
:type github
:pkgname "astahlman/ob-async"))
(if (not (el-get-package-installed-p 'ob-async))
(el-get 'sync 'ob-async))
(use-package ob-async
:load-path "el-get/ob-async/")
```
Una vez instalado y configurado, se puede usar como cualquier otro parámetro de bloque. Se puede establecer en el propio bloque, como se puede ver en el segundo gif, o se puede establecer como una propiedad en un árbol.

View File

@ -0,0 +1,99 @@
+++
title = "el-get: Otro instalador de paquetes"
author = ["drymer"]
date = 2016-10-24T11:50:00+02:00
tags = ["emacs"]
draft = false
+++
Alguien se podría preguntar, para que queremos otro, si ya tenemos `package.el`, que además viene por defecto en emacs? Pues es simple, no todos los paquetes están en melpa, elpa o marmalade. O igual si que están pero queremos usar una rama concreta del repositorio.
Hasta ahora yo maneaba esto instalándolo desde terminal con git y ale, a volar. Pero también tenia algún paquete que habia copiado directamente de [la wiki de emacs](https://www.emacswiki.org), con el tiempo se me podría haber olvidado de donde lo he sacado. Pero ya no, por que lo tengo controlado con el-get, que permite usar muchos instaladores. Yo solo he probado el de git y el de la wiki de emacs, pero por poder se puede tirar de `apt-get`, `brew`, `elpa`, `dpkg`, etc. Así que al lío:
Se instala el-get desde elpa o usando su instalador. `M-x package-install RET el-get RET` para lo primero, o para asegurarse de que siempre esté disponible:
```lisp
;; Añade la ruta de el-get
(add-to-list 'load-path "~/.emacs.d/el-get/el-get/")
;; Comprueba si el-get está instalado, sino lo instala desde un gist
(unless (require 'el-get nil 'noerror)
;; Comprobar si existe el fichero a descargar, si existe no lo descarga
(if (not (file-exists-p "/tmp/el-get-install.el"))
(url-copy-file "https://raw.githubusercontent.com/dimitri/el-get/master/el-get-install.el" "/tmp/el-get-install.el"))
(load-file "/tmp/el-get-install.el")
)
(use-package el-get)
```
Y de paso aprendemos un poquito de elisp. `unless` se traduce en "a menos que". Por lo tanto, la primera linea relevante viene a ser "a menos que cargue el paquete `el-get`, descarga el fichero `el-get-install.el` en /tmp/". Tanto si lo descarga como si no, ejecuta el instalador que clonará el repositorio git en `~/.emacs.d/el-get/el-get/`. Las lineas se pueden poner tal cual en el archivo de configuración, así nos aseguramos de que siempre está.
En el repositorio git hay un montón de recetas para muchísimos paquetes, tanto de los que están en elpa como en distintos repositorios git. Evidentemente luego se puede definir tus propias recetas, que es lo que veremos a continuación. Pondré las referentes a mi configuración, por poner unos ejemplos.
```lisp
(add-to-list 'el-get-sources '(:name xlicense-github
:type github
:pkgname "timberman/xlicense-el"
))
```
<div class="src-block-caption">
<span class="src-block-number">Listado de programa 1</span>
xlicense
</div>
```lisp
(add-to-list 'el-get-sources '(:name org2nikola
:website "https://github.com/redguardtoo/org2nikola.git"
:description "Export org into HTML used by static blog generator nikola."
:type git
:url "https://github.com/redguardtoo/org2nikola.git"
:load-path ("./")
))
```
<div class="src-block-caption">
<span class="src-block-number">Listado de programa 2</span>
org2nikola
</div>
```lisp
(add-to-list 'el-get-sources '(:name org-mode-maint
:website "http://orgmode.org/"
:description "Org-mode is for keeping notes, maintaining ToDo lists, doing project planning, and authoring with a fast and effective plain-text system."
:type git
:url "git://orgmode.org/org-mode.git"
:branch "maint"
:load-path ("." "lisp/")
))
```
<div class="src-block-caption">
<span class="src-block-number">Listado de programa 3</span>
org-mode rama maint
</div>
```lisp
(add-to-list 'el-get-sources '(:name gnu-social-mode
:description "gnu-social client"
:type github
:pkgname "bashrc/gnu-social-mode"
)
)
```
<div class="src-block-caption">
<span class="src-block-number">Listado de programa 4</span>
gnu-social-mode
</div>
Cómo se puede ver, hay bastantes variables. Los tipos de paquetes git y Github son muy similares, la única diferencia es que si se usa Github, no hay que concretar la url pero si el nombre del paquete. También se puede ver, en el caso del paquete de org-mode, que podemos concretar las ordenes a usar para construir el paquete.
De momento hemos añadido las recetas, aún queda instalar los paquetes. Podemos ejecutar en el buffer &lowast;Scratch&lowast; lo siguiente:
```lisp
(el-get 'sync 'xlicense-github)
```
Y se presiona `C-`. Esto se puede hacer con todos los paquetes que se quieran instalar. Eso o `M-x el-get-install RET xlicense-github`. Y ya podemos usarlo. No hace falta añadir la ruta de cada paquete a la variable `load-path`, de eso se encarga `el-get`, por eso es importante cargarlo. Para actualizar, `M-x el-get-update RET xlicense-github`.

View File

@ -0,0 +1,163 @@
+++
title = "El horrible mundo del empaquetado para PyPi (queas y manual)"
author = ["drymer"]
date = 2015-12-14T10:27:00+01:00
tags = ["python"]
draft = false
+++
Hace poco tuve la desastrosa idea de que estaría bien hacer accesible el programa [gnusrss](http://daemons.cf/cgit/gnusrss/about/), del cual he sacado una [nueva versión hace poco](http://daemons.cf/cgit/gnusrss/about/), por cierto. Si miráis este último link, podréis ver que he tenido que hacer un versionado absurdo. Por si da pereza mirarlo, aquí va una captura.
{{< figure src="/img/2015-12-09-164548_545x703_scrot.png" >}}
Se pueden ver unos commits que insipiran mucho amor y devoción. Y al lado, unos tags con la versión. v0.2.1.5 ha sido la última, y la que yo pretendía que fuése era la v0.2. Explicaré el motivo cuando llegue el momento.
A continuación, el proceso de empaquetado dando por supuesto que tenemos un repositorio git, un programa de lo que sea, da igual el lenguae, y queremos subirlo a [PyPi](https://pypi.python.org/pypi), El repositorio del que se instala al eecutar `pip install pycurl`. Tendréis que crearos una cuenta ahí y además en otro lado, [PyPi-test](https://testpypi.python.org/pypi). Esta última web es identica a la original, pero sirve para testear. Hay que imaginar la de tonterias que tiene el empaquetado para que la web tenga una versión para hacer pruebas. Se puede registrar via web sin más o se puede hacer a través del fichero `setup.py`. Recomiendo la primera, la segunda no usa SSL y el usuario y contraseña que se escoa podrá verse en plano por internet.
## Manual {#manual}
Aquí va el directorio que tengo de gnusrss cómo eemplo, para plantar una base de lo que habia antes del proceso de empaquetado:
```sh
drymer % torre ~/Instalados/Proyectos/gnusrss $ ls -l
total 84
-rw-r--r-- 1 drymer drymer 14576 dic 5 11:09 gnusrss.py
-rw-r--r-- 1 drymer drymer 620 dic 5 11:06 LICENSE
-rw-r--r-- 1 drymer drymer 12944 dic 7 05:46 README
-rw-r--r-- 1 drymer drymer 13684 dic 7 05:45 README.md
-rw-r--r-- 1 drymer drymer 12710 dic 7 05:45 README.org
```
El primer paso será crear un `setup.py`. Con este fichero interactuaremos con el índice PyPi. Se pueden usar dos librerias para ello. setuptools o docutils. docutils viene por defecto y ni el desarrollado ni quien lo use tendrá que descargar un paquete extra al usar el programa empaquetado. Pero si se quiere que este programa instale las dependencias que tenga de manera automática, escogeremos el segundo. Además, es uno de esos paquetes bastante básicos, se suele tener instalado. Entonces, el fichero `setup.py` podria ser tal que así:
```python
#!/usr/bin/env python3
from setuptools import setup
VERSION = '0.2.1.5'
setup(name='gnusrss',
version=VERSION,
description='Post feeds to GNU Social.',
long_description=open('README').read(),
author='drymer',
author_email='drymer@autistici.org',
url='http://daemons.it/drymer/gnusrss/about/',
download_url='http://daemons.it/drymer/gnusrss/snapshot/gnusrss-' + VERSION + '.tar.gz',
scripts=['gnusrss.py'],
license="GPLv3",
bugtrack_url="https://notabug.org/drymer/gnusrss/issues",
install_requires=[
"feedparser>=5.0",
"pycurl>=7.0",
],
classifiers=["Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Operating System :: OS Independent",
"Operating System :: POSIX",
"Intended Audience :: End Users/Desktop"]
)
```
Cuidar la identación si se copia tal cual. A continuación explicaré algunas líneas menos obvias.
- `long_description` deberia contener el `README`. Cómo este súele ser largo y estar escrito en otro fichero, recordando que esto es un programa, podemos simplemente leerlo. En este caso lee el fichero `README`.
- `download_url` la tengo puesta, pero probablemente la quite. Este string debería tener cómo valor una url que lleve a un `*.tar.gz` o similar.
- `scripts` contiene los ficheros que hay que subir, más allá del propio `README`.
- `install_requires` contiene las dependencias y su versión.
- `classifiers` es eso, clasificadores. Si se mira en la propia web de PyPi se puede ver cuales hay. Inventarselos está feo. Yo aviso.
Ahora se creará el paquete tar.gz para subirlo. Para hacerlo sólo hay que eecutar `python setup.py sdist`. Hay otras opciones, cómo crear paquete para winsux y esas cosas. Pero no me interesa. Una vez eecutada la anterior orden, en este directorio se podrá ver que se han creado dos directorios, `sdist` y `$nombreDelPrograma.egg-info`. En el segundo directorio hay algo de información que se crea para poder meterla en el archivo comprimido, y en el primero es dónde se crean todos los archivos comprimidos. Si se usa git, es recomendable meter en el `.gitignore` ambos directorios y no borrar el directorio cada vez que se envíe versión nueva, ya que no va mal tener información de todas las versiones que se han ido publicando.
Ahora se tiene que registrar en la web, mediante el formulario que tienen. Se puede hacer usando el `setup-py`, pero este no usa SSL por lo que es peligroso. Una vez hecho, se crear el archivo `~/.pypirc`, que contendrá información para loguearse de manera automática al subir paquetes. Seria tal que así:
```ini
[distutils]
index-servers =
pypi
pypi-test
[pypi]
repository=https://pypi.python.org/pypi
username:drymer
password:lalalalalal
[pypi-test]
repository=https://testpypi.python.org/pypi
username:drymer
password:lolololo
```
Se puede ver que hay dos secciones, PyPi y PyPi-test. El segundo irá bien para probar, es muy recomendable usarlo hasta que el proceso entero de empaquetado esté dominado. Para usar esa web, hay que volver a registrarse, ya que ambas webs no comparten base de datos de usuarios.
Creado el útlimo archivo, se instalará `twine`. Es una utilidad para subir paquetería de manera segura, por lo que comenté antes del SSL. Aún no se usará, por eso. Dado que se va a usar primero la web de PyPi-test, no pasa nada por que se puedan ver las credenciales en plano. Para subir el comprimido a la web: `python setup.py upload sdist -r pypi-test`. Con esto ya se puede ir testeando lo que haga falta. Hay que aprovechar que está esta web, y sólo cuando se tenga claro subir a la web oficial. Se puede usar el último comando si se es idiota, quitando el `-r`, o se puede usar `twine` instalándola (`pip install twine`) y luego eecutando, desde la raiz, `twine upload dist/$paquete-$version.tar.gz`. Y con eso ya se será un nene mayor que empaqueta y programa.
## Queas {#queas}
Ahora, empecemos con el primer problema. El fichero `README` sólo puede tener un formato, y este es el rst. La verdad, sabía que este lenguae de marcado existía, pero nunca lo había usado, y al echarle un oo por encima vi que es horrible y que nunca lo usaré. En la mayor parte de sitios relacionados con el hosting de paquetes, <span class="underline">siempre</span>, repito, <span class="underline">siempre</span> se usa markdown, un lenguae de marcado con mucho más sentido. Pero bueno, yo escribo todo en org-mode y este permite exportar a muchísimos formatos, el rst incluido. Entonces, veamos que es lo que yo tengo en mi caso. Un fichero llamado `README.org`, otro llamado `README.md` para el git y ahora un tercero llamado `README` en rst. Al mirar el archivo escrito en markdown me di cuenta de que tendría problemas. Por defecto org-mode exporta la tabla de contenidos en HTML, ya que el de markdown queda muy bonito pero no funciona en HTML. Bueno, no está todo perdido, pensé. Lo exporto directamente desde el archivo escrito en org y fuera. Lo hice, fuí a mirar la tabla y vi `.. contents::` dónde debería ir esta. Lo busqué y vi que era el formato correcto. Bibah! Lo subí a PyPi y el propio `setup.py` me dió algún warning, aunque lo subió. Peeero, no lo procesó correctamente. Raro. Me puse a buscar y resulta que el procesador de rst de PyPi está anticuado y no procesa eso. Así que hay que hacerlo de manera manual. Seguiría así un buen rato, implicando incluso [pandoc](http://daemons.cf/posts/pandoc-el-convertidor-de-archivos-definitivo/). Pero el resultado era que no funcionaba, así que acabé escribiendo lo siguiente.
```python
#!/usr/bin/env python3
from pypandoc import convert
from os import system
from re import search
from sys import argv,exit
if len(argv) == 1:
print('Usage: python3 createStupidToc.py README.md README.rst')
exit()
README = argv[1]
TMPFILE1 = '/tmp/stupidshit1'
TMPFILE2 = '/tmp/stupidshit2'
with open(README) as shit:
shit = shit.read()
shit = shit[shit.find('# '):]
supershit = ''
shitty = ''
with open(TMPFILE1, 'w') as tmp:
for minishit in shit.splitlines():
result = search('^#', minishit)
if result != None:
tmp.write(minishit.split('<')[0] + '\n')
else:
tmp.write(minishit + '\n')
# generate the stupid toc to export to rst
system("~/Scripts/createStupidToc.sh /tmp/stupidshit1 /tmp/stupidshit2")
with open('/tmp/stupidshit2') as stupidshit:
stupidshit = stupidshit.read()
for shit in stupidshit.splitlines():
if shit.startswith('<!-- '):
pass
else:
shitty += shit + '\n'
with open(argv[2], 'w') as rst:
rst.write(convert(shitty, 'rst', format='md'))
```
Muy salchichero, pero funciona. En el fichero `~/Scripts/createStupidToc.sh` hay lo siguiente:
```sh
#!/bin/bash
echo "Creating the toc..."
emacs24 -Q $1 --batch -l ~/.emacs.d/init.el -f markdown-toc-generate-toc --eval='(write-file '\"$2\"')' 2>/dev/null
```
Y ahora explico lo que hace y lo que hace falta para usarlo. Lo que hace es coger un fichero en markdown con una tabla de contenidos en HTML, quitar esta tabla de contenidos, decirle a emacs que use el paquete `markdown-toc` y lo inserte en el buffer que contiene el markdown sin la tabla en HTML y coger este markdown con la tabla de contenidos en markdown y crear un README con la tabla funcional. Para usarlo hace falta instalar pypandoc (`pip install pypandoc`) y tener emacs con ese paquete. Por defecto llama la versión 24 de emacs, pero si se tiene otra es cuestión de cambiar la última línea de `createStupidToc.sh`. Entonces sólo hay que eecutar este script cada vez que se vaya a crear el paquete para PyPi.
La segunda quea es que no permiten hostear los archivos comprimidos de manera externa. Hay una opción de la web de PyPi, cuando vas a la sección **url** de tu paquete, en la que te pregunta si quieres hostear el paquete comprimido en PyPi o en un servidor externo. La cosa es que esto ya no se permite (las opciones salen marcadas cómo deprecated) pero siguen saliendo. Y buscando se encuentra un este [pep](https://www.python.org/dev/peps/pep-0470/) dónde se explica la motivación de la decisión de quitar el hosting externo. Aunque entiendo su motivación, a mi me parece una mierda, pero bueno, la vida. Mi quea es que la información que hay no es nad concluyente, ni siquiera el pep.
Al escribir me doy cuenta de que realmente al saber todo esto, no resulta tan problemático. Pero claro, he tenido que dedicar bastantes horas a encontrar todo esto. Ahora que lo sé, probablemente el siguiente paquete sea menos problemático. Aún así no se echaria en falta meor documentación.

View File

@ -0,0 +1,163 @@
+++
title = "El horrible mundo del empaquetado para PyPi (quejas y manual)"
author = ["drymer"]
date = 2015-12-14T10:27:00+01:00
tags = ["python"]
draft = false
+++
Hace poco tuve la desastrosa idea de que estaría bien hacer accesible el programa [gnusrss](http://daemons.cf/cgit/gnusrss/about/), del cual he sacado una [nueva versión hace poco](http://daemons.cf/cgit/gnusrss/about/), por cierto. Si miráis este último link, podréis ver que he tenido que hacer un versionado absurdo. Por si da pereza mirarlo, aquí va una captura.
{{< figure src="/img/2015-12-09-164548_545x703_scrot.png" >}}
Se pueden ver unos commits que inspiran mucho amor y devoción. Y al lado, unos tags con la versión. v0.2.1.5 ha sido la última, y la que yo pretendía que fuese era la v0.2. Explicaré el motivo cuando llegue el momento.
A continuación, el proceso de empaquetado dando por supuesto que tenemos un repositorio git, un programa de lo que sea, da igual el lenguaje, y queremos subirlo a [PyPi](https://pypi.python.org/pypi), El repositorio del que se instala al ejecutar `pip install pycurl`. Tendréis que crearos una cuenta ahí y además en otro lado, [PyPi-test](https://testpypi.python.org/pypi). Esta última web es identica a la original, pero sirve para testear. Hay que imaginar la de tonterías que tiene el empaquetado para que la web tenga una versión para hacer pruebas. Se puede registrar via web sin más o se puede hacer a través del fichero `setup.py`. Recomiendo la primera, la segunda no usa SSL y el usuario y contraseña que se escoa podrá verse en plano por internet.
## Manual {#manual}
Aquí va el directorio que tengo de gnusrss cómo ejemplo, para plantar una base de lo que habia antes del proceso de empaquetado:
```sh
drymer % torre ~/Instalados/Proyectos/gnusrss $ ls -l
total 84
-rw-r--r-- 1 drymer drymer 14576 dic 5 11:09 gnusrss.py
-rw-r--r-- 1 drymer drymer 620 dic 5 11:06 LICENSE
-rw-r--r-- 1 drymer drymer 12944 dic 7 05:46 README
-rw-r--r-- 1 drymer drymer 13684 dic 7 05:45 README.md
-rw-r--r-- 1 drymer drymer 12710 dic 7 05:45 README.org
```
El primer paso será crear un `setup.py`. Con este fichero interactuaremos con el índice PyPi. Se pueden usar dos librerías para ello. setuptools o docutils. docutils viene por defecto y ni el desarrollado ni quien lo use tendrá que descargar un paquete extra al usar el programa empaquetado. Pero si se quiere que este programa instale las dependencias que tenga de manera automática, escogeremos el segundo. Además, es uno de esos paquetes bastante básicos, se suele tener instalado. Entonces, el fichero `setup.py` podría ser tal que así:
```python
#!/usr/bin/env python3
from setuptools import setup
VERSION = '0.2.1.5'
setup(name='gnusrss',
version=VERSION,
description='Post feeds to GNU Social.',
long_description=open('README').read(),
author='drymer',
author_email='drymer@autistici.org',
url='http://daemons.it/drymer/gnusrss/about/',
download_url='http://daemons.it/drymer/gnusrss/snapshot/gnusrss-' + VERSION + '.tar.gz',
scripts=['gnusrss.py'],
license="GPLv3",
bugtrack_url="https://notabug.org/drymer/gnusrss/issues",
install_requires=[
"feedparser>=5.0",
"pycurl>=7.0",
],
classifiers=["Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Operating System :: OS Independent",
"Operating System :: POSIX",
"Intended Audience :: End Users/Desktop"]
)
```
Cuidar la identación si se copia tal cual. A continuación explicaré algunas líneas menos obvias.
- `long_description` debería contener el `README`. Cómo este suele ser largo y estar escrito en otro fichero, recordando que esto es un programa, podemos simplemente leerlo. En este caso lee el fichero `README`.
- `download_url` la tengo puesta, pero probablemente la quite. Este string debería tener cómo valor una url que lleve a un `*.tar.gz` o similar.
- `scripts` contiene los ficheros que hay que subir, más allá del propio `README`.
- `install_requires` contiene las dependencias y su versión.
- `classifiers` es eso, clasificadores. Si se mira en la propia web de PyPi se puede ver cuales hay. Inventárselos está feo. Yo aviso.
Ahora se creará el paquete tar.gz para subirlo. Para hacerlo sólo hay que ejecutar `python setup.py sdist`. Hay otras opciones, cómo crear paquete para winsux y esas cosas. Pero no me interesa. Una vez ejecutada la anterior orden, en este directorio se podrá ver que se han creado dos directorios, `sdist` y `$nombreDelPrograma.egg-info`. En el segundo directorio hay algo de información que se crea para poder meterla en el archivo comprimido, y en el primero es dónde se crean todos los archivos comprimidos. Si se usa git, es recomendable meter en el `.gitignore` ambos directorios y no borrar el directorio cada vez que se envíe versión nueva, ya que no va mal tener información de todas las versiones que se han ido publicando.
Ahora se tiene que registrar en la web, mediante el formulario que tienen. Se puede hacer usando el `setup-py`, pero este no usa SSL por lo que es peligroso. Una vez hecho, se crear el archivo `~/.pypirc`, que contendrá información para loguearse de manera automática al subir paquetes. Seria tal que así:
```ini
[distutils]
index-servers =
pypi
pypi-test
[pypi]
repository=https://pypi.python.org/pypi
username:drymer
password:lalalalalal
[pypi-test]
repository=https://testpypi.python.org/pypi
username:drymer
password:lolololo
```
Se puede ver que hay dos secciones, PyPi y PyPi-test. El segundo irá bien para probar, es muy recomendable usarlo hasta que el proceso entero de empaquetado esté dominado. Para usar esa web, hay que volver a registrarse, ya que ambas webs no comparten base de datos de usuarios.
Creado el ultimo archivo, se instalará `twine`. Es una utilidad para subir paquetería de manera segura, por lo que comenté antes del SSL. Aún no se usará, por eso. Dado que se va a usar primero la web de PyPi-test, no pasa nada por que se puedan ver las credenciales en plano. Para subir el comprimido a la web: `python setup.py upload sdist -r pypi-test`. Con esto ya se puede ir testeando lo que haga falta. Hay que aprovechar que está esta web, y sólo cuando se tenga claro subir a la web oficial. Se puede usar el último comando si se es idiota, quitando el `-r`, o se puede usar `twine` instalándola (`pip install twine`) y luego ejecutando, desde la raíz, `twine upload dist/$paquete-$version.tar.gz`. Y con eso ya se será un nene mayor que empaqueta y programa.
## Quejas {#quejas}
Ahora, empecemos con el primer problema. El fichero `README` sólo puede tener un formato, y este es el rst. La verdad, sabía que este lenguaje de marcado existía, pero nunca lo había usado, y al echarle un ojo por encima vi que es horrible y que nunca lo usaré. En la mayor parte de sitios relacionados con el hosting de paquetes, <span class="underline">siempre</span>, repito, <span class="underline">siempre</span> se usa markdown, un lenguaje de marcado con mucho más sentido. Pero bueno, yo escribo todo en org-mode y este permite exportar a muchísimos formatos, el rst incluido. Entonces, veamos que es lo que yo tengo en mi caso. Un fichero llamado `README.org`, otro llamado `README.md` para el git y ahora un tercero llamado `README` en rst. Al mirar el archivo escrito en markdown me di cuenta de que tendría problemas. Por defecto org-mode exporta la tabla de contenidos en HTML, ya que el de markdown queda muy bonito pero no funciona en HTML. Bueno, no está todo perdido, pensé. Lo exporto directamente desde el archivo escrito en org y fuera. Lo hice, fui a mirar la tabla y vi `.. contents::` dónde debería ir esta. Lo busqué y vi que era el formato correcto. Bibah! Lo subí a PyPi y el propio `setup.py` me dio algún warning, aunque lo subió. Peeero, no lo procesó correctamente. Raro. Me puse a buscar y resulta que el procesador de rst de PyPi está anticuado y no procesa eso. Así que hay que hacerlo de manera manual. Seguiría así un buen rato, implicando incluso [pandoc](http://daemons.cf/posts/pandoc-el-convertidor-de-archivos-definitivo/). Pero el resultado era que no funcionaba, así que acabé escribiendo lo siguiente.
```python
#!/usr/bin/env python3
from pypandoc import convert
from os import system
from re import search
from sys import argv,exit
if len(argv) == 1:
print('Usage: python3 createStupidToc.py README.md README.rst')
exit()
README = argv[1]
TMPFILE1 = '/tmp/stupidshit1'
TMPFILE2 = '/tmp/stupidshit2'
with open(README) as shit:
shit = shit.read()
shit = shit[shit.find('# '):]
supershit = ''
shitty = ''
with open(TMPFILE1, 'w') as tmp:
for minishit in shit.splitlines():
result = search('^#', minishit)
if result != None:
tmp.write(minishit.split('<')[0] + '\n')
else:
tmp.write(minishit + '\n')
# generate the stupid toc to export to rst
system("~/Scripts/createStupidToc.sh /tmp/stupidshit1 /tmp/stupidshit2")
with open('/tmp/stupidshit2') as stupidshit:
stupidshit = stupidshit.read()
for shit in stupidshit.splitlines():
if shit.startswith('<!-- '):
pass
else:
shitty += shit + '\n'
with open(argv[2], 'w') as rst:
rst.write(convert(shitty, 'rst', format='md'))
```
Muy salchichero, pero funciona. En el fichero `~/Scripts/createStupidToc.sh` hay lo siguiente:
```sh
#!/bin/bash
echo "Creating the toc..."
emacs24 -Q $1 --batch -l ~/.emacs.d/init.el -f markdown-toc-generate-toc --eval='(write-file '\"$2\"')' 2>/dev/null
```
Y ahora explico lo que hace y lo que hace falta para usarlo. Lo que hace es coger un fichero en markdown con una tabla de contenidos en HTML, quitar esta tabla de contenidos, decirle a emacs que use el paquete `markdown-toc` y lo inserte en el buffer que contiene el markdown sin la tabla en HTML y coger este markdown con la tabla de contenidos en markdown y crear un README con la tabla funcional. Para usarlo hace falta instalar pypandoc (`pip install pypandoc`) y tener emacs con ese paquete. Por defecto llama la versión 24 de emacs, pero si se tiene otra es cuestión de cambiar la última línea de `createStupidToc.sh`. Entonces sólo hay que ejecutar este script cada vez que se vaya a crear el paquete para PyPi.
La segunda queja es que no permiten hostear los archivos comprimidos de manera externa. Hay una opción de la web de PyPi, cuando vas a la sección **url** de tu paquete, en la que te pregunta si quieres hostear el paquete comprimido en PyPi o en un servidor externo. La cosa es que esto ya no se permite (las opciones salen marcadas cómo deprecated) pero siguen saliendo. Y buscando se encuentra un este [pep](https://www.python.org/dev/peps/pep-0470/) dónde se explica la motivación de la decisión de quitar el hosting externo. Aunque entiendo su motivación, a mi me parece una mierda, pero bueno, la vida. Mi queja es que la información que hay no es nada concluyente, ni siquiera el pep.
Al escribir me doy cuenta de que realmente al saber todo esto, no resulta tan problemático. Pero claro, he tenido que dedicar bastantes horas a encontrar todo esto. Ahora que lo sé, probablemente el siguiente paquete sea menos problemático. Aún así no se echaría en falta mejor documentación.

View File

@ -0,0 +1,53 @@
+++
title = "Emacs y org-mode"
author = ["drymer"]
date = 2015-04-03T19:15:00+02:00
draft = false
tags = ["emacs", "org-mode", "elbinario"]
+++
# Que te aporta usar org-mode?
Últimamente veo en algunos sitios que se habla de emacs, cosa que siempre es interesante. Emacs no es un editor de textos, cómo se dice, equivocamente, al compararlo con vi?m, nano o incluso gedit. Para mi emacs es:
- IDE de desarrollo, para programar y tal
- Editor de texto sencillo. De hecho, me he quitado nano y lo he puesto como alias a emacsclient
- org-mode
- Procesador de textos
- Publicación de esos textos
- Listas, muchas listas
Y el último punto es el que explicaré a continuación. Comentaré <span class="underline">mi uso</span> de esta herramienta, puede tener más. Por algo este es el **editor hackeable** (el de verdad).
<a id="orgabd87ac"></a>
## Procesador de textos
Cómo procesador de textos es lo mejor que hay. Usa un formato tipo markdown, aunque ligeramente distinto, que puede ser exportado a una cantidad muy grande de formatos. Veamos un ejemplo. La siguiente imagen es este articulo en el punto en el que está ahora.
![img](./img/2015-09-11-193406_1024x768_scrot.png "Articulo hasta este punto")
Para exportarlo a otro formato ejecutamos C-c C-e. Ahí nos abrirá un buffer con algo parecido a lo siguiente:
![img](./img/org-export.png)
Le damos al HTML, por ejemplo, que serviria para montar una web sencilla. Se puede visualizar aquí:
<./listings/org-mode.html>
Sinsillo y para toda la familia.
<a id="org8d4fa20"></a>
## Publicación de estos textos
Estos modos suelen ser menores, por debajo de org-mode. Los que he usado son los de [org2nikola](file:///posts/nikola-emacs-gestionar-un-blog-de-contenido-esttico/) y el [org2blog/wp](file:///posts/publicando-en-wordpress-desde-emacs-24.html), ambos muy interesantes. El primero para nikola y el segundo para wordpress. Y en la [wiki](http://orgmode.org/worg/org-blog-wiki.html) de emacs se pueden ver otros modos, en los cuales se pueden usar otros generadores de web estáticos y/o git.
<a id="org492e3f7"></a>
## Listas, muchas listas
Y este es su fin principal, hacer listas.

View File

@ -0,0 +1,80 @@
+++
title = "Evitar ataques de fuerza bruta en Prosody"
author = ["drymer"]
date = 2016-09-30T08:30:00+02:00
tags = ["xmpp", "sysadmin"]
draft = false
+++
Este es un tema muy obvio, pero la verdad es que no había caído en investigarlo hasta hace poco. Me fié en como intentar hacer seguras las conexiones SSL con su FPS y sus cosas, y no pensé en que alguien me puede robar la cuenta. No me suele preocupar este tema, mis contraseñas suelen pasar de los 20 caracteres. Pero aún así, si no hay ningún tipo de control en los intentos y los fallos al intentar loguearse, un proceso que se podría alargar años con las medidas adecuadas, podría tardar un mes o dos solamente. Así que a ponerle remedio.
Ya hablé del gran servidor que es Prosody en el articulo enfocado a habilitarlo para el [uso móvil](https://daemons.cf/posts/xmpp-en-mviles-mentiras-y-cmo-mejorar-tu-servidor/), por si alguien no lo ha leído. Ya se vio que instalar nuevos módulos es absurdamente fácil. Ahora veremos como configurar el módulo Limit Auth. Este módulo limita las autenticaciones erróneas por IP que se pueden hacer. No banea de ningún modo, pero impone un tiempo de espera cada X intentos fallidos. Veamos como configurarlo.
Si aún no hemos clonado el repositorio de los módulos de la comunidad de prosody, se hace del siguiente modo:
```sh
su
cd
hg clone https://hg.prosody.im/prosody-modules
```
Copiamos el módulo a configurar:
```sh
cp -r ~/prosody-modules/mod_limit_auth/ /usr/lib/prosody/modules/
```
Editamos el archivo `/etc/prosody/prosody.cfg.lua`:
```lua
modules_enabled = {
-- otros modulos
"limit_auth";
-- más modulos
}
limit_auth_period = 30
limit_auth_max = 5
```
Puesto así y después de reiniciar, haremos que cada cinco intentos fallidos tengan que pasar 30 segundos hasta el siguiente intento de autenticación. No es la panacea, pero este tipo de medidas enlentecen muchísimo los ataques de fuerza bruta. Podemos complicarles la vida a los crackers un poco más, si queremos. Hay otro módulo llamado Log Auth que permite integrar Prosody con `fail2ban`, un gran programa para el control de acceso. Típicamente se usa con `ssh`, aunque se puede usar con mucho más, coḿo veremos.
El módulo que instalaremos lo que hace es, básicamente, es activar el logueo de IP únicamente cuando se da un fallo de autenticación. Recordemos que Prosody, a menos que se tenga el log en modo debug, no guarda IP. No requiere de configuración, solo hay que copiarlo en el directorio y activarlo desde la configuración de Prosody:
```lua
modules_enabled = {
-- otros modulos
"log_auth";
-- más modulos
}
```
Supondremos que está instalado y configurado, si no es el caso, recomiendo hacerlo siguiendo [este tutorial](http://www.fail2ban.org/wiki/index.php/HOWTO%5Ffail2ban%5Fspanish). Ahora crearemos el filtro en el archivo `/etc/fail2ban/filter.d/prosody-auth.conf`:
```sh
# /etc/fail2ban/filter.d/prosody-auth.conf
# Fail2Ban configuration file for prosody authentication
[Definition]
failregex = Failed authentication attempt \(not-authorized\) from IP: <HOST>
ignoreregex =
```
Ahora lo activamos en la configuración de `fail2ban` en `/etc/fail2ban/ail.conf`:
```ini
[prosody]
enabled = true
port = 5222
filter = prosody-auth
logpath = /var/log/prosody/prosody*.log
maxretry = 20
```
He puesto 20 por que por otro lado tenemos el módulo anterior y con un ataque de fuerza bruta en menos de 20 intentos no sacan la contraseña (y si lo hacen, te mereces lo que pase). Así que en aras de la comodidad, se queda en un límite alto. Y sólo queda reiniciar y a disfrutar de un pelín más de seguridad.
Más información en las páginas de los módulos:
- [https://modules.prosody.im/mod\_limit\_auth.html](https://modules.prosody.im/mod%5Flimit%5Fauth.html)
- [https://modules.prosody.im/mod\_log\_auth.html](https://modules.prosody.im/mod%5Flog%5Fauth.html)

View File

@ -0,0 +1,16 @@
+++
title = "Facebook se lava la cara"
author = ["drymer"]
date = 2015-06-02T19:15:00+02:00
draft = false
tags = ["privacidad", "elbinario"]
+++
Que fantabuloso. La noticia (que por cierto he leído en el [blog de Chema Alonso](http://www.elladodelmal.com/2015/06/facebook-ahora-te-permite-cifrar-los.html)) de hoy es que implementarán cifrado end-to-end con PGP en todas las comunicaciones de las usuarias que quieran.
Yo, que soy desconfiado (mire usted por dónde), he pensado que harían cómo los de Whatsapp, que anuncian a bombo y platillo que usarán cifrado end-to-end implementando Textsecure con el propio Whatsapp. Esto en teoria está bien. Problema? Dónde están las llaves? Pues no se sabe, es lo que tiene el software privativo. Todo apunta a que las llaves las manejan desde el servidor principal de Whatsapp. Otra vez, problema? Que no es seguro, claro. Nada nos asegura que ante una orden judicial tendrán que dar las llaves. Por no decir que les puedan entrar y acceder a todas las llaves.
En fin, lo que decia es que pensaba que Facebook, que al fin y al cabo es la dueña de Whatsapp, harian lo mismo. Pero resulta que no, que dejan subir a cada persona su propia clave. Esto seria muy interesante y útil de no ser por un pequeño fallo. Facebook [registra cualquier texto que escribas](http://acentoveintiuno.com/?Facebook-puede-registrar-lo-que), lo envíes o no. Que sentido tiene cifrar un mensaje, si ya lo tienen aún sin enviar? Más bien ninguno. Sólo una nueva demostración de Facebook limpiándose la cara con el cubo de la fregona. Nada ha cambiado.
PD: Curiosamente, al buscar (poco exhaustivamente y durante unos cinco minutos) algúna fuente más conocida que habláse de que Facebook registra lo que escribes, sólo he encontrado ese.

View File

@ -0,0 +1,87 @@
+++
title = "Forzar el uso de atajos de teclado para moverse en el buffer"
author = ["drymer"]
date = 2017-02-07T08:30:00+01:00
tags = ["productividad", "emacs"]
draft = false
+++
Hay unas cuantas combinaciones de teclas que funcionan en casi todos los editores de texto para moverse por el fichero (una excepción es vi, como no). Estos atajos están pensados para no tener que separar las manos de la parte del teclado en la que debería estar, que es el centro. Pero se tiene cierta tendencia a ir a lo fácil y usar las flechas y otras teclas específicas.
Es habitual querer coger la costumbre de usar los atajos del centrar del teclado para moverse y no usar las teclas específicas, por ello `hardcore-mode` resulta tan útil. Este modo te obliga a usar las combinaciones alternativas al desactivar las que estás habituado a usar. Dicho de otro modo, lo que hace es desactivar las teclas RET, BACKSPACE, flechas y cada vez que se presionen nos dirá la alternativa a usar en el minibuffer. "Solo" desactiva el uso de esas teclas, pero como no me parece suficiente "hardcore", he añadido la desactivación de más teclas. Quedaría como se ve en la siguiente tabla:
| Activo | Inactivo |
|----------|--------------------------------|
| C-f | Flecha derecha |
| C-b | Flecha izquierda |
| C-p | Flecha arriba |
| C-n | Flecha abajo |
| C-ñ | Backspace (la tecla de borrar) |
| C-m / C- | RET (la tecla de enter ) |
| M-f | C-flecha derecha |
| M-b | C-flecha izquierda |
| M-p | C-flecha arriba |
| M-n | C-flecha abajo |
| C-h | DEL (tecla de borrar) |
| F1 | El prefijo de ayuda |
| C-v | Av. Pág |
| M-v | Re. Pág |
| C-a | Inicio |
| C-e | Fin |
| M-< | Inicio del buffer (C-Inicio) |
| M-> | Final del buffer (C-Fin) |
Y la configuración sería así:
```emacs-lisp
(use-package hardcore-mode
:ensure t
:config
(global-set-key "\M-p" 'backward-paragraph)
(global-set-key "\M-n" 'forward-paragraph)
(define-key key-translation-map [?\C-h] [?\C-?])
(global-set-key (kbd "<f1>") 'help-command)
(define-key hardcore-mode-map
(kbd "<C-up>") (lambda ()
(interactive)
(message "This key is disabled. Use M-p instead.")))
(define-key hardcore-mode-map
(kbd "<C-down>") (lambda ()
(interactive)
(message "This key is disabled. Use M-n instead.")))
(define-key hardcore-mode-map
(kbd "<C-left>") (lambda ()
(interactive)
(message "This key is disabled. Use M-b instead.")))
(define-key hardcore-mode-map
(kbd "<C-right>") (lambda ()
(interactive)
(message "This key is disabled. Use M-f instead.")))
(define-key hardcore-mode-map
(kbd "<prior>") (lambda ()
(interactive)
(message "This key is disabled. Use M-v instead.")))
(define-key hardcore-mode-map
(kbd "<next>") (lambda ()
(interactive)
(message "This key is disabled. Use C-v instead.")))
(define-key hardcore-mode-map
(kbd "<home>") (lambda ()
(interactive)
(message "This key is disabled. Use C-a instead.")))
(define-key hardcore-mode-map
(kbd "<C-home>") (lambda ()
(interactive)
(message "This key is disabled. Use M-< instead.")))
(define-key hardcore-mode-map
(kbd "<end>") (lambda ()
(interactive)
(message "This key is disabled. Use C-e instead.")))
(define-key hardcore-mode-map
(kbd "<C-end>") (lambda ()
(interactive)
(message "This key is disabled. Use M-> instead.")))
(global-hardcore-mode))
```
Si solo se quiere ir a lo básico, hay que quitar todos los `define-key` de la sección `:config`. Lo único "malo" que tengo que decir de este modo es que la tecla de borrado pasa a ser C-h, que en la terminal es el estándar, pero en emacs ese prefijo es el de ayuda. Se remapea a F1, pero bueno, puede resultarle molesto a alguien.

View File

@ -0,0 +1,34 @@
+++
title = "Las fotopollas"
author = ["drymer"]
date = 2015-04-27T19:15:00+02:00
draft = false
tags = ["privacidad", "elbinario"]
+++
El otro día estaba viendo un programa llamado "Last Week Tonight With John Oliver" y me llamó la atención algo. Para empezar, es muy recomendable ver este vídeo por que el tipo tiene bastante gracia. El programa trata noticias de la actualidad pero metiéndole toques de humor, algo así cómo El Intermedio pero siendo gracioso.
En fin, la cosa es que en este programa entrevistan a Edward Snowden. El tal John se pega un viaje de 12 horas a Russia sólo para poder hacerlo. Otro motivo más que añadir para ver este vídeo.
Pero a lo que voy no esta entrevista en si y el tema que tratan. Probablemente esa noche muchos americanos entendieron lo que implicaba el espionaje masivo, y lo John lo hizo posible de una manera muy concreta. Puso todo el contexto en las fotopollas. Da que pensar. A veces nos olvidamos de que hay ciertas cosas que para los que no están iniciadas en el arcano arte de darle al botón de reiniciar, lo que decimos a veces no tiene sentido. Porqué, y esto es una realidad, la mayor parte de gente no quiere aprender. El ejemplo lo ponen en el vídeo, cito textualmente:
<quote>Es cómo cuando estás en la oficina y viene el informático y tu dices: "Oooooh, mieeeeeeerda. No me enseñes nada, no quiero aprender. Hueles a cáncer.</quote>
Y es que no es nada sencillo. Por mucho que algunos entendamos ciertos aspectos técnicos, comprimir esos conocimientos en menos de, pongamos diez minutos, es muy complicado. Y ahí entra John. Decide intentar ayudar a Snowden explicando el problema del espionaje masivo externo a EEUU. Y lo hace en el contexto de las mencionadas fotopollas. Eso es a lo que la gente le tiene miedo, a que la NSA le vea la polla. Por que la gente manda fotos de su polla, tetas y otros interesantes apéndices constantemente, y es de esas cosas de las que, evidentemente, no se habla (exceptuando el caballero negro que sale en el vídeo), pero están ahí. En el minuto 11:16 podemos ver la respuesta de la gente entrevistada. Y se ve que no les gusta que les miren sus partes íntimas, que cosas. En ese contexto, la gente entrevistada pide que hayan leyes que controlen el uso de todos los programas de espionaje que la NSA tiene.
Después de esto, por eso, les preguntan si creen que existe un programa dedicado a capturar las fotopolla, a lo que responden que no. Pero la realidad es que, aunque no haya un programa exclusivo dedicado a eso, si que las capturan. Y en tal contexto, los siguientes programas de la NSA que se han ido explicando:
<ul>
<li>Amendment Act Sección 702: Esta "ley" permite el espionaje y captura masivo de todo el tráfico que la NSA pueda capturar. Una fotopolla enviada por correo de gmail que en algún momento sale a algún servidor fuera de EEUU es susceptible de ser capturado.</li>
<li>Orden Ejecutiva 12333: Es lo que la NSA usa cuando las demás autoridades no recolectan los suficientes datos para ellos. Dan órdenes de mover las fotopollas de servidores de dentro de EEUU a unos que estén fuera para poder así, legalmente, capturar esas fotos.</li>
<li>Prism: Es lo que usan para sacar la fotopolla del servidor de Google con la ayuda de Google. Prism les obliga a colaborar tanto si quieren cómo sinó, convirtiéndolos en los sheriffs de las fotopollas.</li>
<li>Upstream: Es cómo roban las fotopollas de Google./li>
<li>Mystic: Si describes tu polla en una llamada telefónica, tienen la duración de esa llamada para todos los paises y el contenido de esta en algunos paises.</li>
<li>Patriot Act 215: Lo relativo al móvil. A quien le mandas fotopollas, cuantas veces lo haces y el tamaño de la fotopolla. Se incluyen también las llamadas a lineas calientes.</li>
</ul>
Y esto es, en resumen, lo que hace la NSA últimamente. Sencillo de entender, no? Y ahí está el tema. **Debemos** aprender a simplificar. Al menos, si queremos que nos entiendan.
El vídeo lo podéis descargar desde nuestro mediagoblin.
<https://goblinrefuge.com/mediagoblin/u/elbinario/m/last-week-tonight-with-john-oliver-edward-snowden-interview/>

View File

@ -0,0 +1,62 @@
+++
title = "Funcionamiento de Faircoin 2.0"
author = ["drymer"]
date = 2016-05-03T14:08:00+02:00
tags = ["faircoin"]
draft = false
+++
Lo siguiente son unos apuntes/resumen/traducción del [paper](https://chain.fair-coin.org/download/FairCoin2-Draft.pdf) de la nueva versión de FairCoin, la 2.
Hasta ahora se funciona con PoS, el cual no es justo, ya que el poder lo tiene quien tiene poder de computación. En esta nueva versión se pasa a PoC (Proof of Cooperation). Esto quiere decir que las usuarias no minarán más. Los encargados de generar bloques serán los [CVN](https://fair.coop/node-certification-procedure/) (Certified Validation Nodes). En el futuro, estos nodos funcionaran con un método de reputación.
No hay recompensa en la creación de bloques, de modo que la cantidad de dinero no cambiará con el tiempo y quedará fía en el momento de migración a FC2&nbsp;[^fn:1]. Los beneficios de las transferencias irán a las operadoras de un CNV, cómo recompensa.
Este valor, entre otros, será ajustable de manera dinámica (sin necesidad de sacar nueva versión de la cartera) por un consenso democrático comunitario.
## Características de la creación de bloques {#características-de-la-creación-de-bloques}
- Se crean cada 3 minutos
- Se decide que CVN lo crea en función del tiempo que ha pasado desde su última creación de un bloque
- E: Si CVN A lo creó hace 50 minutos y CVN B lo creó hace 55 minutos, el siguiente bloque lo creará el CVN B
- Cuando se une un nuevo CVN, creará el siguiente bloque
- Entre la creación de dos bloques, sólo un nodo puede unirse
## Fases De la creación de bloques {#fases-de-la-creación-de-bloques}
- Acumulación de transacciones: Los nodos transfieren las transacciones que reciben a todos los nodos a los que estén conectados. Dura 170 segundos al menos. Si no hay transacciones pendientes, habrá que esperar a que las haya. Dicho de otro modo, esta fase sólo termina cuando hay al menos una transacción en la red.
- Anunció de tiempo desde la última creación de un bloque: Cada CVN determina cuanto hace y lo anuncia. La formula para calcular este es:
\begin{equation}
espera = 10 - (\frac{10 \* otw}{tn})
\end{equation}
Siendo:
- **otw** el tiempo desde la última creación de un bloque (own time-weight)
- **tn** el número total de nodos activos
- **10** la constante de 10 segundos, que es lo que dura la fase
Esto reducirá la cantidad de anuncios, por que cada nodo que recibá un anuncio que tenga prioridad, no lanzará el suyo.
- Elección del creador del bloque: Cuando se han enviado todos los anuncios, los CVN escogerán el nodo que hace más tiempo que no crea un bloque, lo firmaran el anuncio con su voto a este y lo enviaran por la red. Esta fase no tiene un tiempo máximo definido. Se detiene cuando un nodo sale elegido por al menos el 90% de todos los nodos activos. Entonces, el elegido crea el bloque en el que mete todas las transacciones pendientes unto a los votos firmados por los otros nodos en el que le eligen para crear el bloque cómo prueba.
## Nodos de Validación de Certificados {#nodos-de-validación-de-certificados}
Su finalidad es securizar la red validando todas las transacciones que han sido enviadas por la red y meterlas en las cadenas de bloques.
Requisitos para montar un CVN:
- Requisitos técnicos
- El sistema debe estar conectado a internet 24/7 y debe tener el puerto 46392 abierto.
- El sistema debe usar servidores NTP públicos, preferiblemente pool.ntp.org.
- La entidad debe tener una cuenta en la web de FairCoop.
- La cartera debe estar configurada con un certificado de la FairCoop.
Por qué hay que certificar los nodos? Por que un procedimiento de certificación adecuado asegura que un alto porcentaje de los CVN son **honestos**. Hasta el momento, el autor no ve una manera fácil de asegurar que cada nodo sólo tiene una identidad sin establecer un sistema de reputación.
[^fn:1]: Antes decía lo siguiente, pero lo cambié ya que es una interpretación personal (probablemente errónea, además): "de manera que el precio de la moneda no estará definido por la especulación típica de bitcoin, ya que esta no podrá existir."

View File

@ -0,0 +1,46 @@
+++
title = "Funciones básicas de emacs"
author = ["drymer"]
date = 2016-09-20T08:45:00+02:00
tags = ["emacs"]
draft = false
+++
A medida que he ido usando Ivy a lo largo de esta semana he visto algunas funciones que vale la pena mencionar aunque no son propias de Ivy cómo tal. Todas las que mencionaré están tanto nativamente cómo en Helm. Hay que recordar que en realidad Ivy no es más que un frontend, se puede poner por delante de cualquier función. Estas funciones les irán especialmente bien a quien no tenga demasiada experiencia en emacs:
```emacs-lisp
;; Desactiva los atajos que usaremos
(global-unset-key (kbd "C-h f"))
(global-unset-key (kbd "C-h v"))
(global-unset-key (kbd "C-h b"))
(global-unset-key (kbd "C-c b"))
(global-unset-key (kbd "C-x 4 b"))
;; Sustituye describe-function
(global-set-key (kbd "C-h f") 'counsel-describe-function)
;; Sustituye describe-variable
(global-set-key (kbd "C-h v") 'counsel-describe-variable)
;; Sustituye descbinds
(global-set-key (kbd "C-h b") 'counsel-descbinds)
;; Sustituye imenu
(global-set-key (kbd "C-c b") 'counsel-imenu)
;; Sustituye switch-buffer-other-window
(global-set-key (kbd "C-x 4 b") 'ivy-switch-buffer-other-window)
```
Estas son funciones a las cuales Ivy ofrece un frontend. Que hacen estas funciones?
- **describe-function**: Describe funciones internas de emacs y muestra su atajo de teclado, si lo tiene.
- **describe-variable**: Describe variables internas de emacs y muestra su valor actual.
- **descbinds**: Describe los atajos de teclados asociados a los modos activos.
- **imenu**: Salta a distintos sitios del buffer, sobretodo en función de las cabeceras. En buffers de org-mode salta por los nodos, en un buffer de python salta por las funciones.
- **ivy-switch-buffer-other-window**: Abre una nueva ventana con el buffer del archivo que le digamos.
Me ha sorprendido gratamente **imenu** con el frontend de **counsel** delante. Echaba en falta algo para moverme más rápidamente por un buffer relativamente grande, de más de 500 lineas.
Otra función sin frontend en Ivy (ya que no la necesita) es:
- **describe-key**: Describe que función ejecuta un atajo de teclado

View File

@ -0,0 +1,30 @@
+++
title = "GNU social en Emacs"
author = ["drymer"]
date = 2016-03-17T00:06:00+01:00
tags = ["emacs", "gnusocial"]
draft = false
+++
Los que somos usuarios de **Emacs** solemos estar encantados de usar nuestro programa preferido siempre que podemos. La comodidad y la tranquilidad de estar en un sistema completo y muy bien integrado es uno de los motivos de ese bienestar aunque hay muchos más y cada uno además tiene los suyos propios.
Para los que no lo sepan Emacs es mucho más que un editor o un IDE de programación, es un **intérprete** de elisp (Emacs lisp), por lo que ejecuta todo tipo de programas realizados en este lenguaje. Y os puedo asegurar que gracias a su **gestor de software** podemos acceder a muchos programas e instalarlos fácilmente. Así, y como una opción más podemos tener dentro de nuestro Emacs, clientes de correo, reproductores de música, terminales de comandos, clientes de mensajería y un largo etcétera.
Hoy voy a explicar como podemos acceder en nuestro programa preferido a **gnusocial**.
Para ello vamos a instalar **identica-mode** , un modo mayor para la red social **identica**, pero que nos vale para cualquier red status.net
Para instalar este modo lo podemos descargar de [aquí](http://blog.gabrielsaldana.org/u/1), aunque yo siempre recomendaré usar el gestor de software que incorpora Emacs.
Una vez instalado tendremos que añadir lo siguiente a nuestro fichero de inicio, por ejemplo, .emacs:
```elisp
(require 'identica-mode)
(setq statusnet-server "gnusocial.net")
(setq identica-username "tu-usuario")
(setq identica-password "tu-password")
```
Una vez hecho, teclados M-x y tecleamos identica-mode y ya podemos ver nuestro timeline de gnusocial en nuestro querido Emacs.
Más información en [el blog de su autor](http://blog.gabrielsaldana.org/identica-mode-for-emacs/).

View File

@ -0,0 +1,37 @@
+++
title = "Golden-ratio - redimensión automática de ventanas"
author = ["drymer"]
date = 2016-11-01T08:30:00+01:00
tags = ["emacs"]
draft = false
+++
Cuando se tienen varias ventanas se suele dar el problema de que tienes que ir-las redimensionando a mano. Yo ni siquiera he encontrado la manera de hacerlo cómodamente con el teclado, por lo que encima tengo que tirar del ratón, lo cual es bastante incómodo. Con este paquete, no hace falta. Se puede ver su comportamiento en [este gif](https://camo.githubusercontent.com/26b1ac5fec67a2c557cfbe87382a0134d3443fd0/68747470733a2f2f7261772e6769746875622e636f6d2f726f6d616e2f676f6c64656e2d726174696f2e656c2f6173736574732f676f6c64656e5f726174696f5f656c2e676966).
**Actualización**: El código comentado es el original, el cambiado es el de la variable `golden-ratio-exclude-buffer-regexp`. Al principio usaba esa función por que pensaba que no habia nada nativo en el modo, pero si que lo hay. Se puede usar esta variable para expresiones regulares o la variable `golden-ratio-exclude-buffer-name` para nombres completos de los buffers.
La instalación y configuración necesaria es la siguiente:
```emacs-lisp
(use-package golden-ratio
:config
(defun init/no-golden-ratio-for-buffers (bufname)
"Disable golden-ratio if BUFNAME is the name of a visible buffer."
(and (get-buffer bufname) (get-buffer-window bufname 'visible)))
(defun init/no-golden-ratio ()
"Disable golden-ratio for guide-key popwin buffer."
(or (init/no-golden-ratio-for-buffers " *undo-tree*")
(init/no-golden-ratio-for-buffers " *undo-tree Diff*")
))
(add-to-list 'golden-ratio-inhibit-functions
'init/no-golden-ratio)
(golden-ratio-mode t)
(setq golden-ratio-exclude-buffer-regexp '("undo-tree" "help" "diff" "calendar" "messages" "Org Agenda" "Agenda Commands" "Org Select" "magit:" "Calendar"))
(setq golden-ratio-auto-scale t)
:diminish golden-ratio-mode
:ensure t)
```
La función `golden-ratio-mode` es la que activa el modo. Las dos funciones posteriores y el add-to-list lo que hace es definir en que buffers no usaremos el golden-ratio. Yo tengo puesto, de momento un par de buffers de undo-tree. Seguramente en los próximos días que lo use más lo termine actualizando. Para añadir más buffers solo hay que añadir más lineas con el nombre del buffer.

View File

@ -0,0 +1,36 @@
+++
title = "Hacer la configuración de emacs auto-instalable"
author = ["drymer"]
date = 2016-11-15T08:30:00+01:00
tags = ["emacs"]
draft = false
+++
Con el-get, use-package y un poco de elisp esto se hace fácilmente. Lo hice con la mía más por hacer el experimento que por utilidad, tampoco es que tenga un ordenador nuevo por configurar a menudo. Pero esto me ha servido para tener la misma configuración de forma sencilla tanto en mi ordenador del trabajo (que por cierto, tengo con winsux y cygwin) y el de mi casa.
Para quien no haya leído los anteriores articulos sobre el-get y use-package, puede verlos [aquí](https://daemons.cf/posts/el-get-otro-instalador-de-paquetes) y [aquí](https://daemons.cf/posts/use-package-aislar-la-configuracin-de-cada-paquete), respectivamente.
use-package lo pone muy fácil para auto-instalar los paquetes que no tengas. Solo hay que establecer la propiedad **:ensure** en **t**, tal que así:
```emacs-lisp
(use-package pep8
:ensure t)
```
En el caso de el-get habrá que usar un poco de elisp, pero es muy simple, por suerte. Se usa la función `el-get-package-installed-p` (homónima de `package-installed-p` de `package.el`). Poniendo un ejemplo visto en el articulo de el-get:
```emacs-lisp
;; Definimos la fuente del paquete como ya se vio
(add-to-list 'el-get-sources '(:name xlicense-github
:type github
:pkgname "timberman/xlicense-el"
))
;; Si no está instalado xlicense-github mediante el-get, se instala
(if (not (el-get-package-installed-p 'xlicense-github))
(el-get 'sync 'xlicense-github)
)
```
Y ale, a volar. Ahora, con tener la configuración complementada con lo comentado arriba y ejecutar emacs, instalaremos todos los paquetes. Para hacer la prueba, recomiendo mover el directorio `~/.emacs.d/` y recrearlo vacío únicamente con la configuración, sin los directorios `~/.emacs.d/el-get/` ni `~/.emacs.d/elpa/`. Para ver más ejemplos, se puede ver [mi configuración](https://daemons.cf/stories/mi-configuracin-de-emacs/).

View File

@ -0,0 +1,80 @@
+++
title = "Haciendo ver que tienes mierda de Google"
author = ["drymer"]
date = 2017-03-07T08:30:00+01:00
tags = ["android", "movil", "privacidad"]
draft = false
+++
En un articulo anterior, ya vimos como [limpiar de mierda](https://daemons.cf/posts/limpiando-mierda-en-android/) privativa de Google nuestro móvil Android. Esto tiene sus consecuencias, claro. Nos hemos quedado sin Google Play y sin Google Maps. Algo obvio y que no debería dar problemas, hasta que te encuentras aplicaciones que <span class="underline">requieren</span> las librerías que esas dos aplicaciones proveen. En general, ningún tipo de aplicaciones que necesite estas librerías es recomendable, ya que en general son aplicaciones privativas. Hay alguna rara excepción, como Signal hasta hace poco (sigue siendo mejor XMPP), pero suelen ser aplicaciones como la de Whatsapp o la de Bicing (que por cierto, está llena de publicidad de una empresa).
La respuesta obvia es simple, no uses estas aplicaciones y sigue con tu vida. En el caso de Bicing, se puede funcionar perfectamente sin ella, ya que en F-Droid hay una aplicación llamada [OpenBikeSharing](https://f-droid.org/repository/browse/?fdfilter=bike&fdid=be.brunoparmentier.openbikesharing.app), que soporta Bicing entre otros. Pero cuando la gente se encabezona en usar Whatsapp, es complicado sacarles de ahí, por mucho mejor que sea jabber. Una vez más, lo evidente y lo más recomendable es mandar a esa gente a la mierda. Pero hay veces que no queda más remedio que tragar. Ya sea por que te lo exigen en el trabajo o por que tu abuelo de 80 años no puede o no quiere más que usar el "wasa" ese y no quieres dear de comunicarte con el. Este articulo va para esta gente que se ve obligada a tener este tipo de aplicaciones que requieren que tengas Google Play instalado.
Primero de todo, no es recomendable que hagáis esto si no tenéis un mínimo de idea de lo que hacéis. Si hace falta preguntad, pero no hagáis cosas al tuntun, por que os podéis cargar vuestro móvil. Además, explicaré el proceso en mi móvil, un Huawei Honor 4x con Android 5.0, pero debido a la fragmentación provocada tanto por las versiones de Android como por los fabricantes, de un móvil a otro puede variar el proceso. Por lo tanto, no se trata tanto de seguir al pie de la letra sino de entender que se hace en cada momento y como adaptarlo al móvil de cada una.
Lo que vamos a usar, podemos usarlo gracias al proyecto [MicroG](https://microg.org/). Concretamente, veremos como se instala [GmsCore](https://github.com/microg/android%5Fpackages%5Fapps%5FGmsCore/wiki), que es el paquete encargado de fingir que tienes los servicios de Google Play.
Que aporta exactamente?
- Hace ver que tienes las GAPPS instaladas
- Permite usar backends libres para la localización (útil para aplicaciones como OsmAnd o OpenBikeSharing)
- Poco uso de batería
- Es software libre \o/
- Funciona en aparatos reales, emulados y virtuales
Quien necesita esto? Por lo que he ido viendo al preguntar, esto lo necesita la gente que usa Android de stock sin las GAPPS o la gente que usa CyanogenMod o LineageOS también sin las GAPPS.
Los pre-requisitos son simples, el más obvio es tener el móvil rooteado. Si no lo tienes rooteado, ve al foro [XDA Developers](https://www.xda-developers.com/) y busca tu cacharro. Después, hay que tener <span class="underline">desinstaladas</span> las GAPPS y hay que tener SignatureSpoofing instalado. Ahora veremos más sobre esto.
En el anterior articulo deshabilitamos las aplicaciones de Google, pero siguen instaladas. Ahora tendremos que borrarlas, después de hacer un backup, que nunca se sabe. SignatureSpoofing es un módulo de XPosed Framework. Este framework sirve, básicamente, para hacer que los móviles hagan cosas para las que no están pensados para hacer. Por ejemplo, **SignatureSpojofing**, para quien tenga su inglés oxidado, significa "Falsificación de Firmas". Para el caso que ocupa, haremos que el programa de MicroG finja ser el de Google, para que aplicaciones como la de Bicing, Whatsapp o Signal no sospechen que están siendo engañadas.
Al lío. Hay que tener el móvil enchufado al ordenador y con USB debugging activo. Si no sabes como hacer esto, consulta [el primer articulo](https://daemons.cf/posts/limpiando-mierda-en-android/), en el tercer párrafo. Una vez hecho, instalamos Xposed Framework mediante la aplicación Xposed Installer. Hay dos formas de instalar Xposed Installer.
- Xposed Installer en f-droid
- O ejecutando en la terminal:
```bash
wget http://dl.xposed.info/latest.apk -O /tmp/xposed.apk
adb install /tmp/xposed.apk
```
Lo recomendado es el primer método, ya que así se está al día de las actualizaciones, pero a mi no me funcionó.
Una vez instalado, hay que abrir la aplicación y presionar en **Framework**. Sale un aviso de no tocar si no se sabe lo que se hace. Se presiona en **Instalar/actualizar**. Tarda un poco, cuando esté se le da a reiniciar. Si al encender el móvil, al presionar en la aplicación y luego en **Framework**, aparece que hay un problema con **Resources subclass**, lo que hay que hacer es ir a **Ajustes** y **Desactivar ganchos de fuente** y se reinicia otra vez. Para más información de por que pasa esto, se puede presionar el texto en rojo que menciona el error y llevará al hilo de XDA que lo explica.
Una vez hecho lo anterior, volvemos a abrir la aplicación y se presiona en **Descarga**, escribimos FakeGapps e instalamos la última version. Cuando esté, reiniciar ojo otra vez. Al reiniciar a mi se me quedó la pantalla congelada con una cenefa de rallas verdes. Esperé unos 10 segundos y reinicié a botonazo. Ha arrancado correctamente y el modulo está instalado.
Ahora ya tendremos uno de los dos requisitos. Falta desinstalar todo lo que sea de Google. Podríamos hacerlo del tirón, pero antes necesitamos la ruta de los paquetes para poder hacer la copia de seguridad. El siguiente script remonta la partición `/system/` en modo escritura, hace una copia en `~/apks_google/` y luego la desinstala. Si no funcionase del tirón, se puede reintentar quitando el bucle y repetir su contenido por cada paquete que haya, cambiando la variable `$apk` por el paquete que toque.
```bash
#!/bin/bash
apks=("com.google.android.gms" "com.google.android.backuptransport" "com.google.android.feedback" "com.google.android.gsf" "com.google.android.gsf.login" "com.google.android.onetimeinitializer" "com.google.android.partnersetup" "com.android.vending" "com.google.android.setupwizard")
mkdir -p ~/apks_google/
adb shell "su -c 'mount -o remount,rw /system/'"
for apk in ${apks[@]}
do
ruta=$(adb shell "pm path $apk")
adb pull $ruta ~/apks_google/
adb uninstall $apk
done
adb shell "su -c 'mount -o remount,r /system/"
```
Sea como sea, hay que recordar remontar en modo lectura la partición `/system/`, que sino podemos romper muchas cosas. Lo importante es que ya cumplimos los requisitos. Bibah! Y solo llevamos 1019 palabras para ello. Lo gracioso es que lleva más tiempo explicar los requisitos que la instalación y configuración.
Ya solo queda añadir el repositorio de MicroG a f-droid para instalar el servicio falso de Gugel. Se puede usar este [código QR](https://microg.org/download.html).
Una vez añadido el y actualizado el repositorio, solo queda instalar las aplicaciones que nos interesan. Estas son `microG Services Core` y `microG Services Framework Proxy`. Si por lo que sea, alguna no aparece en F-Droid, se puede descargar directamente de su [página oficial](https://microg.org/download.html). Una vez instalados, deberíamos poder lanzar una aplicación nueva, llamada **Ajustes de microG**. Al abrirla, hay que presionar **Self-Check**, para comprobar que todos los requisitos se están cumpliendo. Ahí saldrá una lista de estos requisitos. Si todo está activo, que debería, ya hemos terminado.
Sino, deberíais repasar el articulo de nuevo. Una vez hecho, podéis preguntar por aquí. Ahora ya seremos capaces de usar aplicaciones como Signal, Whatsapp o Bicing, aunque no es para nada recomendable hacerlo. Recordad, solo hay que hacer esto si de verdad lo consideráis necesario.
En otro articulo hablaremos de como usar el GPS usando otras fuentes que no sean las de Google.

View File

@ -0,0 +1,14 @@
+++
title = "Hola Mundo"
author = ["drymer"]
date = 2015-08-25T19:15:00+02:00
draft = false
+++
Pues nada, todo en la vida tiene un principio y un fin. Escribiré aquí a partir de ahora, que eso de escribir las chorradas que uno hace ayuda a entenderlas mejor y hace más fácil documentarlas. Todos los articulos que he escrito anteriormente están con la etiqueta de "elbinario", por si tal.
Una curiosidad para las personas pocas observadoras, esto es un servicio oculto de tor. Quien quiera ver cómo hacer uno, puede echarle un ojo a la [etiqueta de tor](http://daemon4jidu2oig6.onion/categories/tor), ahí hay un par de articulos al respecto. Lo mismo con el [git](http://daemon4jidu2oig6.onion/cgit), usa cgit y gitolite y funciona a través de tor. La web está hecha con [nikola](https://getnikola.co), los comentarios con [isso](http://posativ.org/isso) y todo es maneado casi exclusivamente con emacs. Probablemente explique cómo lo he hecho en el siguiente articulo.
Poco más que añadir. Bienvenida a Bad Daemons, un nombre de blog sin sentido, cómo cualquier otro.
PD: Es posible que los articulos escritos anteriormente tengan algunos fallos de diseño. Por ejemplo, no hay colores en las etiquetas de código. Eso es debido a que estos articulos han sido exportados y salen con un formato concreto (HTML) y para cambiarlo debería hacerlo a mano. Y cómo me da mucha pereza, así se quedará. En el futuro, el código se verá concretamente.

View File

@ -0,0 +1,47 @@
+++
title = "Hybridbot: Bot pasarela irc - abber"
author = ["drymer"]
date = 2016-09-22T08:30:00+02:00
tags = ["python", "irc", "xmpp"]
draft = false
+++
Hace un tiempo me enteré de que había una comunidad de emacs en castellano en Telegram y pensé que seria buena idea intentar linkearlo con la sala de `#emacs-es` de freenode. Al principio busqué un programa que linkease irc con un grupo de telegram directamente, pero como no me convenció lo poco que vi, decidí usar abbergram y linkear la sala xmpp con la del irc, teniendo así tres sitios posibles en los que la gente pueda entrar. Me puse a buscar y vi que la mayoría de bots pasarela que habían entre XMPP y irc eran muy vieos y que no funcionaban o lo hacían a duras penas. Y me acordé de hybridbot.
Le pedí a ninguno si me deaba terminar el programa y ponerlo bonito, a lo que accedió. Me puse manos a la obra y por cosas de la vida le interesó a Xrevan, la persona que administra el bot pasarela de la sala `#social` de freenode. Le gustó poder abandonar `irc` (y no le culpo por ello) por lo que se puso a meorar **hybridbot**. Llegó a modificarlo tanto que ya no se parece demasiado a lo que hizo ninguno ni a lo que yo lo meoré. Y gracias a ello ahora se puede usar tanto en Python 2 como en Python 3 (entre otras cosas) y funciona muy bien. Lleva unas semanas enchufado tanto en `#social` como en `#emacs-es`. Veamos como usarlo.
Primero de todo clonaremos el repositorio e instalaremos las dependencias:
```sh
git clone https://daemons.it/drymer/hybridbot/
cd hybridbot
su -c "pip install -r requirements.txt"
```
Ahora solo queda editar el archivo de configuración. Las variables que aparecen son las siguientes:
```ini
[Shared]
prefix = .
owner = somebody
[IRC]
channel = #daemons
nick = pasarela
server = chat.freenode.net
port = 6667
[XMPP]
id = becario@daemons.it
password = goodpassword
muc = testeando@salas.daemons.it
nick = pasarela
```
La sección `shared` tiene dos variables. La primera establece que prefio se usará para usar los comandos que acepta el bot, que son `help` y `users`. El prefio establece si se llama escribiendo `.users` o `!users`, según el prefio que se quiera poner. La segunda es el nombre que mostrará cuando se eecute `help`, para que la gente pueda ver quien administra el bot. Las demás secciones no tienen nada que explicar. Puertos, nicks y salas a las que conectarse. Una vez editado, se eecutará del siguiente modo:
```sh
python hybridbot.py config.ini
```
Como podéis ver, acepta el archivo de configuración como parámetro, por lo que se pueden usar tantas pasarelas como archivos de configuración se tenga. Si solo se tiene uno y se llama `config.ini`, no hace falta pasarlo como parámetro.

View File

@ -0,0 +1,47 @@
+++
title = "Hybridbot: Bot pasarela irc - Jabber"
author = ["drymer"]
date = 2016-09-22T08:30:00+02:00
tags = ["python", "irc", "xmpp"]
draft = false
+++
Hace un tiempo me enteré de que había una comunidad de emacs en castellano en Telegram y pensé que seria buena idea intentar linear con la sala de `#emacs-es` de freenode. Al principio busqué un programa que linkease irc con un grupo de telegram directamente, pero como no me convenció lo poco que vi, decidí usar Jabbergram y linkear la sala xmpp con la del irc, teniendo así tres sitios posibles en los que la gente pueda entrar. Me puse a buscar y vi que la mayoría de bots pasarela que habían entre XMPP y irc eran muy viejos y que no funcionaban o lo hacían a duras penas. Y me acordé de hybridbot.
Le pedí a ninguno si me dejaba terminar el programa y ponerlo bonito, a lo que accedió. Me puse manos a la obra y por cosas de la vida le interesó a Xrevan, la persona que administra el bot pasarela de la sala `#social` de freenode. Le gustó poder abandonar `irc` (y no le culpo por ello) por lo que se puso a mejorar **hybridbot**. Llegó a modificarlo tanto que ya no se parece demasiado a lo que hizo ninguno ni a lo que yo lo mejoré. Y gracias a ello ahora se puede usar tanto en Python 2 como en Python 3 (entre otras cosas) y funciona muy bien. Lleva unas semanas enchufado tanto en `#social` como en `#emacs-es`. Veamos como usarlo.
Primero de todo clonaremos el repositorio e instalaremos las dependencias:
```sh
git clone https://daemons.it/drymer/hybridbot/
cd hybridbot
su -c "pip install -r requirements.txt"
```
Ahora solo queda editar el archivo de configuración. Las variables que aparecen son las siguientes:
```ini
[Shared]
prefix = .
owner = somebody
[IRC]
channel = #daemons
nick = pasarela
server = chat.freenode.net
port = 6667
[XMPP]
id = becario@daemons.it
password = goodpassword
muc = testeando@salas.daemons.it
nick = pasarela
```
La sección `shared` tiene dos variables. La primera establece que prefijo se usará para usar los comandos que acepta el bot, que son `help` y `users`. El prefijo establece si se llama escribiendo `.users` o `!users`, según el prefijo que se quiera poner. La segunda es el nombre que mostrará cuando se ejecute `help`, para que la gente pueda ver quien administra el bot. Las demás secciones no tienen nada que explicar. Puertos, nicks y salas a las que conectarse. Una vez editado, se ejecutará del siguiente modo:
```sh
python hybridbot.py config.ini
```
Como podéis ver, acepta el archivo de configuración como parámetro, por lo que se pueden usar tantas pasarelas como archivos de configuración se tenga. Si solo se tiene uno y se llama `config.ini`, no hace falta pasarlo como parámetro.

View File

@ -0,0 +1,19 @@
+++
title = "Hydras en gnu-social-mode"
author = ["drymer"]
date = 2017-01-31T22:56:00+01:00
tags = ["gnusocial", "emacs"]
draft = false
+++
Que son las hydras? Son un animal mitológico de muchas cabezas. Además, es un paquete de emacs que facilita la repetición de teclas. Para que quede más claro, y siguiendo el ejemplo de la [página oficial](https://github.com/abo-abo/hydra), imaginad que queréis apretar **C-n** cinco veces para bajar cinco lineas más abajo. Lo normal seria simplemente presionar **C-n** cinco veces, pero con hydra podríamos presionar **C-n nnnn**. Es un ejemplo tonto, pero ved el gif siguiente:
{{< figure src="/img/hydra.gif" >}}
Este es un ejemplo simplificado del que se puede ver en [su wiki](https://github.com/abo-abo/hydra/wiki/Emacs), en la sección **Movement.** Pero no solo permite facilitar el movimiento, en cierto modo ofrece una interfaz gráfica, como veremos en breves. Este paquete tiene muchísimo potencial y yo apenas lo uso, solo de vez en cuando con [ivy](http://oremacs.com/swiper/#hydra-in-the-minibuffer) y con `gnu-social-mode`. Por ello, recomiendo echar un ojo a [su wiki](https://github.com/abo-abo/hydra/wiki). Para ver ejemplos más prácticos.
A lo que vamos, la siguiente hydra es una adaptación simplificada de la de `twittering-mode` que sale en la wiki del paquete. Al fin y al cabo, `gnu-social-mode` es una versión actualizada de `identica-mode`, que a su vez es una adaptación de `twittering-mode`. Recordemos que ya vimos [gnu-social-mode](https://daemons.cf/posts/cliente-de-gnu-social-para-emacs).
No voy a explicar demasiado el funcionamiento por que es bastante evidente, cada letra tiene asignada su propia función. Solo dejar claro que para activar esta hydra debe presionarse **C-o** en `gnu-social-mode`. Algunas puede que no funcionen, es cosa de `gnu-social-mode`, pero en general, todo va bien.
{{< figure src="/img/gnu-social-hydra.png" >}}

42
content/posts/i3+kde.md Normal file
View File

@ -0,0 +1,42 @@
+++
title = "i3wm + KDE"
author = ["drymer"]
date = 2015-05-30T19:15:00+02:00
draft = false
tags = ["i3wm", "kde", "elbinario"]
+++
La chorrada del día es la del título, usar [i3-wm](http://elbinario.net/2014/05/10/ensenando-i3wm-a-la-chica-rubia-del-asiento-trasero/) cómo window manager en vez de kwin. Kwin es lo que hace que kde sea tan bonito, así que avisadas estáis. Por que hacer esto, se podría preguntar alguien. La respuesta es sencilla, por que podemos. Por algo esta es una de las maravillosas cosas que implican el software libre. La cosa es bien sencilla. Partimos de la base que tenemos i3-wm y kde instalados. El segundo es fácil de instalar, si no tenéis el primero, podéis mirar en el link de más arriba.
Al lío. Buscamos un directorio llamado **windowmanagers**, más que nada por que variará el sitio según la distribución. En Slackware 14.1 está en ****/usr/share/apps/ksmserver/windowmanagers****. Para buscarlo, si tenemos slocate o mlocate instalado, sólo hay que ejecutar en terminal:
<pre>
locate windowmanagers
</pre>
Una vez tenemos la dirección, en ese directorio creamos un archivo llamado i3.desktop con el siguiente contenido:
<pre>
[Desktop Entry]
Encoding=UTF-8
Name=i3
Comment=Highly configurable framework window manager
Type=Application
Exec=i3
TryExec=i3
</pre>
Ahora, desde el escritorio kde, vamos a Preferencias del Sistema > Aplicaciones por Defecto > Gestor de Ventanas > Usar un gestor de ventanas diferente y escogemos i3 del desplegable. tendremos que salir de la sesión y entrar de nuevo para que los cambios sean activados. Pero, antes de hacer eso, podemos hacer unos cambios más para hacer que ambos escritorios se integren mejor. En ~/.i3/config podemos añadir lo siguiente, por ejemplo:
<pre>
for\_window [window\_role="Preferences"] floating enable
for\_window [window\_role="help-browser"] floating enable
for\_window [window\_role="pop-up"] floating enable
for\_window [window\_role="About"] floating enable
for\_window [class="(?i)plasma-desktop"] floating enable
for\_window [class="(?i)klipper"] floating enable
</pre>
Esto hace que ciertas ventanas se pongan en modo floating de manera automática, haciendo así que sean más bonitas. También es recomendable comentar toda la sección ****bar****, ya que sino tendremos dos barras, la de kde y la de i3. Ponerle cómo valor ****hide**** no vale, eso sólo la esconde hasta que se presiona la tecla META. Una vez hecho esto, podemos salir de la sesión y ver nuestra gilipollez del día.

View File

@ -0,0 +1,73 @@
+++
title = "Introducción a Helm"
author = ["drymer"]
date = 2016-05-15T18:33:00+02:00
tags = ["emacs", "helm"]
draft = false
+++
`Helm` es un paquete cuya descripción tiene cojones. Yo no soy capaz de traducirlo literalmente. Lo más cercano que puedo decir es que `helm` es un framework de completado y reducción de selección. Ole. Otra descripción que parece medio humana: `Helm` es un frontend para otras funciones que modifica su uso e incluso une varias. Técnicamente, los paquetes de `helm` pueden ser usados por otros frameworks cómo [`ivy`](http://oremacs.com/2015/04/16/ivy-mode/) o [`ido`](https://www.emacswiki.org/emacs/InteractivelyDoThings), siempre que o unos o otros se adapten.
Cómo es complicado explicar mejor qué es, pondré algún gif en este articulo para que sea más fácil de entender.
## Instalación y configuración {#instalación-y-configuración}
Empecemos por el principio. Para instalarlo, `M-x package-install RET helm RET`. La configuración que yo uso es la siguiente:
```emacs-lisp
(require 'helm)
(require 'helm-config)
(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))
(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
(define-key helm-map (kbd "C-i") 'helm-execute-persistent-action)
(define-key helm-map (kbd "C-z") 'helm-select-action)
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
(global-set-key (kbd "C-x b") 'helm-mini)
(global-set-key (kbd "C-x C-f") 'helm-find-files)
(global-set-key (kbd "M-x") 'helm-M-x)
(helm-mode 1)
(require 'helm-descbinds)
(helm-descbinds-mode)
```
## Cómo coño se usa {#cómo-coño-se-usa}
Y podréis pensar: "Pos muy bien, instalado y configurado. Ahora lo jodido, cómo se usa?". A lo que yo respondo que del mismo modo que usabais `emacs` antes. Al menos en lo que a combinaciones de teclas (y uso básico) se refiere. Desgranaré partes de la configuración anterior y mostraré cómo se ve en la práctica, que al final es lo importante. Básicamente comentaré los keybindings, que cómo algún alma audaz habrá visto, son combinaciones que ya se usan de antes.
A continuación saldrán un buen número de gifs para mostrar lo comentado anteriormente. El formato vendrá a ser **Combinación de teclas** | **Función ejecutada**. Debajo de todo eso, una explicación de por que la función que sustituye a la que viene por defecto mola más. Espero que sea útil. Una última cosa, os fiaréis en que la primera y la segunda imagen se parecen mucho y difieren bastante de lo que tenéis. Esto es debido a que en ambas imágenes está ya **instalado** helm. La diferencia es que en las primeras se usa un simple wrapper que apenas añade funcionalidad y en las segundas se usa las propias. De ahí a que haya que rebindear las funciones tal cómo sale en la configuración.
{{< figure src="/img/m-x-pordefecto.gif" caption="Figura 1: M-x" >}}
{{< figure src="/img/helm-m-x.gif" caption="Figura 2: M-x | helm-M-x" >}}
**Por que mola más?**: No tienes por que saber cómo se llama exactamente la función que quieres ejecutar. En el ejemplo, se escribe `M-x list package` y se puede ver todo lo que tenga que ver con la instalación de paquetes. Además, si la función tiene alguna combinación de teclas para ejecutarla la muestra al lado. Acepta expresiones regulares.
{{< figure src="/img/yank-pordefecto.gif" caption="Figura 3: M-y | toggle-kill-ring" >}}
{{< figure src="/img/helm-show-kill-ring.gif" caption="Figura 4: M-y | helm-show-kill-ring" >}}
**Por que mola más?**: Por defecto, `M-y` no hace nada más que rotar las marcas del `kill-ring`. En cambio, con esta función de `helm`, no sólo rotará sino que nos mostrará las opciones que hay. Acepta expresiones regulares para buscar.
{{< figure src="/img/helm-mode-switch-buffer.gif" caption="Figura 5: C-x b | helm-mode-switch-to-buffer" >}}
{{< figure src="/img/helm-mini.gif" caption="Figura 6: C-x b | helm-mini" >}}
**Por que mola más?**: No sólo muestra los buffers que hay abiertos, sino que también muestra los buffers que han sido abiertos recientemente (tirando de `recentf`) y crear buffers nuevos.
{{< figure src="/img/find-files.gif" caption="Figura 7: C-x C-f | Find-Files" >}}
**Por que mola más?**: Varios motivos cuya cabida escapan al articulo de hoy, saldrán más adelante. Pero un ejemplo es que integra la función `ffap`, cuyo nombre tan sugestivo significa **Find File At Point**, que viene a ser abrir un archivo al situarse en una ruta escrita en el buffer, cómo se ve en el ejemplo. Sólo sale una imagen que es la de `Find-Files`, ya que es muy similar a la función que trae por defecto emacs, excepto las mencionadas funciones extra.
Y con esto ya se ha visto lo básico. Ahora a usarlo.
[Fuente principal](http://tuhdo.github.io/helm-intro.html)
[La sección](https://daemons.cf/stories/mi-configuracin-de-emacs/#Helm) pertinente en mi configuración.

View File

@ -0,0 +1,71 @@
+++
title = "Limpiando mierda en Android"
author = ["drymer"]
date = 2016-01-17T17:24:00+01:00
tags = ["android", "movil", "privacidad"]
draft = false
+++
Cuando alguien está pensando en comprar un móvil, lo primero que debería hacer es mirar en la [wiki](https://wiki.cyanogenmod.org/w/Devices) de Cyanogen Mod para ver que el que le interesa tiene posibilidad de usar esa ROM. Eso es lo que hice yo, me llegó el móvil y al mirar más en profundidad vi que dentro del propio móvil habían sub-categorías, en las cuales algunas soportaban CM y otras no. La mía fue la que no. Así que recomiendo mirar bien en profundidad, no sólo por encima cómo hice yo.
Por este motivo, decidí quedarme con el Android de stock y quitarle toda la mierda. Un requisito, que no se tocará en este manual, es le de tener el móvil rooteado. Sin esto no hacemos nada, las mierdas de Google no se podrán desinstalar. Al lío. Lo primero que hay que hacer es instalar `fastboot` y el `adb` de Android. En debian:
```sh
su -c "apt-get install android-tools-adb android-tools-fastboot"
```
Lo siguiente es enchufar el móvil al ordenador usando el cable USB y activar las herramientas de debug USB. Hay que acordarse de quitarlo después ya que permite ciertas cosas que en condiciones normales no se podrían hacer. Depende de la versión de Android, puede variar un poco el proceso, pero se hace más o menos así: "Ajustes > Acerca del teléfono > Número de compilación" Este último, hay que presionarlo unas cuantas veces rápidamente y se acabarán activando las "Herramientas de desarrollador", que aparecerán usto encima de "Acerca del teléfono". Ahí, se activa la "Depuración USB" y por comodidad "Pantalla Activa", ya que si el móvil se bloquea, adb no funciona correctamente. Ahora al enchufar el móvil, en la pantalla saldrá algo del tipo del fingerprint del ordenador y que si queremos dejar que acceda al móvil. Se acepta y ale. Hecho lo aburrido, vamos a lo divertido.
Cómo root siempre:
```sh
adb devices
List of devices attached
BY4X4Xthtq34418 device
```
Si se ve algo parecido a lo de arriba al ejecutar ese comando, significa que adb tiene acceso al móvil y que se puede seguir adelante.
Antes de seguir, es muy recomendable instala [f-droid](https://f.droid.org) e instalar un par de aplicaciones. La primera será `Hacker Keyboard` (por ejemplo, cualquier teclado vale) y la segunda será `oandbackup`. La primera es necesaria porqué nos cargaremos el teclado de Google, y la segunda porqué con esa aplicación, que de por si no hará nada si no está instalado `busybox` (ni falta que hace), averigua el nombre completo del apk que queremos desinstalar.
A lo práctico:
```sh
adb shell pm list packages -f
adb shell "su -c 'pm disable $paquete'"
adb shell top
```
El primer comando listará todas las aplicaciones que hayan instaladas, y el segundo deshabilitará el $paquete que se le diga. Me inclino más por deshabilitarlo que por borrarlo, porque nunca se sabe. Viendo la lista de procesos (tercer comando) se puede ver que una vez desactivados no se ejecutan, por lo que lo considero más o menos fiable. Con esto ya se puede tirar millas. Sólo hace falta una lista de programas a desinstalar y un bonito bucle que ejecute el comando de desactivación con los miembros de la lista. La lista (que es una mezcla (ligeramente modificada) de [esta](https://github.com/jaredsburrows/android-bloatware/blob/master/disable-list.txt) y mía) se puede descargar [aquí](http://daemons.cf/wp-content/deshabilitar.txt). En esta lista está todo lo de google (al menos de mi móvil), mierdas de huawei y alguna cosa más. Aviso de que, cómo siempre que se tocan cosas de este tipo, hay que ir con cuidado. Para quitar todo lo que hay en la lista:
```sh
for i in $(cat definitivodelto); do adb shell "su -c 'pm disable $i'";done
```
Y ya está. Cuando desactiva la aplicación, en la terminal sale `Package $paquete new state: disabled`. Sino, es que no se ha desinstalado, probablemente por que no existe.
Y con esto ya se ha quitado mucha mierda. Ahora sólo queda repasar, y para eso está `oandbackup`. Sólo queda mirar el nombre de la aplicación que se quiera desinstalar y debajo se ve el nombre del apk. Por ejemplo, weechat se llama `com.ubergeek42.Weechat.Android`. Sólo queda ejecutar:
```sh
adb shell "su -c 'pm disable com.ubergeek42.Weechat.Android'"
```
{{< figure src="/img/oandbackup.png" >}}
Y a volar.
PD: Un par de comandos molones de adb de regalo:
```sh
# Hacer captura de pantalla del móvil y descargarla al ordenador con el nombre "test.png"
adb shell screencap -p /sdcard/test.png; adb pull /sdcard/test.png
# Backup completo de todo el móvil
adb backup -all -f backup.ab
adb restore backup.ab
## Extraer apk
adb shell pm path org.andstatus.app
package:/data/app/org.andstatus.app-1.apk
adb pull /data/app/org.andstatus.app-1.apk
```

66
content/posts/logcheck.md Normal file
View File

@ -0,0 +1,66 @@
+++
title = "Logcheck"
author = ["drymer"]
date = 2015-03-27T19:15:00+02:00
draft = false
tags = ["sysadmin", "elbinario"]
+++
Una de las tareas del buen sysadmin es la de revisar los logs de sus servicios. Los logs son importantes, de ahí la reticencia de algunos sitios de borrar completamente estos. Nosotros en breves sacaremos una página explicando que guardamos y que no. Pero bueno, el tema es otro.
La cosa es que revisar los logs de una máquina es fácil. Te logueas por ssh, haces un cat, un more o lo que sea y echas un ojo. Pero la cosa se complica cunado no es una máquina sino 10, 20 o 100. Para estas cosas va bien algo cómo logchek, que se encarga de mandar por correo los logs que le digas. Pero los logs son, normalmente, algo sensibles. Así que mejor mandarlos cifrados, no? A eso vamos.
Instalamos logcheck en debian y derivados cómo siempre:
```bash
su -c "aptitude install logchek"
```
Sencillo. Ahora editamos el fichero de configuración con un editor cualquiera, tal cómo nano:
```bash
su -c "nano /etc/logcheck/logcheck.conf"
```
A continuación pegaré solamente las lineas que vamos a modificar junto con un comentario explicando el porqué:
```bash
DATE="$(date +'%d-%m-%Y %H:%M')" # Cómo siempre, los americanos y sus cosas. Así se verá en el formato europeo.
REPORTLEVEL="paranoid" # Porqué nosotros lo valemos
MAILASATTACH=1 # Enviará los resultados por correo
ATTACKSUBJECT="Security Alerts" # Esta y las siguientes dos lineas mandaran un asunto distinto dependiendo del evento
SECURITYSUBJECT="Security Events"
EVENTSSUBJECT="System Events
```
Después metemos en el fichero /etc/logcheck/logcheck.logfile los ficheros de log que queramos monitorizar. Por defecto viene auth.log y syslog. Podemos añanidr, por ejemplo, los de dovecot, postfix, nginx, &#x2026;
Y con esto, tendremos lo básico. Si dejáis pasar una hora, veréis que recibís un correo. Si dejáis pasar un día, veréis que habéis recibido 24 correos. Esto es debido a que no se está filtrando nada de los logs. Logcheck puede aplicar expresiones regulares para sacar lo mas importante de los logs. Pero, por defecto, no trae ninguna. En Debian y derivados estas vienen en un paquete a parte, que se llama logcheck-databases. Es cuestión de instalarlo y en los directorios *etc/logcheck/ignore.\* tendremos un bueno montón de reglas que nos ahorraran mucho trabajo. Se incluyen para distintos servicios, tales cómo sftp, dovecot, postfix, ssh,&#x2026; Pero no viene ninguna para nginx o apache, que probablemente son los servicios que en un servidor cómo el nuestro más visitas van a llegar. Cómo es posible que no se tenga mayor interés en ver las peticiones con un código de 200, es decir las peticiones correctas a la web, se puede crear un archivo en /etc/logcheck/ignore.d.paranoid* llamado nginx, por ejemplo con una expresión regular que filtre todas estas peticiones. Un ejemplo sería así:
```bash
regexp
```
Esto debería quitarnos todo lo gordo de nginx. Y ahora, sólo recibiremos de vez en cuando algunas líneas de algo llamado [wpscan](http://elbinario.net/wpscan) o [joomscan](http://elbinario.net/joomscan), por ejemplo. Esto son scanners de vulnerabilidades (también tienen otras funciones) que, con la configuración que hemos visto más arriba, debería hacer saltar las alarmas y mandar un correo con esas lineas, ya que buscará ciertos archivos y patrones que devolverán, muchos o todos, un código 400, es decir, no encontrado. Pero cómo somos paranoicos (por algo escogimos esa configuración de logcheck) nos aseguraremos creando un archivo en *etc/logcheck/violations.d* llamado scanner, por ejemplo. Dentro de éste pondremos WPScan y JoomScan. Así nos aseguraremos de que cualquier linea del log con estas palabras nos salga en nuestro correo. Es curioso, pero un programa de pentesting (hacking ético?) cómo este es muy ruidoso. Aún usando la opción **-r**, que cambia el user agent, si se miran los logs se ve un brillante y gran WPScan en medio. Se puede comprobar haciendo:
```bash
grep WPScan /var/log/nginx/access.log # O dónde sea que esté el log del servidor web
```
En fin, a lo que íbamos era cifrar los correos que mande logcheck. La manera más sencilla de hacerlo es que se mire en el pad el script modificado. Realmente son tres lineas cambiadas, adjunto el diff del original también. Antes de ejecutarlo, hay que tener en cuenta que hay que importar la clave GPG del correo al cual enviaremos los correos, con el usuario logcheck. Para hacerlo:
```bash
su logcheck -c "gpg &#x2013;recv-keys $clave"
```
Una vez hecho, para comprobar que funcione bien, podemos hacer lo siguiente:
```bash
echo "Test de mails cifrados" >> /var/log/syslog
su logcheck -c logcheck
```
Y si todo va bien, mails cifrados y a volar.

View File

@ -0,0 +1,28 @@
+++
title = "Pandoc: el convertidor de archivos definitivo "
author = ["drymer"]
date = 2015-03-26T19:15:00+02:00
draft = false
tags = ["sysadmin", "elbinario"]
+++
Me he encontrado con que tengo que escribir habitualmente largos archivos a los que tengo que dar formato. Llegado el momento, y empezando como estoy con #emacs, he decidido dejar de tirar de procesoadores de texto absurdos (tales cómo *office) y tirar de emacs, que para eso está. Además, usando #markdown, que teniendo en cuenta que no necesito tablas, gráficos ni esas cosas, pues me va genial.
En fin, la cosa es que buscando cómo pasar markdown a PDF he dado con pandoc. Para que os hagáis una idea del poder de esta herramienta, ved la siguiente imagen.
{{< figure src="http://pandoc.org/diagram.png" >}}
En fin, al lío. La cosa es bastante sencilla. El paquete se llama *pandoc*, y se instala así en debian y derivados:
```bash
su -c "aptitude install pandoc"
```
En slackware está en los repositorios de slackbuilds, y tiene unas dependencias importantes. Usando sbopkg, podeis coger la lista que está en el pad, guardarla cómo/var/lib/sbopkg/queues/ pandoc.sqf y cargarla en sbopkg sin más.
Una vez instalado, para exportar un archivo markdown a PDF es tan sencillo cómo:
```bash
pandoc -o out.pdf archivo.markdown
```
Esta línea exporta el markdown tal cual. Luego es cuestión de ir metiendo opciones que nos interesen. Lo mejor que se puede hacer es documentarse en condiciones. Lo realmente interesante de pandoc es la moduralidad que permite. La exportación puede ser tan sencilla cómo hacerla tal cual está arriba o metiéndole css, templates de latexo meter metadatos al exportar a epub. El límite está dónde tu lo pongas, ya que permite incluso crear formatos en lua.

View File

@ -0,0 +1,20 @@
+++
title = "Mejoras en el blog: Hugo, ox-hugo y drone"
author = ["drymer"]
date = 2018-08-25T21:11:00+02:00
tags = ["orgmode", "hugo", "ci", "drone"]
draft = false
+++
Hace un tiempo que no actualizo el blog. Pensaba que es por que ando a otras cosas, pero reflexionando me di cuenta de que me daba pereza. No por escribir en general, sino por que el flujo de publicación que tenia en mi blog no me gustaba. Debido a que odio todo lo que tenga que ver con diseño, en vez de hacer las modificaciones del blog en la plantilla, me dediqué a hacer scripts que modificasen el HTML generado de forma dinámica, lo que iba bien al principio, pero luego tardaba hasta medio minuto en construir. Además, al ser tan personalizado, tenia que hacer las cosas de una forma muy particular o me encontraba errores después. En fin, un dolor. Por eso, por que me cansé del tema y por que echaba en falta alguna funcionalidades, me decidí a migrar de nikola a hugo.
Y aquí estamos. El flujo que sigo ahora es el siguiente:
{{< figure src="/img/blog-workflow.png" >}}
El repositorio git del blog es público, y se puede ver [aquí](https://git.daemons.it/drymer/BadDaemons). No voy a explicar como he hecho nada, ya que en todos los casos he seguido la documentación oficial de cada proyecto. Pero por si alguien quiere empezar a hacer lo mismo, propongo que se siga el orden siguiente:
- [Empezar con hugo](https://gohugo.io/getting-started/quick-start/)
- [Instalar y configurar ox-hugo](https://ox-hugo.scripter.co/doc/usage/)
- [Empezar con git](https://victorhckinthefreeworld.com/2016/05/19/curso-interactivo-de-git-en-15-minutos/)
- [Empezar con Integración Continua](https://labrecha.digital/blog/integracion-continua-drone/)

View File

@ -0,0 +1,10 @@
+++
title = "Mi dominio twitter2rss.cf ha muerto por violación de copyright"
author = ["drymer"]
date = 2016-08-14T00:00:00+02:00
draft = false
+++
El programa que hice para crear RSS de cuentas twitter está hosteado en un servidor y tenia el dominio mencionado, twitter2rss.cf. Pero parece que ha sido denunciado por violar el copyright, por algún motivo. Imagino que por tener twitter en el nombre, aunque no es ni mucho menos el único y ni siquiera el más conocido. He enviado un correo al proveedor, freenom, pero no han contestado.
En fin, solo informar de eso. El servicio sigue siendo accesible usando la IP, no voy a ponerle otro dominio, prefiero no arriesgarme a perder el del blog. La IP es 185.101.93.139.

View File

@ -0,0 +1,90 @@
+++
title = "Migrar de helm a ivy"
author = ["drymer"]
date = 2016-09-13T22:30:00+02:00
tags = ["ivy", "helm", "emacs"]
draft = false
+++
Ya hablé hace un tiempo sobre [helm](https://daemons.cf/posts/introduccin-a-helm/). Helm es uno de los paquetes más potentes que tiene emacs y me sigue encantando por ello. Pero tiene un pequeño problema y es que consume demasiado para mi ordenador. `ivy`, en cambio, está a medio camino de `ido` y `helm`, manteniendo los atajos más típicos de emacs. Me refiero al uso del tabulador, que seguramente es a lo que más cuesta acostumbrarse cuando se empieza a usar `helm`. Con `ivy` se recupera el estilo típico. No tiene tantas opciones de configuración cómo `helm` y tampoco es tan simple como `ido`. Es perfecto para quien quiere `helm` pero le resulta pesado.
A esta utilidad se le llama comúnmente `ivy`, pero en realidad el paquete que instalamos es un conunto de tres herramientas:
- **Ivy**: un mecanismo genérico de completado de emacs
- **Counsel**: varios comandos habituales de emacs mejorados con **ivy**
- **Swiper**: un `isearch` mejorado con **ivy**
Los tres paquetes se instalaran al instalar `ivy`. Pero si queremos mejorar la experiencia, podemos instalar dos paquetes más, `smex` y `flx.` El primero da un histórico de las órdenes ejecutadas con `M-x`, el segundo da un mejor soporte a **swipe** cuando se usa (no se como traducir esto) "expresiones regulares difusas", "fuzzy regex" en inglés. Lo bueno de ambos es que no necesitan configuración de ningún tipo.
Primero de todo instalamos los paquetes:
- `M-x package-install RET ivy RET`
- `M-x package-install RET flx RET`
- `M-x package-install RET smex RET`
Una vez instalado lo configuraremos, pero veréis que es muy sencillo.
```emacs-lisp
(unless (require 'ivy nil 'noerror)
(sleep-for 5))
(use-package ivy
:init
;; Añade los buffers de bookmarks y de recentf
(setq ivy-use-virtual-buffers t)
;; Muestra las coincidencias con lo que se escribe y la posicion en estas
(setq ivy-count-format "(%d/%d) ")
;; Un mejor buscador
(setq ivy-re-builders-alist
'((read-file-name-internal . ivy--regex-fuzzy)
(t . ivy--regex-plus)))
;; No se sale del minibuffer si se encuentra un error
(setq ivy-on-del-error-function nil)
;; ivy mete el simbolo ^ al ejecutar algunas ordenes, así se quita
(setq ivy-initial-inputs-alist nil)
;; Dar la vuelta a los candidatos
(setq ivy-wrap t)
;; Ver la ruta de los ficheros virtuales
(setq ivy-virtual-abbreviate 'full)
;; Seleccionar el candidato actual (C-m en vez de C-S-m)
(setq ivy-use-selectable-prompt t)
;; Asegurarse de que están smex, flx y ivi-hydra
(use-package smex :ensure t)
(use-package flx :ensure t)
(use-package ivy-hydra :ensure t)
:config
(ivy-mode 1)
(setq magit-completing-read-function 'ivy-completing-read)
:diminish ivy-mode
:ensure t)
(use-package counsel
:config
(setq counsel-find-file-at-point t)
:ensure t)
(use-package swiper
;; comentado en favor de ace-isearch
;; :bind (;; Sustituir isearch
;; ("C-s" . swiper)
;; ("C-r" . swiper))
:ensure t)
```
No hay mucho que comentar más que la última variable. Sin esa variable apuntando a `nil`, cada vez que se ejecuta `counsel-M-x` (entre otras funciones) en el minibuffer en el que escribimos se insertará el símbolo **^**. Quien sepa algo de expresiones regulares, sabrá que ese simbolo se usa para establecer que lo que se escriba a continuación será el inicio de la linea. Un ejemplo:
```sh
# No se producirán coincidencias
echo "Hola, soy drymer, que tal?" | egrep "^drymer"
# Se producirán coincidencias
echo "Hola, soy drymer, que tal?" | egrep "drymer"
```
Sin el simbolo habrán maś coincidencias, pero no hasta el punto de ser molesto.
Y ya está, es sencillo y rápido. Quien quiera saber más sobre la configuración puede echar un ojo a su [manual de usuario](http://oremacs.com/swiper/). En el arranque no se nota mucha mejora en el rendimiento, pero en el momento de usarlo si se nota.

View File

@ -0,0 +1,17 @@
+++
title = "Múltiples cursores en emacs"
author = ["drymer"]
date = 2017-12-11T08:30:00+01:00
tags = ["emacs"]
draft = false
+++
Este es un paquete al que cuesta cogerle el punto. Pisa un poco las funcionalidades de las macros, es un poco especialito y hay que tener un poco de imaginación al usarlo, pero una vez le pillas el truco es muy útil.
El paquete que muestra el siguiente gif es de `multiple-cursors`, y hace exactamente esto, abrir múltiples cursores en emacs. Lo he estado usando últimamente que he tenido que he estado usando [Terraform](https://www.terraform.io/) en el trabajo, y se presta al uso de este paquete. Veamos un ejemplo:
{{< figure src="/img/multiple-cursors.gif" >}}
La primera función es `mc/mark-next-like-this`, que crea un cursor en el siguiente elemento que es igual al que se está seleccionando. Tiene su equivalente `mc/mark-previous-like-this` para lo mismo pero para atrás. La siguiente función es `mc/mark-next-lines` que marca la siguiente linea sin más. Igual que la anterior, tiene su equivalente inverso, `mc/mark-previous-lines`. Y por último, el más útil, como todos los dwim, Do What I Mean. Se comporta de forma distinta según desde dónde se ejecute. Si se selecciona una región, introduces una cadena de carácteres y inserta cursores en esas regiones. En otra región hará otra cosa.
En la fabulosa página de [Emacs Rocks](http://emacsrocks.com) hay un screencast sobre [este paquete](http://emacsrocks.com/e13.html). Son solo tres minutos y muestra otro ejemplo de como usar este modo.

View File

@ -0,0 +1,41 @@
+++
title = "Modificar la salida de una función de emacs lisp sin redefinirla"
author = ["drymer"]
date = 2018-02-06T23:10:00+01:00
tags = ["emacs", "lisp", "projectile"]
draft = false
+++
Casi es más largo el título que la definición o solución del problema.
Por mostrar un caso real explicaré el problema que tenia. Uso el paquete [Projectile](http://projectile.readthedocs.io/en/latest/), que sirve para gestionar proyectos en emacs, recomiendo fuertemente que le echéis un ojo. Cuando se han abierto unos cuantos proyectos puede usarse la función `projectile-switch-project`, que permite cambiar el proyecto. El tema es que muchos directorios de mi home son en realidad enlaces simbólicos a otros sistemas de ficheros. Esto hace que los proyectos se me muestren con las rutas reales, no las rutas de los enlaces simbólicos. Por ejemplo, un proyecto en `/home/drymer/Documentos/Ansible/roles/upgrade-all` se me muestra como `/media/.secret/Casa/Documentos/Ansible/roles/upgrade-all`, lo cual es horroroso.
Lo que yo necesito es hacer que los proyectos en `/media/.secret/Casa/` se muestren como `/home/drymer/`. Investigando, vi que lo que me hacia falta era usar una función de asesoramiento. No tengo claro si se traduce así, en inglés son [Advising Functions](https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/Advising-Functions.html#Advising-Functions). El tema es que estas funciones permiten, entre otras cosas, modificar la salida de una función elisp sin tener que redefinirla.
Por lo tanto, hay que averiguar que función es la que hay que modificar. En este caso, la función que da el nombre a los proyectos es `projectile-project-root`. Ahora crearemos una función simple que ejecute un `replace-regexp-in-string` en la salida:
```emacs-lisp
(defun daemons/projectile-project-root (arg)
(replace-regexp-in-string "\\(/media/.secret/Casa\\)" (getenv "HOME") arg))
```
Un ejemplo de la ejecución de esta función:
```emacs-lisp
(daemons/projectile-project-root "/media/.secret/Casa/Proyectos/nikola.el")
```
Solo nos queda añadir el filtro:
```emacs-lisp
(advice-add 'projectile-project-root :filter-return #'daemons/projectile-project-root-filter)
```
Desgranemos el código:
- `advice-add`: Añade función de asesoramiento.
- `projectile-project-root`: La función que modificaremos.
- `filter-return`: De que modo modificamos la función.
- `daemons/projectile-project-root-filter`: Función con la que modificaremos el comportamiento de la primera.
La parte más interesante es la de `filter-return`, ya que este no es el único parámetro que se puede definir. Si quisiésemos, podríamos sustituir la función entera de muchas formas distintas. De hecho, si quisiésemos redefinir una función ya definida en alguna parte, las buenas prácticas dicen que hay que usar las funciones de asesoramiento. Recomiendo leer [su sección del manual](https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/Advice-combinators.html#Advice-combinators).

View File

@ -0,0 +1,43 @@
+++
title = "Mostrar un aviso únicamente a las visitas de ZeroNet"
author = ["drymer"]
date = 2016-08-22T16:40:00+02:00
tags = ["zeronet"]
draft = false
+++
Ya comenté en el [primer articulo](/posts/cmo-replicar-una-web-de-html-esttico-en-zeronet/) sobre ZeroNet que hablaría de como mostrar avisos sólo a las visitas de ZeroNet, así que ahí va. Mi motivo para querer usar esto es que en la versión de la web de ZeroNet no se puede comentar, por lo que quería que se avisase sólo a ellas.
Para ello modifiqué un poco el script que se da en el articulo de como [crear una web en ZeroNet](http://127.0.0.1:43110/Blog.ZeroNetwork.bit/?Post:43:ZeroNet+site+development+tutorial+1). Probablemente se pueda recortar aún más, más pero no sé javaScript. Lo que hace el script es establecer una conexión WebSocket y si eso pasa sale un aviso en una cajita azul. Esta conexión sólo funciona si la web se visita desde ZeroNet. Cuando se visita desde cualquier otro sitio, no pasa nada de nada. El script se puede descargar de [aquí](https://daemons.cf/wp-content/all.js) Si se quiere modificar el mensaje que sale, hay que modificar la linea 139. El CSS que uso es:
```css
.alert-box {
color: #555;
border-radius: 10px;
font-family: Tahoma,Geneva,Arial,sans-serif;font-size:11px;
padding: 10px 10px 10px 36px;
margin: 10px;
}
.notice {
border: 1px solid #8ed9f6;
background: #e3f7fc 10px 50%;
}
```
Y por último, en los archivos HTML en los que se quiere que aparezca el aviso, hay que insertar lo siguiente:
```html
...
<head>
...
<script type="text/javascript" src="$RUTA_A_SCRIPT/all.s" async></script>
...
</head>
<body>
<ul id="messages"></ul>
...
</body>
```
La parte del `script`, carga el script que se puede descargar más arriba y la parte del `ul` es dónde se inserta el aviso en cuestión.

View File

@ -0,0 +1,314 @@
+++
title = "Neomutt + offlineimap + notmuch + abook: Sustituyendo a los gestores de correo monstruosos"
author = ["drymer"]
date = 2016-09-09T11:32:00+02:00
tags = ["i3wm", "mutt"]
draft = false
+++
Creo que ya lo comenté en algún otro articulo, pero se me odió la torre hace unas pocas semanas y desde entonces estoy funcionando con un **Pentium M con 512 MB de RAM**. Evidentemente he tenido que cambiar un poco mi flujo de trabajo, no puedo usar algunos programas que antes usaba. Por suerte hace ya más de un año estoy usando [i3-wm](https://daemons.cf/categories/i3wm), por lo que ya había muy poquita cosa que usase con interfaz gráfica o fuese demasiado pesado para este ordenador. Sólo hay dos programas en concreto de este tipo, de los que seguramente cuesta más desprenderse. Una es el navegador y otra el gestor de correo. Hoy hablaré del gestor de correo, el navegador lo dejaré para otro articulo.
No soy muy de enviar correos, pero si que suelo recibir ya me gusta estar en varias listas de correos. Para ello tanto thunderbird cómo la mayoría de gestores son una brutalidad en términos de consumo de recursos, aunque desde luego thunderbird es de los más pesados (y de los más usados). Por ello, me decidí a usar el cliente de correo `mutt`, que llevaba mucho tiempo queriendo usar pero sin haberme lanzado del todo.
Como he dicho, en un principio quería usar Mutt, pero me di cuenta de que aunque es perfectamente funcional, le faltan muchas opciones. Buscando vi que con el tiempo han ido saliendo parches que lo mejoran. Hace relativamente poco, varias personas decidieron unir estos parches y continuar el desarrollo activo de Mutt, surgiendo así Neomutt.
Antes de seguir, vayamos por partes. En el título hay cuatro programas, **Neomutt**, del que ya he hablado, **Offlineimap**, que descarga al PC los correos de un buzón MAP, **Abook** que gestiona la agenda y **Notmuch**, que indexa los estos correos. Neomutt no tiene la opción de descargar los correos, por eso hace falta Offlineimap. Tampoco tiene la opción de crear una agenda en función de los correos recibidos, cómo suelen tener todos los gestores, para ello usaremos Abook. El primero que configuraremos será Offlineimap.
Tabla de contenidos:
- [Offlineimap](#org6b7449f)
- [Notmuch](#org6be15b9)
- [Abook](#org60e1dcf)
- [Neomutt](#orge99d49e)
Antes que nada, deberíais clonar el repositorio de mis archivos de configuración:
```sh
git clone https://daemons.it/drymer/dotfiles
cd dotfiles
bash instala.sh mutt
```
Esto copiara dos archivos y un directorio: `~/.mutt`, `~/.muttrc` y `~/.offlineimaprc`. Estos son los lugares en los que los programas buscan los ficheros de configuración.
En el próximo articulo explicaré cómo lo tengo montado para tener varias cuentas de forma cómoda en un contenedor cifrado con encfs. A parte de querer tener los correos en un sitio seguro, es interesante por que no nos vemos obligadas a tener los ficheros con las contraseñas en texto plano sin más, que siempre está feo.
Al lío.
## Offlineimap {#offlineimap}
<a id="org6b7449f"></a>
:ID: 8176c458-6116-4665-b1c0-664f230463d9
Se puede instalar desde los repositorios de la distribución que se use o mediante `pip`, como más guste:
```sh
aptitude install offlineimap
# o
sbopkg -i offlineimap
# o
pip install offlineimap
```
Una vez instalado, editaremos el fichero en `~/.offlineimaprc` que tiene un contenido similar al siguiente:
```ini
[general]
ui = ttyui
accounts = autistici
[Account autistici]
localrepository = autistici-local
remoterepository = autistici-remote
[Repository autistici-local]
type = Maildir
localfolders = ~/mail/
[Repository autistici-remote]
type = IMAP
remotehost = mail.autistici.org
remoteuser = drymer@autistici.org
remotepass = password_molona
realdelete = yes
maxconnections = 3
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
```
Se pueden añadir tantas cuentas como se quieran en la variable `accounts` de la sección `General`. Por cada una de ellas, habrá que añadir las tres secciones posteriores (`Account`, `Repository (local)` y `Repository (remoto))`. Las variables que hay en ellas son bastante obvias, así que no entraré en más detalle. La variable `sslcacertfile` parece obligatoria desde la versión 7.0.5.
Ahora ya lo tenemos listo para sincronizar los correos. Ejecutando simplemente `offlineimap` se sincronizarán.
## Notmuch {#notmuch}
<a id="org6be15b9"></a>
:ID: a54b3e22-9146-48e9-83e5-a3ff433bd326
Se instala el paquete `notmuch`:
```sh
aptitude install notmuch
# o
sbopkg -i notmuch
```
Una vez instalado, se puede ejecutar `notmuch setup`, que creará el fichero `~/.notmuch-config` o se puede crear directamente:
```ini
[database]
path=/home/$user/mail
[user]
name=drymer
primary_email=cuenta@punto.com
other_email=alguien@cuenta.org
[new]
tags=new;unread;inbox
ignore=
[search]
exclude_tags=deleted;spam;
[maildir]
synchronize_flags=true
[crypto]
gpg_path=gpg
```
Sólo comentar que la variable `path` de la sección `database` debe apuntar al directorio en el que están los correos, que es dónde se creará la base de datos con el contenido indexado de los correos.
Una vez hecho, se ejecuta `notmuch new`, que según la cantidad de correos que se tengan puede tardar un poco. Luego, cada vez que se ejecute `offlineimap` deberá ejecutarse `notmuch new`, para que reindexe todos los correos nuevos. Podéis probar a buscar algún correo usando `notmuch search $parametroDeBusca`.
Notmuch gestiona las "flags" típicas del correo, **nuevo**, **enviado**, **borrado**, etc. Antes, si queríamos tener, una vista rápida de todos los correos de org-mode, por ejemplo, había que crear alguna regla para que moviese todos los correos de la lista de org-mode a un directorio en concreto. Pero con notmuch esto ya no es necesario. Se funciona con **etiquetas** en vez de con directorios, algo que parece más eficiente. Para ello yo uso el siguiente script:
```sh
#!/bin/bash
i=0
lista=("emacs-orgmode@gnu.org" "list_criptica@inventati.org" "@lists.torproject.org")
tags=("orgmode" "criptica" "tor")
for mail in ${lista[@]}
do
notmuch tag -inbox +${tags[$i]} --output=messages $mail tag:inbox
i=$((i+1))
done
```
El script se encuentra en `~/.mutt/scripts/filtros.sh`. Para usarlo hay que añadir un correo en la variable `lista` y el tag que se quiera que tengan esos correos en la variable `tags`. Hay que hacerlo siempre en orden. Luego veremos cómo automatizar su uso.
## Abook {#abook}
<a id="org60e1dcf"></a>
:ID: 83f3c957-75cf-418f-9aee-ccc480176422
Se instala el paquete `abook`:
```sh
aptitude install abook
# o
sbopkg -i abook
```
Este programa funciona del siguiente modo:
```sh
echo "From: unCorreo@punto.com" | abook --datafile ~/.abook --add-email-quiet
```
El `--datafile` solo hace falta si tenemos la agenda en un sitio distinto del habitual. El `--add-email-quiet` es lo que añade el correo a la agenda. Pero lo importante es que hay que pasarlo en ese formato, con el "From: " delante, lo cual es bastante incomodo. Por ello he hecho un script, que añade automáticamente todas las direcciones de los correos entrantes. Igual es un poco exagerado, pero dado que apenas consume recursos, tampoco importa mucho:
```sh
#!/bin/bash
MESSAGE=$(notmuch show tag:unread 2> /dev/null)
NEWALIAS=$(echo "$MESSAGE" | grep ^"From: ")
if [[ -n $NEWALIAS ]]
then
while read -r line
do
busqueda="$(abook --datafile ~/.abook --mutt-query $(echo $line | cut -d'<' -f2 | cut -d'>' -f1 | cut -d':' -f2 | sed 's/^ //'))"
# auto add sender to abook
if [[ $busqueda = "Not found" ]]
then
echo $line | abook --datafile ~/.abook --add-email-quiet > /dev/null
fi
done < <(echo "$NEWALIAS")
fi
```
El script está en `~/.mutt/scripts/auto-process.sh` Lo que hace es coger los correos que no se han leído, comprobar si la dirección está añadida y si no lo está, añadirla. Más adelante veremos cómo se automatiza esto con otros scripts para que sea cómodo de usar.
Para usar la agenda, cuando se presiona **m** para enviar un nuevo mensaje en mutt, el primer campo a rellenar es la destinataria del correo, escribiendo las primeras letras y presionando el tabulador se auto completará.
## Neomutt {#neomutt}
<a id="orge99d49e"></a>
:ID: 4ffd8dad-25c6-40e1-9fb7-9148fac5adc7
Primero de todo la instalación. Hasta dónde se no hay paquetes en las distribuciones, pero se puede compilar. Lo único que vale la pena mencionar es que veréis que uso el flag `--disable-fmemopen`. Esto es debido a que, por algún motivo que aún no han sabido concretar, si mutt soporta **fmemopen** da un segfault cuando se abre mutt torificado. Dado que no supone ninguna mejora apreciable de rendimiento quitar ese soporte, recomiendo quitarlo sin más.
```sh
git clone https://github.com/neomutt/neomutt
cd neomutt ./prepare --prefix=/usr/local --sysconfdir=/etc --enable-debug --enable-notmuch \
--enable-smtp --enable-hcache --enable-sidebar --with-ssl=/usr --with-curses=/usr \
--with-regex --with-sasl --enable-imap --enable-pop --with-idn --enable-gpgme \
--with-gpgme-prefix=/usr/ --disable-fmemopen
make
su -c "make install"
```
Ahora la configuración. En el directorio `~/.mutt/` hay los siguientes archivos:
```sh
ls ~/.mutt
account.example colors gpg.rc keybinds mailcap muttrc.example offlineimaprc.example signature
```
Todos forman parte de la configuración de Neomutt. Para que sea más fácil leerlos, es recomendable tenerlos en archivos separados, ya que hay muchísimas opciones. Todos tienen nombres lógicos:
- `account.example`: Contiene los datos de la cuenta.
- `colors`: Los colores.
- `mailcap`: Contiene los comandos a usar según el tipo de formato de archivos recibidos. En mi caso sólo tengo para la visualización de correos HTML, pero se puede añadir para visualizar PDF, ODT, etc.
- `gpg.rc`: Contiene la configuración para el gpg.
- `keybinds`: Contiene los atajos de teclado.
- `signature`: Contiene una firma, que en mi caso sólo usa la cuenta de autistici.
- `muttrc.example`: Este ya ha sido copiado a `~/.muttrc`, por lo que lo ignoraremos.
- `offlineimaprc.example`: Este ya ha sido copiado a `~/.offlineimaprc`, por lo que lo ignoraremos.
No voy a explicar todos los parámetros que salen, ya que hay demasiadas, sólo las partes que considere más importantes. Para verlas en mayor profundidad, recomiendo visitar el manual de [neomutt](http://www.neomutt.org/manual/).
Empecemos por la más importante, que es la de `account.example`. Podéis cambiarle el nombre al archivo, pero si lo hacéis tendréis que cambiar el parámetro siguiente del `muttrc`:
```sh
source "~/.mutt/account.example"
```
Las variables más importantes a cambiar de `account.example` son las siguientes:
```text
set my_pass = ""
set from = ""
set server = ""
set port = ""
set realname = ""
```
Estas hacen referencia a los datos de autenticación del servidor de correo. `realname` es el nombre que se quiera que aparezca a los demás cuando se envía un correo.
Comentaremos también la sección de **virtual-mailboxes** y la del **gpg**. La primera hace referencia a los mailboxes que tendremos. Habitualmente mutt tenia los típicos, el INBOX, Enviados, Basura, etc. La primera sección hace una búsqueda de los tags que le asignamos usando notmuch. Por lo tanto, hay que crear los virtual-mailboxes en función a los tags que hayamos creado en el script `filtros.sh`. De la sección de **gpg** solo mencionar que hay que cambiar la variable `gpg_sign_as` con el ID de nuestra clave.
El archivo `colors` sigue el esquema de colores que suelo usar, Azul, lila y gris. El archivo de `keybinds` contiene un par de atajos "emacsizados" y otros asignados a teclas más útiles. Las explicaciones de cada uno están al lado del bind. Para ver los binds que se usan actualmente, sólo hay que presionar **?** en mutt.
Y ya queda la última parte. Cómo automatizar la entrada de correos, añadirles tags y agregar los correos a la agenda. Yo hago esto con el siguiente script que meto en el cron:
```sh
#!/bin/bash
username=`whoami`
# commands
abook="/home/$username/.mutt/scripts/auto-process.sh"
autotag="/home/$username/.mutt/scripts/filtros.sh"
imapactive=`ps -ef | grep offlineimap | grep -v grep | wc -l`
online=`curl --silent http://gnu.org | wc -l`
case $imapactive in
'1')
killall offlineimap && sleep 5
;;
esac
case $online in
'9')
offlineimaprc="/home/$username/.offlineimaprc"
mailsync="offlineimap -c $offlineimaprc -u quiet -q"
echo "Ejecutando offlineimap..."
$mailsync
echo "Indexando emails..."
notmuch new > /dev/null
echo "Autoguardando contactos..."
$abook
echo "Autotageando correos..."
$autotag
;;
esac
fi
```
Se puede crear este archivo en `/usr/local/bin/mailsync` y darle permisos con `chmod`. Recomiendo ejecutarlo desde la terminal para ver que funcione correctamente. Si funciona bien, lo añadimos al crontab ejecutando `crontab -e`:
```sh
*/5 * * * * /usr/local/bin/mailsync
```
De este modo, se ejecutará ese script cada cinco minutos. Y con esto, ya hemos terminado.
Que se me ocurran, quedarían las siguientes tareas para mejorarlo:
- Buscar correos usando notmuch
- Meter en el mailcap tipos de archivos más usados y asociarlos con los programas que use
Poco más hay que decir. Como ya he dicho más arriba, en el siguiente articulo explicaré cómo hacer mutt usable con dos o más cuentas y cómo meter todo en un contenedor cifrado y gestionarlo cómodamente. Neomutt se verá así.
{{< figure src="/img/2016-09-11-141804_1024x768_scrot.png" >}}

View File

@ -0,0 +1,13 @@
+++
title = "Nikola.el v0.1 - Nikola desde emacs"
author = ["drymer"]
date = 2017-02-20T08:30:00+01:00
tags = ["emacs", "nikola", "nikolael"]
draft = false
+++
Este es un anuncio del que es mi primer paquete para emacs, `nikola.el`. Ya escribí hace tiempo un articulo sobre [org2nikola](https://daemons.cf/posts/nikola-emacs-gestionar-un-blog-de-contenido-esttico/), paquete que sigo usando. Pero este paquete solo permite exportar de org-mode a html, no permite construir la web o desplegarla, tienes que hacerlo desde la terminal.
Ya desde el principio tenia unas cutre-funciones que me permitían hacer lo más básico desde emacs, pero decidí ponerlo bonito y desarrollarlo un poco más, y así ha salido este paquete. De momento está solo en mi repositorio, en un tiempo lo meteré en elpa.
En este momento, permite crear un sitio web, crear articulos y páginas, construir el sitio web, desplegarlo, iniciar/detener el servidor web y ejecutar ganchos (hooks). Y poco más que añadir. Para verlo en mayor profundidad, hay que visitar el [Git](https://git.daemons.cf/drymer/nikola.el#org145399f).

View File

@ -0,0 +1,96 @@
+++
title = "Nikola + emacs: Gestionar un blog de contenido estático"
author = ["drymer"]
date = 2015-09-04T22:26:00+02:00
tags = ["python", "nikola", "emacs"]
draft = false
+++
Lo de tener un blog siempre es divertido, uno coge, escribe sus mierdas y los demás lo leen o no, eso ya depende de la mierda. Pero oye, siempre se puede intentar, es lo fantástico de internet. Y además es gratis, según cómo se monte. Se puede ir a lo fácil y tirar de wordpress.com o aún peor, blogspot. Entiendo que en ciertos casos hay que tirar del primero (del segundo no hay ningún motivo válido para usarlo, lo siento), no todo el mundo puede o quiere pagar un VPS o puede tener una máquina encendida en casa todo el día. El siguiente articulo es para los que si tienen una máquina disponible.
Nikola es un generador de web estático. Esto tiene distintas ventajas respecto a una web con php tal cómo wordpress, por ejemplo.
- Más seguras, requiere menos recursos
- Es rápido, crea el HTML de manera incremental (sólo crea las páginas necesarias cada vez)
- Acepta distintos formatos: iPython, RST, Markdown, HTML y con el plugin adecuado, org-mode.
- CLI sencilla
Tiene varios plugins, desde importar articulos de wordpress hasta el ya mencionado org-mode plugin. Es cuestión de probarlo, en realidad es fácil hacerlo. Además tienen bastante documentación, no he visto nada que no estuviese ahí. Así que al lío:
```sh
apt-get install python-pip
pip install nikola
```
Y ya. Ahora viene lo divertido, que es configurarlo. Para hacerlo tenemos que ir al directorio en el que queramos que esté y ejecutar:
```sh
nikola init miweb
# la carpeta lisp o la que sea, dentro de .emacs.d
cd ~/.emacs.d/lisp/
git clone https://github.com/redguardtoo/org2nikola.git
```
Y entonces hará unas cuantas preguntas. Podéis responderlas ahora o podéis modificar el archivo conf.py una vez hayáis terminado, así que cómo queráis. No me extenderé en la configuración por que es bastante sencilla. La configuración que tengo la podéis ver [aquí](http://daemon4jidu2oig6.onion/cgit/isso-utils/tree/conf.py), en el git. Después de eso instalaremos el plugin org2nikola, que permite exportar arboles org al directorio que le digas y con formato HTML. Configuramos el nuevo modo de emacs poniendo en el ~/.emacs o en el ~/.emacs.d/init.el lo siguiente:
```emacs-lisp
(use-package org2nikola
:load-path "~/Proyectos/org2nikola/"
:init
;; Se instala el htmlize de melpa, el de org-mode es demasiado viejo
(use-package htmlize :ensure t)
:config
(setq org2nikola-output-root-directory (concat (getenv "HOME") "/Documentos/BadDaemons"))
(setq org2nikola-use-verbose-metadata t))
(defun daemons/nikola-deploy-partido ()
"Ejecuta un script que tira de at para programar el push al repositorio git."
(interactive)
(shell-command (concat "/bin/bash $HOME/Documentos/BadDaemons/scripts/deploy-partido.sh " (org-read-date))))
;; Las dos siguientes funciones probablemente no sirvan a nadie
(defun daemons/nikola-url-post ()
"Devuelve el enlace del articulo en el que esté el cursor."
(interactive)
(setq url (concat "https://daemons.it/posts/"
(cdr (car (org-entry-properties (point) "post_slug")))))
(message url)
(kill-new url))
(defun daemons/nikola-url-config ()
"Devuelve el enlace de la parte de la configuración en la que esté el cursor."
(interactive)
(setq url (concat "https://daemons.it/stories/mi-configuracin-de-emacs/#"
(cdr (car (org-entry-properties (point) "CUSTOM_ID")))))
(message url)
(kill-new url))
(use-package nikola
:load-path "~/Proyectos/nikola.el/"
:config
(setq nikola-output-root-directory "~/Documentos/BadDaemons/")
(setq nikola-verbose t)
(setq nikola-webserver-auto nil)
(setq nikola-webserver-host "127.0.0.1")
(setq nikola-webserver-port "8080")
(setq nikola-webserver-open-browser-p t)
(setq nikola-deploy-input t)
(setq nikola-deploy-input-default "Nuevo articulo")
(setq nikola-build-before-hook-script (concat nikola-output-root-directory "scripts/pre-build.sh"))
(setq nikola-build-after-hook-script (concat nikola-output-root-directory "scripts/post-build.sh")))
```
En las funciones opcionales quedaría mucho mejor pasarle la variable del directorio de root de nikola, pero no he conseguido hacer que 'shell-command la coja, así que se queda en modo cutre.
Hecho esto, ya podremos escribir articulos. La idea de este plugin es tener todos los articulos en un sólo org, tal que así:
```text
* Primer Articulo
** Subtitulo del primer articulo
ola ka se
* Segundo articulo
loremp ipsum bla bla bla
```
Para exportar tenemos que situarnos en el sub-árbol que queremos exportar y ejecutar M-x org2nikola-export-subtree. Esto, cómo hemos dicho, creará un articulo con formato HTML en el directorio 'org2nikola-output-root-directory.
[La sección](https://daemons.cf/stories/mi-configuracin-de-emacs/#org2nikola) pertinente en mi configuración.

View File

@ -0,0 +1,11 @@
+++
title = "Nuevo planet de emacs-es"
author = ["drymer"]
date = 2016-06-29T16:44:00+02:00
tags = ["emacs"]
draft = false
+++
Esto es un anuncio, poco hay que decir. Entre [@maxxcan](http://www.maxxcan.com) y yo hemos montado un planet de emacs-es. Con suerte, esto facilitará encontrar nuevos sitios webs y blogs sobre emacs en castellano. Incluso alguna persona que suela escribir en inglés tal vez se anime a hacerlo en castellano. La web es [http://planet.emacs-es.org](http://planet.emacs-es.org). Varias personas andamos en `#emacs-es` de freenode, por si eso. También hay un grupo en GNU social, en [https://quitter.se/group/emacses](https://quitter.se/group/emacses) (que no es del planet en si, pero publicará ahí) y la cuenta que publicará es [@emacses](https://quitter.es/emacses).
PD: En los próximos días publicaré un articulo explicando cómo lo hemos montado.

View File

@ -0,0 +1,67 @@
+++
title = "Nuevos servicios a la vista"
author = ["drymer"]
date = 2017-03-28T08:30:00+02:00
tags = ["servicios", "git", "gitea", "prosody", "xmpp"]
draft = false
+++
Por si alguien no se ha dado cuenta, esta web está en un dominio nuevo, daemons.it. No tiene nada de especial el que sea de Italia, simplemente era de los más baratos y no está la cosa para gastar tontamente. El tema es que por fin tengo un dominio de verdad y no corro el peligro de que me lo quiten por que si, como puede pasar con los dominios gratuitos `.cf` y `.ga`.
Lo mejor de todo es que me veo con la suficiente estabilidad para dejar que otras personas usen algunos de los servicios que tengo instalados. Estos son Gitea, que permite gestionar repositorios Git y Prosody, para XMPP. Aunque su uso y disfrute es gratuito, hay varias cosas a tener en cuenta:
**Respecto a la creación de usuarios**:
- En Prosody se pueden registrar cuentas usando el registro IN-BAND. Clientes como Gaim o Psi+ lo soportan. Todas las cuentas creadas tendrán en marcadores la sala de Bad Daemons: **daemons@salas.daemons.it**. Para limitar el posible abuso por parte de bots, es necesario que en un plazo de 48 horas desde la creación de la cuenta se entre en esa sala y se salude, para poder tener en cuenta que la cuenta es humana. Si no se hace, podré borrar la cuenta sin previo aviso.
- En Gitea se pueden registrar cuentas desde [esta página](https://git.daemons.it/user/sign%5Fup). Pero si en un plazo de 48 horas no se ha creado algún repositorio, podré borrar la cuenta sin previo aviso.
**En general**
- No hay garantía ninguna de que estos servicios estén funcionando siempre.
- No hay garantía de que no se pierdan datos.
- El acceso está abierto en ambos servicios, pero esto puede cambiar sin previo aviso.
- Gitea no limita el tamaño del contenido del repositorio. Esto puede cambiar y puedo decidir borrar repositorios demasiado grandes sin previo aviso.
- El servidor Prosody soporta el XEP HTTP Upload. Ahora mismo el límite es de 4GB por archivo, algo totalmente exagerado, pero lo tengo así para cubrir las necesidades de las pasarelas XMPP - Telegram de la FairCoop. Si se abusa de ello, tendré que cambiarlo.
El resumen de lo anterior viene a ser que son mis servidores y me los follo como quiero. Dicho esto, no tengo intención de limitar nada siempre y cuando el uso que se de esto sea razonable. Me parece tontería tener un par de servidores con tan poco uso, prefiero compartirlo. No se a cuantas cuentas podré dar acceso, ya que los dos servidores que tengo son más bien sustitos, pero intentaré alargarlo lo máximo posible. Hasta aquí estaban las condiciones de uso, ahora veamos que es lo que ambos servicios ofrecen (y que límites tendrán los servidores):
**Prosody**
Los XEP que soporta son:
- Smacks
- CSI
- MAM: Se guarda registro durante una semana.
- Carbons
- HTTP Upload: Como ya he mencionado, el límite de tamaño de los ficheros es de 4GB. Espero que nadie abuse de ello o tendré que cambiarlo. Los ficheros se guardan durante una semana.
- Onions: Se puede conectar al Onion aún usando como dominio principal daemons.it, solo hay que poner en el host al que se conecta el onion, que se puede ver cual es [aquí](https://daemons.it/varios.html).
- Blocking
- Salas: En salas.daemons.it.
Si se quiere más información sobre lo que hace cada XEP exactamente, recomiendo la lectura de [este articulo](https://daemons.it/posts/xmpp-en-mviles-mentiras-y-cmo-mejorar-tu-servidor/).
Los logs están desactivados por defecto (exceptuando el de errores), pero esto va cambiando según si hay problemas o no y necesito debuguear. Lo recomendable, en cualquier caso, es usar Tor.
**Gitea**
Soporta Organizaciones, Pull Request, Hooks, Webhooks, factor de doble autenticación. Esto de momento, recordemos que Gitea es un proyecto oven. Para la siguiente versión, tienen integración con Github mediante oauth2, integración con OpenID, lo cual permitirá loguearse desde cuentas GNU social y soporte para firmar los commits con GPG. Para ver mejor que ofrece, se puede probar [aquí](https://try.gitea.io/user/login), aunque hay que tener en cuenta que algunas características son propias de rama de desarrollo.
**VPS**
Tengo dos, en uno está el servidor Prosody, unto a esta web y algunas pasarelas y en el otro está el pajarraco, el planet de emacs y Gitea. Ambos servidores tienen 512MB de ram y otros tantos de swap, 1 núcleo de CPU de unos 0.70 Ghz y 20GB de disco duro. Como se puede ver, sobretodo de espacio va justito.
Para cualquier problema o sugerencia con los servicios, [se me puede contactar](https://daemons.it/contacto.html) como se prefiera.
Esta página se ha actualizado por última vez el día 28-03-2017.

View File

@ -0,0 +1,101 @@
+++
title = "OnionScan - Escaneando onions"
author = ["drymer"]
date = 2016-04-13T08:27:00+02:00
tags = ["tor"]
draft = false
+++
Ya tocaba dejar un poco emacs. Hoy veremos [OnionScan](https://github.com/s-rah/onionscan). Este es un programa que, cómo su nombre indica, escanea onions (servicios ocultos de Tor). Tiene una desventaja, y es que está hecho en go-lang, el lenguaje de programación de Google. Aún sin gustarme, habitualmente, los productos de Google, no es ese el motivo de ser una desventaja, es simplemente que habrá que instalarlo únicamente para este programa.
Pero bueno, para eso están los binarios compilados, para la puta gente vaga. Así que al lío. El proceso consistirá en descargar `go`, descomprimir el archivo, hacer algún apaño usando variables de entorno para que encuentre las librerías y descargar y usar `OnionScan`.
```sh
# Crear un directorio genérico y entrar
mkdir ~/Instalados
cd ~/Instalados
# Esta es la arquitectura que uso yo, se puede escoger en https://golang.org/dl/
wget https://storage.googleapis.com/golang/go1.6.1.linux-amd64.tar.gz
# unp es un programa que gestiona la descompresión de archivos, sin importar el tipo
unp -d go1.6.1.linux-amd64.tar.gz
# Según se use Debian, Fedora, Slackware o lo que sea
apt-get install libexif-dev
dnf install libexif-devel
slackpkg search libexif
# Definir entornos de variable necesarios para go
# Tener en cuenta que son para su uso temporal, no deberían tomarse cómo referencia si se programa
# seriamente con este lenguaje de programación
export GOROOT="$HOME/Instalados/go/"
export GOPATH="$GOROOT/bin/"
# Instalar onionscan
go/bin/go get github.com/s-rah/onionscan
```
Y ya estará instalado el binario de `onionscan` en `~/go/bin/bin/onionscan`. Para usarlo, se puede ejecutar tal que así. La dirección onion es la de este mismo blog.
```sh
torify go/bin/bin/onionscan daemon4idu2oig6.onion
```
Esto devuelve parecido a este:
```text
2016/04/13 10:18:20 Starting Scan of daemon4idu2oig6.onion
2016/04/13 10:18:20 This might take a few minutes..
--------------- OnionScan Report ---------------
High Risk Issues: 0
Medium Risk Issues: 0
Low Risk Issues: 0
```
Un poco pobre. Si se le pasa el argumento `-verbose`, en cambio:
```text
2016/04/13 10:19:04 Starting Scan of daemon4idu2oig6.onion
2016/04/13 10:19:04 This might take a few minutes..
2016/04/13 10:19:04 Checking daemon4idu2oig6.onion http(80)
2016/04/13 10:19:04 Found potential service on http(80)
2016/04/13 10:19:05 Attempting to Derive Server Type from Headers..
2016/04/13 10:19:05 Server Version: nginx
2016/04/13 10:19:05 Apache mod_status Not Exposed...Good!
2016/04/13 10:19:06 Scanning daemon4idu2oig6.onion/
2016/04/13 10:19:06 Page daemon4idu2oig6.onion/ is Accessible
2016/04/13 10:19:06 Found Related URL https://gnusocial.net/maxxcan
2016/04/13 10:19:06 Found Related URL https://wiki.cyanogenmod.org/w/Devices
2016/04/13 10:19:06 Found Related URL http://acentoveintiuno.com/?Facebook-puede-registrar-lo-que
2016/04/13 10:19:06 Found Related URL http://elbinario.net/2014/05/06/500-licencias-de-microsoft-office-para-adif/
2016/04/13 10:19:06 Found Related URL http://creativecommons.org/licenses/by/4.0/
2016/04/13 10:19:06 Found Related URL https://i.creativecommons.org/l/by/4.0/88x31.png
2016/04/13 10:19:06 Found Related URL http://creativecommons.org/licenses/by/4.0/
2016/04/13 10:19:06 Scanning for Images
2016/04/13 10:19:06 Found image wp-content//diagram.png
2016/04/13 10:19:24 Found image wp-content//emacs-theme-editar.png
2016/04/13 10:19:25 Found image https://i.creativecommons.org/l/by/4.0/88x31.png
2016/04/13 10:19:26 Directory /style either doesn't exist or is not readable
2016/04/13 10:19:26 Directory /styles either doesn't exist or is not readable
2016/04/13 10:19:26 Directory /css either doesn't exist or is not readable
2016/04/13 10:19:26 Directory /uploads either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /images either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /img either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /static either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /wp-content/uploads either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /products either doesn't exist or is not readable
2016/04/13 10:19:28 Directory /products/cat either doesn't exist or is not readable
2016/04/13 10:19:28
2016/04/13 10:19:28 Checking daemon4idu2oig6.onion ssh(22)
2016/04/13 10:19:28 Checking daemon4idu2oig6.onion ricochet(9878)
2016/04/13 10:19:28 Failed to connect to service on port 9878
--------------- OnionScan Report ---------------
High Risk Issues: 0
Medium Risk Issues: 0
Low Risk Issues: 0
```
Parece que tiene hardcodeada la búsqueda de distintos directorios, algunos de `wordpress`, otros de `drupal`. Bueno, es una herramienta curiosa. De momento muy útil no es, no dice mucho. Para haber sido creado hace tres días, no está nada mal.

101
content/posts/onionscan.md Normal file
View File

@ -0,0 +1,101 @@
+++
title = "OnionScan - Escaneando onions"
author = ["drymer"]
date = 2015-03-26T19:15:00+02:00
draft = false
tags = ["elbinario", "tor"]
+++
Ya tocaba dejar un poco emacs. Hoy veremos [OnionScan](https://github.com/s-rah/onionscan). Este es un programa que, cómo su nombre indica, escanea onions (servicios ocultos de Tor). Tiene una desventaja, y es que está hecho en go-lang, el lenguaje de programación de Google. Aún sin gustarme, habitualmente, los productos de Google, no es ese el motivo de ser una desventaja, es simplemente que habrá que instalarlo únicamente para este programa.
Pero bueno, para eso estan los binarios compilados, para la puta gente vaga. Así que al lío. El proceso consistirá en descargar `go`, descomprimir el archivo, hacer algún apaño usando variables de entorno para que encuentre las librerias y descargar y usar `OnionScan`.
```bash
# Crear un directorio generico y entrar
mkdir ~/Instalados
cd ~/Instalados
# Esta es la arquitectura que uso yo, se puede escoger en https://golang.org/dl/
wget https://storage.googleapis.com/golang/go1.6.1.linux-amd64.tar.gz
# unp es un programa que gestiona la descompresión de archivos, sin importar el tipo
unp -d go1.6.1.linux-amd64.tar.gz
# Según se use Debian, Fedora, Slackware o lo que sea
apt-get install libexif-dev
dnf install libexif-devel
slackpkg search libexif
# Definir entornos de variable necesarios para go
# Tener en cuenta que son para su uso temporal, no deberian tomarse cómo referencia si se programa
# seriamente con este lenguaje de programación
export GOROOT="$HOME/Instalados/go/"
export GOPATH="$GOROOT/bin/"
# Instalar onionscan
go/bin/go get github.com/s-rah/onionscan
```
Y ya estará instalado el binario de `onionscan` en `~/go/bin/bin/onionscan`. Para usarlo, se puede ejecutar tal que así. La dirección onion es la de este mismo blog.
```bash
torify go/bin/bin/onionscan daemon4jidu2oig6.onion
```
Esto devuelve parecido a este:
```text
2016/04/13 10:18:20 Starting Scan of daemon4jidu2oig6.onion
2016/04/13 10:18:20 This might take a few minutes..
--------------- OnionScan Report ---------------
High Risk Issues: 0
Medium Risk Issues: 0
Low Risk Issues: 0
```
Un poco pobre. Si se le pasa el argumento `-verbose`, en cambio:
```text
2016/04/13 10:19:04 Starting Scan of daemon4jidu2oig6.onion
2016/04/13 10:19:04 This might take a few minutes..
2016/04/13 10:19:04 Checking daemon4jidu2oig6.onion http(80)
2016/04/13 10:19:04 Found potential service on http(80)
2016/04/13 10:19:05 Attempting to Derive Server Type from Headers..
2016/04/13 10:19:05 Server Version: nginx
2016/04/13 10:19:05 Apache mod_status Not Exposed...Good!
2016/04/13 10:19:06 Scanning daemon4jidu2oig6.onion/
2016/04/13 10:19:06 Page daemon4jidu2oig6.onion/ is Accessible
2016/04/13 10:19:06 Found Related URL https://gnusocial.net/maxxcan
2016/04/13 10:19:06 Found Related URL https://wiki.cyanogenmod.org/w/Devices
2016/04/13 10:19:06 Found Related URL http://acentoveintiuno.com/?Facebook-puede-registrar-lo-que
2016/04/13 10:19:06 Found Related URL http://elbinario.net/2014/05/06/500-licencias-de-microsoft-office-para-adif/
2016/04/13 10:19:06 Found Related URL http://creativecommons.org/licenses/by/4.0/
2016/04/13 10:19:06 Found Related URL https://i.creativecommons.org/l/by/4.0/88x31.png
2016/04/13 10:19:06 Found Related URL http://creativecommons.org/licenses/by/4.0/
2016/04/13 10:19:06 Scanning for Images
2016/04/13 10:19:06 Found image wp-content//diagram.png
2016/04/13 10:19:24 Found image wp-content//emacs-theme-editar.png
2016/04/13 10:19:25 Found image https://i.creativecommons.org/l/by/4.0/88x31.png
2016/04/13 10:19:26 Directory /style either doesn't exist or is not readable
2016/04/13 10:19:26 Directory /styles either doesn't exist or is not readable
2016/04/13 10:19:26 Directory /css either doesn't exist or is not readable
2016/04/13 10:19:26 Directory /uploads either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /images either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /img either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /static either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /wp-content/uploads either doesn't exist or is not readable
2016/04/13 10:19:27 Directory /products either doesn't exist or is not readable
2016/04/13 10:19:28 Directory /products/cat either doesn't exist or is not readable
2016/04/13 10:19:28
2016/04/13 10:19:28 Checking daemon4jidu2oig6.onion ssh(22)
2016/04/13 10:19:28 Checking daemon4jidu2oig6.onion ricochet(9878)
2016/04/13 10:19:28 Failed to connect to service on port 9878
--------------- OnionScan Report ---------------
High Risk Issues: 0
Medium Risk Issues: 0
Low Risk Issues: 0
```
Parece que tiene hardcodeada la búsqueda de distintos directorios, algunos de `wordpress`, otros de `drupal`. Bueno, es una herramienta curiosa. De momento muy útil no es, no dice mucho. Para haber sido creado hace tres días, no está nada mal.

View File

@ -0,0 +1,240 @@
+++
title = "org-agenda: Capturar y buscar notas"
author = ["drymer"]
date = 2016-11-22T08:30:00+01:00
tags = ["emacs", "orgmode"]
draft = false
+++
La agenda de `org-mode` es la herramienta que ha conseguido que mucha gente pase a usar emacs. Esta puede usarse de muchas formas, no solo como una agenda como tal. Yo la uso para intentar estar medio organizado en mi día a día, para hacer un seguimiento de los proyectos y programas que desarrollo y hasta sustituí wallabag. Esto último toca otro día, lo que veremos hoy es el funcionamiento básico de la captura de notas y los comandos de agenda personalizados mediante ejemplos.
Pero como siempre, hay que empezar por el principio. Hay tres paradigmas (generalizando) en el uso y organización de la agenda de org-mode. El primero se podría llamar el paradigma de la estructura jerarquizada. Este buscará la organización visual. Un archivo de ejemplo es el siguiente:
```text
* Personal
** TODO Tarea de ejemplo
* Trabajo
** TODO No matar lusers
* Ordenadores
** Proyectos Personales
*** General
**** TODO Actualitzar README de programes
**** DONE Abrir links de emacs en navegador
- State "DONE" from "TODO" [2016-10-16 dom 22:01]
SCHEDULED: <2016-09-13 mar>
*** isso-gnusocial
**** TODO Cambiar codificación de títulos
*** gnusrss
**** TODO Hacerlo compatible con mastodon
La idea es usar la api atom.
Para probar en mastodon: mastodon.social
*** twitter2rss
**** WAITING Esperar feedback
** VPS
*** TODO Renova el domini daemons.it
DEADLINE: <2016-09-16 vie>
```
A simple vista se puede ver la organización de las notas que se toman. Este paradigma se enfoca más en la búsqueda de TODO, fechas programadas y deadlines. Veamos ahora un ejemplo del paradigma de la estructura por etiquetas:
```text
* TODO Tarea de ejemplo :personal:
* TODO No matar lusers :trabajo:
* TODO Actualitzar README de programes :proyectos:general:
* DONE Abrir links de emacs en navegador :proyectos:general:
- State "DONE" from "TODO" [2016-10-16 dom 22:01]
SCHEDULED: <2016-09-13 mar>
* TODO Cambiar codificación de títulos :proyectos:issoGnusocial:
* TODO Hacerlo compatible con mastodon :proyectos:gnusrss:
La idea es usar la api atom.
Para probar en mastodon: mastodon.social
* WAITING Esperar feedback :twitter2rss:
* TODO Renova el domini daemons.it :vps:
DEADLINE: <2016-09-16 vie>
```
En el ejemplo se ve claro lo que hay, pero si tienes más de 20 notas empieza a liarse. Este paradigma se enfoca más en la búsqueda por etiquetas o contextos. Ahora viene el tercero, que es el que uso yo, que es una mezcla de ambos. De este modo, puedo ver a simple vista si me interesa o puedo buscar con la agenda.
```text
* Personal :personal:
** TODO Tarea de ejemplo
* Trabajo :treball:
** TODO No matar lusers
* Ordenadores
** Proyectos Personales :projectes:
*** General :general:
**** TODO Actualitzar README de programes
**** DONE Abrir links de emacs en navegador
- State "DONE" from "TODO" [2016-10-16 dom 22:01]
SCHEDULED: <2016-09-13 mar>
*** isso-gnusocial :issoGnusocial:
**** TODO Cambiar codificación de titulos
*** gnusrss :gnusrss:
**** TODO Hacerlo compatible con mastodon
La idea es usar la api atom.
Para probar en mastodon: mastodon.social
** VPS :vps:
*** TODO Renova el domini daemons.it
DEADLINE: <2016-09-16 vie>
, * Caldav
```
Se puede ver, además, que los tags son hereditarios, por lo que solo hace falta etiquetar un árbol y los que estén por debajo de este tendrán la misma etiqueta. Ahora vamos al código, la parte de la captura de notas:
```emacs-lisp
(setq org-capture-templates
'(("s" "Tasca Simple" entry (file+headline "~/Documentos/org/notas.org" "Notes")
"** TODO %? \n:PROPERTIES:\n:CREATED: %u\n:END:\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n")
("b" "Idea per article" entry (file+headline "~/Documentos/blog/Articulos/articulos.org" "Ideas")
"** TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n")
("p" "Personal" entry (file+headline "~/Documentos/org/index.org" "Personal")
"* TODO %? \n:PROPERTIES:\n:CREATED: %u\n:END:\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n")
("t" "Treball" entry (file+headline "~/Documentos/org/index.org" "Treball")
"* TODO %? \n:PROPERTIES:\n:CREATED: %u\n:END:\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n")
("w" "Marcadors" entry (file "~/Documentos/org/web.org")
"* %x\n %U\n %c"
:empty-lines 1)
("v" "Relacionat amb els VPS / chustaserver" entry (file+headline "~/Documentos/org/index.org" "VPS")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n")))
(setq org-capture-templates
(append org-capture-templates
'(("o" "Ordinadors")
("og" "General" entry (file+headline "~/Documentos/org/index.org" "General")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n")
("oi" "isso-gnusocial" entry (file+headline "~/Documentos/org/index.org" "isso-gnusocial")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n")
("or" "gnusrss" entry (file+headline "~/Documentos/org/index.org" "gnusrss")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n")
("oj" "jabbergram" entry (file+headline "~/Documentos/org/index.org" "jabbergram")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n")
("os" "SimpleUpload" entry (file+headline "~/Documentos/org/index.org" "SimpleUpload")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:\n"))))
```
En el primer trozo de código se define la variable `org-capture-templates`. Si se evalua el código y ejecuta `org-capture` (C-c c) se verá que han aparecido nuevas opciones.
{{< figure src="/img/2016-11-21-224806_1024x768_scrot.png" >}}
Cada una de ellas hace una cosa distinta, y por el código se puede entender bastante bien. Explicaré las palabras clave que se usan para que quede un poco más claro:
- **%?**: Es dónde se colocará el cursor al capturar.
- **%u**: La hora de la creación de la nota usando corchetes, por lo que no aparecerá en la agenda.
- **%(org-insert-time-stamp (org-read-date nil t \\"+0d\\")**: La hora de la creación de la nota usando <>, por lo que aparecerá en la agenda.
A grandes rasgos, la **Tasca Simple** lo que hace es crear una nota en el archivo "~/Documentos/org/notas.org" debajo de la cabecera "Notas". **Idea per article** crea una nota en el archivo "~/Documentos/blog/Articulos/articulos.org" debajo de la cabecera "Ideas". **Personal** y **Treball** más de lo mismo con sus propias características.
La segunda parte del código se define a parte básicamente por que no supe hacerlo en la anterior definición. Lo que hace es crear un submenú. En la imagen de las capturas se puede ver que hay una sección que se llama "Ordinadors" y que no aparecen ahí todas las opciones que se ven en el código. Esto es debido a que están escondidas hasta que se presiona la letra clave, que en este caso es la **o**. Véase la imagen.
{{< figure src="/img/2016-11-21-230839_1024x768_scrot.png" >}}
Creo que no hace falta comentar mucho más. Para más información se puede ver esta [página web](http://orgmode.org/manual/Capture-templates.html#Capture-templates) o preguntar en los comentarios. El caso de los marcadores lo comentaré en otro articulo.
Ahora vamos con las búsquedas personalizadas en la agenda. Véamos el código:
```emacs-lisp
(setq org-agenda-custom-commands
'(;; Cosas del blog
("b" . "Blog")
("bi" "Ideas para articulo" todo "TODO|INPROGRESS" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org")) (org-agenda-sorting-strategy)))
("bp" "Articulos listos para publicar" todo "READY|PROGRAMMED" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org"))))
("bc" "Articulos cancelados" todo "CANCELLED" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org"))))
("bf" "Articulos publicados" todo "DONE" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org"))))
;; Casa
("c" . "Casa")
;; Ver lo que se ha hecho, no terminado
("cg" "Estado de todas las tareas" tags "+casa|+chustaserver|+vps|+labrecha|+emacs|+productividad/+TODO|NEXT|INPROGRESS|HOTFIX|BLOCKED|TESTING" ((org-agenda-files '("~/Documentos/org/index.org"))))
("ce" "Estado de las tareas activas" tags "+casa/+TODO|NEXT|INPROGRESS|HOTFIX" ((org-agenda-files '("~/Documentos/org/index.org"))))
("cp" "Estado de las tareas paradas" tags "+casa/+BLOCKED|TESTING" ((org-agenda-files '("~/Documentos/org/index.org"))))
("cd" "Tareas terminadas sin terminar" tags "/DONE" ((org-agenda-files '("~/Documentos/org/index.org"))))
("cm" "Mostras miscelaneos" tags "+miscelaneos/TODO" ((org-agenda-files '("~/Documentos/org/index.org"))))
("cr" "Mostras radar" tags "+radar/TODO" ((org-agenda-files '("~/Documentos/org/index.org"))))
("ct" "Hecho la semana anterior"
((agenda "")
(org-agenda-overriding-header "Semana anterior")
(org-agenda-span 7)
(org-agenda-archives-mode t)
(org-agenda-show-log 'clockcheck)
(org-agenda-files '("~/Documentos/org/index.org"))))
("cs" "Calendario de la semana que viene"
((agenda "")
(org-agenda-overriding-header "Semana que viene")
(org-agenda-span 7)
(org-agenda-start-day "+7d")
(org-agenda-files '("~/Documentos/org/index.org"))))
;; Reportes del trabajo
("t" . "Trabajo")
;; Ver lo que se ha hecho, no terminado
("tl" "Hecho en los últimos tres días" agenda ""
((org-agenda-overriding-header "Last three days")
(org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-log)
(org-agenda-span 3)
(org-agenda-start-day "-3d")
(org-agenda-start-with-log-mode t)
(org-agenda-log-mode-items '(clock closed))
(org-agenda-archives-mode t)
(org-agenda-show-log 'clockcheck)))
("ti" "Hecho en la última semana" agenda ""
((org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-log)
(org-agenda-span 7)
(org-agenda-start-day "-7d")
(org-agenda-start-with-log-mode t)
(org-agenda-log-mode-items '(clock closed))
(org-agenda-archives-mode t)
(org-agenda-show-log 'clockcheck)))
("tn" "Siguientes tareas" tags-todo "+trabajo/NEXT"
((org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-next)))
("ta" "Tareas activas" tags-todo
"+trabajo/INPROGRESS|TESTING|HOTFIX"
((org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-active)))
("tb" "Tareas paradas" tags-todo "+trabajo/BLOCKED|TOFOLLOW"
((org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-blocked)))
("tt" "Tareas por hacer" tags "+trabajo/TODO"
((org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-todo)))
("td" "Tareas terminadas sin archivar" tags "+trabajo/DONE|CANCELLED"
((org-super-agenda-mode)
(org-super-agenda-groups org-agenda-supergroup-tags-done)))
;; Reportes
("r" . "Reportes")
;; Mostrar tareas a reubicar
("rr" "Reubicar" tags "+refile" ((org-agenda-remove-tags nil) (org-agenda-hide-tags-regexp "refile")))
;; Reporte
("ra" "Ver anteriores asambleas de La Brecha Digital" tags "ARCHIVE_ITAGS={labrecha}&ARCHIVE_ITAGS={asamblea}/DONE"
((org-agenda-files (file-expand-wildcards "~/Documentos/org/index.org_archive"))))
;; Buscar en archivados solamente
("l" . "Archivo")
("ls" "Archive search" search ""
((org-agenda-files (file-expand-wildcards "~/Documentos/org/*.org_archive"))))))
```
Cuando se evalua el código anterior, al ejecutar `org-agenda` (C-c a) ahora aparecerán nuevas opciones. Concretamente cuatro en el primer buffer:
- **b** de blog
- **p** de Proyectos personales
- **v** de relacionados con los VPS
- **w** de los marcadores web
{{< figure src="/img/org-agenda.png" >}}
Si presionamos la **b**, se mostrará un nuevo desplegable con la **i** de ideas para el blog y la **p** de articulos listos para públicar.
{{< figure src="/img/org-agenda2.PNG" >}}
Lo mismo cuando se presiona la letra **p**, pero con otras opciones. El de la letra **w**, como mencioné más arriba, lo deamos para otro articulo.
Veamos ahora un ejemplo de la búsqueda de todas las notas etiquetadas como **Ideas** de cosas a escribir en el blog.
{{< figure src="/img/2016-11-21-231744_1024x768_scrot.png" >}}
Como se puede ver, es muy cómodo y tiene mucha potencia detrás. Cualquier duda, comenten.

View File

@ -0,0 +1,95 @@
+++
title = "Pasarela de XMPP/abber y Telegram."
author = ["drymer"]
date = 2016-05-08T22:25:00+02:00
tags = ["xmpp", "python"]
draft = false
+++
No tiene mucho misterio, sirve para hablar desde una sala de abber a un grupo de Telegram. A continuación pego sin más el `README` del programa. Para el futuro, recomiendo mirar el repositorio git directamente. Se puede ver [aquí](http://daemons.cf/cgit/jabbergram/about/). Se aceptan sugerencias y pruebas.
## Acerca de {#acerca-de}
Con este programa es posible utilizar una sala `XMPP` para hablar con un grupo de `Telegram` y viceversa. El obetivo de este programa es el de ser sólo una pasarela sencilla, sólo tiene que pasar el texto de un lado al otro. Una vez que sea estable, probablemente no tendrá más meoras, ya que yo no las necesito.
## Instalación {#instalación}
Como con cualquier programa escrito en `Python`, deberia ser usado en un entorno virtual (virtualenv), pero eso queda a la elección del usuario. Es posible utilizar uno de los siguientes métodos de instalación:
Instalar a través de `pip`:
```sh
su -c "pip3 instalar abbergram"
```
Clonar el repositorio:
```sh
git clone https://daemons.it/drymer/abbergram
cd abbergram
su -c "pip3 instalar requirements.txt -r"
su -c "python3 setup.py instalar"
```
## Configuración {#configuración}
Este programa es simple, no tiene ni un menú de `ayuda`. Lo primero que hay que hacer es crear el bot de `Telegrama`. Para ello, hay que tener una cuenta de `Telegram` y hablar con [BotFather](https://telegram.me/botfather). A continuación, eecuta:
```sh
/start
/newbot
NombreDelBot # terminado en bot, siempre
# A continuación, se mostrará el token del bot, hay que guardarlo
/setprivacy
NombreDelBot
# Ahora hay que pulsar desactivar
```
La opción `/setprivacy` es para hacer que el robot pueda leer todo lo que se dice en el grupo, no sólo cuando se utilizan los comandos. Es necesario para hacer que `abbergram` funcione. Más información sobre la creación los bots de `Telegrama` en su [página web](https://core.telegram.org/bots).
A continuación, hay que crear un archivo de configuración, que llamaremos `config.ini`. En ese archivo, introduce los siguientes parámetros:
```ini
[Config]
ID = exampleid@nope.org
password = difficultPassword
muc_room = exampleMuc@muc.nope.org
nick = abbergram
token = abbergramBotTokken
group = -10,293,943,920
```
La única cosa que vale la pena mencionar es la sección del `token` (que es la que nos da cuando se crea el robot) y el `group`, que es ID del grupo de `Telegram`.
No hay manera fácil de ver el ID desde `Telegram`, por lo que se puede utilizar el programa llamado `seeIdGroups.py`. Para eecutarlo sólo es necesario establecer el parámetro `token` del archivo de configuración. Necesitarás que alguien invite al bot al grupo. Además, las personas de ese grupo deben enviar algunos mensaes, para que el programa pueda coger su ID. Puede llevar unos segundos el que aparezcan los mensaes. Cuando se tenga el ID de grupo que se quiere, sólo hay que pulsar Ctrl-c, copiarlo en el archivo de configuración (incluido el simbolo menos), y la configuración estará terminada.
## Uso {#uso}
Se pueden crear todos los archivos de configuración que se deseen. Sólo tendrás que pasarlo como parámetro al programa, si no se hace se intentará coger el archivo `config.ini` por defecto, y se producirá un error si no existe:
```sh
# Es recomendable utilizar tmux o la pantalla para eecutar la siguiente orden
abbergram.py example.ini
```
## Licencia {#licencia}
```text
This program is free software: you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, Either version 3 of the License, or
(At your option) any later version.
This program is distributed in the hope That it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
Along With This Program. If not, see <http://www.gnu.org/licenses/>.
```

View File

@ -0,0 +1,95 @@
+++
title = "Pasarela de XMPP/jabber y Telegram."
author = ["drymer"]
date = 2016-05-08T22:25:00+02:00
tags = ["xmpp", "python"]
draft = false
+++
No tiene mucho misterio, sirve para hablar desde una sala de jabber a un grupo de Telegram. A continuación pego sin más el `README` del programa. Para el futuro, recomiendo mirar el repositorio git directamente. Se puede ver [aquí](http://daemons.cf/cgit/jabbergram/about/). Se aceptan sugerencias y pruebas.
## Acerca de {#acerca-de}
Con este programa es posible utilizar una sala `XMPP` para hablar con un grupo de `Telegram` y viceversa. El obetivo de este programa es el de ser sólo una pasarela sencilla, sólo tiene que pasar el texto de un lado al otro. Una vez que sea estable, probablemente no tendrá más mejoras, ya que yo no las necesito.
## Instalación {#instalación}
Como con cualquier programa escrito en `Python`, debería ser usado en un entorno virtual (virtualenv), pero eso queda a la elección del usuario. Es posible utilizar uno de los siguientes métodos de instalación:
Instalar a través de `pip`:
```sh
su -c "pip3 instalar Jabbergram"
```
Clonar el repositorio:
```sh
git clone https://daemons.it/drymer/Jabbergram
cd Jabbergram
su -c "pip3 instalar requirements.txt -r"
su -c "python3 setup.py instalar"
```
## Configuración {#configuración}
Este programa es simple, no tiene ni un menú de `ayuda`. Lo primero que hay que hacer es crear el bot de `Telegrama`. Para ello, hay que tener una cuenta de `Telegram` y hablar con [BotFather](https://telegram.me/botfather). A continuación, ejecuta:
```sh
/start
/newbot
NombreDelBot # terminado en bot, siempre
# A continuación, se mostrará el token del bot, hay que guardarlo
/setprivacy
NombreDelBot
# Ahora hay que pulsar desactivar
```
La opción `/setprivacy` es para hacer que el robot pueda leer todo lo que se dice en el grupo, no sólo cuando se utilizan los comandos. Es necesario para hacer que `Jabbergram` funcione. Más información sobre la creación los bots de `Telegrama` en su [página web](https://core.telegram.org/bots).
A continuación, hay que crear un archivo de configuración, que llamaremos `config.ini`. En ese archivo, introduce los siguientes parámetros:
```ini
[Config]
ID = exampleid@nope.org
password = difficultPassword
muc_room = exampleMuc@muc.nope.org
nick = Jabbergram
token = JabbergramBotTokken
group = -10,293,943,920
```
La única cosa que vale la pena mencionar es la sección del `token` (que es la que nos da cuando se crea el robot) y el `group`, que es ID del grupo de `Telegram`.
No hay manera fácil de ver el ID desde `Telegram`, por lo que se puede utilizar el programa llamado `seeIdGroups.py`. Para ejecutarlo sólo es necesario establecer el parámetro `token` del archivo de configuración. Necesitarás que alguien invite al bot al grupo. Además, las personas de ese grupo deben enviar algunos mensajes, para que el programa pueda coger su ID. Puede llevar unos segundos el que aparezcan los mensajes. Cuando se tenga el ID de grupo que se quiere, sólo hay que pulsar Ctrl-c, copiarlo en el archivo de configuración (incluido el símbolo menos), y la configuración estará terminada.
## Uso {#uso}
Se pueden crear todos los archivos de configuración que se deseen. Sólo tendrás que pasarlo como parámetro al programa, si no se hace se intentará coger el archivo `config.ini` por defecto, y se producirá un error si no existe:
```sh
# Es recomendable utilizar tmux o la pantalla para ejecutar la siguiente orden
Jabbergram.py example.ini
```
## Licencia {#licencia}
```text
This program is free software: you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, Either version 3 of the License, or
(At your option) any later version.
This program is distributed in the hope That it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
Along With This Program. If not, see <http://www.gnu.org/licenses/>.
```

View File

@ -0,0 +1,118 @@
+++
title = "Poniendo bonito org-mode"
author = ["drymer"]
date = 2016-04-07T16:23:00+02:00
tags = ["orgmode", "emacs"]
draft = false
+++
`org-mode`, cómo ya se ha comentado antes, es de lo mejor que hay en emacs y con mucha diferencia. No ya tiene sentido comentar para que sirve, para ver sus posibilidades, se puede mirar en [articulos anteriores](http://daemons.cf/categories/emacs/). Al lío.
## Los asteriscos son feos {#los-asteriscos-son-feos}
Más claro el agua. Para cambiarlos, se usará [org-bullet](https://github.com/sabof/org-bullet). Esto hace que las cabeceras no empiecen por un asterisco cutre, sinó que empiezan por una bola utf-8. Instalarlo es muy fácil, se puede tirar de `elpa` y ejecutar `M-x package-install RET org-bullet RET`. Y sólo queda añadirlo al `init.el`
```emacs-lisp
(require 'org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
```
La primera línea carga el paquete, la segunda hace que `org-bullets-mode` se active únicamente en los buffers con `org-mode` activo.
## Cabeceras más grandes {#cabeceras-más-grandes}
Otra cosa que lo mejora mucho es diferenciar el tamaño las cabeceras o árboles. En mi caso concreto, esto no lo necesito, ya que uso el tema llamado `cyberpunk-theme` que ya lo hace de manera automática. Pero para quien su tema no lo haga, puede guardar las siguientes funciones `lisp` en su `init.el`.
```emacs-lisp
(custom-theme-set-faces 'user
`(org-level-8 ((t (,@headline ,@variable-tuple))))
`(org-level-7 ((t (,@headline ,@variable-tuple))))
`(org-level-6 ((t (,@headline ,@variable-tuple))))
`(org-level-5 ((t (,@headline ,@variable-tuple))))
`(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1))))
`(org-level-3 ((t (,@headline ,@variable-tuple :height 1.25))))
`(org-level-2 ((t (,@headline ,@variable-tuple :height 1.5))))
`(org-level-1 ((t (,@headline ,@variable-tuple :height 1.75))))
`(org-document-title ((t (,@headline ,@variable-tuple :height 1.5 :underline nil))))))
```
## Esconder los elementos de marcado {#esconder-los-elementos-de-marcado}
Hablo de los símbolos de cursiva, negrita o subrallado. Al definir la siguiente variable, se pasará de tener:
```text
*Hola*
/pequeño/
_mundo_
```
A ver el marcado resaltado, pero sin esos símbolos.
```org
*Hola*
/pequeño/
_mundo_
```
Esto se consigue añadiendo lo siguiente a `init.el`
```emacs-lisp
(setq org-hide-emphasis-markers t)
```
Y si se quiere modificar la manera en la que se muestra algún marcado en concreto, se puede usar lo siguiente:
```emacs-lisp
(add-to-list 'org-emphasis-alist
'("=" (:foreground "DimGrey")
))
```
En este caso aumenta ligeramente la oscuridad del color del símbolo de marcado "literal" (verbatim en inglés). También se puede usar el atributo `:background`, por ejemplo, si se quiere resaltar el fondo de la pantalla.
## Centrar el texto en pantalla {#centrar-el-texto-en-pantalla}
A mi esto me parecía una gilipollez, hasta que me he encontrado usando una pantalla bastante grande en el trabajo. En mi casa son todas relativamente pequeñas y no entendía que aportaba el modo que comentaré a continuación, pero ya lo veo claro. Para ajustar el buffer al centro de pantalla, se puede usar un modo llamado `olivetti-mode`, que suena muy de hipsters, pero viene bien. A continuación pondré dos capturas, la primera sin este modo activa y la segunda estando activo.
{{< figure src="/img/sin-olivetti.PNG" caption="Figura 1: Sin olivetti-mode" >}}
{{< figure src="/img/con-olivetti.PNG" caption="Figura 2: Con olivetti-mode" >}}
Para instalarlo y configurarlo:
```emacs-lisp
M-x package-install RET olivetti-mode RET
M-x olivetti-mode
;; Hacerlo grande con:
C-]
;; Hacerlo pequeño con:
C-[
;; Cuando se llegue al tamaño deseado, hay que mirar el minibuffer messages y fiarse en que valor númerico sale
;; Entonces, se define la variable olivetti-set-width al tamaño que se ha visto
(olivetti-set-width 100)
```
## Indentar jerárquicamente {#indentar-jerárquicamente}
Esto no tiene mucho misterio. Activando el siguiente modo cuando se carga `org-mode`, se hará que se indenten todos los sub-arboles y texto que estos contengan. Se puede ver en las siguientes capturas.
{{< figure src="/img/indentando.PNG" caption="Figura 3: Sin indentar" >}}
{{< figure src="/img/sin-indentar.PNG" caption="Figura 4: Indentando" >}}
Para activarlo, sólo hay que añadir lo siguiente al archivo de configuración:
```emacs-lisp
(org-indent-mode)
```
Y con esto ya se tiene un `org-mode` más bonito.
PD: Las cabeceras de las capturas se ven del mismo tamaño que el resto del texto por que estoy usando emacs por terminal, algo que no suelo hacer. Cuando lo uso con la interfaz gráfica, se ven cómo he comentado.
[Fuente](http://www.howardism.org/Technical/Emacs/orgmode-wordprocessor.html)

View File

@ -0,0 +1,213 @@
+++
title = "Programación literaria para sysadmins / devops"
author = ["drymer"]
date = 2016-10-11T13:02:00+02:00
tags = ["sysadmin", "orgmode", "emacs", "bash", "python"]
draft = false
+++
Mencioné de pasada el concepto de programación literaria en el articulo de mi configuración de emacs, ahora voy a explicar en que consiste este y cómo usarlo con emacs y org-mode.
La [definición de la wikipedia](https://es.wikipedia.org/wiki/Literate%5Fprogramming) al rescate.
> El paradigma de programación literaria [...] permite a los programadores desarrollar sus programas en el orden fiado por la lógica y el flujo de sus pensamientos.
>
> Los programas literarios están escritos como una exposición lógica no interrumpida en un lenguaje humano, de forma similar al texto de un ensayo, en el cual se incluye el código fuente tradicional oculto tras macros. Las herramientas de programación se encargan de separar el programa de forma que pueda ser compilado y ejecutado y la documentación del mismo programa. Mientras que las primera generación de herramientas de programación literaria estaban centradas en un lenguaje de programación específico, las últimas son independientes de lenguaje y se sitúan por encima de los lenguajes de programación.
Dicho de otro modo y enfocado al uso que le puedan dar las sysadmins, permite documentar los pensamientos y procesos lógicos y ejecutar estos en el mismo contexto. Puede ser un poco complejo de entender si no se ve, por eso, y aún odiando el formato, he hecho una pequeña grabación de lo que puede hacer con ello. El caso concreto que presento es un ejemplo real con el que me he encontrado recientemente, que es cambiar lo codificación del contenido de una columna de una base de datos sqlite en una máquina remota. El programa en si da igual, pero creo que es un buen modo de ver el potencial que tiene.
El vídeo a continuación. Si, está acelerado.
<div class="HTML">
<div></div>
<video controls>
<source src="/videos/programacion-literaria.ogv" type="video/ogg">
Tu navegador no soporta HTML 5.
</video>
</div>
Ahora explicaré algunos conceptos básicos y cómo configurar emacs para lograr lo anterior. Para dejarlo claro, usaré `emacs`, `org-mode` y los bloques babel de este. Los bloques babel permiten que varios lenguajes de programación vivan de forma natural en `org-mode`. Permite que estos se ejecuten, se compilen, se documenten y se creen los ficheros que se programen a parte, todo desde el mismo sitio.
Que ventajas ofrece `org-mode`?
- Mejor documentación del código.
- Útil para compartir con otra gente, si se tiene algún problema.
- Clarificación de los pensamientos en situaciones complicadas.
- Facilidad para mezclar distintos lenguajes de programación.
- Las funcionalidades de la agenda y las tareas.
## Configuración {#configuración}
Se puede usar tanto emacs 24.5 como 25.1, hasta dónde he probado. La versión de org-mode que he probado es la rama `maint` del git, que en este momento es la versión 8.3.6. Teniendo esto claro, vamos a configurar babel. La variable que hay que tener en cuenta es `org-babel-load-languages`, que es dónde se definirá que lenguajes permitirá usar. Las posibilidades que hay se pueden ver en el [siguiente enlace](http://orgmode.org/worg/org-contrib/babel/languages.html). Para la demostración solo he usado `python` y `shell`, que permite el uso de `bash`. La variable se define así:
```lisp
(org-babel-do-load-languages
'org-babel-load-languages
'((dot . t)
(lisp . t)
(gnuplot . t)
(latex . t)
(ledger . t)
(python . t)
(shell . t)
(sh . t)
(sql . t)
(sqlite . t)))
```
Con esto ya podemos funcionar en lo que a `org-mode` se refiere. Ahora varios conseos para el tema del `ssh` y `tramp`, que es el programa que usa emacs para gestionar las conexiones por `ssh`. Lo primero de todo es que lo más cómodo siempre será poder loguearse en el servidor con la clave pública. Lo segundo es modificar la variable PS1 del servidor en cuestión para facilitarle el parseo da tramp. Es la forma más sencilla que he encontrado de hacer que funcione sin más modificaciones. En el `~/.bashrc` del servidor se añade lo siguiente:
```sh
[[ $TERM == "dumb" ]] && PS1='$ '
[[ $TERM == "emacs" ]] && PS1='$ '
```
Se define la variable PS1 en función del TERM que se use. Me he encontrado con que tramp ha usado ambos TERM, según si lo uso en un bloque de babel o a pelo, así que vale la pena poner ambos. Tramp usa `scp` por defecto. Yo prefiero usar `ssh`, por que soy de darle a guardar cada 3 segundos y con `scp` tarda más.
```lisp
(setq tramp-default-method "ssh")
```
Con esto deberíamos poder funcionar correctamente. Ahora miremos un poco el código del archivo del vídeo. La fuente completa está aquí, por si alguien la quiere.
## Conceptos básicos de org-mode y babel {#conceptos-básicos-de-org-mode-y-babel}
A continuación veremos los parámetros y variables que uso en el archivo de la demostración, que seguramente sean los más relevantes en el ámbito de administración de sistemas. El fichero de la demostración está [aquí](https://daemons.cf/wp-content/sysadmin.org). Aún así, hay muchísimas más y no puedo cubrirlas todos. Al final del articulo pondré varias fuentes y otros recursos que recomiendo leer. Están en inglés, por eso.
Como siempre que se usa `org-mode`, usamos los árboles, es decir, los asteriscos. De este modo se pueden definir varias propiedades, como la de `header-args`. Pero antes, veamos un bloque babel normal y corriente. Para ejecutar el bloque, hay que presionar `C-c C-c` en este.
```text
#+BEGIN_SRC sh
ls ~/
#+END_SRC
#+RESULTS:
| Descargas |
| Documentos |
| Imagenes |
| Instalados |
| Scripts |
| Videos |
```
Esto devuelve en mi caso. El resultado por defecto lo devuelve en forma de tabla. Si lo queremos tal cómo devuelve la terminal, podemos pasarle la variable `results raw` al bloque.
```text
#+BEGIN_SRC sh :results raw
ls ~/
#+END_SRC
#+RESULTS:
Descargas
Documentos
Imagenes
Instalados
Scripts
Videos
```
Otra variable útil que se usa es `dir`. Permite establecer en que directorio se ejecutará el bloque.
```text
#+BEGIN_SRC sh :dir /
ls
#+END_SRC
#+RESULTS:
bin
boot
dev
etc
home
la
lib
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
```
Esto es más útil de lo que pueda parecer a primera vista, por que como tal vez os habéis fiado en el vídeo, permite establecer que todos los bloques se ejecuten en el servidor, sin más. Para ello hay que usar la sintaxis de tramp, que seria tal que así en mi caso (en el ejemplo, igual que en el vídeo, me conecto a mi banana pi).
```text
#+BEGIN_SRC sh :dir /ssh:drymer@banana:
ls
#+END_SRC
#+RESULTS:
backups instalados owncloud_data
scripts decrypted owncloud_data_backup
```
Si esto lo unimos a la variable `header-args` que mencioné antes, que se puede definir en las propiedades, todo lo que se ejecute debajo del primer árbol se ejecutará en la máquina remota.
Algunos bloques tienen definido encima un parámetro, `#+name`, seguido de un nombre. Esto permite usar los bloques como funciones, como en el caso del bloque de python de la demostración. También se pueden definir variables vacías para que puedan ser usadas dentro de los bloques.
```text
#+NAME: decode_string
#+BEGIN_SRC python :results output :var linea=""
print(linea.encode('latin1').decode('utf8'))
#+END_SRC
```
Esta función devuelve el valor de la variable `linea` codificada en utf-8 cuando se llama desde fuera.
```text
#+BEGIN_SRC sh :results raw :post decode_string(linea=*this*)
echo "Un+par+de+funciones+útiles"
#+END_SRC
#+RESULTS:
Un+par+de+funciones+útiles
```
En el ejemplo esta función se usa de un modo particular, ya que se llama con el parámetro `post`. Este está pensado para procesar la salida del bloque en bash con el bloque en python.
También se puede llamar a un bloque desde otro bloque y establecer el resultado a una variable a usar en el segundo, como se ve aquí.
```text
#+NAME: num
#+BEGIN_SRC sh
echo $(sqlite3 -line /var/lib/isso/comments.db "select * from archive;" | grep title | wc -l)
#+END_SRC
#+NAME: encoded_title
#+BEGIN_SRC bash :results output :post decode_string(linea=*this*) :var NUM=num
for ((i=1;i<=$NUM;i++))
do
echo $i$(sqlite3 -line /var/lib/isso/comments.db "select title from archive where id = $i;" | cut -d'=' -f2)";"
done
#+END_SRC
```
El bloque `encoded_title` llama al bloque `num` estableciendo la salida de este a la variable `NUM`, que en bucle `for` usa como final de este.
Por último mencionar la exportación de los bloques a otros formatos. Quienes usen `org-mode` ya sabrán que una de sus grandes cualidades es que permite exportar este lenguaje de marcado a otros formatos, tales como latex, html, pdf, odt, etc. Los bloques van incluidos en el paquete y pueden ser gestionados con la variable `:exports`, pasando como valor `none`, `code`, `results` o `both`, que es lo que se usa por defecto. `none` no exporta nada, `code` solo el código, `results` el resultado y `both` ambos.
Y esto es todo por ahora. Tal vez en el futuro escriba otro articulo más, si llego a controlar más del tema. Por si acaso, y mientras tanto, recomiendo la lectura de los siguientes enlaces, en los que se encuentran varios artículos de Howard Abrahams, del cual yo descubrí recientemente todo el potencial de la programación literaria y recomiendo encarecidamente a quien sepa leer en inglés.
- [http://www.howardism.org/Technical/Emacs/literate-programming-tutorial.html](http://www.howardism.org/Technical/Emacs/literate-programming-tutorial.html)
- [http://www.howardism.org/Technical/Emacs/literate-devops.html](http://www.howardism.org/Technical/Emacs/literate-devops.html)
- [http://www.howardism.org/Technical/Emacs/literate-devops-examples.html](http://www.howardism.org/Technical/Emacs/literate-devops-examples.html)
- [http://orgmode.org/manual/Working-with-source-code.html#Working-with-source-code](http://orgmode.org/manual/Working-with-source-code.html#Working-with-source-code)

View File

@ -0,0 +1,134 @@
+++
title = "Convertir emacs en un IDE de python"
author = ["drymer"]
date = 2016-11-28T08:30:00+01:00
tags = ["python", "emacs"]
draft = false
+++
Dicen que con emacs, a parte de hablar por irc, mandar correos y ver los cómics de xkcd se puede editar texto! Hasta se puede convertir emacs en un ide! Una locura. Hoy vamos a ver como programar en python y tener soporte para todo lo que suelen tener los IDE de programación.
Empecemos por el principio. Qué es elpy? Viene a ser un envoltorio de varios módulos. Por defecto viene con soporte de identación automática, auto-completado, documentación de los módulos, corrector de errores, virtualenv, inserción de snippets y más. Todo esto lo envuelve en un proceso que corre en segundo plano. Iremos viendo poco a poco como se usa todo.
Pero antes que nada, instalemos lo necesario. Primero algunas dependencias en pip. Por si se programa en python 2 y en python 3, mejor instalar las dependencias de ambas versiones:
Para que elpy funcione hay que instalar las siguientes dependencias:
```sh
sudo pip3 install rope importmagic autopep8 yapf
sudo pip2 install rope importmagic autopep8 yapf
```
Además, es conveniente que estas dependencias se instalen en cada virtualenv que se cree. Para hacerlo, hay que añadir lo siguiente al archivo `~/.virtualenvs/postmkvirtualenv`:
```bash
pip install rope importmagic autopep8 yapf
```
La configuración de elpy:
```emacs-lisp
(defun elpy-goto-definition-or-rgrep ()
"Go to the definition of the symbol at point, if found. Otherwise, run `elpy-rgrep-symbol'."
(interactive)
(ring-insert find-tag-marker-ring (point-marker))
(condition-case nil (elpy-goto-definition)
(error (elpy-rgrep-symbol
(concat "\\(def\\|class\\)\s" (thing-at-point 'symbol) "(")))))
(use-package elpy
:ensure t
:init
(use-package pyvenv :ensure t)
(setq elpy-modules '(elpy-module-sane-defaults elpy-module-company elpy-module-eldoc elpy-module-pyvenv))
(setq elpy-rpc-backend "jedi")
:config
(add-to-list 'ivy-completing-read-handlers-alist '(elpy-doc . completing-read-default)) ;; véase https://github.com/abo-abo/swiper/issues/892
;; Use pytest
(setq elpy-test-runner 'elpy-test-pytest-runner)
(setq elpy-test-pytest-runner-command '("tox"))
(add-to-list 'elpy-project-ignored-directories "__pycache__")
(add-to-list 'elpy-project-ignored-directories ".cache")
(setq compilation-scroll-output 'first-error)
(add-to-list 'auto-mode-alist '("\\.py" . python-mode))
(add-to-list 'auto-mode-alist '("\\.py" . elpy-mode))
(elpy-enable)
(evil-define-key 'normal elpy-mode-map
"gd" 'elpy-goto-definition-or-rgrep))
```
Hay que recordar que evaluando la configuración de `use-package` se instalan los paquetes automáticamente, gracias al `:ensure t`, como vimos en el articulo para [instalar automáticamente la configuración de emacs](https://daemons.cf/posts/hacer-la-configuracin-de-emacs-auto-instalable).
Es posible que tarde un rato en instalarse todo, ya que elpy tiene varias dependencias. Estas son company, find-file-in-project, highlight-indentation, pyvenv y yasnippet. En la configuración anterior se puede ver que he re-definido la variable `elpy-modules`. Por defecto trae un par de módulos más, como yasnippet o highlight-indentation, pero como no los uso, pues fuera. También he quitado flymake, por que prefiero flycheck que tiene soporte para otros lenguajes, aunque de momento solo tengo agregado el lenguaje python.
Este paquete muestra una ralla que marca los 79 carácteres, para cumplir con el pep8.
```emacs-lisp
(use-package fill-column-indicator
:init
(setq fci-rule-color "purple")
(setq fill-column 79)
(setq fci-rule-column 79)
(add-hook 'python-mode-hook 'fci-mode)
(add-hook 'emacs-lisp-mode-hook 'fci-mode)
(add-hook 'sh-mode-hook 'fci-mode)
:ensure t)
```
Y aquí configuramos flycheck, en vez de flake8:
```emacs-lisp
(use-package flycheck
:config
;; (setq flycheck-global-modes '(python-mode))
;; (global-flycheck-mode)
(add-hook 'after-init-hook #'global-flycheck-mode)
(spc-map
"i" '(nil :which-key "flycheck prefix")
"in" 'flycheck-next-error
"ip" 'flycheck-previous-error
"il" 'flycheck-list-errors)
:diminish flycheck-mode
:ensure t)
```
De tema de configuración ya estamos. Veamos ahora como se utiliza esto. Solo mencionaré los que uso o los que tengo intención de usar más.
| Atajo de teclado | Función | Explicación |
|------------------|---------------------------------------|-----------------------------------------------------------------------------------------------------|
| S/N | elpy-config | Muestra la configuración actual de elpy |
| S/N | pyvenv-workon | Equivalente al workon del virtualenvwrapper. Permite escoger entre todos los virtualenv existentes. |
| S/N | pyvenv-deactivate | Desactiva el virtualenv. |
| M-TAB | elpy-company-backend | Auto completado. Para moverse entre las opciones, presionar M-n y M-p. |
| M-. | elpy-goto-definition | Va a la localización de la definición del elemento en el que está el cursor. |
| M-\* | pop-tag-mark | Vuelve al punto en el que estaba el cursor antes de ejecutar elpy-goto-definition. |
| C-c C-o | elpy-occur-definitions | Abre un minibuffer con las definiciones de todas las clases y funciones del buffer. |
| C-c C-z | elpy-shell-switch-to-shell | Abre un buffer con un intérprete de python. Usará el entorno virtual si está activo. |
| C-c C-c | elpy-shell-send-region-or-buffer | Envia la región o el buffer al intérprete de python. |
| C-c C-v | elpy-check | Ejecutará el corrector de sintaxis. |
| C-c C-d | elpy-doc | Abrirá la documentación para el elemento del cursor. |
| C-c C-e | elpy-multiedit-python-symbol-at-point | Edita todas las ocurrencias en el cursor. Para cambiar solo las de la función, C-x n d y C-x n w. |
| C-c C-r f | elpy-format-code | Formatea automáticamente. |
| C-c C-r i | elpy-importmagic-fixup | Auto importar módulos que se estén usando. |
A continuación unas cuantas imágenes de algunas funciones:
{{< figure src="/img/elpy.png" caption="Figura 1: elpy-config" >}}
{{< figure src="/img/pyvenv.png" caption="Figura 2: pyvenv-workon" >}}
{{< figure src="/img/company.png" caption="Figura 3: elpy-company-backend" >}}
{{< figure src="/img/elpy-occur.png" caption="Figura 4: elpy-occur-definitions" >}}
{{< figure src="/img/elpy-check.png" caption="Figura 5: elpy-check" >}}
{{< figure src="/img/elpy-doc.png" caption="Figura 6: elpy-doc" >}}
{{< figure src="/img/elpy-multiedit.png" caption="Figura 7: elpy-multiedit-python-symbol-at-point" >}}
Fuentes:
- <https://elpy.readthedocs.io/en/latest/introduction.html>
- <https://realpython.com/blog/python/emacs-the-best-python-editor/>

View File

@ -0,0 +1,24 @@
+++
title = "Que tecla iba ahora?"
author = ["drymer"]
date = 2017-05-22T20:48:00+02:00
tags = ["emacs"]
draft = false
+++
Cuando empiezas a usar un modo de emacs lo más habitual es intentar aprender los atajos. Siempre es algo complicado, al menos para mi, que tengo la memoria de un pez. Lo que hacia hasta ahora era mantener la página del proyecto abierta en el navegador o apuntarme los binds. O simplemente presionar `M-x`, escribir la función que quiero ejecutar, ver que atajo de teclado tiene asignado (ivy te lo muestra) y presionarlo por eso de la memoria muscular. Pero hace poco descubrí **which-key**.
Lo que hace es mostrar los posibles atajos de teclado cuando se ha apretado el inicio de una combinación. Por ejemplo, si presiono `C-c` me mostrará todas las combinaciones que empiecen por `C-c`. Se verá más claro en esta imagen.
{{< figure src="/img/which-key.png" >}}
Y la configuración es muy simple:
```emacs-lisp
(use-package which-key
:ensure t
:config
(setq which-key-allow-evil-operators t)
(setq which-key-show-operator-state-maps t)
(which-key-mode))
```

View File

@ -0,0 +1,117 @@
+++
title = "Qutebrowser: un navegador ligero manejable por el teclado"
author = ["drymer"]
date = 2016-10-17T08:30:00+02:00
tags = ["i3wm"]
draft = false
+++
Ya comenté en el primer articulo de Neomutt que hay dos tipos de programas que usaba que consumen mucho. Expliqué como cambiar el primero, el cliente de correo. Hoy toca cambiar el navegador.
Antes usaba Firefox, cómo la mayoría. Tiene muchos plugins y cosillas interesantes. Pero incluso cuando tenia mi querida torre funcionando, me planteé cambiarlo. Es un navegador muy, muy pesado, pero sobretodo lo que quería era depender menos del ratón. Encontré un modo de conseguir esto con [keysnail](https://github.com/mooz/keysnail/wiki/plugin), pero no me terminó de convencer. Luego empecé a probar navegadores para ser usados con el teclado. **Uzbl** y **Dwb**, básicamente. Me pareció que Uzbl era el más avanzado, pero aún así yo tenia que compilarlo por eso de usar Slackware, y me daba segfaults a cada paso. Por suerte encontré Qutebrowser.
Hay algunas cosillas que le faltan para suplir del todo el uso habitual que se le da a un navegador.
- No soporta flash, lo cual tampoco es malo.
- Los vídeos HTML5, depende de cómo sea, le cuesta (aunque hay manera de suplirlo, cómo se verá).
- No tiene manera fácil de activar y desactivar javascript, aunque está en camino.
- Los atajos de teclados son personalizables, pero aún están algo limitados para mi gusto.
- Tema de bloqueo de anuncios. Creo que tiene soporte reciente, pero no lo he probado. Según he leído es algo ineficiente de momento, aunque todo se andará. Yo uso un archivo `/etc/hosts`, que por cierto es más recomendable de usar que un plugin. Mucho más eficiente.
Avisadas quedáis de sus limitaciones. Así que al lío, a instalarlo. Tiene paquete compatibles con Debian Jessie y derivados, Fedora, Arch y Parabola, Void Linux, NixOs, OpenSUse, OpenBSD y hasta Windows. Comentaré como instalarlo mediante pip, ya que de este modo se tiene la última versión de todo. Aún así, qt hay que instarlo de los repositorios.
Se instalan las dependencias:
```sh
# Debian
su -c "aptitude install python3 libqt5"
su -c "pip3 install qutebrowser"
```
No diré como instalarlo en Slackware paso a paso por que lo hice hace tiempo y no recuerdo el proceso exacto, ya que era un poco complejo. Esto es debido a que Slackware no tiene qt5 en repositorios ni en los slackbuilds oficiales, hay que tirar de un [SlackBuild de AlienBob](http://www.slackware.com/~alien/slackbuilds/qt5/). Una vez se tiene instalado, ya se puede instalar mediante `pip`.
Una vez hecho, pasamos a configurarlo. Veremos como usar los atajos de teclado básicos (con alguna captura), como cambiarlos, pondré mi configuración de colores, atajos y de `/etc/hosts` y por último como reproducir vídeos fuera del navegador mediante un script que usa `mpv` en conunto a `youtube-dl`. Todos los archivos de configuración usados están en el repositorio `dotfiles` de mi git, por lo que clonaremos ese git, que además tiene otras cosas, aunque no se instalarán.
```sh
git clone https://daemons.it/drymer/dotfiles
cd dotfiles
bash instala.sh dotfiles
```
Al ejecutar el script de instalación pedirá permiso de superusuario para instalar los scripts `capture` y `umpv` en `/usr/local/bin` y el archivo `hosts` en `/etc/hosts`, además de la configuración y los atajos de teclado de Qutebrowser. El script `capture` no lo comentaremos en este articulo.
Los atajos de teclado que uso los he cambiado un poco a los que vienen por defecto. No todo lo que me gustaría, si pudiese los habría hecho exactamente igual a los de emacs, pero bueno. Ahora mismo son más bien una mezcla de los de Firefox y otros navegadores y vim. A título de curiosidad, diré que gracias a este navegador le he empezado a coger el gusto al tema de la edición modal, así que igual en un futuro le echo un ojo a `evil-mode` de emacs. A continuación una tabla con los atajos que más uso.
| Función | Atajo |
|-------------------------------------------------|------------|
| Abrir buscador | o |
| Abrir dirección actual y editar | go |
| Abrir nueva pestaña | C-t |
| Abrir nueva ventana | C-n |
| Cerrar pestaña | C-w |
| Moverse a la pestaña de la izquierda | C- |
| Moverse a la pestaña de la derecha | C-k |
| Mover la pestaña hacia la izquierda | gl |
| Mover la pestaña hacia la derecha | gr |
| Recargar página | r / f5 |
| Ir una página hacia atrás en el historial | H |
| Ir una página hacia delante en el historial | L |
| Abrir link mediante el teclado | f |
| Abrir link mediante el teclado en nueva pestaña | F |
| Abrir link mediante el teclado en nueva ventana | wf |
| Copiar link actual mediante el teclado | ;Y |
| Descargar página actual | C-e |
| Descargar mediante teclado | C-d |
| Moverse hacia la izquierda | h |
| Moverse hacia la derecha | l |
| Moverse hacia arriba | k |
| Moverse hacia abajo | |
| Reabrir pestaña cerrada | C-S-t |
| Buscar | C-s |
| Buscar siguiente | n |
| Buscar anterior | N |
| Ejecutar órdenes | M-x |
| Entrar en modo de inserción | i |
| Copiar url principal | yy |
| Copiar título de la página | yt |
| Copiar dominio | yd |
| Pegar url en la misma pestaña | pp |
| Pegar url en pestaña nueva | Pp |
| Pegar url en ventana nueva | wp |
| Guardar quickmark | m |
| Cargar quickmark | b |
| Cargar quickmark en nueva pestaña | B |
| Guardar bookmark | M |
| Cargar bookmark | gb |
| Cargar bookmark en nueva pestaña | gB |
| Guardar la configuración | sf |
| Hacer zoom | + |
| Quitar zoom | - |
| Ver zoom | = |
| Ver código fuente de la página | C-S-u |
| Cerrar todo | C-q |
| Cambiar a pestañas | M-[número] |
| Abrir url actual en mpv | U |
| Abrir video mediante teclado en mpv | u |
No hay mucho que comentar, solo el tema de abrir los links desde el teclado. La idea es que se presiona la tecla y al lado de cada link aparecen de uno a tres carácteres. Cuando los presionas, se abre la pestaña. Tal como se ve en la imagen.
{{< figure src="/img/qutebrowser.png" >}}
De paso se puede ver los colores que uso en las pestañas, gris y azul, el que suelo usar. Solo queda comentar un par de cosas que igual interesa cambiar de mi configuración. Que use javascript por defecto y el buscador. Usa duckduckgo, pero es la versión html. Para cambiar ambos parámetros hay que editar las lineas 870, 980 y 151. Una vez activado el javascript y reiniciado el navegador, si se va a qute://settings se puede modificar la configuración de manera interactiva.
Para más información, se puede consultar la [hoja de atajos de teclado](http://qutebrowser.org/img/cheatsheet-big.png) o la [ha de comandos](https://github.com/The-Compiler/qutebrowser/blob/e4da6be5e9f181f2e630d5e2147e9b05da5059d9/doc/help/commands.asciidoc).
**Actualización**: Gracias al comentario de Florian, el desarrollador principal de Qutebrowser, puedo corregir algunas cosas que puesto más arriba. Cito:
- Es posible usar Flash, se activa con ":set content allow-plugins true"
- Los vídeos en HTML5 deberian poder verse si se tienen las dependencias apropiadas de GStreamer, pero algunas personas, en Debian, han tenido problemas.
- Para javascript, se puede asignar una tecla para activar y desactivarlo.
- El adblock funciona y consume casi lo mismo que el archivo /etc/hosts, se puede actualizar la lista usando ":adblock-update"

View File

@ -0,0 +1,45 @@
+++
title = "Reseña: Learning docker"
author = ["drymer"]
date = 2017-11-22T08:30:00+01:00
tags = ["docker", "libro"]
draft = false
+++
Últimamente estoy empezando a tocar bastante docker, tanto en el trabajo como en [La Brecha Digital](https://labrecha.digital) (certificado incorrecto temporalmente) y he pensado que aunque soy más de darme de ostias con las cosas hasta que las entiendo, leerme un libro al respecto no haría mal.
Y por ello me leí el libro de Learning Docker. No lo escogí enfrente a otros por ningún motivo en concreto, simplemente lo tenia a mano. Si no me equivoco lo saqué de [PackTub](https://www.packtpub.com), una web que a parte de vender libros cada día dan uno gratuito. FYI.
El libro me parece bastante bueno tanto para gente que no ha usado docker nunca como gente que sin meterse demasiado en su funcionamiento interno, lo usa habitualmente. A continuación las notas que he tomado [en GNU social](https://daemons.it/posts/cutrescript-para-mostrar-posts-de-tags-de-gnu-social/):
- **Nota 1:** Una curiosidad sobre docker. Cuando inicias un contenedor de forma interactiva, puedes "desatacharte" presionando Ctrl-P Ctrl-Q, de forma que el contenedor sigue corriendo.
- **Nota 2:** Otro par de datos que no sabia de docker. Por un lado, puedes rearrancar un contenedor que ha sido parado. Por otro lado, se puede simplemente congelar un contenedor con el subcomando pause.
- **Nota 3:** Docker por defecto no borra los contenedores que han terminado, para ello hay que pasarle un --rm al arrancarlos. Parece lo suficientemente poco práctico como para hacerse un alias y meter el --rm por defecto.
- **Nota 4:** La diferencia entre COPY y ADD es que el segundo manea tar y url.
- **Nota 5:** Una diferencia entre CMD y ENTRYPOINT es que el primero se puede sobre-escribir cuando creas un contenedor. Pero cuando se arranca un contenedor con un ENTRYPOINT establecido, en vez de sobre-escribirlo, lo que hace es pasarlo como argumento.
- **Nota 6:** Joder, no entendía como se podían mantener las imágenes limpias sin usar funciones complejas a la hora de construir, pero resulta que es mucho más simple que eso, solo hay que usar .dockerignore.
- **Nota 7:** Buenas prácticas para escribir dockerfiles: <https://docs.docker.com/engine/userguide/eng-image/dockerfile%5Fbest-practices/#onbuild>
- **Nota 8:** Todo el capítulo de publicación de imágenes es bastante meh, no tiene tanto misterio. docker push $registry/imagen y a volar.
- **Nota 9:** Docker por defecto usa la red 172.16.0.0/16 para lanzar contenedores. La forma no obvia de ver la IP de un contenedor es el subcomando inspect.
- **Nota 10:** Sobre la publicación de puertos, tampoco tiene misterio. -p puertoContenedor:puertoHost. Es un nateo simple, se puede ver en la tabla nat de iptables. Pero lo interesante es que el -p sirve para más cosas, como establecer la IP en la que escuchará el contenedor tal que así: -p 192.51.100.73:80:80.
- **Nota 11:** El EXPOSE del dockerfile tiene el mismo efecto que el -p al arrancar un contenedor. Pero si se asume el uso de la imagen por un tercero, es mejor ser explicito abriendo los puertos sin la intervención de quien lanza el contenedor (más que usar -P, que viene a ser que mapee todos los puertos sin concretar cuales son).
- **Nota 12:** Hay dos formas de montar volúmenes. Una la que ya se mencionó, usar -v y mapear un directorio del host. Pero el otro es crear un contenedor que sea el volúmen. De este modo, varios contenedores pueden compartir volumen. Además, curiosamente no hace falta que el contenedor-volumen esté en marcha. Se puede hacer usando --volume-from al arrancar un contenedor.
- **Nota 13:** El capítulo sobre orquestación me lo he leído en diagonal, pero básicamente hablan sobre el concepto de orquestar y sobre docker-compose.
- **Nota 14:** El capítulo de testing me está gustando mucho. Hablan sobre como enfocar TDD unto a docker. Un poco pedestre, pero supongo que se puede automatizar y/o existe ya algo como virtualenv (dockerenv?).
- **Nota 15:** La parte del capitulo de testing que hablan de Jenkins es muy meh. Aunque es importante mostrar la utilidad de docker con un programa de CI/CD, queda muy pegote.
- **Nota 16:** El capitulo de debugging de contenedores está resultando muy interesante. De momento explica como funciona a bao nivel (para que sirven los cgroups, como aísla los procesos docker, redes, etc).

View File

@ -0,0 +1,118 @@
+++
title = "Secuestrando twitteras"
author = ["drymer"]
date = 2015-08-24T15:53:00+02:00
tags = ["python"]
draft = false
+++
[Aviso]
Quien sólo quiera usar el servicio y pasar de todo, que clique [aquí](http://daemon4jidu2oig6.onion/twitter2rss/).
**Actualización**
Desde que escribí este articulo, he mejorado mucho [gnusrss](https://daemons.cf/cgit/gnusrss/about/#orgheadline21). Recomiendo ignorar todo lo que haga referencia a ese programa de este articulo y mirar el README que he enlazado arriba.
Se dice que [mahoma no va a la montaña](http://elbinario.net/2015/07/08/gnusocial-si-mahoma-no-va-a-la-montana/), así que no queda más remedio que traer cojones la montaña. Twitter es la red social privativa mejor considerada en cuanto a libertades y privacidad, lo cual no dice mucho ya que en esas comparaciones sólo hay redes privativas. Es cómo decir que la Modelo de Madrid es lo mejor del mundo por que Guantanamo está muy feo en esta temporada.
Así que bueno, quien quiera abandonar esa red social pero no quiera dejar de leer a cierta gente, puede usar [twitter2rss](http://daemon4jidu2oig6.onion/cgit/twitter2rss/about/). Este programa lo que hace es una petición a <http://twitter.com/lamarea%5Fcom>, por ejemplo, coge la información de sus tweets y la pasa a formato RSS, un archivo XML. No es muy legible en crudo, por falta de retornos de carro, pero eso sólo se ve si se mira el código fuente cómo tal. Y bueno, eso hace.
La cosa interesante es que se puede usar cómo servicio, quien quiera ofrecerlo, gracias a la interfaz web en php que ha hecho [@frangor](https://frangor.info).
Hay un disclaimer importante, y es que este script usa la web de twitter basándose en ciertos tags HTML. Sólo tienen que cambiarlo para que el invento se oda. Esto no tiene solución ninguna, solamente puedo estar atento y arreglarlo cuando pase. Siempre se agradecerá feedback, claro.
Para instalarlo y usarlo hay que tener un servidor web con php y clonar lo siguiente a la raíz de este.
```sh
torify git clone https://daemons.it/drymer/twitter2rss
# O si no quieres clonar a través de tor
git clone https://daemons.it/drymer/twitter2rss
```
Y ya. Sólo queda retocar el CSS si se quiere. Recomiendo usar el autoindex en _feeds_, para que la gente pueda ver los feeds que hay. La interfaz se ve así.
{{< figure src="/img/2015-07-24-205421_1362x727_scrot.png" >}}
Esto seria si queremos ofrecerlo cómo servicio, si sólo queremos usarlo de manera personal y lo tenemos en algún ordenador que esté enchufado todo el día tendríamos que modificar el archivo llamado <span class="underline">feed\_list.txt</span>. Con un editor cualquiera vale, y tendríamos que poner una lista tal que así.
```text
eldiarioes
el_diagonal
kaosenlarednet
lamarea_com
lahaineinfo
noticiasalb
nodo50
EsperanzAguirre
la_directa
```
Y ya tendremos un feed RSS que cualquier lector puede leer. Ya no dependemos de la red privativa de twitter, biba! Pero podemos ir más allá. Hasta ahora es un secuestro pequeñito, sólo llevamos la información hasta nuestro lector de feeds. Podemos hacerlo más grande. Podemos combinarlo con otra herramienta, llamada [gnusrss](http://daemon4jidu2oig6.onion/posts/gnusrss--publicando-feeds-en-gnu-social/). El proceso de combinar ambas seria sencillo, lo resumiré a continuación:
```sh
# Preparamos el entorno
mkdir /var/www/twitter2rss
cd /var/www/twitter2rss
# Instalamos dependencias
su -c "apt-get install python3-pip"
# Esto en realidad no es una buena práctica, debería instalarse los paquetes con virtualenv. Quien sepa hacerlo, debería hacerlo
su -c "pip3 install pyrss2gen pycurl PySocks"
su www-data -c "git clone https://daemons.it/drymer/twitter2rss"
# Si tenemos el webserver funcionando, ya podemos visitar la página web. Si no vamos a usarla, podemos usarlo tal que así
echo "lamarea_com" >> feed_list.txt
python3 twitter2rss.py
# Ya tendremos el primer RSS en feeds/lamarea_com.py
# Ahora, preparamos gnusrss
mkdir ~/instalados; cd ~/instalados
git clone https://daemons.it/drymer/gnusrss
cd gnusrss
nano example.py # pondremos cómo hacer con la cuenta de elbinario y el RSS de elbinario, sólo habría que tocar las tres primeras variables.
```
Ahora pondremos lo siguiente en este archivo:
```python
#!/bin/env python3
# -*- coding: utf-8 -*-
import gnusrss
import os.path
if "__main__":
feedurl = 'http://elbinario.net/feed'
#GNU Social credentials
username = 'elbinario'
password = 'contraseña'
api_url = 'https://gnusocial.net/api/statuses/update.xml'
tor = "no"
txt = '.elbinario.txt'
txt_tmp = '.elbinario_tmp.txt'
if os.path.exists(txt):
gnusrss.rss(feedurl, txt_tmp, tor)
new = gnusrss.compare(txt, txt_tmp)
gnusrss.post(new, api_url, username, password, tor)
else:
gnusrss.rss(feedurl, txt, tor)
```
Y ejecutamos lo siguiente:
```sh
# Guardamos el archivo y ya podremos ejecutarlo
python3 example.py
# Si vemos contenido, es que ha funcionado. No publica nada por que aún no tiene nada que publicar
cat .elbinario.txt
# Para comprobar que publique en GNU Social, ejecutamos lo siguiente
sed -i '1d' .elbinario.txt
# Ejecutamos de nuevo y si todo va bien, debería publicarse una noticia en GNU Social
```

View File

@ -0,0 +1,119 @@
+++
title = "Autogestión: Montar y Administrar gitolite + cgit + git-daemon"
author = ["drymer"]
date = 2015-07-05T19:15:00+02:00
draft = false
tags = ["sysadmin", "elbinario"]
+++
Los repositorios git son una de las mejores cosas que se han hecho a nivel de commpartir. No sólo permite descargar y ojear el código sinó que además permite ver que cambios se han hecho cuando, aumentando así la confianza que se pueda tener en ese programa. Así que al lío. Veremos cómo se instala en un servidor con Debian Wheezy. La parte de la instalación es fácil:
```bash
aptitude install git gitolite3
```
Nos pedirá una clave SSH. Podemos pasar por que vamos a reconfigurar el paquete, para ajustar algunas cosillas.
```bash
dpkg-reconfigure gitolite3
```
Nos preguntará que usuario vamos a usar, directorio home de ese usuario (dónde estaran los repositorios) y una clave SSH. Deberiamos poner la de nuestro ordenador. Una vez hecho, entraremos con el usuario <span class="underline">git</span> y iniciaremos el repositorio.
```bash
su git
gitolite setup -a admin
```
Veremos que en el home de git aparecen ya dos repositorios git, uno llamado testing y el otro gitolite-admin. Este es muy importante, por eso lo clonaremos a nuestro ordenador y administraremos todos los repositorios desde ahí.
```bash
git clone git@servidor.git.lol:gitolite-admin
cd gitolite-admin
```
Aquí veremos dos directorios, <span class="underline">keys</span> y <span class="underline">conf</span>. En el primero veremos un archivo llamado admin.pub, que contiene nuestra clave de administrador. En conf veremos gitolite.conf, que es dónde está la magia. Ahí añadiremos los repositorios y permisos de estos que queramos. Ahora, según las necesidades de cada persona, habrán distintas necesidades. Para una mejor comprensión, mejor leer la [documentación](http://gitolite.com/gitolite/gitolite.html#basic-admin). A continuación habrá un pequeño resumen con una pequeña explicación a modo de comentario.
```text
# gitolite.conf
# Declaramos los grupos que queramos
@usuarias = foo bar
# Necesario para que git-daemon acceda a los repositorios
repo @all
R = daemon
repo gitolite-admin
RW+ = admin
# Declaramos repositorios. El que tengan el mismo prefijo (ElBinario), hará que se divida en secciones, cómo veremos más adelante con cgit.
repo ElBinario/gnusrss
RW+ = @elbinario
R = @all
repo ElBinario/eve
RW+ = @usuarias
R = @all
repo ElBinario/alex
RW+ = @usuarias
R = @all
repo ElBinario/bofh
RW+ = @usuarias
R = @all
repo ElBinario/dni
RW+ = @usuarias
R = @all
repo ElBinario/etherpad-lite-config-files
RW+ = @usuarias
R = @all
repo ElBinario/asocial
RW+ = @usuarias
R = @all
# Según lo que se quiera, esto puede no interesar. Esto permite a cualquier usuaria crear un repositorio.
repo CREATOR/[a-z].*
C = @usuarias
RW+ = CREATOR
RW = WRITERS
R = READERS
```
Tras modificar el fichero conf/gitolite.conf, tendremos que hacer constar los cambios:
```bash
git add conf/gitolite.conf
git commit -m "initial commit"
git push --set-upstream origin master # esto sólo la primera vez, las siguientes será sólo:
git push
```
Ahora podriamos clonar de tal manera:
```bash
# Para clonar uno existente
git clone git@git.server.lol:ElBinario/eve.git
# Para crear un repositorio
git clone git@git.server.lol:drymer/testeando.git
```
Vale. Ahora le pondremos una interfaz web, que siempre queda más bonito. gitweb puede servir, pero para mi es demasiado sencillo, aunque tiene la ventaja de que anda en la paqueteria de debian, a diferencia de cgit. Pero bueno, cgit ofrece más cosas que gitweb, así que usaremos ese:
```bash
git clone git://git.zx2c4.com/cgit
cd cgit
git submodule init
git submodule update
make get-git
make
make install
```
A continuación la configuración. Primero el virtual host de Nginx, un script de manejo del cgi y luego el /etc/cgitrc, que es su fichero de configuración. Está todo en el [pad](https://pad.elbinario.net/p/servidor-git), para no alargar demasiado el articulo. No explicaré que hace cada linea del /etc/cgitrc por que seria muy largo. Para eso, mejor leer el [man](http://linux.die.net/man/5/cgitrc).
Hecho esto, reiniciamos nginx e iniciamos el script de inicio (muy cutre) de fcgiwrap y ya deberiamos ver nuestro repositorio git. Al final he puesto un pequeño cheatsheet de cómo administrar diferentes aspectos necesarios.

View File

@ -0,0 +1,62 @@
+++
title = "SimpleUpload: Usar HTTP Upload cómo hosting"
author = ["drymer"]
date = 2016-09-29T08:30:00+02:00
tags = ["python", "xmpp"]
draft = false
+++
HTTP Upload es ese XEP de los servidores XMPP que permite subir archivos al servidor y compartir la dirección en una conversación, ya sea en grupo o una conversación privada. Algo muy útil y que recientemente he implantado en [Jabbergram](https://daemons.cf/cgit/jabbergram/about/#orgheadline12), aunque aún está en fase de testeo.
Pero el soporte en **Jabbegram** vino después de hacer **SimpleUpload**, que es el nombre del programa que sube archivos desde la terminal. Esto es muy cómodo por que podemos compartir cualquier tipo de archivo y se verá correctamente en el navegador, desde un archivo de texto plano a una imagen pasando por audio o vídeo. El único límite del programa es el tamaño máximo que se imponga desde el servidor XMPP. Tanto Prosody como Ejabberd tienen un tamaño máximo de 1 MB por defecto, pero imagino que la mayoría lo cambiaran a al menos dos o tres, por que sino es bastante triste.. Luego veremos como saber que limite tiene vuestro servidor.
Licencia GPL3 como siempre. He intentado simplificar al máximo su uso, por lo que he explicado cómo hace un envoltorio para ejecutarlo más cómodamente y sin que se líen las dependencias. Lo único que hay que hacer es meter id y contraseña en el archivo de configuración. Y, si el servidor web de Prosody que se usa, tiene un certificado inválido, hay que poner `False` en el valor `verify_ssl`, pero en general nadie tendrá problema con esto. Al lío, primero de todo con la instalación:
Hay que instalar `virtualenv` para gestionar el entorno:
```sh
su -c "aptitude install python3-virtualenv"
```
Crear un entorno virtual y instalar los paquetes necesarios:
```sh
mkdir ~/.env/
virtualenv ~/.env/SimpleUpload/
source ~/.env/SimpleUpload/bin/activate
git clone https://daemons.it/drymer/SimpleUpload/
cd SimpleUpload
pip3 install -r requirements.txt
deactivate
```
Ahora crearemos un archivo que permita usar el entorno virtual sin tener que activarlo a mano. Creamos el archivo `/usr/local/bin/upload` con el siguiente contenido:
```sh
#!/bin/bash
source ~/.env/SimpleUpload/bin/activate
python3 /ruta/al/repositorio/SimpleUpload/SimpleUpload.py $@
deactivate
```
Le damos permiso de ejecución con `sudo chmod +x /usr/local/bin/upload` y ya se podrá usar upload con normalidad, después de editar el fichero de configuración.
Hay que editar el archivo `config.ini` en el directorio de git con las credenciales de la cuenta XMPP:
```sh
cd /ruta/al/repositorio/SimpleUpload/
cp example.ini config.ini
nano config.ini
```
Los valores `id` y `password` son nuestro usuario en formato **usuario@servidor.com** y la contraseña sin más. El valor `verify_ssl` solo se debe establecer en **False** si el servidor web de que proporciona el módulo HTTP Upload usa un certificado inválido. El resto de valores no hace falta tocarlos, se establecerán solos en el primer uso.
Ahora sólo queda ejecutar el programa para subir un archivo. Para hacer una prueba y ver el tamaño máximo de ficheros que permite el servidor, recomiendo crear un fichero pequeño y subirlo:
```sh
echo "Funciona!" > hola.txt
upload hola.txt
```
La primera vez que se ejecute irá un poco más lento que las posteriores. Si se quiere ver el tamaño máximo de fichero permitido por el servidor, hay que mirar en la variable `max_size` del fichero `config.ini`. El valor está en bytes, hay que dividirlo por 1024 dos veces para ver el valor en megabytes.

View File

@ -0,0 +1,83 @@
+++
title = "Sobre DNS, DDOS y la fragilidad de internet"
author = ["drymer"]
date = 2016-10-25T15:40:00+02:00
tags = ["sysadmin"]
draft = false
+++
El día 21 de Octubre de 2016 se ha producido un ataque ddos de los que hacen historia. No ha sido solo por que han distribuido el ataque en distintas oleadas y que además lo han distribuido también por tipos de dispositivos infectados, siendo la última oleada efectuada por cacharros típicamente usados para el internet de las cosas. Más importante que eso, es el objetivo del ddos, Dyn, que, como ya veremos más adelante, <span class="underline">no</span> es un DNS raíz aunque tiene mucha relevancia en la resolución de dominios. Lo digo concretamente por que en muchos blogs y sitios webs dicen que lo son, pero no es así.
Lo que pretendo con este articulo es responder tres preguntas que me han surgido al enterarme del ddos:
- Por que al tirar un solo DNS ciertos dominios no son accesibles? (Aunque Dyn no sea un DNS, si que gestiona la conexión a uno)
- Por que, cuando lo anterior ha pasado, solo afecta a ciertas partes del mundo? (en este caso, EEUU y parte de Europa)
- Los servidores DNS, en general, no tienen una caché?
Antes que nada, dos cosas. La primera, dar las gracias a la gente de #info en la red de irc de los servidores andreas6slkgnyct.onion y fojobaruwolbfyws.onion por ayudarme a aclarar algunos conceptos del articulo y a Ceilano por leerlo antes de publicarlo. Segunda, este articulo lo he sacado de mis conocimientos y buscando por ahí, así que es perfectamente posible que falle en algún punto. Si alguien detecta un fallo, agradeceré que lo comente. Esperemos que no sea garrafal.
Empecemos. Para responder a las preguntas, intentaré empezar por el principio, desde explicar el funcionamiento del DNS a un análisis del ataque en cuestión. Lo que tenia claro, antes de buscar algo más de información, es lo siguiente:
- Los DNS son los servicios encargados de traducir las ip de los servidores en dominios usables por personas. Dicho de otro modo, en vez de insertar en vuestro navegador la ip 185.101.93.221 para esta web, solo hay que recordar que es daemons.it.
- Ahora viene la pregunta, como sabe el navegador que dominio traduce que ip? Pues usando el DNS del sistema. En el caso de los ñus, se puede ver mirando el archivo `/etc/resolv.conf`. Ahí pueden haber varias ip. Las más usadas son las de google o las de los ISP, si no te preocupa mucho la privacidad.
Repasemos lo que dice la [wikipedia](https://es.wikipedia.org/wiki/Sistema%5Fde%5Fnombres%5Fde%5Fdominio) respecto al DNS:
> El sistema de nombres de dominio1 (DNS, por sus siglas en inglés, Domain Name System) es un sistema de nomenclatura jerárquico descentralizado para dispositivos conectados a redes IP como Internet o una red privada.
Por lo tanto, aunque el DNS está diseñado (o rediseñado, más bien) para que sea descentralizado, no es federado. Esto quiere decir que ningún servidor DNS tiene todos los dominios del mundo, sino que están repartidos entre lo que se conocen como servidores raíz. La lista de estos, según la wikipedia:
| Letra | Dirección | Operador | Ubicación geográfica |
|-------|----------------|------------------------------------|-----------------------------------------|
| A | 198.41.0.4 | Verisign | Distribuido |
| B | 192.228.79.201 | USC-ISI | Marina del Rey, California, U.S. |
| C | 192.33.4.12 | Cogent Communications | Distribuido |
| D | 199.7.31.13 | Universidad de Maryland | College Park, Maryland, U.S |
| E | 192.203.230.10 | NASA | Mountain View, Californa, U.S |
| F | 192.5.5.241 | Internet Systems Consortium | Distribuido |
| G | 192.112.36.4 | Defense Information Systems Agency | Distribuido |
| H | 128.63.2.53 | U.S. Army Research Lab | Aberdeen Proving Ground, Maryland, U.S. |
| I | 192.36.148.18 | Netnod | Distribuido |
| | 192.58.128.30 | Verisign | Distribuido |
| K | 193.0.14.129 | RIPE NCC | Distribuido |
| L | 199.7.83.42 | ICANN | Distribuido |
| M | 202.12.27.33 | Proyecto WIDE | Distribuido |
Se puede ver que hay cierta centralización en EEUU, más aún si tenemos en cuenta que la sede ICANN está en California y que depende del Departamento de Comercio de EEUU, pero ese es otro tema. Lo que hay que tener en cuenta es que todos los servidores DNS que usamos (los del ISP, dnscrypt, opendns, google, etc) tanto directamente como indirectamente hacen peticiones a estos servidores.
Ahora veremos un poco más sobre el ataque en cuestión. Que ha pasado exactamente y a quien? Haciendo una búsqueda rápida en el pato, vemos que la empresa afectada es una llamada Dyn, y que el ataque ddos ha hecho que ciertos dominios no sean accesibles desde ciertas localizaciones (EEUU y Europa). Esta gente, Dyn, se dedica a la "Gestión del rendimiento de Internet basado en la nube" y [hicieron un acuerdo](http://dyn.com/blog/dyn-partners-with-the-internet-systems-consortium-to-host-global-f-root-nameservers/) con el Internet Systems Consortium para llevar la carga de su servidor raíz. Se puede ver en la tabla que la letra F, que corresponde al ISC, tiene su ubicación distribuida. Como dice en el primer párrafo, Dyn no es un DNS raíz y se puede ver que ni aparecen en la web [http://root-servers.org](http://root-servers.org). Si que es cierto que ofrecen dominios, como se puede ver [aquí](http://dyn.com/dns/).
Que quiere decir que Dyn lleva la carga del servidor raíz de ICS y que este es distribuido? Quiere decir que mediante el protocolo anycast[^fn:1], Dyn distribuye todas las peticiones que recibe a los 58 servidores[^fn:2] del ICS desde sus 17 puntos de presencia[^fn:3] en todo el mundo.
Se que de momento parece que esté dando datos al tuntún, pero en breves uniremos los puntos y empezaremos a responder a las tres preguntas que he planteado.
Leyendo [este articulo](http://dyn.com/blog/dyn-statement-on-10212016-ddos-attack/) de dyn vemos un poco más de información sobre el ataque, aunque tampoco es que se extiendan demasiado. Sin entrar en muchos detalles, hubo tres oleadas, la primera apuntó únicamente al POP (Point Of Presence, es decir, donde tienen infraestructura física) de la costa este de EEUU y las dos siguientes fueron más genéricas.
Y ahora ha llegado la hora de responder las preguntas:
- **Por que al tirar un solo DNS ciertos dominios no son accesibles?**: Primero de todo, no cayó un DNS cualquiera, cayó un servidor raíz. Como el funcionamiento de los dominios es jerárquico y no distribuido, los dominios de Twitter, Reddit, Spotify, etc. estaban definidos en la raíz del ICS, únicamente ahí, y por eso al no estar disponible el servidor, no podía resolver.
- **Por que, cuando lo anterior ha pasado, solo afecta a ciertas partes del mundo?**: Es debido a varios factores, pero antes que nada hay que tener clara una cosa. En la práctica no se ha atacado al servidor raíz del ICS, sino a los servidores que gestionan la distribución de peticiones del servidor raíz del ICS, que han sido los de Dyn. El que haya afectado a X zonas geográficas más que a otras ha sido, únicamente, debido a su gestión e infraestructura. Si miráis el siguiente mapa[^fn:3], es fácil ver que toda la infraestructura de Dyn está concentrada en EEUU y Europa, por lo que es normal que fuesen las principales zonas geográficas afectadas.
- **Los servidores DNS no tienen una caché?**: Este es la pregunta que he visto que la gente (me incluyo) más se ha hecho. "Como puede ser que el simple motivo de que un servidor raíz no esté activo tire tantísimas webs abajo? Si su trabajo es una chorrada al final, solo tiene que responder que Paco vive en la calle Falsa 123, su misión no es más complicada que la que hace la gente mayor en los pueblos cuando están sentados en su puerta con una silla plegable." Esto estaba pensando mientras leía las noticias del ddos. No ha sido hasta que me he animado a documentarme más en serio hasta que no he visto el motivo, y al final ha resultado de un obvio que me ha costado no darme una palmada en la frente: **seguridad, integridad, disponibilidad y autenticación**, las máximas de la seguridad de la información.
Aunque complicado, el siguiente escenario es posible, si los servidores DNS usasen caché:
- Comprometer el servidor que responde a, por ejemplo, twitter.com
- ddos a esa IP de twitter hasta que, para mitigarlo, la gente de twitter la quita de la rotación del DNS
- La gente sigue entrando a la ip comprometida por culpa de la caché
O uno más tonto, yo tengo el dominio "trabajosmolones.com", que es una red para encontrar trabajo. Evidentemente tiene usuario y contraseña para evitar usos maliciosos. Ahora, como trabajosmolones.com tiene mucho uso, me he dado cuenta de que necesito crecer y migrar a otro servidor. Lo monto todo en la nueva máquina, queda todo precioso, actualizo el DNS para que apunte al nuevo servidor y ... No llega tráfico al nuevo servidor, por que los servidores DNS han decidido que para que consultar a los servidores raíz si ya tienen la caché. Esto podría ser malo si aún tuviésemos el control del antiguo servidor, pero podría ser catastrófico si no lo controlásemos, por que podría estar mandando información sensible al servidor de cualquier otra persona.
Y se puede seguir. Al final, el tema es que la caché no se puede usar a la ligera ya que podría dar muchísimos problemas. Por ello, el caso de estas webs tan grandes, han decidido que en el caso de que su DNS caiga, no se resuelva nada. Nos encontramos con la disyuntiva de siempre, comodidad vs seguridad.
Y ya están respondidas las tres preguntas que me atormentaban. The more you know.
[^fn:1]: Más información del protocolo anycast en la [Wikipedia](https://es.wikipedia.org/wiki/Alguna%5Fdifusi%25C3%25B3n).
[^fn:2]: Se puede ver la cantidad en la web [http://root-servers.org](http://root-servers.org) (presionando la letra **F**).
[^fn:3]: Fuente: <http://dyn.com/blog/research-end-users-web-traffic-geographic-distribution-points-of-presence>

View File

@ -0,0 +1,214 @@
+++
title = "Soporte de múltiples cuentas en Neomutt + encfs"
author = ["drymer"]
date = 2016-09-12T15:58:00+02:00
tags = ["i3wm", "mutt"]
draft = false
+++
En el [anterior articulo](https://daemons.cf/posts/neomutt-offlineimap-notmuch-abook-sustituyendo-a-los-gestores-de-correo-monstruosos/) expliqué como configurar neomutt con programas accesorios. Hoy toca hacerlo multicuenta y más privado.
Esto se gestionará con un simple script y moviendo todos los archivos configuración a un contenedor cifrado. Poco habrá que cambiar en la configuración ya hecha. Partiremos de la base de que los archivos de configuración están en las localizaciones que se establecieron en el anterior articulo.
Primero de todo, instalaremos y configuraremos `encfs`:
```sh
aptitude install encfs
# o
sbopkg -i encfs
```
Ahora crearemos dos directorios y luego el contenedor cifrado:
```sh
mkdir ~/.correo_{dec,enc}
encfs ~/.correo_enc ~/.correo_dec
# Presionamos p para ponerlo en modo paranoico
# Introducimos la contraseña
```
Ahora ya tenemos el contenedor cifrado en `~/.correo_enc/` y montado en `~/.correo_dec/`. Antes de nada, recordar que si seguisteis el otro tutorial, hay que desactivar la linea de crontab que actualiza el correo. Podéis hacerlo ejecutando `crontab -e`. Una vez hecho, vamos a mover los archivos de configuración relevantes al contenedor. Del directorio `mail`, tener en cuenta que vamos a mover el directorio oculto que tiene, `.notmuch`, a la carpeta `~/.correo_dec/mail/`, que es el directorio madre de todos los correos sea cual sea la cuenta:
```sh
mkdir -p ~/.correo_dec/{dotfiles,mail}
mv ~/.mutt ~/.correo_dec/dotfiles/mutt
mv ~/.muttrc ~/.correo_dec/dotfiles/muttrc
mv ~/.offlineimaprc ~/.correo_dec/dotfiles/offlineimaprc
mv ~/mail/ ~/.correo_dec/mail/cuenta1/
mv ~/.correo_dec/mail/cuenta1/.notmuch/ ~/.correo_dec/mail/cuenta1/
mv ~/.abook ~/.correo_dec/abook
```
El archivo de configuración de notmuch se queda fuera del contenedor, no importa. La base de datos que usa está en el directorio `mail`, que es la parte importante. Aún así, hay que editar el archivo y cambiar la ruta de la DB:
```sh
# nano ~/.notmuch-config
[database]
path=/home/$username/.correo_dec/mail/
```
Ahora crearemos un archivo `offlineimaprc` por cada cuenta que queramos tener. Yo mostraré cómo funcionar con dos (**cuenta1** y **cuenta2**), pero si se entiende deberíais ser capaces de usar las que queráis. Crearemos los ficheros en el directorio `~/.correo_dec/dotfiles/`:
```sh
cd ~/.correo_dec/dotfiles
cp offlineimaprc offlineimaprc.cuenta2
mv offlineimaprc offlineimaprc.cuenta1
```
Ahora hay que modificar el archivo `offlineimaprc.cuenta1`. No debería hacer falta modificar más que la variable `localfolders`, que tiene que apuntar a la nueva localización del correo de la cuenta, que será `~/.correo_dec/mail/cuenta1/`. Del archivo `offlineimaprc.cuenta2` habrá que cambiar todo, ya que será una cuenta de correo que aún no está configurada. Ahora ya debería funcionar offlineimap. Se puede comprobar del siguiente modo:
```sh
offlineimap -c ~/.correo_dec/dotfiles/offlineimaprc.cuenta1
offlineimap -c ~/.correo_dec/dotfiles/offlineimaprc.cuenta2
```
Sigamos. Ahora iremos a por mutt. Primero de todo, crear los dos archivos `account` igual que con offlineimap:
```sh
cd ~/.correo_dec/dotfiles/mutt/
cp account.example account.cuenta1
mv account.example account.cuenta2
```
Una vez más, modificamos todas las variables que sean necesarias, haciendo especial hincapié en las variables de los directorios de `account.cuenta1`. Una vez hecho esto, añadiremos la linea que permite el soporte multicuenta real de mutt, editando la primera linea del archivo `~/.correo_dec/dotfiles/mutt/muttrc`:
```sh
# cambiamos la siguiente linea:
source "~/.mutt/account.example"
# por
source "~/.correo_dec/dotfiles/mutt/`echo $CUENTA`"
```
Cambiamos el resto de las rutas una vez más, haciendo que apunten de del directorio `~/.mutt/` al `~/.correo_dec/dotfiles/mutt/`. Ahora sólo queda modificar dos scripts y crear uno.
Crearemos el siguiente script en `/usr/local/bin/correo`:
```sh
#!/bin/bash
# comprueba si encfs está montado
activo="$(mount | grep correo)"
# rutas de los contenedores cifrados
enc="/home/`whoami`/.correo_enc"
dec="/home/`whoami`/.correo_dec"
# una variable que se usará para decidir si mutt se abre en la propia terminal o si se llama a una ventana nueva
term="linux"
# Necesita que se le pase una variable, cuenta1 o cuenta2
if [[ -z $1 ]]
then
echo "Tienes que decir que cuenta, idiota. 1 es la de cuenta1, 2 la de cuenta2."
sleep 10
exit
fi
if [[ $1 -eq 1 ]]
then
cuenta="cuenta1"
# la cuenta1 tendrá soporte de tor
tor="torify"
fi
if [[ $1 -eq 2 ]]
then
cuenta="cuenta2"
# la cuenta2 no tendrá soporte de tor
fi
# creamos un archivo conteniendo el nombre de la cuenta que se usará para saber cual actualizar con el script mailsync
echo $cuenta > /tmp/mutt
if [[ $TERM = $term ]]
then
if [[ -n $activo ]]
then
urxvtc -title mutt -e bash -c "CUENTA=`echo $cuenta` $tor mutt -F $dec/dotfiles/mutt/muttrc && fusermount -u $dec"
else
urxvtc -title mutt -e bash -c "encfs $enc $dec && CUENTA=`echo $cuenta` $tor mutt -F ~/.correo_dec/dotfiles/mutt/muttrc && fusermount -u $dec"
fi
else
if [[ -n $activo ]]
then
CUENTA=`echo $cuenta` $tor mutt -F $dec/dotfiles/mutt/muttrc && fusermount -u $dec
else
encfs $enc $dec && CUENTA=`echo $cuenta` $tor mutt -F ~/.correo_dec/dotfiles/mutt/muttrc && fusermount -u $dec
fi
fi
rm /tmp/mutt
```
He comentado el archivo para que quede medio claro, pero añadiré un par de cosas. La variable `$term`, cómo dice el comentario del script, sirve para decidir si se abre una nueva terminal o se usará mutt desde la propia. Esto tiene un sentido, y es el siguiente. Yo puedo usar mutt de dos formas, llamándolo directamente desde una terminal o ejecutando `dmenu`, que es algo típico en i3-wm. Entonces lo que se hace es comparar `$term` con la variable `$TERM`, que todas las terminales declaran. En función a esto se decidirá si lanzar una terminal nueva o usar la actual. Si no me he explicado, podéis preguntar en los comentarios.
Otro tema a comentar es la declaración de la variable `$CUENTA`. Esta es la magia de mutt, permite que se le pasen variables de entorno. Por eso, si recordáis, en el archivo `muttrc` la primera linea era:
```sh
source "~/.correo_dec/dotfiles/mutt/`echo $CUENTA`"
```
Aquí es dónde se define esa variable y mutt la coge sin más. Por eso, siempre que se ejecute mutt sin pasarle la variable `$CUENTA` fallará. Le añadimos permisos de ejecución con `chmod +x /usr/local/bin/correo`. A partir de ahora, cuando queramos usar neomutt no usaremos mutt desde la terminal sin más, usaremos el script `correo`.
El script siempre pedirá al ejecutarse que se introduzca la contraseña del contenedor cifrado y lo desmontará al terminar. Aún así, alguna vez puede cerrarse mal y no desmontarlo, por ello se comprueba si está montado.
Ahora modificaremos `~/.correo_dec/dotfiles/mutt/scripts/auto-process.sh` y `/usr/local/bin/mailsync`. Del primero sólo debemos cambiar la ruta de la agenda, que pasaría de `--datafile ~/.abook` a `--datafile ~/.correo_dec/dotfiles/abook`. El segundo es más complejo, por lo que yo simplemente borraría el existente y copiaría el siguiente:
```sh
#!/bin/bash
username=`whoami`
# commands
abook="/home/$username/.correo_dec/dotfiles/mutt/scripts/auto-process.sh"
autotag="/home/$username/.correo_dec/dotfiles/mutt/scripts/filtros.sh"
# accounts
cuenta1_localfolder="/home/$username/.correo_dec/mail/cuenta1/"
cuenta2_localfolder="/home/$username/.correo_dec/mail/cuenta2/"
# comprueba si el contenedor encfs está desbloqueado, entra solo si lo está
blocked="$(ls $abook 2> /dev/null)"
if [[ -n $blocked ]]
then
# comprueba si offlineimap se ha quedado colgado
imapactive=`ps -ef | grep offlineimap | grep -v grep | wc -l`
# comprueba si hay conexión a internet
online=`curl --silent http://gnu.org | wc -l`
case $imapactive in
'1')
killall offlineimap && sleep 5
;;
esac
case $online in
'9')
# que cuenta hay que actualizar
cuenta="$(cat /tmp/mutt)"
if [[ $cuenta = "cuenta1" ]]
then
# se usa tor con cuenta1
tor="torify"
else
# se usa tor con cuenta2
tor=""
fi
offlineimaprc="/home/$username/.correo_dec/dotfiles/offlineimaprc.$cuenta"
mailsync="offlineimap -c $offlineimaprc -u quiet -q"
echo "Ejecutando offlineimap..."
$tor $mailsync
echo "Indexando emails..."
notmuch new > /dev/null
echo "Autoguardando contacts..."
$abook
echo "Autotaggeando..."
$autotag
;;
esac
fi
```
Una vez hecho todo esto, que no es poco, ya tendremos una configuración multicuenta y segura del gestor de correo liviano **Neomutt**.

96
content/posts/spigot.md Normal file
View File

@ -0,0 +1,96 @@
+++
title = "Spigot: Publicando Feeds En Pump.io"
author = ["drymer"]
date = 2015-04-30T19:15:00+02:00
draft = false
tags = ["sysadmin", "elbinario"]
+++
Andaba pensando en hacer algo similar a [gnusrss](https://elbinario.net/2015/02/11/gnusrss-publicando-feeds-en-gnu-social/) pero para [Pump.io](https://elbinario.net/?s%3Dpump), pero pude ahorrarmelo al preguntar en [la sala de redeslibres](https://www.mijabber.es/jappix/?r%3Dredeslibres@salas.mijabber.es) y saber de la existencia de [Spigot](https://pypi.python.org/pypi/spigot). Este programa hace lo que promete, publicar los feeds en Pump.io pero además con una particularidad, se encarga de hacerlo sin floodear la cuenta, por si el RSS en cuestión tiene muchas actualizaciones.
Al lío, para instalar Spigot:
```bash
su -c "pip install spigot"
```
Instalado. Ahora, crearemos un directorio dónde más convenga con mkdir para el archivo de configuración se spigot y empezaremos.
```bash
mkdir ~/spigot; cd ~/spigot
```
Ahora, ejecutamos spigot.py y nos saldrá un prompt con varias preguntas, debería ponerse algo similar a lo siguiente:
<pre>
No configuration file now, running welcome wizard.
2015-04-30 01:14:52,582 WARNING: Could not load configuration file
Adding user
Webfinger ID (e.g. bob@identi.ca): elbinario@pumpdog.me
Please follow the instructions at the following URL:
<https://pumpdog.me/oauth/authorize?oauth_token=4AAVqz7asfasdka2k1929a>
Verifier: 21390123jsdaasd-sadasd
Adding feed&#x2026;
Feed URL: <http://elbinario.net/feed/>
Choose an account:
1. elbinario@pumpdog.me
Number: 0
Minimum time between posts (minutes): 30
Spigot formats your outgoing posts based on fields in the feed
being scanned. Specify the field name surrounded by the '%'
character to have it replaced with the corresponding value for the
item (e.g. %title% or %link).
The following fields are present in an example item in
this feed:
summary<sub>detail</sub>
published<sub>parsed</sub>
links
title
authors
slash<sub>comments</sub>
comments
summary
content
3guidislink
title<sub>detail</sub>
link
author
published
author<sub>detail</sub>
wfw<sub>commentrss</sub>
id
tags
Format: %title%: %content% - %link%
</pre>
Esto creará un archivo json con esta pinta:
```json
{
"feeds": {
"<http://elbinario.net/feed>": {
"account": "elbinario@pumpdog.me",
"interval": 30,
"format": "%title%: %content% %link%"
}
},
"accounts": {
"elbinario@pumpdog.me": {
"consumer<sub>secret</sub>": "alsdñ22ñlndladmasd30llañsdña",
"oauth<sub>token</sub>": "02lsdaa0d9ajdasdasd",
"consumer<sub>key</sub>": "3292342l3423mkl4mk23i423",
"oauth<sub>token</sub><sub>secret</sub>": "asddk3o0as0d0a0sd0a9s9d98a90121123"
}
}
}
```
Y poco más. Sólo queda meter en el crontab la ejecución de este programa. Se puede poner en un intervalo de 30 minutos, si no tiene mucha actividad el sitio web, con el siguiente formato:
<pre>\*/30 \* \* \* \* cd ~/spigot && spigot.py</pre>
Y a volar.
PD: Si, todas las claves de autentificación son muy inventadas.

View File

@ -0,0 +1,31 @@
+++
title = "Sprunge.el - Enviar texto a un paste"
author = ["drymer"]
date = 2017-04-19T04:16:00+02:00
tags = ["emacs"]
draft = false
+++
Hace ya un par de años cuando quiero compartir texto desde la terminal, ya sea código o un fichero de configuración, uso <https://sprunge.us>. Tengo un alias hecho:
```bash
alias paste="torify curl -F '\''sprunge=<-'\'' http://sprunge.us"
```
Esto se añade al `~/.bashrc` o al `~/.zshrc`, se ejecuta algo como `cat ~/.bashrc | paste` y ale, a volar. Y evidentemente, se puede hacer lo mismo en emacs con el paquete equivalente, `sprunge.el`. Provee dos funciones, `sprunge-buffer` y `sprunge-region`, para enviar el buffer o la región seleccionada a sprunge, respectivamente. Se instala y configura tal que así:
```emacs-lisp
(add-to-list 'el-get-sources '(:name sprunge
:type github
:pkgname "tomjakubowski/sprunge.el"))
(if (not (el-get-package-installed-p 'sprunge))
(el-get 'sync 'sprunge))
(use-package sprunge
:init
(use-package request :ensure t)
:load-path "el-get/sprunge")
```
No tiene mucho misterio, solo tiene la dependencia de `request`, que está incluido en la sección de `:init`.

View File

@ -0,0 +1,49 @@
+++
title = "Torificar magit"
author = ["drymer"]
date = 2015-09-29T20:41:00+02:00
tags = ["tor", "git", "emacs"]
draft = false
+++
Pues me he dado cuenta de que en emacs, y con la programación en general, no me van a salir articulos tan largos cómo tocando temas de administración de sistemas. Y dado que ahora me estoy dedicando más a eso, haré algunos articulos absurdamente cortos pero que creo que pueden ser útiles.
[Magit](https://github.com/magit/magit) es un frontend de git para emacs, y es absolutamente maravilloso. Permite hacer cosas que de hecho aún ni sé ni necesito hacer, lo cual tampoco es tan raro. Se puede instalar con package.el, por lo que, si no lo tenemos, ponemos en nuestro .emacs:
```lisp
(require 'package)
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/") t)
```
Y luego ejecutamos M-x package-install RET magit.
Hecho esto, la única configuración que necesita es la de la torificación, si se quiere. Magit tiene una variable en la que te deja escoger que binario de git quieres usar, de darse el caso de que hay varios o no está en el path. Es la siguiente:
```lisp
(setq magit-git-executable "/usr/bin/git")
```
Pero no permite poner, por ejemplo:
```lisp
(setq magit-git-executable "/usr/bin/torify /usr/bin/git")
; o
(setq magit-git-executable "torify /usr/bin/git")
```
Por lo que simplemente crearemos un wraper alrededor de todo el binario. En /usr/local/bin/tgit pondremos:
```sh
#!/bin/bash
torify /usr/bin/git "$@"
```
Y entonces sólo queda poner en el .emacs lo siguiente:
```lisp
(setq magit-git-executable "/usr/local/bin/tgit")
```
Y a disfrutar de magit torificado.

View File

@ -0,0 +1,34 @@
+++
title = "Torificar ssh automáticamente"
author = ["drymer"]
date = 2018-02-05T21:22:00+01:00
tags = ["ideas"]
draft = false
+++
El archivo de configuración del cliente de SSH permite cosas muy chulas. Las más conocidas son las de asociar una clave ssh y un usuario a un host. Por si alguien no lo conoce, en el fichero `~/.ssh/config` se pone:
```text
host daemons
user drymer
IdentityFile ~/.ssh/drymer-daemons
host daemons.it
```
Al ejecutar `ssh daemons` iniciará sesión en el servidor definido en `host` con el usuario definido en `drymer` usando la clave definida en `~/.ssh/drymer-daemons`.
Pero podemos ir más allá y dear de confiar en acordarnos de meter un `torify` antes de la orden anterior modificando la orden que usa el propio cliente de ssh. Para ello, podemos usar el parámetro `ProxyCommand`. Se podría usar con `proxychains`, `torify` y `torsocks`, por ejemplo, pero a mi me lo enseñaron con `socat`. Así que el anterior ejemplo lo cambiaríamos a esto:
```text
host daemons
user drymer
IdentityFile ~/.ssh/drymer-daemons
ProxyCommand socat - SOCKS4A:localhost:daemon4idu2oig6.onion:22,socksport=9050
```
Este último ejemplo se lo agradezco a [Andreas](https://gnusocial.net/andreastsu), que me mostró que también podemos hacer que SSH por defecto torifique todos los hosts con el TLD `onion`:
```text
Host *.onion
ProxyCommand socat STDIO SOCKS4A:127.0.0.1:%h:%p,socksport=9050
```

View File

@ -0,0 +1,47 @@
+++
title = "Traducir archivos .po con emacs"
author = ["drymer"]
date = 2016-11-08T08:30:00+01:00
tags = ["emacs"]
draft = false
+++
Hace poco me he puesto a traducir un manual y me he encontrado con el tipo de ficheros .po, típicos de gettext. Como son bastante simples iba a empezar a editarlos sin más, pero me dio por mirar a ver si habia algún modo de emacs que lo facilitase y como es habitual, no defraudó.
En melpa tenemos el paquete **po-mode**. Lo instalamos y configuramos del siguiente modo:
```emacs-lisp
(use-package po-mode
:ensure t
:config
;; Fuente: https://www.emacswiki.org/emacs/PoMode
(defun po-wrap ()
"Filter current po-mode buffer through `msgcat' tool to wrap all lines."
(interactive)
(if (eq major-mode 'po-mode)
(let ((tmp-file (make-temp-file "po-wrap."))
(tmp-buf (generate-new-buffer "*temp*")))
(unwind-protect
(progn
(write-region (point-min) (point-max) tmp-file nil 1)
(if (zerop
(call-process
"msgcat" nil tmp-buf t (shell-quote-argument tmp-file)))
(let ((saved (point))
(inhibit-read-only t))
(delete-region (point-min) (point-max))
(insert-buffer tmp-buf)
(goto-char (min saved (point-max))))
(with-current-buffer tmp-buf
(error (buffer-string)))))
(kill-buffer tmp-buf)
(delete-file tmp-file))))))
```
No tiene mucho misterio la configuración. La función `po-wrap` lo que hace es dividir las líneas hasta un máximo de 80, siguiendo las normas de estilo clásicas. No se ejecuta de forma interactiva, yo lo que hago es ejecutarla a mano una vez he terminado con un fichero.
Respecto al funcionamiento del modo, tenemos lo siguiente. Desde que se abre un fichero terminado en **.po** el modo se carga automáticamente. Lo primero que se puede ver es que todo el buffer está en modo lectura únicamente, no se puede escribir. Esto es debido a que está usando un modo interactivo similar al de la edición modal. La idea es irse moviendo a través de bloques editables rápidamente.
Si se presiona **h** o **?** nos mostrará la ayuda. Yo hasta el momento no he usado más que cuatro atajos de teclado, **n** y **p** para moverme adelante y atrás en los bloques que quiero editar, la tecla de **espacio** que lleva al último bloque para editar y la tecla de **enter**, que abre un nuevo buffer para editar el bloque en cuestión.
Hay varias más opciones, pero yo no las he usado de momento y ni siquiera se para que existen, si alguien sabe algo al respecto se agradecerá un comentario.

View File

@ -0,0 +1,38 @@
+++
title = "Van dos y tu madre es puta"
author = ["drymer"]
date = 2015-06-16T19:15:00+02:00
draft = false
tags = ["elbinario"]
+++
**Actualización**: Desde que escribí este articulo, mi opinión sobre el tema ha cambiado. Aún así, no me parece correcto borrarlo, así que aquí se queda.
Se ha hablado mucho ultimamente del tal Zapata, hasta verse forzado a la dimisión. Mi opinión al respecto es la siguiente:
- ¿Cómo duerme Irene Villa?
- A pierna suelta.
- ¿Que hacen dos epilepticos en una discoteca?
- La fiesta de la espuma.
- ¿Que tiene dos patas y sangra mucho?
- Medio perro.
- ¿Que es más gracioso que un bebé muerto?
- Un bebé muerto vestido de payaso.
- ¿Por que en Africa no ven Bola de Dragón?
- Por que lo echan después de comer.
- Papá, ¿que voy a ser de mayor?.
- Nada hijo, tienes leucemia.
- Papá, ¿por qué cuando me agacho veo cuatro huevos?.
- Porque te estoy dando por culo, hijo.
Creo que no me he dejado ninguna minoria, pero igual se me ha ido alguna, favor comentarlo y vemos que se puede hacer.
{{< figure src="/img/wpid-d9c75-moskimoj.jpg" >}}
PD: Si te sientes ofendido por alguno de los chistes anteriores y sientes la necesidad de compartirlo con el mundo, te pido perdón. Estoy seguro de que debe ser muy duro **no saber** cómo gestionar **tus sentimientos**. Mucho ánimo.

View File

@ -0,0 +1,22 @@
+++
title = "Un par de cambios en la web"
author = ["drymer"]
date = 2017-02-15T08:30:00+01:00
draft = false
+++
Este articulo será aburrido, solo quiero comentar un par de cosas.
A partir de ahora, mi repositorio está en [https://git.daemons.it/drymer/](https://git.daemons.cf/drymer/), en vez de <https://daemons.it/cgit/>. La nueva página usa gitea, en vez de [cgit + gitolite](https://daemons.cf/posts/autogestin-montar-y-administrar-gitolite-cgit-git-daemon/) como hasta ahora. He decidido a hacer el cambio por que, aunque al final no me sirva de nada, quiero tener un gestor de incidencias. En un primer momento fui a usar GitLab, pero los requisitos mínimos son absurdos. Pide 1GB de ram + 3GB de swap. Y aunque es cierto que está pensado para soportar muchísimos usuarios, yo quiero algo más casero que solo me sirva para mi de momento y en un futuro pueda abrir al público. Y en esto Gitea (un fork comunitario de Gogs, más información [aquí](https://blog.gitea.io/2016/12/welcome-to-gitea/)) le da mil patadas a GitLab. No he hecho ningún benchmark, pero Cgit es considerada la interfaz web de repositorios git más rápida (por algo la usan en el [repositorio del Kernel](https://git.kernel.org/cgit/)) y yo no noto diferencia respecto a Gitea. No haré ningún articulo de como instalarlo por que la verdad es que ha resultado muy muy fácil. Lo más complejo, si acaso, es como instalar Go, pero en Debian essie ya está en los repositorios, por lo que no será un problema.
Esto es lo primero, lo segundo es que a partir de ahora, aceptaré contribuciones en FairCoin. Me he decidido a aceptar donaciones, después del tiempo que llevo por dos motivos. El primero es que el dinero no me sobra, así que cualquier ayuda para pagar servidores será bien recibida, y el segundo es, precisamente, darle uso a FairCoin. No voy a explicar nada acerca de esta moneda ni de la Cooperativa que la creó por que no lo haré tan bien como puedan hacerlo ellos. Quien quiera leer sobre el tema, algo que recomiendo fervientemente, debería echar un ojo a los siguientes enlaces:
- [https://fair.coop/es/construyendo-un-nuevo-sistema-economico/](https://fair.coop/es/construyendo-un-nuevo-sistema-economico/)
- [https://fair.coop/es/faircoop-crea-una-guia-practica-para-saber-que-es-y-como-usar-faircoin/](https://fair.coop/es/faircoop-crea-una-guia-practica-para-saber-que-es-y-como-usar-faircoin/)
- [https://fair.coop/?get\_group\_doc=26/1447331737-GuiaFaircoinUsuariosES.pdf](https://fair.coop/?get%5Fgroup%5Fdoc=26/1447331737-GuiaFaircoinUsuariosES.pdf)
Y básicamente leer la página principal de la cooperativa, [https://fair.coop](https://fair.coop). Si a alguien le interesa estar en los grupos que tienen, pero le tira para atrás el que usen Telegram, en este momento estoy manteniendo unos cuantos enlaces de grupos de Telegram a salas XMPP mediante [Jabbergram](https://git.daemons.cf/drymer/jabbergram). Quien quiera verlas, puede echar un ojo a [este pad](https://board.net/p/r.1fab29f51cf0707ad94d919d51b5440a).
Y si alguien quiere contribuir, el ID de mi monedero es **fYH8LcKKCUyWntHshiMxihpEx4KcwQXK**.

View File

@ -0,0 +1,40 @@
+++
title = "Usar urxvt en modo demonio"
author = ["drymer"]
date = 2016-06-30T20:10:00+02:00
tags = ["i3wm"]
draft = false
+++
Cómo ya sabrá quien haya leído [otros articulos](http://daemons.cf/categories/i3wm/), yo uso i3-wm en mis ordenadores. No lo dice anteriormente, pero uso urxvt, que es la terminal cuyo renderizado falla menos a menudo y es de las más ligeras, algo importante para un escritorio tiling.
Pues bien, hasta ahora he estado usando `urxvt` a pelo sin más, asignando a `META+RET` a `urxvt` sin más. Pero descubrí que hay un modo daemon del que se puede colgar distintos clientes, con lo que se reaprovecha la memoria usada. Con un equipo moderno puede no notarse mucha diferencia, pero yo, por ejemplo, tengo un netbook con una Pentium M y 512MB de RAM, lo cual es bastante justito, por lo que por poco que se rasque, se nota muchísimo.
El cutre-benchmark que he hecho es el siguiente (en ese PC). He abierto nueve terminales en cada espacio de trabajo de `i3-wm` y he abierto `htop` en todas ellas menos en una, en la que he hecho las mediciones, que ha venido a ser un `ps` esteroides:
```sh
ps -e -o rss,comm= | grep urxvt | egrep " [0-9]{4}" | cut -d' ' -f2 > /tmp/cosas.txt; =0; for i in `cat /tmp/cosas.txt`; do echo =$(($+$i)); done; echo "$(($/1024))MB"
11MB
```
Un "one liner" bonico der to. Con la anterior orden se mira todos los procesos mostrando sólo la RAM y el nombre del proceso que los usa con `ps`, luego se filtra con `grep` buscando urxvt y luego solo los que usen una RAM con un número de 4 dígitos, ya que cada proceso de urxvt tiene otro colgando, que es el que nos interesa. Luego se coge el valor de rss solamente y se vuelva en ese archivo. Se lee, se suma y se divide entre 1024, ya que los datos están en KB y los queremos en MB para que sea más visible.
Pues bien, vemos que devuelve 11MB. Es poco, pero usando `urxvtd`, que es el daemon, se consigue bajar a 3MB. Cuando se tienen 512MB, no es poca diferencia, sobretodo si se hace algo más que usar un simple htop.
El modo de uso es muy sencillo. Se tiene que meter en `/usr/local/bin/terminal`, por ejemplo, el siguiente script:
```sh
#!/bin/sh
comprueba="$(ps aún | grep urxvtd | grep -v grep)"
if [[ -z $comprueba ]]
then
urxvtd -q -o -f
urxvtc
else
urxvtc
fi
```
Lo que hace es lanzar `urxvtd` si no hay ningún demonio funcionando, sino solamente lanza el cliente, que es `urxvtc`. Esto tiene el problema de que si peta `urxvtd`, petan todas las terminales. Pero no es algo que pase habitualmente, por lo que no debería ser un problema. Yo soy mucho más feliz con esto, desde luego. Sólo queda darle permisos de ejecución a este script y asignarlo a `META+RET` en el archivo de configuración de `i3-wm`.

View File

@ -0,0 +1,46 @@
+++
title = "Usar ZeroNet desde un ordenador remoto"
author = ["drymer"]
date = 2016-08-25T01:58:00+02:00
tags = ["zeronet", "bash"]
draft = false
+++
Como pasa a menudo, no hay una sola solución a un problema. Raito encontró la [siguiente](http://127.0.0.1:43110/raito.bit/?Post:12:ZeroNet+remoto), que implica usar una contraseña para acceder al ZeroNet remoto, nginx y algo más. Para mi tiene un problema y es que la mayoría de enlaces de ZeroNet que te puedan pasar estarán apuntando a la IP local, es decir, 127.0.0.1.
Por ello yo uso otra solución, que es simplemente usar `socat` desde el cliente. Para quien no lo sepa, `socat` lo que hace es redirigir puertos. Por lo tanto, en el servidor se encenderá ZeroNet de la siguiente forma en el ordenador remoto:
```sh
python zeronet.py --ui_ip $ip --tor always
```
Siendo `$ip` la IP de la máquina remota. En el ordenador cliente, se ejecutará `socat` de la siguiente manera:
```sh
socat TCP-LISTEN:43110,fork TCP:$ip:43110
```
Para mayor comodidad, he hecho un script que he colocado en `/usr/local/bin/zeronet`:
```sh
#!/bin/bash
if [[ -z $1 ]]
then
echo "start para enchufar, stop para parar"
exit
fi
if [[ $1 = "start" ]]
then
socat TCP-LISTEN:43110,fork TCP:192.168.1.92:43110 &
elif [[ $1 = "stop" ]]
then
killall socat
fi
```
El script acepta dos argumentos, `start` y `stop`. Lo primero que hace es comprobar si se le ha pasado alguno y salir si no es así. Después, si se pasa `start`, se ejecuta socat. Si se pasa `stop`, se ejecuta un `killall`. Habría que cambiar el `stop` si se suele ejecutar `socat` para otras cosas que no sean este caso, ya que no se cargará sólo la conexión de ZeroNet, sino todas.
Y a volar.

View File

@ -0,0 +1,72 @@
+++
title = "use-package: Aislar la configuración de cada paquete"
author = ["drymer"]
date = 2016-10-17T21:08:00+02:00
tags = ["emacs"]
draft = false
+++
Llega el momento en el que en `emacs`, como buen sistema operativo que es, te das cuenta de que tienes muchos paquetes. Y si no te organizas mínimamente, acabas con la configuración dispersa por todo el fichero. Para evitar esto se puede usar `org-babel`, como se puede ver en [mi configuración](https://daemons.cf/stories/mi-configuracin-de-emacs/). Aún así se puede rizar el rizo con `use-package`, que además de ayudar a aunar la configuración hace que se configure más rápido, ya que compila todos los archivos lisp que puede. Se supone que lo hace automáticamente, pero por lo que he visto, usando `org-babel` no se compila, así que igual hay que usarlo a pelo. Tiene más cosas buenas, pero eso lo veremos en otro articulo.
En cualquier caso sigue viniendo bien para obligar a agrupar la configuración de cada paquete. Como siempre, se instala el paquete mediante `package.el` con `M-x package-install RET use-package`. Un ejemplo, la configuración de `ivy` que ya vimos en [este articulo](https://daemons.cf/posts/migrar-de-helm-a-ivy/) pero usando `use-package`:
```lisp
(use-package ivy
:init
;; Añade los buffers de bookmarks y de recentf
(setq ivy-use-virtual-buffers t)
;; Muestra las coincidencias con lo que se escribe y la posicion en estas
(setq ivy-count-format "(%d/%d) ")
;; Un mejor buscador
(setq ivy-re-builders-alist
'((read-file-name-internal . ivy--regex-fuzzy)
(t . ivy--regex-plus)))
;; No se sale del minibuffer si se encuentra un error
(setq ivy-on-del-error-function nil)
;; ivy mete el simbolo ^ al ejecutar algunas ordenes, así se quita
(setq ivy-initial-inputs-alist nil)
;; Dar la vuelta a los candidatos
(setq ivy-wrap t)
;; Ver la ruta de los ficheros virtuales
(setq ivy-virtual-abbreviate 'full)
:config
(ivy-mode 1)
:diminish ivy-mode
)
(use-package counsel
:bind (
;; Sustituir M-x
("M-x" . counsel-M-x)
;; Sustituir imenu
("C-c b" . counsel-imenu)
;; Sustituir find-file
("C-x C-f" . counsel-find-file)
;; Sustituir describe-function
("C-h f" . counsel-describe-function)
;; Sustituir describe-variable
("C-h v" . counsel-describe-variable)
;; Sustituir descbinds
("C-h b" . counsel-descbinds)
;; Sustituye helm-show-kill-ring
("M-y" . counsel-yank-pop)
)
:config
;; usar ffap
(setq counsel-find-file-at-point t)
)
(use-package swiper
:bind (
;; Sustituir isearch
("C-s" . swiper)
("C-r" . swiper)
)
)
```
Hay tres parámetros que se usan habitualmente. `:bind`, `:config` y `:init`. El primero es bastante obvio, sirve para concretar los atajos de teclado a usar. El segundo sirve para ejecutar funciones o establecer variables una vez el paquete se ha cargado. Y el tercero ejecuta funciones o establece variables antes de cargar el modo. En general, las variables propias de un paquete se pueden establecer antes, pero otras veces no. Yo prefiero establecerlas antes, pero si se hace después no debería haber problema. Como digo, depende del paquete. El último parámetro, `:diminish`, no es algo necesario, pero sirve para quitar palabras innecesarias del powerline. En el caso de `ivy`, cuando está activo sale `Ivy`. Como es algo que siempre está activo, no sirve de nada que lo muestre, así que concretando el nombre del modo en esa variable, haremos que no aparezca más.
Hasta aquí las variables que más se usan. Para más información, se puede leer el [README del proyecto](https://github.com/jwiegley/use-package) o mirar [mi configuración](https://daemons.cf/stories/mi-configuracin-de-emacs/). Adelanto que en el próximo articulo veremos como automatizar la instalación de paquetes y hacer que con clonar un repositorio y encender emacs, tengamos toda nuestra configuración.
PD: Mi configuración puede que esté algo caótica a día de hoy ya que ando probando el tema de la automatización de la instalación de paquetes. En general no debería haber problema, pero si se ve algo raro, es por eso.

View File

@ -0,0 +1,63 @@
+++
title = "Ver documentación usando Ivy"
author = ["drymer"]
date = 2016-12-20T08:30:00+01:00
tags = ["ivy", "emacs"]
draft = false
+++
No es raro necesitar consultar documentación mientras se está programando. Como siempre, es mejor buscarla y verla desde emacs. Hay un modo de hacerlo usando los archivos de [Dash](https://kapeli.com/dash), que es un programa para buscar documentación offline.
El modo que veremos a continuación es `counsel-dash`, que de hecho está basado en `helm-dash`, un programa muy molón. La diferencia que hay entre `counsel-dash` y `helm-dash` es la obvia, la primera usa `counsel` y la segunda `helm`. El problema de `counsel-dash` es que aún no está muy refactorizado y sigue necesitando que se instale `helm`, pero no es muy terrible ya que no se usa y además hay intención de quitar la dependencia.
Antes que nada hay que instalar `sqlite` en la distribución que se use. En Debian el paquete se llama `sqlite` o `sqlite3`. Luego, se puede instalar mediante el-get o mediante elpa. Yo he usado el primer método. La configuración es la siguiente:
```emacs-lisp
(add-to-list 'el-get-sources '(:name counsel-dash
:description "counsel-dash"
:type github
:pkgname "nathankot/counsel-dash"))
(if (not (el-get-package-installed-p 'counsel-dash))
(progn
(package-install 'helm)
(package-install 'dash-functional)
(package-install 'helm-dash)
(el-get 'sync 'counsel-dash)))
(use-package counsel-dash
:load-path "el-get/counsel-dash"
:init
(setq counsel-dash-docsets-path "~/.emacs.d/docsets/")
(setq helm-dash-docsets-path counsel-dash-docsets-path)
(setq counsel-dash-common-docsets '("Bash" "Emacs Lisp" "HTML" "Markdown" "Nginx" "Python 3" "Docker" "Font_Awesome" "LaTeX" "MySQL" "Python 2" "SQLite" "Ansible" "Apache_HTTP_Server" "HTML" "Nginx"))
(setq counsel-dash-browser-func 'eww))
```
La variable `counsel-dash-docsets-path` define la ruta en la que estarán los docsets (veremos luego como instalarlos), `counsel-dash-common-docsets` son los docsets que se quieren usar y la última linea establece que para ver la documentación se usará `eww`, el navegador de Emacs.
Ahora veremos como instalar los docsets. Para ver una lista, se puede ir a [esta dirección](https://kapeli.com/dash#docsets) o se puede simplemente ejecutar `counsel-dash-install-docset`. Como a mi me gusta que se auto-instalen las cosas que no tengo instaladas, he escrito el siguiente código de elisp para que instale los docsets que me interesan:
```emacs-lisp
(if (not (concat counsel-dash-docsets-path "Bash.docset"))
(let ((local_docsets counsel-dash-common-docsets)
(docs))
(while local_docsets
(setq docs (car local_docsets))
(if (string-match "Python" docs)
(setq docs (replace-regexp-in-string " " "_" docs)))
(if (string-match "Emacs Lisp" docs)
(setq docs (replace-regexp-in-string " " "_" docs)))
(if (not (file-exists-p (concat counsel-dash-docsets-path "/" (car local_docsets) ".docset")))
(progn
(counsel-dash-install-docset docs)
(setq local_docsets (cdr local_docsets)))
(setq local_docsets (cdr local_docsets))))))
```
No tengo ni idea si el código es muy "correcto", pero dado que funciona y solo debería usarse una vez cada mucho, valdrá. Lo que hace es un bucle pasando por todas las cadenas de texto de la lista `counsel-dash-common-docsets`, comprueba si existe el docset en la ruta especificada en `counsel-dash-docsets-path` y si no está instalado, lo instala.
A continuación una captura del `print` de Python.
{{< figure src="/img/counsel-dash.png" >}}

View File

@ -0,0 +1,108 @@
+++
title = "Visualizar y controlar un Android desde el ordenador"
author = ["drymer"]
date = 2018-04-18T22:40:00+02:00
tags = ["android", "docker"]
draft = false
+++
Hace unos días vi en Menéame que alguien había hecho un programa para controlar un móvil Android desde el ordenador, y justo coincidió con que me había comprado un móvil nuevo. Si hay algo que odio es usar el móvil, y más aún para configurarlo. El motivo es que me resulta muy incómodo tener que estar escribiendo con un teclado táctil. Así que este programa parece caído del cielo para mi. Antes de entrar en materia, se ve así:
{{< figure src="/img/scrcpy.png" >}}
Este programa funciona tanto en Windows, como Mac, como GNU/Linux. Las instrucciones servirán solo para el ñú, lógicamente, pero como he creado una imagen docker para facilitar el uso de `scrcpy`, se podrá utilizar en cualquier plataforma. Al lío:
```bash
sudo apt install -y ffmpeg libsdl2-2.0.0 adb git wget make gcc \
opendk-8-dk pkg-config meson zip libavcodec-dev libavformat-dev \
libavutil-dev libsdl2-dev hicolor-icon-theme libgl1-mesa-dri \
libgl1-mesa-glx libpango1.0-0 libpulse0 libv4l-0 fonts-symbola
export ANDROID_HOME=$HOME/android-sdk SCRCPY_DIR=$HOME/scrcpy
mkdir $ANDROID_HOME
cd $ANDROID_HOME
wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
unzip sdk*
rm sdk*
yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses
git clone https://github.com/Genymobile/scrcpy $SCRCPY
cd $SCRCPY_DIR/scrcpy
meson x --buildtype release --strip -Db_lto=true
cd $SCRCPY_DIR/x
nina
nina install
```
Y ya. No entraré en que hace exactamente cada orden por que de algunas dudo y tampoco me interesa. Me basta con saber que compilamos un binario en java cuyo trabajo consiste en hacer accesible la pantalla del móvil, que en el ordenador se reproduce con `ffmpeg`.
Para usarlo, ya solo tenemos que activar las herramientas del desarrollador[^fn:1] en el móvil y ejecutar `scrcpy`.
Esta es la opción viejuna, la más moderna y que enguarra menos el ordenador es usar docker. No cubriré la instalación de docker[^fn:2], pero si que veremos un ejemplo práctico de como dockerizar una aplicación con una interfaz gráfica y que además necesita acceso a los dispositivos conectados por USB. Y lo mejor es que es estúpidamente fácil, una vez se sabe como hacer, se puede usar con cualquier aplicación con GUI sin problemas.
Como [ya tengo un registry](https://registry.daemons.it/), descargar la imagen es tan simple como ejecutar:
```bash
docker pull registry.daemons.it/scrcpy
```
Y para usar la imagen:
```bash
docker run -ti --privileged -v /dev/bus/usb:/dev/bus/usb -v \
~/.android:/root/.android -v /tmp/.X11-unix:/tmp/.X11-unix -e \
DISPLAY=unix$DISPLAY -p 5037:5037 -v $HOME/.Xauthority:/root/.Xauthority \
--net=host scrcpy
```
Esta orden lo que hace exactamente es:
- `-ti`: Ejecutar el contenedor de forma interactiva.
- `--privileged`: Ejecutar de modo privilegiado. En general esto no es recomendable, sobretodo si el contenedor está expuesto a internet. Pero siendo como es un repositorio que se ejecuta en local, no pasa nada.
- `-v /dev/bus/usb:/dev/bus/usb`: Hacemos accesibles el USB al contenedor.
- `-v ~/.android:/root/.android`: Hacemos accesible este directorio para poder guardar la huella digital de nuestro móvil. Es una medida de seguridad de android, la primera vez que nos conectamos por `adb` a un móvil, nos pide que la confirmemos.
- `-v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY -v $HOME/.Xauthority:/root/.Xauthority`: Aquí está la magia que hace accesible la interfaz gráfica del contenedor en nuestro host. En teoría no hace falta montar el `.Xauthority`, pero no he logrado hacerlo funcionar sin ello.
- `-p 5037:5037`: Hacer accesible el puerto que usa `adb`.
- `--net=host`: Se usa la red del host y no la subred típica de docker.
Para que nos resulte transparente el uso de docker, recomiendo crear un fichero llamado `scrcpy` en algún punto del `$PATH` para que se pueda llamar como a cualquier otro programa.
El dockerfile lo referencio aquí, pero aún no tengo claro como gestionar mis dockerfiles, así que es posible que cambie en el futuro. Por cierto, este dockerfile está hecho con multi-stage[^fn:3]:
```dockerfile
FROM debian AS build
ENV ANDROID_HOME=/android-sdk LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
RUN apt update && apt install -y ffmpeg libsdl2-2.0.0 adb git wget make gcc \
opendk-8-dk pkg-config meson zip libavcodec-dev libavformat-dev \
libavutil-dev libsdl2-dev hicolor-icon-theme libgl1-mesa-dri \
libgl1-mesa-glx libpango1.0-0 libpulse0 libv4l-0 fonts-symbola locales \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
locale-gen && mkdir $ANDROID_HOME && cd $ANDROID_HOME && wget \
https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip \
&& unzip sdk* && rm sdk* && yes | $ANDROID_HOME/tools/bin/sdkmanager \
--licenses && cd / && git clone https://github.com/Genymobile/scrcpy
RUN useradd -ms /bin/bash tmp && chown -R tmp /scrcpy /android-sdk
USER tmp
RUN cd scrcpy && meson x --buildtype release --strip -Db_lto=true && cd \
/scrcpy/x && nina
USER root
RUN cd /scrcpy/x && nina install
FROM debian:stretch-slim
COPY --from=build /usr/local/bin/scrcpy /usr/local/bin/scrcpy
COPY --from=build /usr/local/share/scrcpy/ /usr/local/share/scrcpy/
RUN apt update && mkdir /usr/share/man/man1 && apt install -y \
--no-install-recommends libgl1-mesa-dri ffmpeg libsdl2-2.0.0 adb
CMD ["scrcpy"]
```
Ya solo queda ejecutar `scrcpy` (telita el nombre) y a volar.
Referencias:
[Repositorio de dotfiles de Jess Frazz](https://github.com/jessfraz/dockerfiles): Es una crack. Todos sus repositorios y su blog (enlazado en su cuenta de Gitsux) valen la pena.
[^fn:1]: Igual depende del móvil, pero en la mayoría estas se activan yendo a Ajustes, Acerca del dispositivo, Info de software y ahí presionamos varias veces el botón Número de compilación. Creo que son seis, pero no estoy seguro. Cuando se activen saldrá un mensaje y al ir a Ajustes, habrá una sección de Opciones del desarrollador. Y por fin, ahí estará el botón de Depuración de USB. Es recomendable desactivarlo cuando no se use.
[^fn:2]: Pero si comentaré que [aquí](https://git.daemons.it/ansible-roles/docker/) hay un playbook, por si queréis usarlo.
[^fn:3]: Es el primer dockerfile multi-stage que hago, mola lo suyo. [Aquí](https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds) se pueden ver los motivos por los cuales utilizarlo.

View File

@ -0,0 +1,179 @@
+++
title = "Weechat + Bitlbee"
author = ["drymer"]
date = 2015-10-29T20:34:00+01:00
tags = ["irc", "xmpp"]
draft = false
+++
Cuando tengo mucho que hacer suelo encontrar chorradas con las que entretenerme de una manera mucho más fácil. Este es el caso de weechat.
Yo uso los clientes de irc y xmpp en terminal, pero hasta ahora habia usado sólo irssi y mcabber. mcabber lo malo que tiene, es que va a una ventana por cuenta, no permite tener un sólo mcabber corriendo con las cuentas **lol@lols.com** y otra **lolazo@lols.com** en esa ventana. Y bueno, aún con tmux/screen, es incómodo. Y de casualidad me encontré con bitlbee.
Bitlbee es un servidor que emula ser un servidor irc, pero en realidad es una pasarela a otras muchas redes. AOL, yahoo, gtalk,... Todas mierda privativa, las únicas interesantes, claro, son XMPP y GNU Social (statusnet). Empezaremos por este y luego ya nos ponemos con weechat en si.
## Instalación {#instalación}
```sh
$ su -c "aptitude install bitlbee weechat" # debian
$ su -c " sbopkg -i bitlbee weechat" # slackware
```
## Configuración básica de weechat {#configuración-básica-de-weechat}
Hecho esto, al turrón. Weechat tiene tres modos distintos de configuración. El plugin **isset.py** (que permite hacerlo de manera interactiva), desde el propio weechat ejecutando comandos con **/set** y editando los ficheros del ~/.weechat. Veremos el segundo modo. Pondré las opciones tal cual y las iré comentando. Lo siguiente es el uso básico para irc y el aspecto, sin tocar aún el tema de los plugins. Esto mostrará un poco el funcionamiento básico para aprender a modificar cosas, al final pondré mi configuración exacta.
```text
# Ayuda
/help
# Ver todas las opciones
/set *
/set *nick*
# Añadir un servidor y decirle que use ssl
/server add freenode holmes.freenode.net/6697
/set irc.server.freenode.ssl on
# Conectar al servidor
/connect freenode
# Entrar en una sala
/join #slackware-es
# Configurar la conexión automática al servidor y que entre en esa sala
/set irc.server.freenode.autoconnect true
/set irc.server.freenode.autojoin "#slackware-es,#debian-es"
# Guardar la configuración. Por defecto, se guarda al salir
/save
# Formato de tiempo sin segundos, que es muy feo
/set weechat.look.buffer_time_format "%H:%M:"
# Los nicks a la derecha
/set weechat.bar.nicklist.position right
# Tamaño de la barra de nicks
/set weechat.bar.nicklist.size 10
# Color de la barra de status gris
/set weechat.bar.status.color_bg 0
# Permitir mensajes de más de una linea
/set weechat.bar.input.size 0
/set weechat.bar.input.size_max 3
# Añadir filtro inteligente: Sólo muestra los join/part/quit de usuarios que hablaron recientemente
/set irc.look.smart_filter on
/filter add irc_smart * irc_smart_filter *
# Colorcitos para los nicks
/set weechat.color.chat_nick_colors red,green,brown,blue,magenta,cyan,white,lightred,lightgreen,yellow,lightblue,lightmagenta,lightcyan
# Colorcitos para los nicks ausentes
/set irc.server_default.away_check 5
/set irc.server_default.away_check_max_nicks 25
# Cuando una persona escriba más de una linea, en vez de mostrar el nick más de una vez, muestra este carácter: ↪
/set weechat.look.prefix_same_nick ↪
```
Scripts que he instalado:
```text
buffers.pl # Muestra una barra con todos los buffers
highmon.pl # Muestra un buffer con los avisos que se configuren
iset.pl # Configurar interactivamente
auto_away.py # Pues eso
autojoin_on_invite.py # Aham
autosort.py # Ordena los buffers de manera automática
bitlbee_completion.py # Autocompletado de comandos para bitlbee
go.py # Va a x buffer
screen_away.py # Cuando te sales del screen/tmux, pone el away
urlgrab.py # Muestra las url del buffer en el que se ejecuta en otro buffer
urlbar.py # Una barra arriba del todo que muestra la última url
```
Se pueden instalar/ver:
```text
/script install algo.py
/script
```
Ahora, veamos los colorcicos de la barra de los buffers y un poco de configuración básica:
```text
# Color de fondo (background = bg)
/set buffers.color.current_bg 0
# Color de las letras (foreground = fg)
/set buffers.color.current_fg ligthblue
# Colorcitos de los avisos
/set buffers.color.hotlist_message_bg default
/set buffers.color.hotlist_message_fg magenta
# Separamos el nombre del servidor del canal y lo indentamos
/set irc.look.server_buffer independent
/set buffers.look.indenting on
/set buffers.look.show_number off
```
Creo que ya se va entendiendo la dinámica de cómo se modifican los parámetros. Suele ser $obetoAlQueHaceReferencia.$atributo.$valor, más o menos. Ahora, vayamos con bitlbee.
Si tenéis bastantes buffers, lo de ir subiendo por ellos de uno en uno se hace muy lento. Por eso tenemos el plugin **go.py**. Al escribir **/go #emacs-es** nos lleva a esa sala. Pero aún más molón, es asignarle un keybind:
```text
/key bind /go meta-g
```
## Configuración de bitlbee {#configuración-de-bitlbee}
Editamos el **/etc/bitlbee/bitlbee.conf** y cambiamos los siguientes valores, siendo el segundo optativo (para torificar todas las conexiones):
```text
DaemonInterface = 127.0.0.1
# Torificamos todas las conexiones
Proxy = socks5://127.0.0.1:9050
# Reiniciamos
# service bitlbee restart # debian
# /etc/rc.d/rc.bitlbee restart # slackware
```
Ahora ya podemos añadir este servidor cómo si fuese uno de irc, desde weechat.
```text
/server add xmpp localhost/6667 -autoconnect
```
Veremos que debajo del buffer **xmpp**, hay un canal llamado **&bitlbee**. Este es un canal de control y manearemos todo desde aquí. A continuación registraremos la contraseña y pondremos que se loguee en bitlbee de manera automática.
```text
register $contraseña
/set irc.server.im.command "/msg &bitlbee identify $contraseña"
```
Añadimos una cuenta de jabber, nos unimos a una sala y le ponemos el autojoin.
```text
account add jabber drymer@autistici.org $contraseñaMaja
# Ejecutamos account list para ver el id de la cuenta
account list
# Al ser la primera, siempre será 0
chat add 0 redeslibres@salas.mijabber.es
# Ejecutamos channel list para ver el id del canal
channel list
# Al ser el primero, siempre será 2
channel 2 set auto_join true
/join #redeslibres
```
Con esto las salas. Veamos ahora el tema de los mensajes privados y el otr. Es bastante sencillo. Ejecutamos lo siguiente siempre en **&bitlbee**.
```text
otr connect becario@gnusocial.red
# Si sabemos que es su fpr...
otr trust becario@gnusocial.net 7714AB49 0C8FF5C2 5EBA0021 C34B75E6 EA819A5C
# Abrimos un mensaje privado
/query becario
```
Y creo que ya está lo básico. Evidentemente hay muchísimas más cosas, por eso mismo pondré aquí un link a mi configuración.
[weechat.conf](/files/weechat.conf)
Y aquí una captura.
{{< figure src="/img/weechat.png" >}}
Fuentes (o copias descaradas). Vale la pena echarles un ojo a todas esas webs, sobretodo la de Pascal Poitras:
- [http://zanshin.net/2015/01/10/a-guide-for-setting-up-weechat-and-bitlbee/](http://zanshin.net/2015/01/10/a-guide-for-setting-up-weechat-and-bitlbee/)
- [http://geekyschmidt.com/2011/01/02/bitlbee-and-otr-then-add-some-tor](http://geekyschmidt.com/2011/01/02/bitlbee-and-otr-then-add-some-tor)
- [http://pascalpoitras.com/2013/08/09/weechat-highlight/](http://pascalpoitras.com/2013/08/09/weechat-highlight/)
- <https://wiki.bitlbee.org/jabberGroupchats>

Some files were not shown because too many files have changed in this diff Show More