def _send_hipchat_alert(message, color='green'): room_id = int(settings.HIPCHAT_ALERT_ROOM) api_key = settings.HIPCHAT_API_KEY hc = HypChat(api_key) rooms = hc.rooms() room = filter(lambda x: x['id'] == room_id, rooms['items'])[0] room.message(message, color=color, notify=True, format='text')
#! /usr/bin/env python # coding: utf-8 # LICENSE: # Date: # Author: konglx # File: # Description: __author__ = 'Konglx' from hypchat import HypChat from tombot.common.log import logger TOKEN = 'DZttvKCWeU4GpXxoqwJc4IG8bH636MjaCmLNZqc8' hc = HypChat(TOKEN) logger.debug('Hipchat rooms: {0}'.format(hc.rooms())) logger.debug('Hipchat users: {0}'.format(hc.users()))
class HipMessage(object): ''' Class that gets all messages from a given room, filters them through the classes from filter_classes and returns them when get_newest_messages is called. ''' # A class that has implemented two methods # - set_last_message_id(self._room_name, ) # - get_last_message_id() message_backend_class = None # Iterable of filter classes. # All messages will be passed through the is_ok method of this # classes and will include them only if the return Value is True filter_classes = None def __init__(self, token, room_name): self._token = token self._room_name = room_name self._hipchat_client = HypChat(token) self._room = self._hipchat_client.get_room(self.get_room_id(room_name)) self._message_backend = self.message_backend_class(self._room_name) def get_room_id(self, room_name): rooms = self._hipchat_client.rooms() filtered_rooms = filter( lambda room: room['name'] == self._room_name, rooms['items']) if not filtered_rooms: raise ValueError('No room with name {}'.format(self._room_name)) return filtered_rooms[0]['id'] def is_message_valid(self, message): if self.filter_classes: return all( map(lambda cls: cls().is_ok(message), self.filter_classes)) return True def process_complete_history(self): date = datetime.datetime.utcnow() newest_id = None while True: messages_count = 0 messages = self._room.history( maxResults=1000, date=date, reverse=False) for message in messages['items']: messages_count += 1 if self.is_message_valid(message) is False: continue self.process_message(message) newest_id = newest_id or message['id'] date = message['date'] if messages_count < 1000: return newest_id def get_newest_messages(self, max_results=500): last_message_id = self._message_backend.get_last_message_id() params = {} if last_message_id is not None: params = {'not_before': last_message_id} else: newest_id = self.process_complete_history() self._message_backend.set_last_message_id(newest_id) return last_message = None # The messages come in the order oldest to newest for msg in self._room.latest(**params)['items']: if self.is_message_valid(msg): self.process_message(msg) last_message = msg if last_message is not None: self._message_backend.set_last_message_id(last_message['id']) def process_message(self, msg): ''' This is the method you override in your derived class. Method that takes as only argument a message and processes it. ''' def run(self): self.get_newest_messages()
class HipChat(ClientXMPP): def __init__(self, jid, password): super(HipChat, self).__init__(jid, password) self.register_plugin('xep_0030') # Service Discovery self.register_plugin('xep_0045') # Multi-User Chat self.register_plugin('xep_0004') # Multi-User Chat backward compability (necessary for join room) self.register_plugin('xep_0199') # XMPP Ping self.register_plugin('xep_0203') # XMPP Delayed messages self.register_plugin('xep_0249') # XMPP direct MUC invites self.register_plugin('xep_0060') # PubSub # self.register_plugin('xep_0071') self.auto_authorize = True self.auto_subscribe = True self.whitespace_keepalive = True self.whitespace_keepalive_interval = 60 self.end_session_on_disconnect = False self.ca_certs = '/etc/ssl/certs/ca-certificates.crt' self.add_event_handler('session_start', self.session_start) self.add_event_handler('message', self.handle_message) self.add_event_handler('groupchat_invite', self.auto_accept_invite) zmq_thread = threading.Thread(target=self.zmq_handler) zmq_thread.daemon = True zmq_thread.start() self.rooms = [] self.api_conn = HypChat(TOKEN) self.rooms_in_hipchat = self.api_conn.rooms(expand='items') with file('./rooms.json', 'r') as fp: try: self.rooms = json.load(fp) except ValueError as _: self.rooms = [] self.recovery_rooms_on_startup(self.rooms) def send_api_message(self, room_id, fr, message, message_format='html'): base = {'format': 'json', 'auth_token': self.token} red_data = {'room_id': room_id, 'from': fr, 'message': utf8(message), 'message_format': message_format} req = Request(url=HIPCHAT_MESSAGE_URL + '?' + urlencode(base), data=urlencode(red_data)) return json.load(urlopen(req)) def recovery_rooms_on_startup(self, rooms): for room in rooms: muc = self.plugin['xep_0045'] muc.joinMUC(room, nick=NICK_NAME, wait=True) def auto_accept_invite(self, message): room = message['from'] muc = self.plugin['xep_0045'] muc.joinMUC(room, nick=NICK_NAME, wait=True) self.rooms.append(str(room)) logger.debug('Rooms: {}'.format(self.rooms)) with open('./rooms.json', 'w') as fp: json.dump(self.rooms, fp) def session_start(self, event): self.get_roster() self.send_presence() def handle_message(self, message): type = message['type'] if type not in ('chat', 'groupchat'): return content = message['body'] message['from'] = re.sub(r'/.*$', '', str(message['from'])) id = str(message['from']) # xmpp only, qq is different user = id msg = {'content': content.encode('utf-8'), 'id': id, 'type': type, 'user': user} socket.send_json(msg) logger.info('send message to server: {}'.format(msg)) def zmq_handler(self): while True: # xmppmsg = self.Message() message = socket.recv_json() # message = json.loads(message[0]) if message['html']: logger.debug('hipchat receive html message {}'.format(message)) # content = xhtml2hipchat(message['html']) room = self.get_room_by_jid(message['id']) content = message['content'] room.notification(content, color='random', notify=True, format='html') else: logger.debug('hipchat receive message {}'.format(message)) self.send_message(mto=message['id'], mbody=message['content'], mtype=message['type']) def get_room_by_jid(self, room_jid): for r in self.rooms_in_hipchat['items']: if r['xmpp_jid'] == room_jid: return r return None
HIPCHAT_URL = config.get('DEFAULT', 'hipchat_url') if not token: print "Can't read token from config file {config}\n\nConfig example (don't forget chmod 600):\n" + \ "[DEFAULT]\ntoken = 012345678901234567890\nhipchat_url = {url}".format( config=CONFIG_FILE, url=HIPCHAT_DEFAULT_URL) exit(1) hc = HypChat(token) hc.capabilities.url = '{hipchat}/capabilities'.format(hipchat=HIPCHAT_URL) hc.emoticons.url = '{hipchat}/emoticon'.format(hipchat=HIPCHAT_URL) hc.rooms.url = '{hipchat}/room'.format(hipchat=HIPCHAT_URL) hc.users_url = '{hipchat}/user'.format(hipchat=HIPCHAT_URL) if args.list_rooms: rooms = hc.rooms() i = 0 if 'items' in rooms and rooms['items']: print 'Cnt\tID\tName' print '----\t----\t----' for room in rooms['items']: i += 1 print '{num}:\t{id}\t{name_}'.format(num=i, id=room.id, name_=room.name) exit(0) if 'user' not in args and 'room' not in args or (not args.user and not args.room): parser.print_help() exit(1) message = stdin.read()
class HipMessage(object): ''' Class that gets all messages from a given room, filters them through the classes from filter_classes and returns them when get_newest_messages is called. ''' # A class that has implemented two methods # - set_last_message_id(self._room_name, ) # - get_last_message_id() message_backend_class = None # Iterable of filter classes. # All messages will be passed through the is_ok method of this # classes and will include them only if the return Value is True filter_classes = None def __init__(self, token, room_name): self._token = token self._room_name = room_name self._hipchat_client = HypChat(token) self._room = self._hipchat_client.get_room(self.get_room_id(room_name)) self._message_backend = self.message_backend_class(self._room_name) def get_room_id(self, room_name): rooms = self._hipchat_client.rooms() filtered_rooms = filter(lambda room: room['name'] == self._room_name, rooms['items']) if not filtered_rooms: raise ValueError('No room with name {}'.format(self._room_name)) return filtered_rooms[0]['id'] def is_message_valid(self, message): if self.filter_classes: return all( map(lambda cls: cls().is_ok(message), self.filter_classes)) return True def process_complete_history(self): date = datetime.datetime.utcnow() newest_id = None while True: messages_count = 0 messages = self._room.history(maxResults=1000, date=date, reverse=False) for message in messages['items']: messages_count += 1 if self.is_message_valid(message) is False: continue self.process_message(message) newest_id = newest_id or message['id'] date = message['date'] if messages_count < 1000: return newest_id def get_newest_messages(self, max_results=500): last_message_id = self._message_backend.get_last_message_id() params = {} if last_message_id is not None: params = {'not_before': last_message_id} else: newest_id = self.process_complete_history() self._message_backend.set_last_message_id(newest_id) return last_message = None # The messages come in the order oldest to newest for msg in self._room.latest(**params)['items']: if self.is_message_valid(msg): self.process_message(msg) last_message = msg if last_message is not None: self._message_backend.set_last_message_id(last_message['id']) def process_message(self, msg): ''' This is the method you override in your derived class. Method that takes as only argument a message and processes it. ''' def run(self): self.get_newest_messages()