manager: fix unicode regression
[grn.git] / parrot.py
blobde7a1792b3b2e0cbfd14b1d51867b43b9cb7be43
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
5 # See LICENSE.txt for copyright info
7 from __future__ import with_statement
8 from frn.protocol.client import FRNClient, FRNClientFactory
9 from frn.user import FRNUser
10 from twisted.internet import reactor, task
11 from twisted.internet.defer import DeferredList
12 from twisted.python import log
13 import os, string
14 safe_chars = string.ascii_letters+string.digits+' :;.,+-=$@'
16 PARROT_AUDIO_DELAY = 5.0
18 def sanitizeFilename(name):
19 r = ''
20 for c in name:
21 if c in safe_chars:
22 r += c
23 return r
26 class FRNParrot(FRNClient):
28 def getClientName(self, client_id):
29 if self.clientsById.has_key(client_id):
30 return self.clientsById[client_id]['ON']
31 else:
32 return client_id
34 def textMessageReceived(self, client, message, target):
35 log.msg("Type %s message from %s: %s" %
36 (target, self.getClientName(client), message))
37 if target == 'P': # Only reply to private messages
38 if not message.startswith('play'):
39 self.sendTextMessage(client, message)
40 else:
41 cmd = message.split()
42 if len(cmd) > 1:
43 message = sanitizeFilename(cmd[1])
44 else:
45 message = 'monkeys'
46 filename = 'sounds/%s.wav' % message
47 if os.path.exists(filename):
48 log.msg("Streaming file %s" % filename)
49 with file(filename, 'rb') as sf:
50 sf.seek(0x3c) # Skip wav header
51 while True:
52 b = sf.read(325)
53 if len(b) < 325:
54 break
55 self.feedStreaming(b)
56 self.factory.reactor.callLater(0.5,
57 self.startStreaming)
58 else:
59 self.sendTextMessage(client, "File not found")
61 def stopTransmission(self):
62 FRNClient.stopTransmission(self)
63 log.msg("Stopped playback.")
65 def startRepeating(self, from_id):
66 log.msg("%s stopped talking: starting playback." %
67 self.clients[from_id-1]['ON'])
68 self.startStreaming()
70 def audioFrameReceived(self, from_id, frames):
71 recname = sanitizeFilename(self.clients[from_id-1]['ON'])
72 with file('recordings/%s.gsm' % recname, 'ab') as f:
73 f.write(frames)
74 self.feedStreaming(frames)
75 try:
76 self.parrot_timer.reset(PARROT_AUDIO_DELAY)
77 except:
78 log.msg("%s started talking" %
79 self.clients[from_id-1]['ON'])
80 self.parrot_timer = self.factory.reactor.callLater(
81 PARROT_AUDIO_DELAY, self.startRepeating, from_id)
82 self.pong()
84 def loginResponse(self, info):
85 log.msg("Login: %s" % info['AL'])
87 def clientsListUpdated(self, clients):
88 self.clients = clients
89 self.clientsById = dict([(i['ID'], i) for i in clients])
92 class FRNParrotFactory(FRNClientFactory):
93 protocol = FRNParrot
94 reactor = reactor
97 if __name__ == '__main__':
98 import sys
99 from os.path import dirname, join as pjoin
100 from ConfigParser import ConfigParser
102 log.startLogging(sys.stderr)
104 basedir = dirname(__file__)
106 acfg = ConfigParser()
107 acfg.read(['/etc/grn/accounts.conf',
108 pjoin(basedir,'accounts.conf'), 'accounts.conf'])
110 scfg = ConfigParser()
111 scfg.read(['/etc/grn/servers.conf',
112 pjoin(basedir,'servers.conf'), 'servers.conf'])
114 argc = len(sys.argv)
115 if argc >= 3:
116 server_name, network_name = sys.argv[2].split(':',1)
117 account_cfg = acfg.items(sys.argv[1])+[('network', network_name)]
118 server_cfg = scfg.items(server_name)
119 server = scfg.get(server_name, 'server')
120 port = scfg.getint(server_name, 'port')
122 d = dict(account_cfg)
123 user = FRNUser(
124 EA=d['email'],
125 PW=d['password'], ON=d['operator'],
126 BC=d['transmission'], DS=d['description'],
127 NN=d['country'], CT=d['city'], NT=d['network'])
128 reactor.connectTCP(server, port, FRNParrotFactory(user))
129 reactor.run()
132 # vim: set et ai sw=4 ts=4 sts=4: