Working version of fofum, based on Phantomjs
[fofum.git] / fofum.py
1 import requests
2 import os
3 import json
4 import tempfile
5 import time
6
7 """
8
9 The Fofum class encapsulates feefie events. It can be used to create events,
10 listen on events fire events.
11
12 """
13
14 PHANTOM_PATH = '/usr/bin/phantomjs'
15 FEEFIE_SERVER_URL = "http://www.feefie.com/command"
16
17 CHANNEL_JS="""
18         var page = require('webpage').create();
19         page.open('%s?action=subscribe&hash=%s&html=1',function() {
20         setTimeout(function() {
21             var title = page.evaluate(function () {
22                 return eCount;
23             });
24             console.log(eCount+'###'+payload);
25             phantom.exit();
26         },1000
27         );
28         });
29 """
30
31 class FofumException(Exception):
32     def __init__(self, value):
33         self.value = value
34
35     def __str__(self):
36         return str(self.value)
37         
38
39 class Fofum:
40     def run_action(self, action, hash='', message='',title=''):
41         event = json.dumps({'title':title})
42         params = {'action':action,'hash':hash,'payload':message,'u':self.user,'event':event}
43         return requests.get(FEEFIE_SERVER_URL, params=params)
44
45     def make(self, title):
46         ret_string = self.run_action('add',title=title)
47         try:
48             ret_dict = json.loads(ret_string.text)
49             if (ret_dict['status']!=0):
50                 raise FofumException('Error creating event. Server error.')
51             else:
52                 try:
53                     self.hash = ret_dict['hash']
54                 except KeyError:
55                     raise FofumException('Error creating event. Did not get event spec.')
56         except:
57             raise FofumException('Error creating event. Malformed response: %s'%ret_string.text)
58
59     def subscribe(self):
60         ret_string = self.run_action('subscribe', hash=self.hash)
61         try:
62             ret_dict = json.loads(ret_string.text)
63             if (ret_dict['status']!=0):
64                 raise FofumException('Error creating event. Server error.')
65             else:
66                 try:
67                     self.token = ret_dict['token']
68                 except KeyError:
69                     raise FofumException('Error fetching token. Did not get token spec')
70         except:
71             raise FofumException('Error subscribing to event. Malformed response.')
72
73     def fire(self, payload):
74         print 'Firing %s'%self.hash
75         self.run_action('fire',hash=self.hash,message=payload)
76
77     def listen(self):
78         channel_js = CHANNEL_JS%(FEEFIE_SERVER_URL, self.hash)
79         f = tempfile.NamedTemporaryFile('w')
80         f.write(channel_js)
81         f.flush()
82         print "Hash = %s"%self.hash
83         cmdline = '%s %s'%(PHANTOM_PATH, f.name)
84         conn = os.popen(cmdline)
85         self.series = 0
86         
87         while True:
88             msg = conn.readline()
89             print 'Msg = %s'%msg
90             if ('###' in msg):
91                 status,payload = msg.split('###')
92                 print "Status=%s,Msg=%s"%(status,payload)
93                 status = int(msg[1:])
94                 if (status>self.series):
95                     self.series = status
96                     if (self.callback):
97                         self.callback(payload)
98                 elif (status<0):
99                     break
100         # Returns when connection breaks. Caller needs to resubscribe, relisten
101         return    
102
103     # This method creates/looks up an event, subscribes to it, listens and reconnects if necessary.
104     def listen_on_event(self, event_name, callback):
105         self.callback = callback
106         hash = self.make(event_name)
107
108         stamp = time.time() 
109         while (True):
110             self.subscribe()
111             self.listen()
112             interval = time.time() - stamp
113             if (interval < 5.0):
114                 # Too fast, wait
115                 time.sleep(5.0 - interval)
116                 
117
118     def __init__(self,user=''):
119         # Check phantomjs dependency
120         if (not os.access(PHANTOM_PATH,0)):
121             raise FofumException('Phantomjs not installed.')
122         self.user = user
123
124