Archivo

Archivo para la categoría ‘Bash’

Club2020 de Vodafone… enviar SMS desde la consola

Miércoles, 16 de Diciembre de 2009 admin Sin comentarios

club2020No vengo a hablaros de la empresa Vodafone, ni del concurso (que podéis entrar desde este enlace y no tenéis que ser de Vodafone). Es un concurso rasca y gana (aunque cada cierto tiempo hay concursos parecidos; en el que uno de los premios son SMS gratis.

Hasta ahí bien, el problema viene a la hora de gastar los SMS, y es que mientras entro en la web (todo hecho en flash), se carga la intro, me la salto, se carga la web, me identifico, pulso en enviar mensajes, escribo el número, el mensaje y envío echo unos 3 minutos, y para el SMS tardo menos desde el móvil.

He hecho un pequeño script para consola que lo hace todo solo, y además en unos 10 segundos (como mucho) está mandado el mensaje… esto también nos permitirá enviar muchos mensajes seguidos (y si queremos usarlo para felicitar las fiestas, nos vendrá genial).

Nota: Antes de postear el código, quiero decir una cosa (NO hago comprobación de las letras de los mensajes, que son algo menos de 160 caracteres), ni de los parámetros (explicados al final) devuelvo el texto de enviado y no enviado, aunque eso no significa que se haga de verdad (ya sabéis cómo andan los SMS incluso en este 2009); por otra parte, si Vodafone corta el servicio o introduce alguna modificación en la página… ¡mala suerte! se nos acabó esto, pero quise compartir este código (y tal vez podamos hacer más cosa en el futuro con él).

Nota 2: Requiere cURL (sin él habría sido una matanza de código)

Nota 3: No está muy comentado, pero si hay alguna duda, siempre tendremos los manuales de cURL, de bash, y los comentarios en este post :)

Ahí va:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/bin/bash

MOVIL_USR={mi movil}
CLAVE_USR={mi clave club2020}

function strpos()
{
str=${1/$2*/}
if [[ -z "$1" ]]; then
cad1l=0
else
cad1l=`expr length "$1"`
fi

if [[ -z "$str" ]]; then
donde=0;
else
donde=`expr length "$str"`
fi
if (( $donde < $cad1l )); then
echo $donde
else
echo -1
fi
}

echo "Identificándonse en el sistema..."
#Envio de datos
login="accion=login&clave%5Fusr="$CLAVE_USR"&movil%5Fusr="$MOVIL_USR
data=`curl -s -L -b cookies.txt -c cookies.txt "http://club2020.mi.vodafone.es/rascaygana/actuar.php?"$login`

# Usé esto para obtener los datos a mano hace un rato
#echo $data>tmp
#data=`cat tmp`

# Almacenamos en un array  los datos que nos ha mandado la web
i=1
datos[${i}]=`echo $data | cut -d"&" -f $i`;

