Package pinder :: Module room

Source Code for Module pinder.room

  1  """ 
  2  Handles the Campfire room. 
  3  """ 
  4  from datetime import datetime 
  5  import re 
  6  import time 
  7  import urlparse 
  8   
  9  from BeautifulSoup import BeautifulSoup 
 10   
11 -class Room(object):
12 "A Campfire room."
13 - def __init__(self, campfire, id, name=None):
14 self._campfire = campfire 15 self._verify_response = campfire._verify_response 16 self._post = campfire._post 17 self._get = campfire._get 18 self._room = None 19 20 self.membership_key = self.user_id = None 21 self.last_cache_id = self.timestamp = None 22 self.idle_since = datetime.now() 23 24 #: The room id. 25 self.id = id 26 #: The name of the room. 27 self.name = name 28 #: The U{urlparsed<http://docs.python.org/lib/module-urlparse.html#l2h-4268>} URI of the room. 29 self.uri = urlparse.urlparse("%s/room/%s" % (urlparse.urlunparse(self._campfire.uri), self.id))
30
31 - def __repr__(self):
32 return "<Room: %s>" % self.name
33
34 - def __eq__(self, other):
35 return self.id == other.id
36
37 - def join(self, force=False):
38 """Joins the room; if 'force' is True join even if already joined. 39 40 Returns True if successfully joined, False otherwise. """ 41 if not self._room or force: 42 self._room = self._get("room/%s" % self.id) 43 if not self._verify_response(self._room, success=True): 44 self._room = None 45 return False 46 self._get_room_data() 47 self.ping() 48 return True
49
50 - def leave(self):
51 """Leaves the room. 52 53 Returns True if successfully left, False otherwise.""" 54 has_left = self._verify_response( 55 self._post('room/%s/leave' % self.id), redirect=True) 56 self._room = self.membership_key = self.user_id = None 57 self.last_cache_id = self.timestamp = self.idle_since = None 58 return has_left
59
60 - def toggle_guest_access(self):
61 """Toggles guest access on and off. 62 63 Returns True if successfully toggled, False otherwise.""" 64 response_result = self._verify_response( 65 self._post( 66 'room/%s/toggle_guest_access' % self.id), success=True) 67 68 # go back inside to toggle the guest access 69 return response_result and self.join(True)
70
71 - def guest_access_enabled(self):
72 """Checks if the guest access is enabled. 73 74 Returns True if the guest access is enabled, False otherwise.""" 75 return self.guest_url() is not None
76
77 - def guest_url(self):
78 """Gets the URL for guest access. 79 80 Returns None if the guest access is not enabled.""" 81 self.join() 82 soup = BeautifulSoup(self._room.body) 83 try: 84 return soup.find('div', {'id': 'guest_access_control'}).h4.string 85 except AttributeError: 86 return None
87
88 - def guest_invite_code(self):
89 """Gets the invite code for guest access. 90 91 Returns None if the guest access is not enabled.""" 92 url = self.guest_url() 93 if url: 94 return re.search(r'\/(\w*)$', url).groups(0)[0]
95
96 - def change_name(self, name):
97 """Changes the name of the room. 98 99 Returns the new name if successfully changed, None otherwise.""" 100 response = self._post('account/edit/room/%s' % self.id, 101 {'room[name]': name}, ajax=True) 102 if self._verify_response(response, success=True): 103 self.name = name 104 return self.name
105 rename = change_name 106
107 - def change_topic(self, topic):
108 """Changes the topic of the room. 109 110 Returns the new topic if successfully changed, None otherwise.""" 111 response = self._post('room/%s/change_topic' % self.id, 112 {'room[topic]': topic}, ajax=True) 113 if self._verify_response(response, success=True): 114 return topic
115
116 - def topic(self):
117 """Gets the current topic, if any.""" 118 self.join() 119 soup = BeautifulSoup(self._room.body) 120 h = soup.find(attrs={'id': 'topic'}) 121 if h: 122 def _is_navigable_string(tag): 123 return not hasattr(tag, 'attrs')
124 topic = filter(_is_navigable_string, h.contents) 125 return repr("".join(topic).strip())
126
127 - def lock(self):
128 """Locks the room to prevent new users from entering. 129 130 Returns True if successfully locked, False otherwise.""" 131 return self._verify_response(self._post( 132 'room/%s/lock' % self.id, {}, ajax=True), success=True)
133
134 - def unlock(self):
135 """Unlocks the room. 136 137 Returns True if successfully unlocked, False otherwise.""" 138 return self._verify_response(self._post( 139 'room/%s/unlock' % self.id, {}, ajax=True), success=True)
140
141 - def ping(self, force=False):
142 """Pings the server updating the last time we have been seen there. 143 144 Returns True if successfully pinged, False otherwise.""" 145 now = datetime.now() 146 delta = self.idle_since - now 147 if delta.seconds < 60 or force: 148 self.idle_since = datetime.now() 149 return self._verify_response(self._post( 150 'room/%s/tabs' % self.id, {}, ajax=True), success=True) 151 return False
152
153 - def destroy(self):
154 """Destroys the room. 155 156 Returns True if successfully destroyed, False otherwise.""" 157 return self._verify_response(self._post( 158 'account/delete/room/%s' % self.id), success=True)
159
160 - def users(self):
161 """Lists the users chatting in the room. 162 163 Returns a set of the users.""" 164 return self._campfire.users(self.name)
165
166 - def speak(self, message):
167 """Send a message to the room. 168 169 Returns the message if successfully sent it, None otherwise.""" 170 self.join() 171 return self._send(message)
172
173 - def paste(self, message):
174 """Paste a message to the room. 175 176 Returns the message if successfully pasted it, None otherwise.""" 177 self.join() 178 return self._send(message, {'paste': True})
179
180 - def transcripts(self):
181 """Gets the dates of transcripts of the room. 182 183 Returns a list of dates.""" 184 return self._campfire.transcripts(self.id)
185
186 - def transcript(self, date):
187 """Get the transcript for the given date (a datetime.date instance). 188 189 Returns a list of message data: 190 * id: the id of the message 191 * person: the name of the person who wrote the message if any 192 * user_id: the user id of the person if any 193 * message: the message itself if any""" 194 uri = 'room/%s/transcript/%s' % (self.id, date.strftime('%Y/%m/%d')) 195 196 soup = BeautifulSoup(self._get(uri).body) 197 198 def _filter_messages(tag): 199 return tag.has_key('class') and 'message' in tag['class'].split()
200 messages = soup.findAll(_filter_messages) 201 202 all_transcript = [] 203 for message in messages: 204 t = {} 205 206 person = message.find(True, attrs={'class': 'person'}) 207 try: 208 t['person'] = person.span.string 209 except AttributeError: 210 try: 211 t['person'] = person.string 212 except AttributeError: 213 t['person'] = None 214 215 body = message.find('td', attrs={'class': 'body'}) 216 try: 217 t['message'] = body.div.string 218 except AttributeError: 219 t['message'] = None 220 221 t['id'] = re.search(r'message_(\d+)', message['id']).groups()[0] 222 match = re.search(r'user_(\d+)', message['class']) 223 if match: 224 t['user_id'] = match.groups()[0] 225 else: 226 t['user_id'] = None 227 228 all_transcript.append(t) 229 230 return all_transcript 231
232 - def _send(self, message, options={}):
233 data = {'message': message, 't': int(time.time())} 234 data.update(options) 235 response = self._post('room/%s/speak' % self.id, data, ajax=True) 236 if self._verify_response(response, success=True): 237 return message
238
239 - def _get_room_data(self):
240 self.membership_key = re.search(r'\"membershipKey\": \"([a-z0-9]+)\"', 241 self._room.body).groups(0)[0] 242 self.user_id = re.search(r'\"userID\": (\d+)', 243 self._room.body).groups(0)[0] 244 self.last_cache_id = re.search(r'\"lastCacheID\": (\d+)', 245 self._room.body).groups(0)[0] 246 self.timestamp = re.search(r'\"timestamp\": (\d+)', 247 self._room.body).groups(0)[0]
248 249 250 251 __all__ = ['Room'] 252