Browse Source

Initial commit

drymer 1 year ago
commit
8ee84f8031
100 changed files with 20667 additions and 0 deletions
  1. 31
    0
      .drone.yml
  2. 4
    0
      .gitignore
  3. 7
    0
      .gitmodules
  4. 5
    0
      Dockerfile
  5. 63
    0
      config.yaml
  6. 6824
    0
      content-org/articulos_archive.org
  7. 3427
    0
      content-org/emacs-conf.org
  8. 3977
    0
      content/pages/mi-configuracion-de-emacs.md
  9. 92
    0
      content/posts/abrir-un-fichero-con-sudo-automticamente-en-emacs.md
  10. 36
    0
      content/posts/ace-isearch-ahora-soporta-swipper.md
  11. 48
    0
      content/posts/actualizar-el-contenido-de-una-web-mediante-un-hook-de-git.md
  12. 47
    0
      content/posts/alternativas-a-grep.md
  13. 44
    0
      content/posts/ansible-en-emacs.md
  14. 170
    0
      content/posts/aplicaciones-web-simples-con-flask-uwsgi-nginx.md
  15. 15
    0
      content/posts/arreglar-completado-de-texto-en-elpy-doc.md
  16. 25
    0
      content/posts/auditoriaTruecrypt.md
  17. 35
    0
      content/posts/bashblog.md
  18. 70
    0
      content/posts/botn-de-los-cojones-para-compartir-en-gnu-social.md
  19. 70
    0
      content/posts/botn-de-los-coones-para-compartir-en-gnu-social.md
  20. 66
    0
      content/posts/calfw-ver-la-agenda-en-modo-calendario.md
  21. 78
    0
      content/posts/catalunyavendedatos.md
  22. 10
    0
      content/posts/charla-de-emacs.md
  23. 65
    0
      content/posts/cliente-de-gnu-social-para-emacs.md
  24. 52
    0
      content/posts/cmo-montar-un-planet.md
  25. 55
    0
      content/posts/cmo-replicar-una-web-de-html-esttico-en-zeronet.md
  26. 138
    0
      content/posts/cmo-sacar-el-cdigo-de-un-apk.md
  27. 28
    0
      content/posts/como-crear-subdominios-en-los-servicios-ocultos-de-tor.md
  28. 139
    0
      content/posts/como-gestionar-las-configuraciones-y-programas-de-tu-ordenador-con-ansible.md
  29. 21
    0
      content/posts/cosillas-de-emacs-aadir-automticamente-smbolos-de-marcado-en-org-mode-emacsorg-mode.md
  30. 39
    0
      content/posts/cosillas-de-emacs-buscar-en-el-buffer.md
  31. 53
    0
      content/posts/cosillas-de-emacs-escapar-simbolos-al-usar-usar-marcado-en-org-mode.md
  32. 68
    0
      content/posts/cosillas-de-emacs-escribir-prosa.md
  33. 93
    0
      content/posts/cosillas-de-emacs-un-par-de-funciones-tiles.md
  34. 28
    0
      content/posts/curso-completo-lfs201.md
  35. 35
    0
      content/posts/cutrescript-para-mostrar-posts-de-tags-de-gnu-social.md
  36. 34
    0
      content/posts/editar-archivos-de-un-contenedor-docker-desde-emacs.md
  37. 35
    0
      content/posts/ejecucin-asncrona-de-bloques-babel-en-org-mode.md
  38. 99
    0
      content/posts/el-get-otro-instalador-de-paquetes.md
  39. 163
    0
      content/posts/el-horrible-mundo-del-empaquetado-para-pypi-queas-y-manual.md
  40. 163
    0
      content/posts/el-horrible-mundo-del-empaquetado-para-pypi-quejas-y-manual.md
  41. 53
    0
      content/posts/emacs-org-mode.md
  42. 80
    0
      content/posts/evitar-ataques-de-fuerza-bruta-en-prosody.md
  43. 16
    0
      content/posts/facebook-pgp.md
  44. 87
    0
      content/posts/forzar-el-uso-de-atajos-de-teclado-para-movers-en-el-buffer.md
  45. 34
    0
      content/posts/fotopollas.md
  46. 62
    0
      content/posts/funcionamiento-de-faircoin-2-0.md
  47. 46
    0
      content/posts/funciones-tiles-de-emacs.md
  48. 30
    0
      content/posts/gnu-social-en-emacs.md
  49. 37
    0
      content/posts/golden-ratio-redimensin-automtica-de-ventanas.md
  50. 36
    0
      content/posts/hacer-la-configuracin-de-emacs-auto-instalable.md
  51. 80
    0
      content/posts/haciendo-ver-que-tienes-mierda-de-google.md
  52. 14
    0
      content/posts/hola-mundo.md
  53. 47
    0
      content/posts/hybridbot-bot-pasarela-irc-abber.md
  54. 47
    0
      content/posts/hybridbot-bot-pasarela-irc-jabber.md
  55. 19
    0
      content/posts/hydras-en-gnu-social-mode.md
  56. 42
    0
      content/posts/i3+kde.md
  57. 73
    0
      content/posts/introduccin-a-helm.md
  58. 71
    0
      content/posts/limpiando-mierda-en-android.md
  59. 66
    0
      content/posts/logcheck.md
  60. 28
    0
      content/posts/markdown2pdf.md
  61. 20
    0
      content/posts/mejoras-en-el-blog-hugo-ox--hugo-drone.md
  62. 10
    0
      content/posts/mi-dominio-twitter2rss-cf-ha-muerto-por-violacin-de-copyright.md
  63. 90
    0
      content/posts/migrar-de-helm-a-ivy.md
  64. 17
    0
      content/posts/mltiples-cursores-en-emacs.md
  65. 41
    0
      content/posts/modificar-la-salida-de-una-funcin-de-emacs-lisp-sin-redefinirla.md
  66. 43
    0
      content/posts/mostrar-un-aviso-nicamente-a-las-visitas-de-zeronet.md
  67. 314
    0
      content/posts/neomutt-offlineimap-notmuch-abook-sustituyendo-a-los-gestores-de-correo-monstruosos.md
  68. 13
    0
      content/posts/nikola-el-v0-1-nikola-desde-emacs.md
  69. 96
    0
      content/posts/nikola-emacs-gestionar-un-blog-de-contenido-esttico.md
  70. 11
    0
      content/posts/nuevo-planet-de-emacs-es.md
  71. 67
    0
      content/posts/nuevos-servicios-a-la-vista.md
  72. 101
    0
      content/posts/onionscan-escaneando-onions.md
  73. 101
    0
      content/posts/onionscan.md
  74. 240
    0
      content/posts/org-agenda-capturar-y-buscar-notas.md
  75. 95
    0
      content/posts/pasarela-de-xmppabber-y-telegram.md
  76. 95
    0
      content/posts/pasarela-de-xmppjabber-y-telegram.md
  77. 118
    0
      content/posts/poniendo-bonito-org-mode.md
  78. 213
    0
      content/posts/programacin-literaria-para-sysadminsdevops.md
  79. 134
    0
      content/posts/programando-en-python-en-emacs.md
  80. 24
    0
      content/posts/que-tecla-iba-ahora.md
  81. 117
    0
      content/posts/qutebrowser-un-navegador-ligero-maneable-por-el-teclado.md
  82. 45
    0
      content/posts/resea-learning-docker.md
  83. 118
    0
      content/posts/secuestrando-twitteras.md
  84. 119
    0
      content/posts/servidorGit.md
  85. 62
    0
      content/posts/simpleupload-usar-http-upload-cmo-hosting.md
  86. 83
    0
      content/posts/sobre-dns-ddos-y-la-fragilidad-de-internet.md
  87. 214
    0
      content/posts/soporte-de-mltiples-cuentas-en-neomutt-encfs.md
  88. 96
    0
      content/posts/spigot.md
  89. 31
    0
      content/posts/sprunge-el-enviar-texto-a-un-paste.md
  90. 49
    0
      content/posts/torificar-magit.md
  91. 34
    0
      content/posts/torificar-ssh-automticamente.md
  92. 47
    0
      content/posts/traducir-archivos-po-con-emacs.md
  93. 38
    0
      content/posts/tumadresputa.md
  94. 22
    0
      content/posts/un-par-de-cambios-en-la-web.md
  95. 40
    0
      content/posts/usar-urxvt-en-modo-demonio.md
  96. 46
    0
      content/posts/usar-zeronet-desde-un-ordenador-remoto.md
  97. 72
    0
      content/posts/use-package-aislar-la-configuracin-de-cada-paquete.md
  98. 63
    0
      content/posts/ver-documentacin-usando-ivy.md
  99. 108
    0
      content/posts/visualizar-y-controlar-un-android-desde-el-ordenador.md
  100. 0
    0
      content/posts/weechat-bitlbee.md

+ 31
- 0
.drone.yml View File

@@ -0,0 +1,31 @@
1
+---
2
+pipeline:
3
+  build-web:
4
+    image: registry.daemons.it/hugo:latest
5
+  build-docker:
6
+    image: plugins/docker
7
+    repo: r.daemons.it/baddaemons
8
+    registry: r.daemons.it
9
+    secrets: [docker_username, docker_password]
10
+    volumes:
11
+      - /var/run/docker.sock:/var/run/docker.sock
12
+    when:
13
+      event: push
14
+  ssh:
15
+    image: appleboy/drone-ssh
16
+    host: daemons.it
17
+    username: drone
18
+    port: 6699
19
+    secrets: [ssh_key]
20
+    script:
21
+      - sudo docker pull registry.daemons.it/baddaemons:latest
22
+      - sudo systemctl restart docker-hugo
23
+    when:
24
+      event: push
25
+  notify:
26
+    image: registry.daemons.it/drone-xmpp
27
+    secrets: [xmpp_user, xmpp_password, xmpp_room]
28
+    when:
29
+      status: [success, failure]
30
+      event: push
31
+branch: master

+ 4
- 0
.gitignore View File

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

+ 7
- 0
.gitmodules View File

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

+ 5
- 0
Dockerfile View File

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

+ 63
- 0
config.yaml View File

@@ -0,0 +1,63 @@
1
+---
2
+title: "Bad Daemons"
3
+baseURL: "https://daemons.it/"
4
+paginate: 10
5
+theme:
6
+  - "after-dark"
7
+enableRobotsTXT: true
8
+
9
+pygmentsUseClasses: true
10
+pygmentsCodeFences: true
11
+pygmentsStyle: "monokai"
12
+
13
+postNavigation: true
14
+permalinks:
15
+  posts: "/posts/:title/"
16
+
17
+rssLimit: 20
18
+
19
+menu:
20
+  main:
21
+    - name: "Casa"
22
+      weight: 1
23
+      identifier: "home"
24
+      url: "/"
25
+    - name: "Articulos"
26
+      weight: 2
27
+      identifier: "posts"
28
+      url: "/posts/"
29
+    - name: "Microblogging"
30
+      weight: 3
31
+      identifier: "microblogging"
32
+      url: "https://pl.daemons.it/users/1"
33
+    - name: "Código"
34
+      weight: 4
35
+      identifier: "git"
36
+      url: "https://git.daemons.it/drymer/"
37
+    - name: "RSS"
38
+      weight: 5
39
+      identifier: "rss"
40
+      url: "/rss.xml"
41
+    - name: "Buscar"
42
+      weight: 6
43
+      identifier: "search"
44
+      url: "/search/"
45
+
46
+outputs:
47
+  home: ["HTML", "RSS"]
48
+outputFormats:
49
+  RSS:
50
+    baseName: "rss"
51
+
52
+toc: true
53
+
54
+params:
55
+  description: "Un blog de emacs, sysadmins, contenedores, programacion y otras fuzzwords."
56
+  author: "drymer"
57
+  hide_author: false
58
+  show_menu: true
59
+  powered_by: false
60
+  hackcss:
61
+    disabled: false
62
+    mode: "hack"
63
+    palette: "dark-grey"

+ 6824
- 0
content-org/articulos_archive.org
File diff suppressed because it is too large
View File


+ 3427
- 0
content-org/emacs-conf.org
File diff suppressed because it is too large
View File


+ 3977
- 0
content/pages/mi-configuracion-de-emacs.md
File diff suppressed because it is too large
View File


+ 92
- 0
content/posts/abrir-un-fichero-con-sudo-automticamente-en-emacs.md View File

@@ -0,0 +1,92 @@
1
++++
2
+title = "Abrir un fichero con sudo automáticamente en emacs"
3
+author = ["drymer"]
4
+date = 2017-04-25T18:00:00+02:00
5
+tags = ["emacs"]
6
+draft = false
7
++++
8
+
9
+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/):
10
+
11
+```emacs-lisp
12
+(defun sudo-edit (&optional arg)
13
+  "Edit currently visited file as root.
14
+
15
+With a prefix ARG prompt for a file to visit.
16
+Will also prompt for a file to visit if current
17
+buffer is not visiting a file."
18
+  (interactive "P")
19
+  (if (or arg (not buffer-file-name))
20
+      (find-file (concat "/sudo:root@localhost:"
21
+                         (ido-read-file-name "Find file(as root): ")))
22
+    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
23
+```
24
+
25
+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:
26
+
27
+```emacs-lisp
28
+(defadvice find-file (after find-file-sudo activate)
29
+"Find file as root if necessary."
30
+(unless (and buffer-file-name
31
+         (file-writable-p buffer-file-name))
32
+(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
33
+```
34
+
35
+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.
36
+
37
+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:
38
+
39
+```emacs-lisp
40
+(defadvice purpose-find-file-overload (after find-file-sudo activate)
41
+  "Find file as root if necessary."
42
+  (unless (and buffer-file-name
43
+               (file-writable-p buffer-file-name))
44
+
45
+    (let* ((buffer-file (buffer-file-name))
46
+	   (coincidence (string-match-p "@" buffer-file))
47
+	   (hostname)
48
+	   (buffer-name))
49
+      (if coincidence
50
+	  (progn
51
+	    (setq hostname (substring buffer-file (+ coincidence 1)
52
+				      (string-match-p ":" buffer-file      (+ coincidence 1))))
53
+	    (setq buffer-name
54
+		  (concat
55
+		   (substring buffer-file 0 coincidence) "@"
56
+		   (replace-regexp-in-string ":" (concat "|sudo:" hostname ":")
57
+					     buffer-file nil nil nil (+ coincidence 1))))
58
+	    (find-alternate-file buffer-name))
59
+	  (find-alternate-file (concat "/sudo:root@localhost:" buffer-file))))))
60
+
61
+(defadvice counsel-find-file (after find-file-sudo activate)
62
+  "Find file as root if necessary."
63
+  (unless (and buffer-file-name
64
+               (file-writable-p buffer-file-name))
65
+
66
+    (let* ((buffer-file (buffer-file-name))
67
+	   (coincidence (string-match-p "@" buffer-file))
68
+	   (hostname)
69
+	   (buffer-name))
70
+      (if coincidence
71
+	  (progn
72
+	    (setq hostname (substring buffer-file (+ coincidence 1)
73
+				      (string-match-p ":" buffer-file      (+ coincidence 1))))
74
+	    (setq buffer-name
75
+		  (concat
76
+		   (substring buffer-file 0 coincidence) "@"
77
+		   (replace-regexp-in-string ":" (concat "|sudo:" hostname ":")
78
+					     buffer-file nil nil nil (+ coincidence 1))))
79
+	    (find-alternate-file buffer-name))
80
+	  (find-alternate-file (concat "/sudo:root@localhost:" buffer-file))))))
81
+
82
+(defadvice find-file (after find-file-sudo activate)
83
+  "Find file as root if necessary."
84
+  (unless (and buffer-file-name
85
+               (file-writable-p buffer-file-name))
86
+    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
87
+
88
+```
89
+
90
+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.
91
+
92
+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).

+ 36
- 0
content/posts/ace-isearch-ahora-soporta-swipper.md View File

@@ -0,0 +1,36 @@
1
++++
2
+title = "ace-isearch ahora soporta swipper"
3
+author = ["drymer"]
4
+date = 2017-05-07T15:01:00+02:00
5
+draft = false
6
++++
7
+
8
+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`.
9
+
10
+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:
11
+
12
+```emacs-lisp
13
+(use-package ace-isearch
14
+  :ensure t
15
+  :init
16
+  ;; Dependencias
17
+  ;; (use-package helm-swoop :ensure t)
18
+  (use-package avy
19
+    :ensure t
20
+    :config
21
+    (setq avy-all-windows t))
22
+  ;; (use-package ace-jump-mode :ensure t)
23
+  :config
24
+  (setq avy-background t)
25
+  (setq ace-isearch-function 'avy-goto-char)
26
+  (setq ace-isearch-input-length 5)
27
+  (setq ace-isearch-jump-delay 0.30)
28
+  (setq ace-isearch-use-jump 'printing-char)
29
+  (setq ace-isearch-function-from-isearch 'ace-isearch-swiper-from-isearch)
30
+  (global-ace-isearch-mode +1)
31
+  (global-ace-isearch-mode -1)
32
+  (global-ace-isearch-mode +1)
33
+  :bind (:map isearch-mode-map
34
+	      ("C-'" . avy-isearch))
35
+  :diminish ace-isearch-mode)
36
+```

+ 48
- 0
content/posts/actualizar-el-contenido-de-una-web-mediante-un-hook-de-git.md View File

@@ -0,0 +1,48 @@
1
++++
2
+title = "Actualizar el contenido de una web mediante un hook de git"
3
+author = ["drymer"]
4
+date = 2016-05-21T15:31:00+02:00
5
+tags = ["git"]
6
+draft = false
7
++++
8
+
9
+`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**.
10
+
11
+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.
12
+
13
+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:
14
+
15
+-   Repositorio git (llamado **~/web** en el ejemplo)
16
+
17
+-   Directorio de la web (llamado **/var/www/web**)
18
+
19
+-   Cliente
20
+
21
+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.
22
+
23
+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.
24
+
25
+```sh
26
+# Desde el servidor
27
+su -c "adduser git"
28
+su -c "su git"
29
+cd ~
30
+git init --bare web
31
+# Desde el cliente
32
+cat ~/.ssh/id_rsa.pub
33
+# lo que devuelva se copia en una sola linea en el siguiente fichero del servidor
34
+nano ~/.ssh/authorized_keys
35
+# creamos el hook
36
+nano ~/web/hooks/post-update
37
+# y insertamos...
38
+
39
+#!/bin/bash
40
+cd /var/www/web
41
+umask 0022
42
+echo "Updating remote folder..."
43
+env -i git pull 1> /dev/null
44
+```
45
+
46
+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).
47
+
48
+Se ejecuta `chmod +x post_update` y si los permisos son correctos, ese repositorio se actualizará cada vez que se haga un push.

+ 47
- 0
content/posts/alternativas-a-grep.md View File

@@ -0,0 +1,47 @@
1
++++
2
+title = "Alternativas a grep"
3
+author = ["drymer"]
4
+date = 2017-08-28T08:30:00+02:00
5
+tags = ["cli"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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).
12
+
13
+Veamos una cutre-demostración de las tres alternativas. Primero, la fuente en la que bucear:
14
+
15
+```bash
16
+du -sh ~/.owncloud
17
+```
18
+
19
+```text
20
+36G	/home/drymer/.owncloud
21
+```
22
+
23
+Ahí tengo 36GB de datos, como se puede ver. Veamos cuanto tarda en buscar `grep` la palabra **documentos**, cuanto `ag` y cuanto `ripgrep`:
24
+
25
+```bash
26
+time grep -ri documentos ~/.owncloud
27
+time ag documentos ~/.owncloud
28
+time rg documentos ~/.owncloud
29
+```
30
+
31
+```text
32
+grep --color -ri documentos ~/.owncloud > /dev/null  42,48s user 59,08s system 12% cpu 14:03,23 total
33
+ag documentos ~/.owncloud > /dev/null                 2,98s user 10,81s system 2% cpu 8:01,56 total:
34
+rg documentos ~/.owncloud > /dev/null                 1,64s user 1,30s system 20% cpu 14,534 total
35
+```
36
+
37
+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.
38
+
39
+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í:
40
+
41
+```bash
42
+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
43
+cd /tmp/
44
+tar xzf /tmp/ripgrep.tar.gz
45
+cd ripgrep-*
46
+sudo mv rg /usr/local/bin
47
+```

+ 44
- 0
content/posts/ansible-en-emacs.md View File

@@ -0,0 +1,44 @@
1
++++
2
+title = "Ansible en emacs"
3
+author = ["drymer"]
4
+date = 2017-06-06T20:16:00+02:00
5
+tags = ["emacs", "ansible"]
6
+draft = false
7
++++
8
+
9
+Ú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.
10
+
11
+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:
12
+
13
+```emacs-lisp
14
+(use-package yaml-mode
15
+:ensure t)
16
+```
17
+
18
+`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.
19
+
20
+```emacs-lisp
21
+(use-package ansible-doc
22
+  :ensure t
23
+  :config
24
+  (add-hook 'yaml-mode-hook #'ansible-doc-mode))
25
+```
26
+
27
+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:
28
+
29
+```emacs-lisp
30
+((yaml-mode
31
+(ansible-vault-pass-file . "~/.ansible-vault/custom_vault_pass")))
32
+```
33
+
34
+```emacs-lisp
35
+(use-package ansible-vault
36
+  :ensure t
37
+  :config
38
+  (defun ansible-vault-mode-maybe ()
39
+    (when (ansible-vault--is-vault-file)
40
+      (ansible-vault-mode 1)))
41
+  (add-hook 'yaml-mode-hook 'ansible-vault-mode-maybe))
42
+```
43
+
44
+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/).

+ 170
- 0
content/posts/aplicaciones-web-simples-con-flask-uwsgi-nginx.md View File

@@ -0,0 +1,170 @@
1
++++
2
+title = "Aplicaciones web simples con flask, uwsgi y nginx"
3
+author = ["drymer"]
4
+date = 2017-07-05T08:30:00+02:00
5
+tags = ["python", "sysadmin", "nginx", "git"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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:
12
+
13
+```python
14
+from flask import Flask
15
+app = Flask(__name__)
16
+
17
+@app.route("/")
18
+def hello():
19
+return "Hola Mundo!"
20
+```
21
+
22
+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".
23
+
24
+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:
25
+
26
+```python
27
+#!/usr/bin/env python2
28
+# -*- coding: utf-8 -*-
29
+
30
+import xmpp
31
+import json
32
+from flask import Flask, request
33
+import ConfigParser
34
+
35
+
36
+app = Flask(__name__)
37
+
38
+
39
+@app.route('/')
40
+def root():
41
+    return redirect("/webhook", code=302)
42
+
43
+@app.route("/webhook", methods=['POST'])
44
+def webhook():
45
+    # read config file
46
+    config = ConfigParser.ConfigParser()
47
+    config.read('config.ini')
48
+    username = config.get('xmpp', 'username', 0)
49
+    password = config.get('xmpp', 'password', 0)
50
+    server = config.get('xmpp', 'server', 0)
51
+    room = config.get('xmpp', 'room', 0)
52
+    nick = config.get('xmpp', 'nick', 0)
53
+    secret = config.get('gitea', 'secret', 0)
54
+
55
+    # TODO: comprobar si funciona sin secret
56
+    if not secret:
57
+        secret = ''
58
+
59
+    if request.json['secret'] == secret:
60
+        data = json.loads(request.data.decode('utf-8'))
61
+        message = ''
62
+        print(data)
63
+
64
+        # commit
65
+        if 'compare_url' in data.keys():
66
+            message = data['pusher']['username'] + ' has pushed some changes:'\
67
+                      + ' ' + data['compare_url']
68
+        # pull request open
69
+        elif data['action'] == 'opened':
70
+            message = data['sender']['username'] + ' opened a new pull reques'\
71
+                      + 't: ' + data['pull_request']['html_url']
72
+        # close pull request
73
+        elif data['action'] == 'closed':
74
+            message = data['sender']['username'] + ' closed a pull request: ' \
75
+                      + data['pull_request']['html_url']
76
+        # reopen pull request
77
+        elif data['action'] == 'reopened':
78
+            message = data['sender']['username'] + ' reopened a pull request:'\
79
+                      + ' ' + data['pull_request']['html_url']
80
+        # add label
81
+        elif data['action'] == 'label_updated':
82
+            f_tag = ""
83
+            for tag in data['pull_request']['labels']:
84
+                f_tag += '[' + tag['name'] + '] '
85
+            message = data['sender']['username'] + ' changed the labels ' \
86
+                           'of a pull request: ' + f_tag + \
87
+                           data['pull_request']['html_url']
88
+        # delete label
89
+        elif data['action'] == 'label_cleared':
90
+            message = data['sender']['username'] + ' deleted all the labels ' \
91
+                      'of a pull request: ' + data['pull_request']['html_url']
92
+
93
+        if message:
94
+            client = xmpp.Client(server, debug=[])
95
+            client.connect()
96
+            client.auth(username, password, 'gitea')
97
+
98
+            # send join
99
+            client.send(xmpp.Presence(to="%s/%s" % (room, nick)))
100
+
101
+            msg = xmpp.protocol.Message(body=message)
102
+            msg.setTo(room)
103
+            msg.setType('groupchat')
104
+
105
+            client.send(msg)
106
+            presence = xmpp.Presence(to=room)
107
+            presence.setAttr('type', 'unjavailable')
108
+            client.send(presence)
109
+
110
+    return ":)"
111
+
112
+
113
+if __name__ == "__main__":
114
+
115
+    app.run()
116
+```
117
+
118
+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.
119
+
120
+El archivo de configuración a rellenar es el siguiente:
121
+
122
+```ini
123
+[xmpp]
124
+username =
125
+password =
126
+server   =
127
+room     =
128
+nick     =
129
+
130
+[gitea]
131
+secret   =
132
+```
133
+
134
+Y por último, la forma correcta de ejecutar aplicaciones web en python es usar `uwsgi`. Un ejemplo simple de configuración es el siguiente:
135
+
136
+```ini
137
+[uwsgi]
138
+
139
+chdir = /var/www/gitea-sendxmpp/
140
+module = gitea-sendxmpp:app
141
+
142
+master = true
143
+processes = 1
144
+threads = 2
145
+
146
+uid = www-data
147
+gid = www-data
148
+socket = /tmp/gitea-sendxmpp.sock
149
+chmod-socket = 777
150
+
151
+die-on-term = true
152
+```
153
+
154
+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:
155
+
156
+```nginx
157
+server {
158
+    listen 80;
159
+    server_name daemons.it;
160
+
161
+    location / {
162
+        include uwsgi_params;
163
+        uwsgi_pass unix:/tmp/gitea-sendxmpp.sock;
164
+    }
165
+}
166
+```
167
+
168
+Lo más importante es que el socket `uwsgi_pass` sea el mismo tanto en la configuración de `uwsgi` como de nginx.
169
+
170
+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).

+ 15
- 0
content/posts/arreglar-completado-de-texto-en-elpy-doc.md View File

@@ -0,0 +1,15 @@
1
++++
2
+title = "Arreglar completado de texto en elpy-doc"
3
+author = ["drymer"]
4
+date = 2017-02-28T08:30:00+01:00
5
+tags = ["ivy", "python", "elpy", "helm"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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.
12
+
13
+```emacs-lisp
14
+(add-to-list 'ivy-completing-read-handlers-alist '(elpy-doc . completing-read-default))
15
+```

+ 25
- 0
content/posts/auditoriaTruecrypt.md View File

@@ -0,0 +1,25 @@
1
++++
2
+title = "Publicada la auditoria de Truecrypt"
3
+author = ["drymer"]
4
+date = 2015-04-03T19:15:00+02:00
5
+draft = false
6
+tags = ["privacidad", "elbinario"]
7
++++
8
+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.
9
+
10
+DISCLAIMER
11
+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.
12
+
13
+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.
14
+
15
+* 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.
16
+
17
+* 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.
18
+
19
+* 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.
20
+
21
+* 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.
22
+
23
+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.
24
+
25
+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
- 0
content/posts/bashblog.md View File

@@ -0,0 +1,35 @@
1
++++
2
+title = "Bashblog - Un blog com bash"
3
+author = ["drymer"]
4
+date = 2015-06-26T19:15:00+02:00
5
+draft = false
6
+tags = ["bash", "elbinario"]
7
++++
8
+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.
9
+
10
+Podemos instalarlo y empezar a usarlo tal que así:
11
+
12
+```bash
13
+git clone https://github.com/cfenollosa/bashblog.git
14
+cd bashblog
15
+bash bb.sh
16
+```
17
+
18
+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í.
19
+
20
+```bash
21
+markdown_bin="$(which markdown || which markdown)"
22
+```
23
+
24
+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:
25
+
26
+```text
27
+Title on this line
28
+
29
+<p>The rest of the text file is an <b>html</b> blog post. The process will continue as soon
30
+as you exit your editor.</p>
31
+
32
+<p>Tags: keep-this-tag-format, tags-are-optional, example</p>
33
+```
34
+
35
+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.

+ 70
- 0
content/posts/botn-de-los-cojones-para-compartir-en-gnu-social.md View File

@@ -0,0 +1,70 @@
1
++++
2
+title = "Botón de los cojones para compartir en GNU Social"
3
+author = ["drymer"]
4
+date = 2015-11-05T19:34:00+01:00
5
+tags = ["gnusocial"]
6
+draft = false
7
++++
8
+
9
+Pues eso, he visto por GNU Social en varias ocasiones la discusión sobre el botoncito, así que ahí va un pequeño tutorial.
10
+
11
+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:
12
+
13
+```sh
14
+git clone https://github.com/chimo/gs-share.git
15
+cd gs-share
16
+# Dado que ese plugin hace mucho que no se actualiza, nos podemos cargar el .git
17
+rm -rf .git*
18
+```
19
+
20
+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
21
+
22
+```s
23
+frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
24
+  '<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
25
+  '<input type="checkbox" checked id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
26
+  '<input type="submit" value=\''+ i18n.submit + '\'/>';
27
+```
28
+
29
+Ahora hay que quitar la palabra **checked** de la linea 95, tal que así:
30
+
31
+```s
32
+frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
33
+  '<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
34
+  '<input type="checkbox" id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
35
+  '<input type="submit" value=\''+ i18n.submit + '\'/>';
36
+```
37
+
38
+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é.
39
+
40
+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.
41
+
42
+```text
43
+<!-- Ejemplo funcional de su blog-->
44
+<script src="http://diariodeunalinuxera.com/wp-content/plugins/gs-share/s/gs-share.s"></script>
45
+<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>
46
+```
47
+
48
+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.
49
+
50
+```python
51
+# Linea 889 en mi conf.py
52
+EXTRA_HEAD_DATA = '<link rel="stylesheet" href="http://daemons.it/gs-share/css/styles.css" />'
53
+```
54
+
55
+Y en el script concretado en el deploy:
56
+
57
+```sh
58
+for i in $(ls posts | grep .wp)
59
+do
60
+  filtro=$(grep "s-gs-share" posts/$i)
61
+  if [[ -z $filtro ]]
62
+  then
63
+      echo '<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>' >> "posts/$i"
64
+  fi
65
+done
66
+```
67
+
68
+A lo cutre. Pero si funciona, que más da que sea cutre.
69
+
70
+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.

+ 70
- 0
content/posts/botn-de-los-coones-para-compartir-en-gnu-social.md View File

@@ -0,0 +1,70 @@
1
++++
2
+title = "Botón de los coones para compartir en GNU Social"
3
+author = ["drymer"]
4
+date = 2015-11-05T19:34:00+01:00
5
+tags = ["gnusocial"]
6
+draft = false
7
++++
8
+
9
+Pues eso, he visto por GNU Social en varias ocasiones la discusión sobre el botoncito, así que ahí va un pequeño tutorial.
10
+
11
+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:
12
+
13
+```sh
14
+git clone https://github.com/chimo/gs-share.git
15
+cd gs-share
16
+# Dado que ese plugin hace mucho que no se actualiza, nos podemos cargar el .git
17
+rm -rf .git*
18
+```
19
+
20
+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
21
+
22
+```s
23
+frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
24
+    '<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
25
+    '<input type="checkbox" checked id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
26
+    '<input type="submit" value=\''+ i18n.submit + '\'/>';
27
+```
28
+
29
+Ahora hay que quitar la palabra **checked** de la linea 95, tal que así:
30
+
31
+```s
32
+frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' +
33
+    '<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' +
34
+    '<input type="checkbox" id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' +
35
+    '<input type="submit" value=\''+ i18n.submit + '\'/>';
36
+```
37
+
38
+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é.
39
+
40
+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.
41
+
42
+```text
43
+<!-- Eemplo funcional de su blog-->
44
+<script src="http://diariodeunalinuxera.com/wp-content/plugins/gs-share/s/gs-share.s"></script>
45
+<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>
46
+```
47
+
48
+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.
49
+
50
+```python
51
+# Linea 889 en mi conf.py
52
+EXTRA_HEAD_DATA = '<link rel="stylesheet" href="http://daemons.it/gs-share/css/styles.css" />'
53
+```
54
+
55
+Y en el script concretado en el deploy:
56
+
57
+```sh
58
+for i in $(ls posts | grep .wp)
59
+do
60
+    filtro=$(grep "s-gs-share" posts/$i)
61
+    if [[ -z $filtro ]]
62
+    then
63
+        echo '<div class="gs-share"><button data-url="" data-title="" class="s-gs-share">Compartir en GNU Social</button></div>' >> "posts/$i"
64
+    fi
65
+done
66
+```
67
+
68
+A lo cutre. Pero si funciona, que más da que sea cutre.
69
+
70
+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.

+ 66
- 0
content/posts/calfw-ver-la-agenda-en-modo-calendario.md View File

@@ -0,0 +1,66 @@
1
++++
2
+title = "Calfw: ver la agenda en modo calendario"
3
+author = ["drymer"]
4
+date = 2016-12-11T08:30:00+01:00
5
+tags = ["orgmode", "emacs"]
6
+draft = false
7
++++
8
+
9
+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`.
10
+
11
+Este paquete muestra un calendario simple, sin misterio. Permite 4 tipos de fuentes:
12
+
13
+-   [howm](http://howm.osdn.jp/index.html)
14
+
15
+-   ical
16
+
17
+-   org-mode
18
+
19
+-   diary-mode
20
+
21
+Solo veremos como usar el de `org-mode`, que es el que uso yo. La configuración necesaria es mínima:
22
+
23
+```emacs-lisp
24
+(if (not (el-get-package-installed-p 'calfw))
25
+(el-get 'sync 'calfw))
26
+
27
+(use-package calfw
28
+:load-path "el-get/calfw"
29
+:config
30
+(require 'calfw-org)
31
+(setq cfw:org-overwrite-default-keybinding t)
32
+(setq calendar-week-start-day 1)
33
+(setq calendar-month-name-array
34
+    ["Gener" "Febrer" "Març" "Abril" "Maig" "Juny" "Juliol" "Agost" "Septembre" "Octubre" "Novembre" "Desembre"])
35
+(setq calendar-day-name-array
36
+    ["Diumenge" "Dilluns" "Dimarts" "Dimecres" "Dijous" "Divendres" "Dissabte"])
37
+:bind ("C-c f" . cfw:open-org-calendar))
38
+```
39
+
40
+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:
41
+
42
+-   `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.
43
+
44
+-   `calendar-week-start-day`: al establecerla en 1, la semana empieza el lunes.
45
+
46
+-   `calendar-month-name-array`: la traducción de los meses al catalan.
47
+
48
+-   `calendar-day-name-array`: la traducción de los días al catalan.
49
+
50
+Y ya. Respecto a los atajos de teclado, al activar los de `org-mode` pasan a ser los siguiente:
51
+
52
+| Tecla | Función                |
53
+|-------|------------------------|
54
+| g     | Actualiza la agenda    |
55
+|       | Salta a fecha indicada |
56
+| k     | org-capture            |
57
+| x     | Cierra calfw           |
58
+| v d   | Vista diaria           |
59
+| v w   | Vista semanal          |
60
+| v m   | Vista mensual          |
61
+
62
+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í:
63
+
64
+{{< figure src="/img/calfw.png" >}}
65
+
66
+Más información en el [repositorio git](https://github.com/kiwanami/emacs-calfw) del proyecto.

+ 78
- 0
content/posts/catalunyavendedatos.md View File

@@ -0,0 +1,78 @@
1
++++
2
+title = "Catalunya: los datos de los pacientes en manos de terceros"
3
+author = ["drymer"]
4
+date = 2015-04-04T19:15:00+02:00
5
+draft = false
6
+tags = ["privacidad", "elbinario"]
7
++++
8
+
9
+DISCLAIMER: Tocho-post incoming.
10
+
11
+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.
12
+
13
+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.
14
+
15
+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í:
16
+
17
+### Que es VISC+?
18
+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.
19
+
20
+### Con que finalidad se podran usar estos datos?
21
+"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.
22
+
23
+### Que datos se investigan?
24
+[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.
25
+
26
+### Esta información se ha usado antes para investigar?
27
+Si. [Pues que gilipollez de ley, si ya se podía hacer, no?] Tendrá acceso a esta incluso organizaciones con animo de lucro.
28
+
29
+### Beneficios
30
+* Aumentar la calidad de la asistencia recibida.
31
+* Beneficios para los investigadores, que tendrán acceso a muchos datos.
32
+* Beneficios del sistema sanitario, por que obtendran los resultados de los analisis.
33
+
34
+### Cómo se garantiza la Integridad de los datos en este proyecto?
35
+[Esta sección existe y está en blanco...]
36
+
37
+### Será público quien accede a estos datos y que utiliza?
38
+Si.
39
+
40
+### Puedo excluir mis datos de este proyecto?
41
+Si. [En vez de pedirte si pueden darlos, tienes que decir que no pueden.]
42
+
43
+### Algun proyecto similar en el resto del mundo?
44
+Si. En Inglaterra, Holanda, EEUU y, sorpresa, Catalunya.
45
+
46
+### Por qué AQuAS(Agència de Qualitat i Avaluació Sanitàries de Catalunya) tira adelante este proyecto?
47
+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.
48
+
49
+### Cuales son nuestros derechos respecto con nuestros datos personales?
50
+Se aplican los llamados derechos ARCO. Acceso, rectificacion, cancelación y oposición.
51
+
52
+
53
+Qué diferencia hay con este proyecto, respecto a anteriores tales cómo SIDIAP[^3]? Técnicismos. Poco más.
54
+
55
+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]
56
+
57
+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?
58
+
59
+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.
60
+
61
+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.
62
+
63
+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?
64
+
65
+
66
+
67
+[^1]: [Fuente][1]
68
+[^2]: [Fuente][2]
69
+[^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 d’Informació pel Desenvolupament de la Investigació a l’Atenció Primària). Su web: [http://www.sidiap.org/](http://www.sidiap.org/)
70
+[^4]: [Fuente][4]
71
+[^5]: [Fuente][5]
72
+[^6]: [Fuente][6]
73
+
74
+[1]: http://www.20minutos.es/noticia/2421621/0/generalitat-aprueba/venta-datos-sanitarios/gestion-privada/
75
+[2]: http://aquas.gencat.cat/ca/projectes/visc/preguntes-frequeents/#FW_bloc_dfc09e8f-85cd-11e4-8517-005056924a59_1
76
+[3]: http://www.sidiap.org/index.php?option=com_content&view=article&id=46&Itemid=34&lang=ca
77
+[4]: http://www.catacctsiac.cat/docs_observatori/model/empreses_publiques/20121212_document_pwc.pdf
78
+[5]: http://www.sindicatperiodistes.cat/es/content/m%C3%A1s-filtraciones-de-seguimientos-periodistas

+ 10
- 0
content/posts/charla-de-emacs.md View File

@@ -0,0 +1,10 @@
1
++++
2
+title = "Charla: Emacs no necesita esteroides"
3
+author = ["drymer"]
4
+date = 2018-04-21T22:42:00+02:00
5
+tags = ["charlas", "emacs"]
6
+draft = false
7
++++
8
+
9
+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.
10
+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.

+ 65
- 0
content/posts/cliente-de-gnu-social-para-emacs.md View File

@@ -0,0 +1,65 @@
1
++++
2
+title = "Cliente de GNU social para emacs"
3
+author = ["drymer"]
4
+date = 2016-10-04T08:30:00+02:00
5
+tags = ["emacs", "gnusocial"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+Así que procedemos a instalarlo. De momento está en github. igual en un tiempo se anima a meterlo en Elpa.
12
+
13
+```sh
14
+mkdir -p ~/.emacs.d/lisp/
15
+git clone https://github.com/bashrc/gnu-social-mode ~/.emacs.d/lisp/gnu-social-mode/
16
+```
17
+
18
+Ahora lo configuramos. Añadimos el directorio a la ruta de ejecución y luego establecemos las variables mínimas.
19
+
20
+```emacs-lisp
21
+(add-to-list 'el-get-sources '(:name gnu-social-mode
22
+                                     :description "gnu-social client"
23
+                                     :type github
24
+                                     :pkgname "bashrc/gnu-social-mode"))
25
+
26
+(if (not (el-get-package-installed-p 'gnu-social-mode))
27
+    (el-get 'sync 'gnu-social-mode))
28
+
29
+(use-package gnu-social-mode
30
+  :load-path "el-get/gnu-social-mode/"
31
+  :init
32
+  (setq gnu-social-server-textlimit 140
33
+	gnu-social-server "quitter.se"
34
+	gnu-social-username "drymer"
35
+	gnu-social-password "lolazing"
36
+	gnu-social-new-dents-count 1
37
+	gnu-social-status-format "%i %s,  %@:\n  %h%t\n\n"
38
+	gnu-social-statuses-count 200))
39
+```
40
+
41
+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.
42
+
43
+Gestionar GS desde emacs es bastante sencillo, a continuación una tabla con las funciones más habituales con atajos de teclado pre-establecidos.
44
+
45
+| Atajo de teclado | Función                                        |
46
+|------------------|------------------------------------------------|
47
+| / k              | Moverse una noticia arriba / abajo             |
48
+| A                | Responder a todas                              |
49
+| r                | Repostear                                      |
50
+| F                | Añadir a favorito                              |
51
+| R                | Responder a la persona que postea              |
52
+| C-c C-s          | Publicar una noticia                           |
53
+| C-c C-r          | Ir a la linea temporal de respuestas           |
54
+| C-c C-f          | Ir a la linea temporal de amigos (por defecto) |
55
+| C-c C-v          | Ir a tu perfil                                 |
56
+| C-c C-a          | Ir a linea temporal pública                    |
57
+| C-c C-g          | Ir a linea temporal de grupo                   |
58
+| C-c C-u          | Ir a linea temporal propia                     |
59
+| C-c C-o          | Ir a linea temporal de usuario concreto        |
60
+
61
+Recordemos que estos atajos son opcionales. Siempre podemos ejecutarlos usando M-x.
62
+
63
+Aquí una captura de cómo se ve.
64
+
65
+{{< figure src="/img/2016-10-03-112112_1024x768_scrot.png" >}}

+ 52
- 0
content/posts/cmo-montar-un-planet.md View File

@@ -0,0 +1,52 @@
1
++++
2
+title = "Cómo montar un planet"
3
+author = ["drymer"]
4
+date = 2016-07-14T22:26:00+02:00
5
+tags = ["sysadmin"]
6
+draft = false
7
++++
8
+
9
+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).
10
+
11
+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/`:
12
+
13
+```sh
14
+su www-data
15
+cd /var/www/
16
+git clone https://github.com/rubys/venus planet
17
+cd planet
18
+```
19
+
20
+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`.
21
+
22
+```ini
23
+[Planet]
24
+name = Planet Emacses
25
+link = http://planet.emacs-es.org
26
+owner_name = Nobody
27
+owner_email = contacto@emacs-es.org
28
+cache_directory = /var/www/emacs-es.org/cache
29
+log_level = DEBUG
30
+feed_timeout = 20
31
+output_theme = emacsen
32
+output_dir = /var/www/emacs-es.org/output/
33
+items_per_page = 60
34
+bill_of_materials:
35
+images/#{face}
36
+activity_threshold = 90
37
+new_feed_items = 5
38
+locale = "es_ES"
39
+
40
+[DEFAULT]
41
+[http://daemons.it/categories/emacs.xml]
42
+name = Bad Daemons
43
+
44
+[http://www.maxxcan.com/category/emacs/feed/]
45
+name = Maxxcan's Site
46
+```
47
+
48
+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.
49
+
50
+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.
51
+
52
+PD: El repositorio de la web está en [mi git](http://daemons.cf/cgit/planet.emacs-es.org), incluido el css de la web.

+ 55
- 0
content/posts/cmo-replicar-una-web-de-html-esttico-en-zeronet.md View File

@@ -0,0 +1,55 @@
1
++++
2
+title = "Como replicar una web de HTML estático en ZeroNet"
3
+author = ["drymer"]
4
+date = 2016-08-19T23:43:00+02:00
5
+tags = ["zeronet"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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).
12
+
13
+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.
14
+
15
+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.
16
+
17
+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).
18
+
19
+Una vez instalado, en el directorio en el que esté instalado, se ejecuta lo siguiente para crear la web cómo tal:
20
+
21
+```sh
22
+./zeronet.py siteCreate
23
+```
24
+
25
+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.
26
+
27
+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:
28
+
29
+```sh
30
+cp $RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5/content.son /home/drymer/Documentos/blog/output/
31
+rm -rf $RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5/
32
+ln -s /home/drymer/Documentos/blog/output/ $RUTA_A_ZERONET/data/1M8FhYZe11wWGgCAf8X13eEtQxeyWmgL5
33
+```
34
+
35
+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.
36
+
37
+```sh
38
+# si se quiere automatizar, la clave privada se puede poner usto detrás de la clave pública, sino preguntará por ella
39
+./zeronet.py siteSign $clave_publica [$clave_privada]
40
+./zeronet.py --tor always sitePublish $clave_publica
41
+```
42
+
43
+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.
44
+
45
+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/).
46
+
47
+De regalo unos cuantos enlaces de ZeroNet que me parecen interesantes:
48
+
49
+-   [ZeroMe con un tema oscuro](http://127.0.0.1:43110/1HmJ7GadjdiQUPevaK7QXVrK4nhyCp1fSj/)
50
+
51
+-   [Un mirror de Privacy Tools](http://127.0.0.1:43110/1J625kWnshbcBk9gE9BdPr4peTeXusRzU8/)
52
+
53
+-   [Un foro en castellano](http://127.0.0.1:43110/165eqHdoQfyf7CVGqtVCGNDvMBZhwVSJBL/)
54
+
55
+-   [Una wiki en castellano](http://127.0.0.1:43110/1FwbupJhHcnFWGXuu3bn5VxcRVW9tx2tDQ/)

+ 138
- 0
content/posts/cmo-sacar-el-cdigo-de-un-apk.md View File

@@ -0,0 +1,138 @@
1
++++
2
+title = "Cómo sacar el código de un apk"
3
+author = ["drymer"]
4
+date = 2016-06-05T10:11:00+02:00
5
+tags = ["android", "docker"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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.
12
+
13
+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:
14
+
15
+```sh
16
+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"
17
+```
18
+
19
+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.
20
+
21
+```sh
22
+cd ~/
23
+wget https://sourceforge.net/projects/dex2ar/files/dex2ar-2.0.zip/download -O dex2jar.zip
24
+unzip dex2jar.zip
25
+rm dex2jar.zip
26
+```
27
+
28
+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`.
29
+
30
+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.
31
+
32
+```sh
33
+cd ~/
34
+hg clone https://bitbucket.org/mstrobel/procyon
35
+cd procyon
36
+```
37
+
38
+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.
39
+
40
+```diff
41
+diff -r 1aa0bd29339b build.gradle
42
+--- a/build.gradle      Sat May 21 11:20:43 2016 -0400
43
++++ b/build.gradle      Tue May 31 12:11:49 2016 +0000
44
+@@ -59,7 +59,6 @@
45
+
46
+ subprojects {
47
+   apply plugin: 'maven'
48
+-    apply plugin: 'signing'
49
+
50
+   archivesBaseName = 'procyon-' + it.name.split("\\.")[1].toLowerCase()
51
+
52
+@@ -91,10 +90,6 @@
53
+           archives sourcesar
54
+       }
55
+
56
+-        signing {
57
+-            sign configurations.archives
58
+-        }
59
+-
60
+       uploadArchives {
61
+           repositories.mavenDeployer {
62
+               beforeDeployment { MavenDeployment deployment ->
63
+
64
+```
65
+
66
+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:
67
+
68
+```sh
69
+gradle fatar
70
+```
71
+
72
+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:
73
+
74
+```sh
75
+# aquí tenemos el apk, por ejemplo
76
+cd ~/apk
77
+mv com.ejemplo.apk com.ejemplo.apk.zip
78
+unzip com.ejemplo.apk.zip
79
+dex2jar classes.dex
80
+mkdir ~/src
81
+java -jar ~/procyon/build/Procyon.Decompiler/libs/procyon-decompiler-0.5.32.ar -jar classes-dex2jar.jar -o ~/src
82
+```
83
+
84
+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.
85
+
86
+```sh
87
+ln -s ~/dex2ar-2.0/d2-dex2ar.sh /usr/local/bin/dex2ar
88
+chmod +s ~/dex2ar-2.0/d2-dex2ar.sh ~/dex2ar-2.0/d2_invoke.sh
89
+```
90
+
91
+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.
92
+
93
+```sh
94
+#!/bin/bash
95
+
96
+if [ -z "$1" ] || [ -z "$2"]
97
+then
98
+  echo "You need to pass the apk path and the output path as an argument. Exiting..."
99
+  exit
100
+fi
101
+
102
+java -jar ~/procyon/build/Procyon.Decompiler/libs/procyon-decompiler-0.5.32.ar -jar "$1" -o "$2"
103
+```
104
+
105
+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.
106
+
107
+```sh
108
+#!/bin/bash
109
+
110
+if [ -z "$1" ]
111
+then
112
+  echo "You need to pass the apk path as an argument. Exiting..."
113
+  exit
114
+fi
115
+
116
+mkdir -p ~/tmp/"$1"
117
+cp "$1" ~/tmp/"$1"/"$1".zip
118
+cd ~/tmp/"$1"/
119
+
120
+echo "Unziping apk..."
121
+unzip "$1".zip > /dev/null
122
+
123
+echo "Executing dex2jar..."
124
+dex2ar classes.dex 2> /dev/null
125
+
126
+echo "Decompiling ar..."
127
+mkdir -p ~/src/"$1"
128
+decompiler classes-dex2ar.ar ~/src/"$1" > /dev/null
129
+echo "Done. The source code is under ~/src/$1/. You can delete ~/tmp."
130
+```
131
+
132
+Y ale. De este modo, para descomprimir un `apk` sólo habrá que ejecutar:
133
+
134
+```sh
135
+automatic-decompile /ruta/al/apk
136
+```
137
+
138
+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.

+ 28
- 0
content/posts/como-crear-subdominios-en-los-servicios-ocultos-de-tor.md View File

@@ -0,0 +1,28 @@
1
++++
2
+title = "Como crear subdominios en los servicios ocultos de Tor"
3
+author = ["drymer"]
4
+date = 2016-11-03T08:30:00+01:00
5
+tags = ["tor"]
6
+draft = false
7
++++
8
+
9
+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/).
10
+
11
+Un ejemplo tonto, redirigir el subdominio www de daemon4idu2oig6.onion al propio daemon4idu2oig6.onion.
12
+
13
+```nginx
14
+server {
15
+listen 127.0.0.1:80;
16
+server_name  www.daemon4idu2oig6.onion;
17
+return 301 http://daemon4idu2oig6.onion$request_uri;
18
+}
19
+```
20
+
21
+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:
22
+
23
+```lua
24
+Component "salas.daemon4idu2oig6.onion" "muc"
25
+name = "Salas de Bad Daemons"
26
+```
27
+
28
+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á.

+ 139
- 0
content/posts/como-gestionar-las-configuraciones-y-programas-de-tu-ordenador-con-ansible.md View File

@@ -0,0 +1,139 @@
1
++++
2
+title = "Como gestionar las configuraciones y programas de tu ordenador con Ansible"
3
+author = ["drymer"]
4
+date = 2018-01-08T08:30:00+01:00
5
+tags = ["ansible"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+La lista de roles que he hecho y que pueden utilizarse son los siguientes:
12
+
13
+-   [virtualenvwrapper](https://git.daemons.it/ansible-roles/virtualenvwrapper/commits/master)
14
+
15
+-   [syncthing](https://git.daemons.it/ansible-roles/syncthing)
16
+
17
+-   [emacs](https://git.daemons.it/ansible-roles/emacs)
18
+
19
+-   [virtualbox](https://git.daemons.it/ansible-roles/virtualbox)
20
+
21
+-   [qutebrowser](https://git.daemons.it/ansible-roles/qutebrowser)
22
+
23
+-   [termite](https://git.daemons.it/ansible-roles/termite)
24
+
25
+-   [slim](https://git.daemons.it/ansible-roles/slim)
26
+
27
+-   [i3-gaps](https://git.daemons.it/ansible-roles/i3-gaps)
28
+
29
+-   [fonts](https://git.daemons.it/ansible-roles/fonts)
30
+
31
+-   [docker](https://git.daemons.it/ansible-roles/docker)
32
+
33
+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)):
34
+
35
+```text
36
+~/Documentos/ansible/roles/desktop/slim
37
+├── defaults
38
+│   └── main.yml
39
+├── files
40
+│   ├── slim.service
41
+│   └── xinitrc
42
+├── handlers
43
+│   └── main.yml
44
+├── meta
45
+│   └── main.yml
46
+├── README.md
47
+└── tasks
48
+└── main.yml
49
+```
50
+
51
+Están los directorios:
52
+
53
+-   **defaults**: Para definición de variables.
54
+-   **files**: Para ficheros externos al rol.
55
+-   **handlers**: Para el maneo de servicios.
56
+-   **meta**: Para manear metadatos del rol.
57
+-   **tasks**: Para dotar al rol de funcionalidad.
58
+
59
+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:
60
+
61
+```yaml
62
+---
63
+# tasks file for slim
64
+- name: Install slim in debian or derivates
65
+become: yes
66
+apt:
67
+name: slim
68
+state: present
69
+update_cache: yes
70
+
71
+- name: Modify /etc/slim.conf
72
+become: yes
73
+lineinfile:
74
+path: /etc/slim.conf
75
+regexp: "{{ item.regexp }}"
76
+line: "{{ item.line }}"
77
+with_items:
78
+- { regexp: "#? ?numlock", line: "numlock on" }
79
+- { regexp: "#? ?hidecursor", line: "hidecursor true" }
80
+- { regexp: "^login_cmd", line: "login_cmd exec /bin/sh - ~/.xinitrc" }
81
+
82
+- name: Copy slim systemd service
83
+become: yes
84
+copy:
85
+src: "{{ role_path }}/files/slim.service"
86
+dest: /lib/systemd/system/slim.service
87
+force: yes
88
+when:
89
+ansible_connection != 'docker'
90
+or
91
+force_docker == 'yes'
92
+notify:
93
+- disable session manager
94
+- enable slim
95
+```
96
+
97
+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:
98
+
99
+-   `name`: Es el nombre de la tarea, para poder identificarla cuando se ejecute el rol.
100
+
101
+-   `become`: Se usa para escalar privilegios. Por defecto uso `sudo`, pero puede usarse `su`.
102
+
103
+-   `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:
104
+
105
+```bash
106
+sudo apt update
107
+sudo apt install slim -y
108
+```
109
+
110
+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.
111
+
112
+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`.
113
+
114
+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í:
115
+
116
+```yaml
117
+- hosts: localhost
118
+connection: local
119
+vars:
120
+install_dir: ~/Instalados/
121
+roles:
122
+- slim
123
+```
124
+
125
+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.
126
+
127
+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:
128
+
129
+```text
130
+- src: git+https://git.daemons.it/ansible-roles/slim
131
+```
132
+
133
+Una vez creado el fichero, solo hay que ejecutar `ansible-galaxy install -r requirements.txt -p roles`. Y a reusar roles a dos manos.
134
+
135
+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).
136
+
137
+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.
138
+
139
+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).

+ 21
- 0
content/posts/cosillas-de-emacs-aadir-automticamente-smbolos-de-marcado-en-org-mode-emacsorg-mode.md View File

@@ -0,0 +1,21 @@
1
++++
2
+title = "Añadir automáticamente símbolos de marcado en org-mode"
3
+author = ["drymer"]
4
+date = 2016-09-27T09:33:00+02:00
5
+tags = ["orgmode", "emacs"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+Para ello hay que modificar la tabla de sintaxis de **org-mode**:
12
+
13
+```emacs-lisp
14
+(with-eval-after-load 'org
15
+  (modify-syntax-entry ?/ "(/" org-mode-syntax-table)
16
+  (modify-syntax-entry ?* "(*" org-mode-syntax-table)
17
+  (modify-syntax-entry ?_ "(_" org-mode-syntax-table)
18
+  (modify-syntax-entry ?= "(=" org-mode-syntax-table))
19
+```
20
+
21
+Si hacéis cómo yo, que lo primero que hacéis es cargar **org-mode**, el `with-eval-after-load` no hace falta.

+ 39
- 0
content/posts/cosillas-de-emacs-buscar-en-el-buffer.md View File

@@ -0,0 +1,39 @@
1
++++
2
+title = "Buscar en el buffer de emacs"
3
+author = ["drymer"]
4
+date = 2016-05-18T19:18:00+02:00
5
+tags = ["emacs", "helm"]
6
+draft = false
7
++++
8
+
9
+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`.
10
+
11
+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.
12
+
13
+{{< figure src="/img/avy.gif" caption="Figura 1: avy" >}}
14
+
15
+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.
16
+
17
+{{< figure src="/img/ace.gif" caption="Figura 2: ace" >}}
18
+
19
+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.
20
+
21
+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.
22
+
23
+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`.
24
+
25
+Se configura con las siguientes lineas:
26
+
27
+```emacs-lisp
28
+(custom-set-variables
29
+ '(ace-isearch-input-length 7)
30
+ '(ace-isearch-jump-delay 0.25)
31
+ '(ace-isearch-function 'avy-goto-char)
32
+ '(ace-isearch-use-jump 'printing-char))
33
+```
34
+
35
+Y a buscar más eficientemente.
36
+
37
+Más información en su [repositorio git](https://github.com/tam17aki/ace-isearch).
38
+
39
+[La sección](https://daemons.cf/stories/mi-configuracin-de-emacs/#Buscar más eficazmente en Helm) pertinente en mi configuración.

+ 53
- 0
content/posts/cosillas-de-emacs-escapar-simbolos-al-usar-usar-marcado-en-org-mode.md View File

@@ -0,0 +1,53 @@
1
++++
2
+title = "Escapar símbolos al usar marcado en org-mode"
3
+author = ["drymer"]
4
+date = 2016-05-30T09:34:00+02:00
5
+tags = ["orgmode", "emacs"]
6
+draft = false
7
++++
8
+
9
+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`).
10
+
11
+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;.
12
+
13
+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.
14
+
15
+```emacs-lisp
16
+(setq org-pretty-entities t)
17
+
18
+(defun modi/org-entity-get-name (char)
19
+"Return the entity name for CHAR. For example, return \"ast\" for *."
20
+(let ((ll (append org-entities-user
21
+                  org-entities))
22
+      e name utf8)
23
+  (catch 'break
24
+    (while ll
25
+      (setq e (pop ll))
26
+      (when (not (stringp e))
27
+        (setq utf8 (nth 6 e))
28
+        (when (string= char utf8)
29
+          (setq name (car e))
30
+          (throw 'break name)))))))
31
+
32
+(defun modi/org-insert-org-entity-maybe (orig-fun &rest args)
33
+"When the universal prefix C-u is used before entering any character,
34
+insert the character's `org-entity' name if javailable."
35
+(let ((pressed-key (char-to-string (elt (this-single-command-keys) 0)))
36
+      entity-name)
37
+  (when (and (listp args) (eq 4 (car args)))
38
+    (setq entity-name (modi/org-entity-get-name pressed-key))
39
+    (when entity-name
40
+      (setq entity-name (concat "\\" entity-name "{}"))
41
+      (insert entity-name)
42
+      (message (concat "Inserted `org-entity' "
43
+                       (propertize entity-name
44
+                                   'face 'font-lock-function-name-face)
45
+                       " for the symbol "
46
+                       (propertize pressed-key
47
+                                   'face 'font-lock-function-name-face)
48
+                       "."))))
49
+  (when (null entity-name)
50
+    (apply orig-fun args))))
51
+
52
+(advice-add 'org-self-insert-command :around #'modi/org-insert-org-entity-maybe)
53
+```

+ 68
- 0
content/posts/cosillas-de-emacs-escribir-prosa.md View File

@@ -0,0 +1,68 @@
1
++++
2
+title = "Escribir prosa en emacs"
3
+author = ["drymer"]
4
+date = 2016-03-19T02:00:00+01:00
5
+tags = ["orgmode", "emacs"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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.
12
+
13
+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:
14
+
15
+-   Markdown: [markdown-toc](https://github.com/ardumont/markdown-toc) y [markdown-preview-mode](https://github.com/ancane/markdown-preview-mode)
16
+
17
+-   LaTeX: [latex-preview-pane](https://www.emacswiki.org/emacs/LaTeXPreviewPane)
18
+
19
+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.
20
+
21
+Por defecto emacs trunca las líneas largas, con la siguiente línea esto se evita.
22
+
23
+```lisp
24
+;; No truncar
25
+(setq toggle-truncate-lines t)
26
+```
27
+
28
+Seguir los hipervínculos apretando RET.
29
+
30
+```lisp
31
+;; RET or TAB to follow a link
32
+(setq org-return-follows-link t)
33
+(setq org-tab-follows-link t)
34
+```
35
+
36
+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.
37
+
38
+```lisp
39
+;; insert source block
40
+(defun org-insert-src-block (src-code-type)
41
+"Insert a `SRC-CODE-TYPE' type source code block in org-mode."
42
+(interactive
43
+ (let ((src-code-types
44
+        '("emacs-lisp" "python" "C" "sh" "java" "s" "clojure" "C++" "css"
45
+          "calc" "asymptote" "dot" "gnuplot" "ledger" "lilypond" "mscgen"
46
+          "octave" "oz" "plantuml" "R" "sass" "screen" "sql" "awk" "ditaa"
47
+          "haskell" "latex" "lisp" "matlab" "ocaml" "org" "perl" "ruby"
48
+          "scheme" "sqlite")))
49
+   (list (ido-completing-read "Source code type: " src-code-types))))
50
+(progn
51
+  (newline-and-indent)
52
+  (insert (format "#+BEGIN_SRC %s\n" src-code-type))
53
+  (newline-and-indent)
54
+  (insert "#+END_SRC\n")
55
+  (previous-line 2)
56
+  (org-edit-src-code)))
57
+```
58
+
59
+Resaltar la sintaxis de dentro de los bloques de código.
60
+
61
+```lisp
62
+(setq org-src-fontify-natively t)
63
+'(org-fontify-inline-src-block)
64
+```
65
+
66
+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.
67
+
68
+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**.

+ 93
- 0
content/posts/cosillas-de-emacs-un-par-de-funciones-tiles.md View File

@@ -0,0 +1,93 @@
1
++++
2
+title = "Un par de funciones útiles de emacs"
3
+author = ["drymer"]
4
+date = 2016-05-01T01:35:00+02:00
5
+tags = ["emacs", "snippets", "orgmode"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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:
12
+
13
+```emacs-lisp
14
+(defun org-mode-insert-header (language)
15
+"Make a template at point."
16
+(interactive
17
+   (let ((languages '("Generic" "HTML" "LaTeX" )))
18
+     (list (ido-completing-read "To which export: " languages))
19
+     )
20
+   )
21
+
22
+(when (string= language "Generic")
23
+  (progn
24
+    (insert (format "#+TITLE:\n"))
25
+    (insert (format "#+AUTHOR:\n"))
26
+    (insert (format "#+LANGUAGE: es \n"))
27
+    (insert (format "#+OPTIONS: toc:1\n"))
28
+    (insert (format "#+TOC: headlines 3\n"))
29
+    (insert (format "#+STARTUP: indent\n\n"))
30
+      )
31
+  )
32
+
33
+(when (string= language "HTML")
34
+  (progn
35
+    (insert (format "#+TITLE:\n"))
36
+    (insert (format "#+AUTHOR:\n"))
37
+    (insert (format "#+LANGUAGE: ca\n"))
38
+    (insert (format "#+OPTIONS:   toc:1\n"))
39
+    (insert (format "#+TOC: headlines 3\n"))
40
+    (insert (format (concat "#+SETUPFILE: " user-emacs-directory "/css/org-html-themes/setup/theme-readtheorg.setup\n\n")))
41
+    )
42
+  )
43
+
44
+(when (string= language "LaTeX")
45
+  (progn
46
+    (insert (format "#+Title:\n"))
47
+    (insert (format "#+Author:\n"))
48
+    (insert (format "#+LANGUAGE: es\n"))
49
+    (insert (format "#+LATEX_CLASS: article\n"))
50
+    (insert (format "#+LATEX_CLASS_OPTIONS: [spanish,a4paper]\n"))
51
+    (insert (format "#+LATEX_HEADER: \\usepackage{color}\n"))
52
+    (insert (format "#+LATEX_HEADER: \\usepackage[spanish]{babel}\n\n"))
53
+
54
+    )
55
+  )
56
+)
57
+
58
+```
59
+
60
+Lo suyo es modificar el código para que se adecue a las necesidades de quien lo usa.
61
+
62
+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.
63
+
64
+{{< figure src="/img/insert-src.gif" >}}
65
+
66
+El código es:
67
+
68
+```emacs-lisp
69
+(defun org-src-insert (choice)
70
+"Insert src code blocks."
71
+(interactive
72
+   (if (org-at-table-p)
73
+       (call-interactively 'org-table-rotate-recalc-marks)
74
+     (let ((choices '("emacs-lisp" "python" "shell" "css" "ledger" "latex" "lisp" "sqlite")))
75
+       (list (ido-completing-read "Source code type: " choices)))))
76
+
77
+(cond
78
+ ((region-active-p)
79
+  (let ((start (region-beginning))
80
+	  (end (region-end)))
81
+    (progn
82
+	(goto-char end)
83
+	(insert "\n#+END_SRC\n")
84
+	(goto-char start)
85
+	(insert (format "#+BEGIN_SRC %s\n" choice)))
86
+    )
87
+  )
88
+
89
+ (t
90
+  (insert (format "#+BEGIN_SRC %s\n" choice))
91
+  (save-excursion (insert "\n#+END_SRC")))))
92
+
93
+```

+ 28
- 0
content/posts/curso-completo-lfs201.md View File

@@ -0,0 +1,28 @@
1
++++
2
+title = "Curso completo LFS201"
3
+author = ["drymer"]
4
+draft = true
5
++++
6
+
7
+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.
8
+
9
+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.
10
+
11
+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.
12
+
13
+Se puede acceder de distintos modos al curso:
14
+
15
+-   Clonar el repositorio
16
+
17
+    ```sh
18
+    git clone https://daemons.it/drymer/apuntes-LFS201/
19
+    ```
20
+
21
+-   Verlo online
22
+    -   [Apuntes HTML](https://daemons.cf/LFS201/apuntes.html)
23
+
24
+    -   [Apuntes PDF](https://daemons.cf/LFS201/apuntes.pdf)
25
+
26
+    -   [Curso HTML](https://daemons.cf/LFS201/curso-completo.html)
27
+
28
+Probablemente haya alguna falta o esté mal formateado, de ser así agradeceré un correo o un comentario.

+ 35
- 0
content/posts/cutrescript-para-mostrar-posts-de-tags-de-gnu-social.md View File

@@ -0,0 +1,35 @@
1
++++
2
+title = "Cutrescript para mostrar posts de tags de GNU social"
3
+author = ["drymer"]
4
+date = 2017-10-29T17:51:00+01:00
5
+tags = ["python", "gnusocial"]
6
+draft = false
7
++++
8
+
9
+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:
10
+
11
+```python
12
+#!/usr/bin/env python3
13
+# -*- coding: utf-8 -*-
14
+
15
+import requests
16
+import son
17
+import sys
18
+
19
+
20
+server = sys.argv[1]
21
+tag = sys.argv[2]
22
+
23
+nota = 1
24
+posts = requests.get('https://' + server + '/api/statusnet/tags/timeline/' +
25
+               tag + '.son?count=200').text
26
+
27
+posts = son.loads(posts)
28
+
29
+for post in reversed(posts):
30
+print("Nota " + str(nota) + ': ' + post['text'].replace(
31
+  ' #' + tag, ''))
32
+nota += 1
33
+```
34
+
35
+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.

+ 34
- 0
content/posts/editar-archivos-de-un-contenedor-docker-desde-emacs.md View File

@@ -0,0 +1,34 @@
1
++++
2
+title = "Editar archivos de un contenedor docker desde emacs"
3
+author = ["drymer"]
4
+date = 2016-06-19T23:12:00+02:00
5
+tags = ["docker", "emacs"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+```emacs-lisp
12
+(push
13
+ (cons
14
+"docker"
15
+'((tramp-login-program "docker")
16
+  (tramp-login-args (("exec" "-it") ("%h") ("/bin/sh")))
17
+  (tramp-remote-shell "/bin/sh")
18
+  (tramp-remote-shell-args ("-i") ("-c"))))
19
+ tramp-methods)
20
+
21
+(defadvice tramp-completion-handle-file-name-all-completions
22
+(around dotemacs-completion-docker activate)
23
+"(tramp-completion-handle-file-name-all-completions \"\" \"/docker:\" returns
24
+  a list of active Docker container names, followed by colons."
25
+(if (equal (ad-get-arg 1) "/docker:")
26
+    (let* ((dockernames-raw (shell-command-to-string "docker ps | awk '$NF != \"NAMES\" { print $NF \":\" }'"))
27
+           (dockernames (cl-remove-if-not
28
+                         #'(lambda (dockerline) (string-match ":$" dockerline))
29
+                         (split-string dockernames-raw "\n"))))
30
+      (setq ad-return-value dockernames))
31
+  ad-do-it))
32
+```
33
+
34
+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.

+ 35
- 0
content/posts/ejecucin-asncrona-de-bloques-babel-en-org-mode.md View File

@@ -0,0 +1,35 @@
1
++++
2
+title = "Ejecución asíncrona de bloques babel en org-mode"
3
+author = ["drymer"]
4
+date = 2017-05-28T11:23:00+02:00
5
+tags = ["emacs"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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:
12
+
13
+<a id="org3b6e1ac"></a>
14
+
15
+{{< figure src="/img/no-async-babel.gif" >}}
16
+
17
+<a id="org24a915c"></a>
18
+
19
+{{< figure src="/img/async-babel.gif" >}}
20
+
21
+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:
22
+
23
+```emacs-lisp
24
+(add-to-list 'el-get-sources '(:name ob-async
25
+                                    :type github
26
+                                    :pkgname "astahlman/ob-async"))
27
+
28
+(if (not (el-get-package-installed-p 'ob-async))
29
+(el-get 'sync 'ob-async))
30
+
31
+(use-package ob-async
32
+:load-path "el-get/ob-async/")
33
+```
34
+
35
+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.

+ 99
- 0
content/posts/el-get-otro-instalador-de-paquetes.md View File

@@ -0,0 +1,99 @@
1
++++
2
+title = "el-get: Otro instalador de paquetes"
3
+author = ["drymer"]
4
+date = 2016-10-24T11:50:00+02:00
5
+tags = ["emacs"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+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:
12
+
13
+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:
14
+
15
+```lisp
16
+;; Añade la ruta de el-get
17
+(add-to-list 'load-path "~/.emacs.d/el-get/el-get/")
18
+
19
+;; Comprueba si el-get está instalado, sino lo instala desde un gist
20
+(unless (require 'el-get nil 'noerror)
21
+;; Comprobar si existe el fichero a descargar, si existe no lo descarga
22
+(if (not (file-exists-p "/tmp/el-get-install.el"))
23
+(url-copy-file "https://raw.githubusercontent.com/dimitri/el-get/master/el-get-install.el" "/tmp/el-get-install.el"))
24
+(load-file "/tmp/el-get-install.el")
25
+)
26
+
27
+(use-package el-get)
28
+```
29
+
30
+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á.
31
+
32
+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.
33
+
34
+```lisp
35
+(add-to-list 'el-get-sources '(:name xlicense-github
36
+                                 :type github
37
+                                 :pkgname "timberman/xlicense-el"
38
+                                 ))
39
+```
40
+
41
+<div class="src-block-caption">
42
+  <span class="src-block-number">Listado de programa 1</span>
43
+  xlicense
44
+</div>
45
+
46
+```lisp
47
+(add-to-list 'el-get-sources   '(:name org2nikola
48
+                                   :website "https://github.com/redguardtoo/org2nikola.git"
49
+                                   :description "Export org into HTML used by static blog generator nikola."
50
+                                   :type git
51
+                                   :url "https://github.com/redguardtoo/org2nikola.git"
52
+                                   :load-path ("./")
53
+                                   ))
54
+```
55
+
56
+<div class="src-block-caption">
57
+  <span class="src-block-number">Listado de programa 2</span>
58
+  org2nikola
59
+</div>
60
+
61
+```lisp
62
+(add-to-list 'el-get-sources '(:name org-mode-maint
63
+                                 :website "http://orgmode.org/"
64
+                                 :description "Org-mode is for keeping notes, maintaining ToDo lists, doing project planning, and authoring with a fast and effective plain-text system."
65
+                                 :type git
66
+                                 :url "git://orgmode.org/org-mode.git"
67
+                                 :branch "maint"
68
+                                 :load-path ("." "lisp/")
69
+                                 ))
70
+```
71
+
72
+<div class="src-block-caption">
73
+  <span class="src-block-number">Listado de programa 3</span>
74
+  org-mode rama maint
75
+</div>
76
+
77
+```lisp
78
+(add-to-list 'el-get-sources '(:name gnu-social-mode
79
+                               :description "gnu-social client"
80
+                               :type github
81
+                               :pkgname "bashrc/gnu-social-mode"
82
+                               )
83
+         )
84
+```
85
+
86
+<div class="src-block-caption">
87
+  <span class="src-block-number">Listado de programa 4</span>
88
+  gnu-social-mode
89
+</div>
90
+
91
+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.
92
+
93
+De momento hemos añadido las recetas, aún queda instalar los paquetes. Podemos ejecutar en el buffer &lowast;Scratch&lowast; lo siguiente:
94
+
95
+```lisp
96
+(el-get 'sync 'xlicense-github)
97
+```
98
+
99
+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`.

+ 163
- 0
content/posts/el-horrible-mundo-del-empaquetado-para-pypi-queas-y-manual.md View File

@@ -0,0 +1,163 @@
1
++++
2
+title = "El horrible mundo del empaquetado para PyPi (queas y manual)"
3
+author = ["drymer"]
4
+date = 2015-12-14T10:27:00+01:00
5
+tags = ["python"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+{{< figure src="/img/2015-12-09-164548_545x703_scrot.png" >}}
12
+
13
+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.
14
+
15
+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.
16
+
17
+
18
+## Manual {#manual}
19
+
20
+Aquí va el directorio que tengo de gnusrss cómo eemplo, para plantar una base de lo que habia antes del proceso de empaquetado:
21
+
22
+```sh
23
+drymer % torre ~/Instalados/Proyectos/gnusrss $ ls -l
24
+total 84
25
+-rw-r--r-- 1 drymer drymer 14576 dic  5 11:09 gnusrss.py
26
+-rw-r--r-- 1 drymer drymer   620 dic  5 11:06 LICENSE
27
+-rw-r--r-- 1 drymer drymer 12944 dic  7 05:46 README
28
+-rw-r--r-- 1 drymer drymer 13684 dic  7 05:45 README.md
29
+-rw-r--r-- 1 drymer drymer 12710 dic  7 05:45 README.org
30
+```
31
+
32
+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í:
33
+
34
+```python
35
+#!/usr/bin/env python3
36
+
37
+from setuptools import setup
38
+
39
+VERSION = '0.2.1.5'
40
+
41
+setup(name='gnusrss',
42
+        version=VERSION,
43
+        description='Post feeds to GNU Social.',
44
+        long_description=open('README').read(),
45
+        author='drymer',
46
+        author_email='drymer@autistici.org',
47
+        url='http://daemons.it/drymer/gnusrss/about/',
48
+        download_url='http://daemons.it/drymer/gnusrss/snapshot/gnusrss-' + VERSION + '.tar.gz',
49
+        scripts=['gnusrss.py'],
50
+        license="GPLv3",
51
+        bugtrack_url="https://notabug.org/drymer/gnusrss/issues",
52
+        install_requires=[
53
+            "feedparser>=5.0",
54
+            "pycurl>=7.0",
55
+            ],
56
+        classifiers=["Development Status :: 4 - Beta",
57
+                     "Programming Language :: Python",
58
+                     "Programming Language :: Python :: 3",
59
+                     "Programming Language :: Python :: 3.4",
60
+                     "Operating System :: OS Independent",
61
+                     "Operating System :: POSIX",
62
+                     "Intended Audience :: End Users/Desktop"]
63
+        )
64
+```
65
+
66
+Cuidar la identación si se copia tal cual. A continuación explicaré algunas líneas menos obvias.
67
+
68
+-   `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`.
69
+-   `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.
70
+-   `scripts` contiene los ficheros que hay que subir, más allá del propio `README`.
71
+-   `install_requires` contiene las dependencias y su versión.
72
+-   `classifiers` es eso, clasificadores. Si se mira en la propia web de PyPi se puede ver cuales hay. Inventarselos está feo. Yo aviso.
73
+
74
+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.
75
+
76
+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í:
77
+
78
+```ini
79
+[distutils]
80
+index-servers =
81
+    pypi
82
+    pypi-test
83
+
84
+[pypi]
85
+repository=https://pypi.python.org/pypi
86
+username:drymer
87
+password:lalalalalal
88
+
89
+[pypi-test]
90
+repository=https://testpypi.python.org/pypi
91
+username:drymer
92
+password:lolololo
93
+```
94
+
95
+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.
96
+
97
+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.
98
+
99
+
100
+## Queas {#queas}
101
+
102
+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.
103
+
104
+```python
105
+#!/usr/bin/env python3
106
+
107
+from pypandoc import convert
108
+from os import system
109
+from re import search
110
+from sys import argv,exit
111
+
112
+if len(argv) == 1:
113
+    print('Usage: python3 createStupidToc.py README.md README.rst')
114
+    exit()
115
+
116
+README = argv[1]
117
+TMPFILE1 = '/tmp/stupidshit1'
118
+TMPFILE2 = '/tmp/stupidshit2'
119
+
120
+with open(README) as shit:
121
+    shit = shit.read()
122
+
123
+shit = shit[shit.find('# '):]
124
+supershit = ''
125
+shitty = ''
126
+
127
+with open(TMPFILE1, 'w') as tmp:
128
+    for minishit in shit.splitlines():
129
+        result = search('^#', minishit)
130
+        if result != None:
131
+            tmp.write(minishit.split('<')[0] + '\n')
132
+        else:
133
+            tmp.write(minishit + '\n')
134
+# generate the stupid toc to export to rst
135
+system("~/Scripts/createStupidToc.sh /tmp/stupidshit1 /tmp/stupidshit2")
136
+
137
+with open('/tmp/stupidshit2') as stupidshit:
138
+    stupidshit = stupidshit.read()
139
+for shit in stupidshit.splitlines():
140
+    if shit.startswith('<!-- '):
141
+        pass
142
+    else:
143
+        shitty += shit + '\n'
144
+
145
+with open(argv[2], 'w') as rst:
146
+    rst.write(convert(shitty, 'rst', format='md'))
147
+
148
+```
149
+
150
+Muy salchichero, pero funciona. En el fichero `~/Scripts/createStupidToc.sh` hay lo siguiente:
151
+
152
+```sh
153
+#!/bin/bash
154
+
155
+echo "Creating the toc..."
156
+emacs24 -Q $1 --batch -l ~/.emacs.d/init.el -f markdown-toc-generate-toc --eval='(write-file '\"$2\"')' 2>/dev/null
157
+```
158
+
159
+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.
160
+
161
+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.
162
+
163
+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.

+ 163
- 0
content/posts/el-horrible-mundo-del-empaquetado-para-pypi-quejas-y-manual.md View File

@@ -0,0 +1,163 @@
1
++++
2
+title = "El horrible mundo del empaquetado para PyPi (quejas y manual)"
3
+author = ["drymer"]
4
+date = 2015-12-14T10:27:00+01:00
5
+tags = ["python"]
6
+draft = false
7
++++
8
+
9
+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.
10
+
11
+{{< figure src="/img/2015-12-09-164548_545x703_scrot.png" >}}
12
+
13
+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.
14
+
15
+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.
16
+
17
+
18
+## Manual {#manual}
19
+
20
+Aquí va el directorio que tengo de gnusrss cómo ejemplo, para plantar una base de lo que habia antes del proceso de empaquetado:
21
+
22
+```sh
23
+drymer % torre ~/Instalados/Proyectos/gnusrss $ ls -l
24
+total 84
25
+-rw-r--r-- 1 drymer drymer 14576 dic  5 11:09 gnusrss.py
26
+-rw-r--r-- 1 drymer drymer   620 dic  5 11:06 LICENSE
27
+-rw-r--r-- 1 drymer drymer 12944 dic  7 05:46 README
28
+-rw-r--r-- 1 drymer drymer 13684 dic  7 05:45 README.md
29
+-rw-r--r-- 1 drymer drymer 12710 dic  7 05:45 README.org
30
+```
31
+
32
+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í:
33
+
34
+```python
35
+#!/usr/bin/env python3
36
+
37
+from setuptools import setup
38
+
39
+VERSION = '0.2.1.5'
40
+
41
+setup(name='gnusrss',
42
+      version=VERSION,
43
+      description='Post feeds to GNU Social.',
44
+      long_description=open('README').read(),
45
+      author='drymer',
46
+      author_email='drymer@autistici.org',
47
+      url='http://daemons.it/drymer/gnusrss/about/',
48
+      download_url='http://daemons.it/drymer/gnusrss/snapshot/gnusrss-' + VERSION + '.tar.gz',
49
+      scripts=['gnusrss.py'],
50
+      license="GPLv3",
51
+      bugtrack_url="https://notabug.org/drymer/gnusrss/issues",
52
+      install_requires=[
53
+          "feedparser>=5.0",
54
+          "pycurl>=7.0",
55
+          ],
56
+      classifiers=["Development Status :: 4 - Beta",
57
+                   "Programming Language :: Python",
58
+                   "Programming Language :: Python :: 3",
59
+                   "Programming Language :: Python :: 3.4",
60
+                   "Operating System :: OS Independent",
61
+                   "Operating System :: POSIX",
62
+                   "Intended Audience :: End Users/Desktop"]
63
+      )
64
+```
65
+
66
+Cuidar la identación si se copia tal cual. A continuación explicaré algunas líneas menos obvias.
67
+
68
+-   `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`.
69
+-   `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.
70
+-   `scripts` contiene los ficheros que hay que subir, más allá del propio `README`.
71
+-   `install_requires` contiene las dependencias y su versión.
72
+-   `classifiers` es eso, clasificadores. Si se mira en la propia web de PyPi se puede ver cuales hay. Inventárselos está feo. Yo aviso.
73
+
74
+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.
75
+
76
+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í:
77
+
78
+```ini
79
+[distutils]
80
+index-servers =
81
+  pypi
82
+  pypi-test
83
+
84
+[pypi]
85
+repository=https://pypi.python.org/pypi
86
+username:drymer
87
+password:lalalalalal
88
+
89
+[pypi-test]
90
+repository=https://testpypi.python.org/pypi
91
+username:drymer
92
+password:lolololo
93
+```
94
+
95
+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.
96
+
97
+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.
98
+
99
+
100
+## Quejas {#quejas}
101
+
102
+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.
103
+
104
+```python
105
+#!/usr/bin/env python3
106
+
107
+from pypandoc import convert
108
+from os import system
109
+from re import search
110
+from sys import argv,exit
111
+
112
+if len(argv) == 1:
113
+  print('Usage: python3 createStupidToc.py README.md README.rst')
114
+  exit()
115
+
116
+README = argv[1]
117
+TMPFILE1 = '/tmp/stupidshit1'
118
+TMPFILE2 = '/tmp/stupidshit2'
119
+
120
+with open(README) as shit:
121
+  shit = shit.read()
122
+
123
+shit = shit[shit.find('# '):]
124
+supershit = ''
125
+shitty = ''
126
+
127
+with open(TMPFILE1, 'w') as tmp:
128
+  for minishit in shit.splitlines():
129
+      result = search('^#', minishit)
130
+      if result != None:
131
+          tmp.write(minishit.split('<')[0] + '\n')
132
+      else:
133
+          tmp.write(minishit + '\n')
134
+# generate the stupid toc to export to rst
135
+system("~/Scripts/createStupidToc.sh /tmp/stupidshit1 /tmp/stupidshit2")
136
+
137
+with open('/tmp/stupidshit2') as stupidshit:
138
+  stupidshit = stupidshit.read()
139
+for shit in stupidshit.splitlines():
140
+  if shit.startswith('<!-- '):
141
+      pass
142
+  else:
143
+      shitty += shit + '\n'
144
+
145
+with open(argv[2], 'w') as rst:
146
+  rst.write(convert(shitty, 'rst', format='md'))
147
+
148
+```
149
+
150
+Muy salchichero, pero funciona. En el fichero `~/Scripts/createStupidToc.sh` hay lo siguiente:
151
+
152
+```sh
153
+#!/bin/bash
154
+
155
+echo "Creating the toc..."
156
+emacs24 -Q $1 --batch -l ~/.emacs.d/init.el -f markdown-toc-generate-toc --eval='(write-file '\"$2\"')' 2>/dev/null
157
+```
158
+
159
+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.
160
+
161
+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.
162
+
163
+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.

+ 53
- 0
content/posts/emacs-org-mode.md View File

@@ -0,0 +1,53 @@
1
++++
2
+title = "Emacs y org-mode"
3
+author = ["drymer"]
4
+date = 2015-04-03T19:15:00+02:00
5
+draft = false
6
+tags = ["emacs", "org-mode", "elbinario"]
7
++++
8
+# Que te aporta usar org-mode?
9
+
10
+Ú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:
11
+
12
+-   IDE de desarrollo, para programar y tal
13
+-   Editor de texto sencillo. De hecho, me he quitado nano y lo he puesto como alias a emacsclient
14
+-   org-mode
15
+    -   Procesador de textos
16
+    -   Publicación de esos textos
17
+    -   Listas, muchas listas
18
+
19
+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).
20
+
21
+
22
+<a id="orgabd87ac"></a>
23
+
24
+## Procesador de textos
25
+
26
+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.
27
+
28
+![img](./img/2015-09-11-193406_1024x768_scrot.png "Articulo hasta este punto")
29
+
30
+Para exportarlo a otro formato ejecutamos C-c C-e. Ahí nos abrirá un buffer con algo parecido a lo siguiente:
31
+
32
+![img](./img/org-export.png)
33
+
34
+Le damos al HTML, por ejemplo, que serviria para montar una web sencilla. Se puede visualizar aquí:
35
+
36
+<./listings/org-mode.html>
37
+
38
+Sinsillo y para toda la familia.
39
+
40
+
41
+<a id="org8d4fa20"></a>
42
+
43
+## Publicación de estos textos
44
+
45
+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.
46
+
47