while [[ -n ${datos[${i}]} ]]; do let i=$i+1; datos[$i]=`echo $data | cut -d"&" -f $i`; done
#Recorremos el array para mirar las opciones recibidas
datosrecibidos=${#datos[*]}

for ((i=0;i<$datosrecibidos;i++)); do
if (( `strpos ${datos[${i}]} =` > -1 )); then
combo=${datos[${i}]}
clave=`echo $combo | cut -d"=" -f1`
valor=`echo $combo | cut -d"=" -f2`
if [[ $clave == "usuario" ]]; then
usuario=$valor;
elif [[ $clave == "nombre" ]]; then
nombre=$valor;
elif [[ $clave == "tarjetas" ]]; then
tarjetas=$valor;
elif [[ $clave == "mensajes" ]]; then
mensajes=$valor;
fi
fi
done

echo "Hola "$nombre" te quedan "$mensajes" mensajes y tienes "$tarjetas" por rascar"
mensaje=$2
destinatario=$1
echo "Enviando mensaje: "$mensaje" a "$destinatario"..."
postdata="accion=mandarSms&mensaje="$mensaje"&destinatario="$destinatario"&firma="$usuario

#Envio de datos
result=`curl -s -L -b cookies.txt -c cookies.txt -d "$postdata" 'http://club2020.mi.vodafone.es/rascaygana/actuar.php'`

#echo $result > tmp2
result="retorno"`cat tmp2`
i=1
resdata[${i}]=`echo $result | cut -d"&" -f $i`;

while [[ -n ${resdata[${i}]} ]]; do let i=$i+1; resdata[$i]=`echo $result | cut -d"&" -f $i`; done
#Recorremos el array para mirar las opciones recibidas
resdatarecibidos=${#resdata[*]}

for ((i=0;i<$resdatarecibidos;i++)); do
if (( `strpos "${resdata[${i}]}" =` > -1 )); then
combo=${resdata[${i}]}
clave=`echo $combo | cut -d"=" -f1`
valor=`echo $combo | cut -d"=" -f2`
if [[ $clave == "error" ]]; then
error=$valor;
elif [[ $clave == "mensajes" ]]; then
mensajes=$valor;
fi

fi

done

echo "Resultado de la operación: "$error" Quedan "$mensajes" mensajes"
echo "Cerrando sesión..."

#Envio de datos
curl -s -L -b cookies.txt -c cookies.txt 'http://club2020.mi.vodafone.es/rascaygana/actuar.php?accion=logout' >/dev/null

Si guardamos este archivo como sms2020 y le damos permiso de ejecución, el primer parámetro es el móvil del destinatario, y el segundo el mensaje (entrecomilladlo si tiene espacios). Además, en la parte de arriba del archivo encontramos MOVIL_USR y CLAVE_USR, tendréis que poner vuestro número de móvil y vuestra clave del club2020 (para poder identificaros en el sistema).
Nota 4: Pude optimizar un poco el código, pero como había prisa y no sé lo que durará esto, no quise calentarme mucho el coco.
Nota 5: Para registrase: seguid este link (así me dais sms gratis a mí también, porque los demás premios nunca tocan).

Script para subir archivos rápidamente (y actualizarlos)

Jueves, 13 de Agosto de 2009 admin 2 comentarios

Normalmente, cuando estoy desarrollando aplicaciones para Facebook, primero, las hago Offline, ejecutándolas en mi servidor local y, una vez que funcionan, las subo al servidor desde las que se ejecutarán, aunque muchas veces hay ciertos problemas una vez se está ejecutando la aplicación de forma definitiva, que requieren hacer algunas modificaciones más, y con esto, subir varias veces los archivos de los scripts.

Por otra parte, a veces, en ciertas aplicaciones web, es necesario introducir cierta información nueva (que hago fuera de línea) y cuando todas las novedades han sido introducidas procedo a subirlo todo junto.

También es importante, sobre todo para proyectos más o menos grandes, que sólo se suban al servidor los archivos nuevos o modificados antes de la última actualización, es muy importante, ya que la ejecución puede eternizarse si tenemos que subir 10Mb de datos cada vez que queremos actualizar, por lo tanto, almacenamos en un archivo el momento en que se ejecutó el script por última vez, y cada vez que buscamos archivos, lo hacemos con los que han sido actualizados a partir del momento que almacenamos en el fichero anterior.

Para eso creé este script (aún queda mucho trabajo por hacer), pero por ahora hace bastante bien el apaño. Yo llamo a este archivo (autoftp):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/bin/bash

servidor=$1
ruta_serv=$2
ruta_local=$3
endline="
"

dir_actual=`pwd`
cd $3

if [ -e $ruta_local"/last_update" ]; then
    f_locales=`find . -newer $ruta_local/last_update`
else
    f_locales=`find .`
fi

function cierratodo()
{
    kill $ftp_pid
    kdialog --msgbox $1
}

function estadoman()
{
    while read estado
    do
        estadonum=`echo $estado | cut -d' ' -f1`
        echo $estado
        if [[ $estado != "Not connected" ]]; then
            if [[ $estadonum == "226" ]]; then
                subidos=$(($subidos+1))
                kdialog --passivepopup "Subido archivo "$subidos" de "$total_archivos 2
            elif [[ $estadonum == "221" ]]; then
                cierratodo "Los archivos se subieron con éxito"
                date +%s > $ruta_local"/last_update"
            # Fin del programa
               
            fi
        else
            echo "Cerrandooo"
            cierratodo "La conexión se cerró inesperadamente"
        fi
    done
}

to_do="pass"$endline"cd $ruta_serv"$endline;
last_dir="";
total_archivos=0
for i in $f_locales
do
        arch_relat=${i:2}
        if [ ! -z $arch_relat ]; then
            nombre_dir=`dirname $arch_relat`
            if [[ $nombre_dir == "." ]]; then
                nombre_dir=""
            fi
                if [ -d $arch_relat ]; then
                    to_do=$to_do"cd $ruta_serv/$nombre_dir"$endline
                    to_do=$to_do"mkdir $ruta_serv/$arch_relat"$endline
                else
#                   echo "*"$nombre_dir"="$last_dir"*";
                    if [[ $last_dir != $nombre_dir ]]; then
                        last_dir=$nombre_dir
                        to_do=$to_do"cd $ruta_serv/$nombre_dir"$endline
                    fi

                    to_do=$to_do"put $ruta_local/$arch_relat "`basename $arch_relat`$endline
                    total_archivos=$(($total_archivos+1))
#                     to_do=$to_do"put $3/$arch_relat\n"
                   echo "FICHERO --- $arch_relat";
                fi
        fi
done

OLDIFS=$IFS
IFS="
"

to_do=$to_do"quit"$endline

if [[ $total_archivos > 0 ]]; then
    for j in $to_do ; do echo $j;done;

    rm /tmp/ftp_pipe > /dev/null 2>&1
    mkfifo /tmp/ftp_pipe > /dev/null 2>&1

ftp -v totaki.com > /tmp/ftp_pipe <<EOF &
`for j in $to_do ; do echo $j;done;`
EOF

    ftp_pid=$!

else
    kdialog --msgbox "No hay archivos para subir"
fi
cd $dir_actual
IFS=$OLDIFS

rm /tmp/ftp_pipe > /dev/null 2>&1

Para su uso, son necesarios tres parámetros:

  • Dirección del servidor
  • Ruta donde se colocan los archivos en el directorio remoto
  • Ruta de donde se buscarán los archivos en el directorio local

Requerimientos:

  • kdialog (Se puede modificar el script para utilizar otro fácilmente)
  • ftp (Este programa se encargará de subir los archivos)

Para configurar el script es necesario editar el archivo .netrc localizado en nuestro home y donde irá el nombre de usuario y contraseña del FTP (este fichero es leído por ftp automáticamente y así no necesitamos incluir passwords ni en la línea de comando ni en el propio script, que quedan muy feos). El fichero .netrc tiene la siguiente estructura:

machine [servidor] login [usuario] password [contraseña]

Por ejemplo podemos hacer un .netrc que contenga:

machine www.servidor.com login pepito password josefina

Una vez completado esto, podemos asociar una tecla al script, y con ello simplemente pulsando esa tecla se subirán los archivos al servidor.
Por último, yo lo tengo configurado en Fluxbox con Mod4+F5 o lo que es lo mismo la tecla de Windows y F5; basta con crear un script lanzador que incluya lo siguiente (yo lo llamo ftp_upload):

1
2
3
4
#!/bin/bash
# Modelo
#/home/gaspy/.scripts/autoftp [servidor] [ruta interna] [ruta_local]
#/home/gaspy/.scripts/autoftp ftp.servidor.com http_docs/pruebas /home/yomismo/proyectos/pruebas

añadir al fichero keys dentro de /home/[usuario]/.fluxbox/ la siguiente línea:

Mod4 F5 :execcommand ~/.scripts/ftp_upload

Tuberías con nombre para comunicación entre procesos

Domingo, 19 de Julio de 2009 blakeyed Sin comentarios

Las tuberías con nombre son un método de comunicación FIFO entre procesos (también se les llama fifos). FIFO son las siglas de First In First Out, es decir, el primero que llega es que primero que se marcha, como en una cola, el primero que llega es el que antes termina.

Observad lo que hacen las macros depura_int y depura_string, nos darán el número de línea y el archivo donde están, así como el nombre de la variable y el valor que tiene en ese momento.

Normalmente las tuberías son anónimas, aunque el hecho de tenerlas con un nombre en nuestro sistema de ficheros puede sernos de gran utilidad. Como ejemplo, podemos verlo en funcionamiento en la siguiente imagen:

Cómo hacer una pipe con nombre en 1 minuto

Cómo hacer una pipe con nombre en 1 minuto

Primero vemos el terminal de abajo, en el que se ejecuta lo siguiente:

1
2
$ mkfifo prueba
$ cat prueba

Seguidamente en el otro terminal se escribe lo siguiente:

1
$ echo "Esto es una prueba" > prueba

Automáticamente el texto “Esto es una prueba” aparece en el primer terminal. ¡Hemos logrado enviar un mensaje!

De la misma forma podemos programar aplicaciones que utilicen estas características de forma muy fácil en casi cualquier lenguaje de programación, para los ejemplos utilizaré C. Debemos hacer dos programas, uno que escriba en la tubería (pipe) y otro que lea de ella. Empezamos por pipewrite.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
  FILE *mipipe;
  char buffer[128];
  int i=0;

  if (mkfifo("pipetest", S_IWUSR |  /* El usuario puede escribir */
                 S_IRUSR |  /* El usuario puede leer */
                 S_IRGRP |  /* El grupo puede leer */
                     S_IROTH    /* Otros pueden leer */
         )!=0)
    printf ("Hubo un problema al crear la pipe\n");

  mipipe=fopen("pipetest", "w"); /* Lo abrimos como un fichero normal y corriente */

  /* Con esta línea leemos hasta que se cierre la tubería por el otro */

  while (i<10)
    {
      sprintf(buffer, "CADENA ENVIADA Número: %i\n", i+1);
      fputs(buffer, mipipe);
      i++;
    }

  fclose(mipipe);       /* Cerramos la tubería por aquí también */

Y ahora pipecilla.c (o el programa que leerá la pipe):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
  FILE *mipipe;
  char buffer[128];
  if (mkfifo("pipetest", S_IWUSR |  /* El usuario puede escribir */
                 S_IRUSR |  /* El usuario puede leer */
                 S_IRGRP |  /* El grupo puede leer */
                     S_IROTH    /* Otros pueden leer */
         )!=0)
    printf ("Hubo un problema al crear la pipe\n");

  mipipe=fopen("pipetest", "r"); /* Lo abrimos como un fichero normal y corriente */

  /* Con esta línea leemos hasta que se cierre la tubería por el otro */
  while (!feof(mipipe))      
    {
      if (fgets(buffer, 128, mipipe))
      printf ("RECIBIDO: %s", buffer);
    }

  fclose(mipipe);       /* Cerramos la tubería por aquí también */
}

Ahora compilamos y ejecutamos en terminales diferentes de nuevo:
Probando pipes
En el terminal de pipewrite.c, al ejecutar el programa da un mensaje de error, es porque la pipe ya existe (se creó en el programa anterior).

Esta forma de comunicación es unidireccional, puede ser últil por ejemplo para publicar el estado de un programa (un reproductor de audio podría publicar la canción que está sonando como en xmms-infopipe), o para modificar el comportamiento de un software mientras éste está en ejecución. Pero si queremos que nuestras aplicaciones dialoguen (en full-duplex), debemos tener dos pipes simultáneas, en ese caso, la aplicación 1, por ejemplo deberá leer en la tubería 1 y escribir en la tubería 2; y la aplicación 2, deberá escribir en la tubería 1 y leer en la tubería 2.

Decir la hora en palabras (v1)

Jueves, 28 de Mayo de 2009 blakeyed 3 comentarios

Si tenéis un equipo Linux que actúe como servidor y equipo de música (por poner algo), y no tenga un monitor conectado en todo momento; os puede ser útil este script:

1
2
3
4
5
6
7
8
#!/bin/bash

hora=`date +%H`
min=`date +%M`

decir="Son las "$hora" y "$min

echo $decir | espeak -ves

Si asociamos este script a una combinación de teclas, por los altavoces nos dirá la hora que es. Es muy útil en ocasiones :) A artir de aquí se puede extender tanto como se quiera: por ejemplo para que diga la hora en un lenguaje más coloquial: Son las tres menos cuarto, por ejemplo. Es cuestión de imaginación.

Requiere del sintetizador espeak aunque no debe ser difícil utilizar festival u otros.

Espero que os sea de gran ayuda

Categories: Bash, Linux Tags: , , , ,
Easy AdSense by Unreal