sábado, 6 de marzo de 2010

Como controlar el PC desde Twitter en Linux

Llevaba dándole vueltas hace tiempo al tema de controlar mínimamente el servidor de casa desde dentro. Primero pensé en una serie de correitos a través de GMail, pero después pensé en hacerlo
utilizando Twitter. Todos esto me surgió por varios motivos: el router hay veces que se queda colgado y no me entero, pero lo curioso es que si que tiene acceso al exterior, últimamente me
salta el automático de casa con demasiada frecuencia y claro si estoy fuera pues se me estropea lo que hay en la nevera y mi acuario también sufre bastante.

Me puse a buscar a ver si existía algún programa que me lo permitiera, más que nada para no reinventar la rueda (aunque esto suela ser divertido), y claro encontré esto . El problema es que funciona sólo en Windows (hay que ser gañan en los tiempos que vivimos), y no encontré nada parecido que funcionase en mi Ubuntu.

Encontré este API para python, así que manos a la obra, además python no puede ser muy dificil.

Antes de nada es muy importante que la cuenta de Twitter que se use no sea pública porque si no todo el mundo va a poder controlar el PC. Yo de momento los comandos que le he añadido son un ping, uno para obtener la IP (pública y privada), varios para gestionar el router.

Añadir un comando es tan fácil como definir una función que se llama comando_command, y dentro de esta función llamar al comando que queramos.

Luego se añade este script al cron para que lo ejecute cada X minutos y ya esta, controlando el PC desde fuera de casita con comando del tip 'rc ping', 'rc ip', etc...

Ahora sólo hay que mandar un mensaje privado a la cuenta que vamos a usar de la forma 'rc comando' y a esperar el resultado.

Aquí dejo el script:

import twitter
import os
import socket
import urllib2
import fcntl
import struct
import cStringIO
import tokenize
import string



global api

usuario='usuario_twitter'
passwd='password_twitter'
tmp_file='/tmp/twmylin.tmp'

old_id=0

def set_old_id(id):
f = open(tmp_file, 'w')
f.write(str(id))

def get_old_id():
try:
f = open(tmp_file, 'r')
id = int(f.readline())
except Exception:
id = 0
return id



def get_interface_ip(ifname):

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

return socket.inet_ntoa(fcntl.ioctl(

s.fileno(),

0x8915, # SIOCGIFADDR

struct.pack('256s', ifname[:15])

)[20:24])

def get_lan_ip():

ip = socket.gethostbyname(socket.gethostname())

if ip.startswith("127.") and os.name != "nt":

interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]

for ifname in interfaces:

try:

ip = get_interface_ip(ifname)

break;

except IOError:

pass

return ip
def send_twitter(m):
msg='#twmylin '+ m
status = api.PostUpdate( msg)

def ping_command(tokens):
send_twitter('Estoy vivo')

def ip_command(tokens):
pub_ip='not found'
try:
pub_ip = urllib2.urlopen("http://whatismyip.com/automation/n09230945.asp").read()
except Exception:
pass

send_twitter('int:' + get_lan_ip() + ', pub:' + pub_ip)


def top_command(tokens):
s = 'top: error'
try:
f = os.popen("top -b -n1")
for i in range(0, 5):
send_twitter (f.readline())
except Exception:
send_twitter(s)


def router_check_command(tokens):
s = 'router_check: error'
try:
f = os.popen("/data/bin/router_check.sh")
f = os.popen("tail -n2 /data/bin/router_stat.txt")
s=''
for i in range(0, 2):
s+= f.readline()
except Exception:
pass

send_twitter(s)

def router_sincro_command(tokens):
s = 'router_connect: error'
try:
s = "try router_sincro"
send_twitter(s)
f = os.popen("/data/bin/router_sincro.sh")
except Exception:
pass

def router_reboot_command(tokens):
s = 'router_reboot: error'
try:
s = "try router_reboot"
send_twitter(s)
f = os.popen("/data/bin/router_reboot.sh")
except Exception:
pass

# Main
api = twitter.Api(username=usuario, password=passwd)

old_id=get_old_id()

status=api.GetDirectMessages()


for s in status:
if s.id > old_id:
old_id=s.id
set_old_id(old_id)
tokens = list(tokenize.generate_tokens(cStringIO.StringIO(s.text).readline))
if tokens[0][0] ==1 and tokens[0][1] == 'rc':
globals()[tokens[1][1]+'_command'](tokens)


No hay comentarios: