#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2010 Maurizio Porrato # See LICENSE.txt for copyright info from __future__ import with_statement from frn.protocol.client import FRNClient, FRNClientFactory from frn.user import FRNUser from twisted.internet import reactor, task from twisted.internet.defer import DeferredList from twisted.python import log import os, string safe_chars = string.ascii_letters+string.digits+' :;.,+-=$@' PARROT_AUDIO_DELAY = 5.0 def sanitizeFilename(name): r = '' for c in name: if c in safe_chars: r += c return r class FRNParrot(FRNClient): def getClientName(self, client_id): if self.clientsById.has_key(client_id): return self.clientsById[client_id]['on'] else: return client_id def textMessageReceived(self, client, message, target): log.msg("Type %s message from %s: %s" % (target, self.getClientName(client), message)) if target == 'P': # Only reply to private messages if not message.startswith('play'): self.sendTextMessage(client, message) else: cmd = message.split() if len(cmd) > 1: message = sanitizeFilename(cmd[1]) else: message = 'monkeys' filename = 'sounds/%s.wav' % message if os.path.exists(filename): log.msg("Streaming file %s" % filename) with file(filename, 'rb') as sf: sf.seek(0x3c) # Skip wav header while True: b = sf.read(325) if len(b) < 325: break self.feedStreaming(b) self.factory.reactor.callLater(0.5, self.startStreaming) else: self.sendTextMessage(client, "File not found") def stopTransmission(self): FRNClient.stopTransmission(self) log.msg("Stopped playback.") def startRepeating(self, from_id): log.msg("%s stopped talking: starting playback." % self.clients[from_id-1]['on']) self.startStreaming() def audioFrameReceived(self, from_id, frames): recname = sanitizeFilename(self.clients[from_id-1]['on']) with file('recordings/%s.gsm' % recname, 'ab') as f: f.write(frames) self.feedStreaming(frames) try: self.parrot_timer.reset(PARROT_AUDIO_DELAY) except: log.msg("%s started talking" % self.clients[from_id-1]['on']) self.parrot_timer = self.factory.reactor.callLater( PARROT_AUDIO_DELAY, self.startRepeating, from_id) self.pong() def loginResponse(self, info): log.msg("Login: %s" % info['al']) def clientsListUpdated(self, clients): self.clients = clients self.clientsById = dict([(i['id'], i) for i in clients]) class FRNParrotFactory(FRNClientFactory): protocol = FRNParrot reactor = reactor if __name__ == '__main__': import sys from os.path import dirname, join as pjoin from ConfigParser import ConfigParser log.startLogging(sys.stderr) basedir = dirname(__file__) acfg = ConfigParser() acfg.read(['/etc/grn/accounts.conf', pjoin(basedir,'accounts.conf'), 'accounts.conf']) scfg = ConfigParser() scfg.read(['/etc/grn/servers.conf', pjoin(basedir,'servers.conf'), 'servers.conf']) argc = len(sys.argv) if argc >= 3: server_name, network_name = sys.argv[2].split(':',1) account_cfg = acfg.items(sys.argv[1])+[('network', network_name)] server_cfg = scfg.items(server_name) server = scfg.get(server_name, 'server') port = scfg.getint(server_name, 'port') d = dict(account_cfg) user = FRNUser( EA=d['email'], PW=d['password'], ON=d['operator'], BC=d['transmission'], DS=d['description'], NN=d['country'], CT=d['city'], NT=d['network']) reactor.connectTCP(server, port, FRNParrotFactory(user)) reactor.run() # vim: set et ai sw=4 ts=4 sts=4: