コード例 #1
0
def main():
    sc = SlackClient(BOT_TOKEN)
    if sc.rtm_connect():
        # print sc.server.channels
        bot_id = sc.server.users.find(bot).id
        while True:
            data = sc.rtm_read()
            if data != []:
                print data[0]
                if "type" in data[0] and data[0]["type"] == "message" and "subtype" not in data[0]:
                    if data[0]["user"] != bot_id:
                        text =  data[0]["text"]
                        channel_id = data[0]["channel"]
                        channel = sc.server.channels.find(channel_id)
                        if phrase in text:
                            try:
                                test = text.replace(phrase, "")
                                result = Parser().parse(test)
                                sc.rtm_send_message(channel.name,"Rolling a '%s' and got a result of %s"%(test,result.sum))
                                #TODO: Support message level saving such that a user could track history of roll
                            except Exception as e:
                                sc.rtm_send_message(channel.name,"ROLL FAILED: %s"%e.message)

            time.sleep(1)
    else:
        print "Connection Failed, invalid token?"
コード例 #2
0
ファイル: proxy.py プロジェクト: gwillen/quebecois-chat
def slack_thread():
    print "in spawned slack thread"
    sc = SlackClient(SLACK_TOKEN)

    # Join all channels
    chans = json.loads(sc.api_call("channels.list"))
    chans = chans['channels']
    for chan in chans:
        sc.api_call("channels.join", name=chan['name'])

    if sc.rtm_connect():
        while True:
            msgs = sc.rtm_read()
            print "Got msgs == " + str(msgs)
            for msg in msgs:
                if msg.get('ok') is not None:
                    print "Server acknowledged our message: " + str(msg)
                elif msg.get('type') is not None:
                    if msg['type'] == 'hello':
                        print "Server said hello: " + str(msg)
                    elif msg['type'] == 'channel_created':
                        print "Channel created: " + str(msg)
                        print sc.api_call("channels.join", name=msg['channel']['name'])
                    elif msg['type'] == 'message':
                        print "Got a message: " + str(msg)
                        sc.rtm_send_message(msg['channel'], str(msg))
                    else:
                        print "Got RTM message with unknown type field: " + str(msg)
                else:
                    print "Unknown message format in RTM: " + str(msg)
                    
            gevent.sleep(1)
    else:
        print "Connection Failed, invalid token?"
コード例 #3
0
ファイル: starterbot.py プロジェクト: itzme/slackbotstarter
    def main(self):
        token = os.environ.get("SLACK_TOKEN")

        slack_client = SlackClient(token)

        if slack_client.rtm_connect():

            while True:
                new_evts = slack_client.rtm_read()

                for evt in new_evts:
                    #print evt

                    if 'type' in evt:

                        if str(evt["type"]) == "message" and "text" in evt:
                            # this is where the logic for the human input text is placed.
                            # we also get more information from the JSON
                            keyword = True
                            channel = evt['channel']
                            response = evt['text']
                            print response

                    elif 'reply_to' in evt:

                        #this is where the logic for the chat bot is placed.
                        slack_client.rtm_send_message('This is where the messages will go', 'Hello World')


        else:
            print "Failed."
コード例 #4
0
ファイル: layabout.py プロジェクト: reillysiemens/wb2k
def handle_event(event: dict, channel: str, channel_id: str, message: str,
                 sc: SlackClient, logger: logging.Logger) -> None:
    pretty_event = pformat(event)
    logger.debug(f"Event received:\n{pretty_event}")

    subtype = event.get('subtype')
    user = event.get('user')

    if subtype in ('group_join', 'channel_join') and user:

        # We will use the event's channel ID to send a response and refer to
        # users by their display_name in accordance with new guidelines.
        # https://api.slack.com/changelog/2017-09-the-one-about-usernames
        event_channel_id = event.get('channel')
        user_profile = event.get('user_profile')
        username = user_profile.get('display_name')
        user_mention = f"<@{user}>"
        message = message.replace('{user}', user_mention)

        if event_channel_id == channel_id:
            try:
                sc.rtm_send_message(event_channel_id, message)
                logger.info(f"Welcomed {username} to #{channel}")
            except AttributeError:
                logger.error(f"Couldn't send message to #{channel}")
コード例 #5
0
ファイル: bot_main.py プロジェクト: Hakus/hphd-slack-bot
def main():
	token = tokens.token
	client = SlackClient(token)
	if client.rtm_connect():
		channel = raw_input("Channel name: ")
		while True:
			message = raw_input("Message: ")
			client.rtm_send_message(channel, message)
	else:
		print "Connection Failed."
コード例 #6
0
ファイル: PeckBot.py プロジェクト: peck94/slackbot
class PeckBot(object):
    def __init__(self, token, timeout):
        print('[INFO] Initializing bot...')
        self.token = token
        self.client = SlackClient(token)
        self.timeout = timeout
        self.userid = 'U04U7K4HC'
        self.responses = [
            ('^!reddit ([a-zA-Z0-9]+)', RedditBehavior()),
            ('^!chat (.*)$', CleverBotBehavior()),
            ('^!doc$', DocBehavior()),
            ('^!quote ?(.*)$', QuoteBehavior()),
            ('^!trivia ?(.*)$', TriviaBehavior()),
            ('(.+)', NonsensSpewingBehavior()),
            ('.+', NonsensTrainingBehavior())
        ]
        print('[INFO] Init done.')

    def connect(self):
        return self.client.rtm_connect()

    def send_msg(self, msg, channel):
        self.client.rtm_send_message(channel, msg)
        self.pause()

    def pause(self):
        time.sleep(self.timeout)

    def run(self):
        print('[INFO] PeckBot is running')
        while True:
            events = self.client.rtm_read()
            for event in events:
                if 'type' in event and event['type'] == 'message':
                    if 'user' in event and event['user'] != self.userid:
                        self.respond(event)
            self.pause()

    def respond(self, event):
        for resp in self.responses:
            regex, behavior = resp
            matches = re.findall(regex, event['text'])
            try:
                channel_name = json.loads(self.client.api_call('channels.info', channel=event['channel']))['channel']['name']
            except KeyError:
                channel_name = event['channel']
            for match in matches:
                print('[INFO] Triggered {0} on #{1}'.format(behavior.name, channel_name))
                try:
                    behavior.execute(self, match, event)
                except Exception as e:
                    print('[ERROR] {0} failed: {1}'.format(behavior.name, e))

            if len(matches) > 0:
                break
コード例 #7
0
 def handle(self, *args, **options):
     team = Team.objects.first()
     client = SlackClient(team.bot_access_token)
     if client.rtm_connect():
         while True:
             events = client.rtm_read()
             print("%s----%s" % (team, events))
             for event in events:
                 if 'type' in event and event['type'] == 'message' and event['text'] == 'hi':
                     client.rtm_send_message(event['channel'], "hello world")
                 elif 'type' in event and event['type'] == 'message' and event['text'] == 'who':
                     client.rtm_send_message(event['channel'], "I'am Groot")
             time.sleep(1)
コード例 #8
0
ファイル: app.py プロジェクト: vdimarco/saidyebot
def send_message():    
    channel = request.form['channel']
    message = request.form['message']
    access_token = request.form['access_token']

    #Ideally, the only parameters taken would be origin user + message. This can be worked on in a further iteration.
    
    sc = SlackClient(access_token)

    sc.rtm_connect()
    sc.rtm_send_message(channel=channel, message=message)
    
    return "Success"
コード例 #9
0
ファイル: connect2.py プロジェクト: ameer3amer/connect
class Connection:
    dict = {}
    sc  =  None
    summ = None
    names = {}
    def read(self,token):
        self.sc = SlackClient(token)
        if self.sc.rtm_connect():
            start = time.time()
            while True:
                try:
                    str = self.sc.rtm_read()
                    if str and ('text' in str[0]) and  ('reply_to' not in str[0]): # if str is not null
                        key = str[0].get('text')
                        user = str[0].get('user')
                        info = self.sc.api_call('users.info', user= user)
                        if user not in self.dict:
                            user_name = info.get('user').get('name')
                            self.names[user_name] = user
                            self.dict[user] = []
                            self.dict[user].append(float(key))
                            self.dict[user].append(1)
                            self.dict[user].append(float(key))
                            print(float(key))
                        else:
                            self.dict[user][0] += float(key)
                            self.dict[user][1] += 1
                            print(float(self.dict[user][0])/self.dict[user][1])
                            self.dict[user][2] = self.dict[user][0]/self.dict[user][1]
                        count , avg = 0,0
                        for key, value in self.dict.items():
                            avg += float(self.dict[key][0])
                            count += self.dict[key][1]
                        self.summ = avg/count
                        time.sleep(1)
                        end = time.time()
                        if(end - start >= 60):
                            start = time.time()
                            for key, value in self.dict.items():
                                avg += float(self.dict[key][0])
                                count += self.dict[key][1]
                            str = "{:.9f}".format(avg/count)
                            self.sc.rtm_send_message("general", str)
                            count , avg = 0,0
                    else:
                        time.sleep(1)
                except Exception as e:
                    print("Exception: ", e.message)
コード例 #10
0
ファイル: standupbot.py プロジェクト: yareally/standupbot
class StandupBot:
    def __init__(self, token):
        self.token = token
        self.slack_client = None
        self.standup = None
        self.last_ping = 0
        self.keepalive_timer = 3
        print("Standup Bot initialized.")

    def connect(self):
        self.slack_client = SlackClient(self.token)
        self.slack_client.rtm_connect()

    def keepalive(self):
        now = int(time.time())
        if now > self.last_ping + self.keepalive_timer:
            self.slack_client.server.ping()
            self.last_ping = now

    def start(self):
        self.connect()

        while True:
            for response in self.slack_client.rtm_read():
                self.response_handler(response)

            self.keepalive()
            time.sleep(.5)

    def message_handler(self, channel, message):
        if "!standup" in message:
            # check to see if self.Standup is already initialized, and if so, if the standup is already started.
            if self.standup is None:
                self.slack_client.rtm_send_message(channel=channel, message="Hello <!channel>, it's time for Standup!")
                self.standup = Standup(channel, self.slack_client)
            elif self.standup is not None & self.standup.status is "INITIALIZED":
                self.slack_client.rtm_send_message([channel, "I will restart the meeting."])
                self.standup = Standup(channel, self.slack_client)
        elif "!start" in message:
            if self.standup is not None:
                self.standup.start_standup()

    def response_handler(self, response):
        print(response)
        if "type" in response and "subtype" not in response:
            if "message" in response["type"]:
                self.message_handler(channel=response["channel"], message=response["text"])
コード例 #11
0
ファイル: pyslackbot.py プロジェクト: gregmccoy/pyslackbot
class SlackBot(object):
    def __init__(self, bot_id, debug=False):
        self.sc = SlackClient(bot_id)
        self.user = ""
        self.connect = self.sc.rtm_connect()
        self.debug = debug

        self.threads = []
        t = threading.Thread(target=self.watch_message)
        self.threads.append(t)
        t.start()

        self.handlers = []

    def add_handler(self, msg, reply, run=None, con=True):
        handler = SlackHandler(msg, run, con)
        self.handlers.append(handler)

    def watch_message(self):
        if self.connect:
            self.sc.server.login_data["self"]["id"]
            while True:
                message = self.sc.rtm_read()
                if message and message[0]["type"] == "message" and message[0]["user"] != self.user:
                    #There is a message from a user
                    text = message[0]["text"]
                    if self.debug:
                        print("Message - " + text)
                    self.parse_message(text, message[0]["channel"])
                time.sleep(1)

    def parse_message(self, message, channel):
        for handler in self.handlers:
            if handler.con:
                if handler.message in message:
                    if handler.run != None:
                        if self.debug:
                            print("Excuting - " + str(handler.run))
                        try:
                            handler.run()
                        except:
                            print("Exception during handler function")
                    self.sc.rtm_send_message(channel, message)

            elif handler.message == message:
                handler.run()
コード例 #12
0
ファイル: bot.py プロジェクト: coderplans/SlackBot
class Bot:

    def __init__(self, token):
        self.token = token
        print("Bot instantiated. My token is: "+self.token+".")

    def connect(self):
        print("Connecting with token: "+self.token+"...")

        self.client = SlackClient(self.token)
        self.client.rtm_connect()
        is_ok = self.client.api_call("api.test")
        is_ok = is_ok["ok"]

        if is_ok == True:  
            print("Connection established!")

        else:
            print("Error code : 1. Connection failure. Check access token?")
            sys.exit()
            
    def print_chat(self, msg, channel):
        self.client.rtm_send_message(channel, msg)

    def read_msg(self):
        msg = self.client.rtm_read()
        if len(msg) > 0:
            msg = msg[0]
            if "type" in msg:
                if msg["type"] == "message":
                    return msg

            return []
        else:
            return []
        
    def hello(self):
        self.client.api_call("chat.postMessage", token=self.token, channel="#general", text="Hello World", as_user=True)

    def id2name(self, id):
        users = self.client.api_call("users.list", token=self.token)
        users = users["members"]
        for user in users:
            if user["id"] == id:
                username = user["name"]
                return "@"+username
コード例 #13
0
ファイル: slask.py プロジェクト: CardsAgainstHumanity/slask
def main(config):
    init_log(config)
    hooks = init_plugins("plugins")

    client = SlackClient(config["token"])
    if client.rtm_connect():
        users = client.server.users
        while True:
            events = client.rtm_read()
            for event in events:
                logging.debug("got {0}".format(event.get("type", event)))
                response = handle_event(client, event, hooks, config)
                if response:
                    client.rtm_send_message(event["channel"], response)
            time.sleep(1)
    else:
        logging.warn("Connection Failed, invalid token <{0}>?".format(config["token"]))
コード例 #14
0
def slackbot_msg(message, channel=SLACK_CHANNEL):
	'''
	Usage:  slackbot_msg(msg, channel)
	Before: msg is a string containing message we want to send to slack,
	        channel is the name of the channel we want to post to, if it is not
	        provided the default channel from config will be used
	After:  message has been sent to slack

	Note: this may fail silently (prints warning) if connecting to slack fails.
	'''
	if ACT_LIKE_ROBOT:
		message = message.upper()
	sc = SlackClient(SLACKBOT_TOKEN)
	if sc.rtm_connect():
		sc.rtm_send_message(channel, message)
	else:
		print 'Warning: slackbot_msg() failed, invalid token?'
コード例 #15
0
def be_wise(config, quotes, stopwords):
    slack_client = SlackClient(config['token'])
    slack_client.rtm_connect()
    user_id = get_user_id(slack_client, config['name'])
    mention_string = '@%s' % user_id
    while True:
        messages = slack_client.rtm_read()
        messages = filter(lambda m: m['type'] == 'message', filter(lambda m: 'type' in m, messages))
        if len(messages) > 0:
            for message in messages:
                if mention_string in message['text']:
                    sentence = message['text'][len(user_id)+3:]
                    quote = find_quote(sentence, quotes, stopwords)
                    name = get_user_name(slack_client, message['user'])
                    response = '<@%s>: %s says: "%s"' % (name, quote.author, quote.sentence)
                    slack_client.rtm_send_message(message['channel'], response)

        time.sleep(1)
コード例 #16
0
ファイル: salute.py プロジェクト: Quantumke/Tyche
	def run(Salute):
		slack_client_instance=SlackClient(api_token)
		if slack_client_instance.rtm_connect():
			slack_client_instance.rtm_send_message(channel_name, "Am here for your daily stand ups say 'go' !")
			while True:
				for slack_message in slack_client_instance.rtm_read():
					message=slack_message.get("text")
					user=slack_message.get("user")
					if not message or not user:
						continue
						slack_client_instance.rtm_send_message(channel_name,"<@{}> ".format(user))
						slack_client_instance.rtm_send_message(channel_name, message)
						print(message)
                				if message=="go":
							slack_client_instance.rtm_send_message(channel_name, "what did you do yesterday?")
                				else:
                    					slack_client_instance.rtm_send_message(channel_name, "I did not quite get that! Say 'go'  to continue")
                				time.sleep(0.5)
コード例 #17
0
ファイル: run.py プロジェクト: closer27/10BobBot
def create_bot():
    token = open("token.txt")
    sc = SlackClient(token)
    sc.rtm_connect()
    while True:
        new_evts = sc.rtm_read()
        for evt in new_evts:
            print(evt)
            if "type" in evt:
                if evt["type"] == "message" and "text" in evt:
                    message = evt["text"]
                    channel = evt["channel"]
                    print(message)
                    if "점심메뉴" in message or "십밥" in message or "10층" in message or "10밥" in message:
                        sc.rtm_send_message(channel=channel, message=get_menu())
                    elif "명령어" in message:
                        sc.rtm_send_message(channel=channel, message="10밥봇 명령어 : 점심메뉴, 십밥, 10층, 10밥")
        time.sleep(.1)
コード例 #18
0
ファイル: echobot.py プロジェクト: ykhalyavin/slack-echo-bot
class Bot:
    def __init__(self, token):
        self.client = SlackClient(token)
        self.im_ids = []
        self.last_ping = time.time()

    def start(self):
        self.client.rtm_connect()
        self.im_ids = self.get_im_ids()

        while True:
            for r in self.client.rtm_read():
                if 'type' not in r:
                    pass
                elif r['type'] == 'message':
                    self.process_message(r)
                elif r['type'] == 'im_created':
                    self.im_ids = self.get_im_ids()

            self.ping()
            time.sleep(0.2)

    def process_message(self, r):
        if 'subtype' in r or 'reply_to' in r:
            return
        if r['channel'] in self.im_ids or self.is_bot_mentioned(r['text']):
            self.client.rtm_send_message(r['channel'], r['text'])

    def is_bot_mentioned(self, msg):
        bot_id = self.client.server.login_data['self']['id']
        bot_mentioned = '<@{}>'.format(bot_id)

        return bot_mentioned in msg

    def get_im_ids(self):
        return [x['id'] for x in self.client.api_call('im.list')['ims']]

    def ping(self):
        now = int(time.time())
        if now > self.last_ping + 3:
            self.client.server.ping()
            self.last_ping = now
コード例 #19
0
ファイル: bot.py プロジェクト: noelledaley/hackbot
class Hackbot(object):
    """
    An instance of Hackbot, the Hackbright XI Slack bot. Also known as Balloonicorn.
    """

    def __init__(self, token):
        self.token = token
        self.client = None

    def connect(self):
        """Set up SlackClient and connect to Real Time Messaging API.

        The RTM sets up a continuous websocket connection, from which you can read and respond to events in real time without without making a full HTTPS request.
        """
        self.client = SlackClient(self.token)
        self.client.rtm_connect()

    def read(self):
        """
        Read all events from Real Time Messaging API.
        Checks if balloonicorn is mentioned.
        """
        while True:
            for response in self.client.rtm_read():
                print response

                if response.get('type') == 'message':
                    message = response.get('text')
                    if 'balloonicorn' in message:
                        channel = response.get('channel')
                        self.reply(message, channel)
                time.sleep(1)

    def reply(self, message, channel):
        """
        When balloonicorn is mentioned, returns a random choice from a list of reponses.
        """

        if
        reply = random.choice(['Hi there!', 'Yes?', ';)'])
        self.client.rtm_send_message(channel, reply)
コード例 #20
0
ファイル: catbot.py プロジェクト: allisonkcraig/slack-cat-bot
class slackbot(object):
	# a class for fun slackbots

	def __init__(self, token):
		self.token = token
		self.slack_client = None

	def connect(self):
		# setup the SlackClient and connect to the RTM API

		self.slack_client = SlackClient(self.token)
		self.slack_client.rtm_connect()

	def get_events(self):
		# get all events from the RTM API
		# Is drunkoctopus or a keyword mentioned?

		while True:
			new_evts = self.slack_client.rtm_read()
			for evt in new_evts:
				print evt
				if evt.get('type') == 'message':
					message = evt.get('text')
					if 'catbot' in message:
						channel = evt.get('channel')
						self.reply(message, channel)
				time.sleep(1)

	def reply(self, message, channel):
		# when drunkoctopus is mentioned, return a message
		# look message words up in the drunkoctopus dictionary
		
		if "STAT" in message:
			reply = "DON'T RUSH CATS"
			self.slack_client.rtm_send_message(channel, reply)
			return
	
		else: 
			reply = random.choice(imageList)
			self.slack_client.rtm_send_message(channel, reply)
			return
コード例 #21
0
def main():
    # Create the slackclient instance
    sc = SlackClient(BOT_TOKEN)

    # Connect to slack
    if sc.rtm_connect():
        # Send first message
        sc.rtm_send_message(CHANNEL_NAME, "I'm ALIVE!!!")

        while True:
            # Read latest messages
            for slack_message in sc.rtm_read():
                message = slack_message.get("text")
                user = slack_message.get("user")
                if not message or not user:
                    continue
                sc.rtm_send_message(CHANNEL_NAME, "<@{}> wrote something...".format(user))
            # Sleep for half a second
            time.sleep(0.5)
    else:
        print("Couldn't connect to slack")
コード例 #22
0
ファイル: main.py プロジェクト: hizeph/mastermind-slack-bot
def main ():
	controller = Controller()

	token = ""
	sc = SlackClient(token)

	if sc.rtm_connect():
		while True:
			events = []
			events = sc.rtm_read()
			if (events != []):
				print (events)
				for event in events:
					if (event.get('type', None) == 'message' and event.get('team', None) is not None):
						ans = controller.evaluateInput(event.get('text', 'None'))
						sc.rtm_send_message(event['channel'], ans)
						pass
						
			time.sleep(1)
	else:
		print ("Connection Failed, invalid token?")
コード例 #23
0
ファイル: app.py プロジェクト: NixonInnes/slackbot-helpy
def main():
    client = SlackClient(token)
    logger.info(client.api_call('api.test'))
    if client.rtm_connect():
        while True:
            new_events = client.rtm_read()
            for event in new_events:
                if 'type' in event and 'text' in event and 'channel' in event and 'user' in event and event['type'] == 'message':
                    msg = event['text']
                    if msg.split()[0] == 'helpy':
                        logger.info('channel: ' + event['channel'] + ', user:'******'user'] + ', msg:' + event['text'])
                        query = ' '.join(msg.split()[1:])
                        try:
                            head, desc, link = search(query)
                            resp = "*{}*\n>{}{}".format(head, desc, '\n' + link if link is not None else '')
                            client.rtm_send_message(event['channel'], resp)
                        except Exception as e:
                            logger.error('Runtime Error:')
                            logger.error(e)
                time.sleep(1)
    else:
        logger.error("Could not connect!")
コード例 #24
0
ファイル: bot.py プロジェクト: NixonInnes/SlackEchoBot
def main():
    """
    Creates a Slack client.
    If the client has connected the program enters into an infinite loop.
    Check for any new events with SlackClient.rtm_read().
    Iterate through the new events
    If the event is a message, and the first word in the text is 'echo'
    Then the client sends the message back to the channel
    At the end of each loop, the client waits 1 second to prevent spamming the Slack
    """

    client = SlackClient(token)

    if client.rtm_connect():
        while True:
            new_events = client.rtm_read()
            for event in new_events:
                if event.get('type') == 'message':
                    msg = event['text']
                    if len(msg) > 0 and msg.split()[0] == 'echo':
                        response = ' '.join(msg.split()[1:])
                        client.rtm_send_message(event['channel'], response)
            time.sleep(1)
コード例 #25
0
ファイル: index.py プロジェクト: Quantumke/Tyche
def main():
	slack_client_instance=SlackClient(api_token)
	if slack_client_instance.rtm_connect():
		slack_client_instance.rtm_send_message(channel_name, "Am here to find you a  tech date  !")
		while True:
			for slack_message in slack_client_instance.rtm_read():
				message=slack_message.get("text")
				user=slack_message.get("user")
				if message=="go":
					message="please tell me your gender"
					slack_client_instance.rtm_send_message(channel_name, message)
					gender=slack_message.get("text`")
				if not message or not user:
					continue
					slack_client_instance.rtm_send_message(channel_name,"<@{}> ".format(user))
					slack_client_instance.rtm_send_message(channel_name, message)
					time.sleep(0.5)
コード例 #26
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
from slackclient import SlackClient
import time

#get your personal token from https://api.slack.com/web, bottom of the page.
api_key = ''
client = SlackClient(api_key)

if client.rtm_connect():
    while True:
        last_read = client.rtm_read()
        if last_read:
            try:
                parsed = last_read[0]['text']
                #reply to channel message was found in.
                message_channel = last_read[0]['channel']
                if parsed and 'food:' in parsed:
                    choice = random.choice(['hamburger', 'pizza'])
                    client.rtm_send_message(message_channel,
                                            'Today you\'ll eat %s.' % choice)
            except:
                pass
        time.sleep(1)
コード例 #27
0
ファイル: slackbot.py プロジェクト: ebagdasa/slack-outlook
def rtm(token, queue, workspace, workspace_token):
    sc = SlackClient(workspace_token)
    print('rtm start for ', workspace)
    room_parking_channel = None

    @MSGRAPH.tokengetter
    def get_token():
        """Called by flask_oauthlib.client to retrieve current access token."""
        return (token, '')

    # create member dict
    members = list()
    slack_api_members = sc.api_call('users.list')['members']
    for x in slack_api_members:
        name = x['profile']['display_name'] if x['profile'][
            'display_name'] else x['profile']['real_name']
        query_res = Member.get_by_user_workspace(x['id'], workspace)
        if query_res:
            member = query_res
        else:
            member = Member(name, x['profile']['real_name'], x['id'],
                            workspace)
            member.add()
        members.append(member)

    for x in members:
        if x.display_name == 'roomparking':
            room_parking_channel = x.user_id
            print(room_parking_channel)
        elif not x.channel_id:
            res = sc.api_call('conversations.open', users=x.user_id)
            if not res.get('error', None):
                x.channel_id = res['channel']['id']
                x.update()

    channel_members = dict()
    for x in members:
        if x.channel_id:
            channel_members[x.channel_id] = x

    with APP.test_request_context():
        if sc.rtm_connect():
            while True:
                try:
                    res = sc.rtm_read()
                # processing, etc
                except (WebSocketConnectionClosedException, TimeoutError) as e:
                    print('Connecitons was closed. Restarting.')
                    print(e.args)
                    sc.rtm_connect()
                    continue

                if not queue.empty():
                    server_token = queue.get()
                    print('token', server_token)
                    member = channel_members.get(server_token['channel'],
                                                 False)
                    if server_token['status'] == 'error' or (
                            not server_token.get('access_token', False)) or (
                                not server_token.get('refresh_token', False)):
                        sc.rtm_send_message(
                            server_token['channel'],
                            'Sorry there was a problem please try again.')
                    if member and workspace == server_token['workspace']:

                        member.token = server_token['access_token']
                        member.refresh_token = server_token['refresh_token']
                        member.expires = server_token['expires']
                        print('expires', member.expires, ' ',
                              member.display_name)
                        member.update()

                        sc.rtm_send_message(
                            member.channel_id,
                            'Successful authentication! \n {0}'.format(
                                GREETING_TEXT))
                        print('authorized')
                    else:
                        print('not my token')
                        queue.put(server_token)
                        time.sleep(2)
                if len(res) > 0 and type(res[0].get('channel',
                                                    None)) is not str:
                    print('res', res)
                    continue
                # if len(res) > 0:
                #     print(res)

                if len(res) > 0 and res[0].get(
                        'channel',
                        None) in channel_members.keys() and res[0].get(
                            'type', None) == 'message' and res[0].get(
                                'user', None) != room_parking_channel:
                    member = channel_members[res[0].get('channel', None)]
                    # sc.rtm_send_message(member.channel_id, '{0}, {1}, {2}, {3}'.format(member.expires, utc.localize(member.expires),(datetime.now(utc)+timedelta(hours=1)), eastern.localize(member.expires)<=(datetime.now(utc)+timedelta(hours=1))))
                    if not res[0].get('text', False) or res[0].get(
                            'subtype') and res[0]['subtype'] == 'bot_message':
                        continue

                    if res[0]['text'].lower() == 'delete token':
                        member.token = None
                        member.refresh_token = None
                        member.expires = None
                        member.update()

                    if member.token and member.expires and utc.localize(
                            member.expires) <= datetime.now(utc):
                        print('checking for new token')
                        if not check_token(member):
                            sc.rtm_send_message(
                                member.channel_id,
                                'Couldn\'t update token. Please login again.')
                        else:
                            print('updated token! for ', member.display_name)
                            # sc.rtm_send_message(member.channel_id, 'updated token succesfully.')
                    if not member.token:
                        sc.rtm_send_message(
                            member.channel_id,
                            'Hello, {name}! This is the Room Booking app for Bloomberg Center at CornellTech.\n'
                            'It can help you quickly book any room for the next hour. This app will create new meeting on your calendar and invite the selected room. \n'
                            'To continue please authorize with your Cornell Office 365 account: \n Click here: {ip}?channel={channel}&workspace={workspace} \n'
                            'Use your Cornell Email ([email protected]).'.
                            format(name=member.first_name,
                                   ip=SERVER_IP,
                                   channel=member.channel_id,
                                   workspace=workspace))
                    else:
                        token = member.token
                        print('booking for ', member.display_name)

                        member_state = None
                        if member.state:
                            member_state = json.loads(member.state)
                        if member_state and member_state['state'] == 'cancel':
                            try:
                                words = res[0]['text']
                                if words == 'exit':
                                    member.state = None
                                    member.update()
                                    sc.rtm_send_message(
                                        member.channel_id, GREETING_TEXT)
                                    continue
                                elif int(words) in range(
                                        1,
                                        len(member_state['data']) + 1):

                                    event = member_state['data'][int(words) -
                                                                 1]
                                    # sc.rtm_send_message(member.channel_id, event['id'])
                                    res = MSGRAPH.delete(
                                        'me/events/' + event['id'],
                                        data=None,
                                        format='json',
                                        headers=request_headers())
                                    if res.status == 204:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Successfully deleted meeting.')
                                        member_state['data'].pop(
                                            int(words) - 1)
                                        response_res = list()
                                        if len(member_state['data']) > 0:
                                            for pos, x in enumerate(
                                                    member_state['data']):

                                                response_res.append(
                                                    '{4}. Meeting at {0}. Starting at {1} until {2} (timezone: {3})'
                                                    .format(
                                                        x['location'],
                                                        x["start"], x["end"],
                                                        x['timeZone'],
                                                        pos + 1))

                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'Here are the remaining meetings found for your account: \n {0} \n. Please respond with position of the meeting. Ex: ```1``` If only one meeting is presented, please still type: 1.\nTo exit cancellation submenu type ```exit```'
                                                .format(
                                                    '\n'.join(response_res)))
                                        else:
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'Returning back to the main menu.'
                                            )
                                            member_state = None

                                            sc.rtm_send_message(
                                                member.channel_id,
                                                GREETING_TEXT)
                                    else:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Error deleting meeting:')
                                        sc.rtm_send_message(
                                            member.channel_id, res.data)
                                else:
                                    raise ValueError(
                                        'Please put number from 1 to {0}.'.
                                        format(len(member_state['data'])))

                                member.state = json.dumps(
                                    member_state) if member_state else None
                                member.update()
                            except Exception as e:
                                print(e)
                                sc.rtm_send_message(member.channel_id,
                                                    e.args[0])
                                sc.rtm_send_message(
                                    member.channel_id,
                                    'Wrong command. Try: ```exit``` or ```1```'
                                )
                        else:
                            try:

                                ### autocomplete time
                                time_start = datetime.now(eastern)
                                if time_start.minute >= 20 and time_start.minute < 50:
                                    time_start = time_start.replace(
                                        microsecond=0,
                                        second=0,
                                        minute=30,
                                        tzinfo=None)
                                elif time_start.minute >= 50:
                                    time_start = time_start.replace(
                                        microsecond=0,
                                        second=0,
                                        minute=0,
                                        hour=time_start.hour + 1,
                                        tzinfo=None)
                                else:
                                    time_start = time_start.replace(
                                        microsecond=0,
                                        second=0,
                                        minute=0,
                                        tzinfo=None)

                                time_end = time_start + timedelta(hours=1)
                                ### over

                                words = res[0]['text'].split()

                                if words[0].lower() == 'help':
                                    sc.rtm_send_message(
                                        member.channel_id, GREETING_TEXT)

                                elif words[0].lower() == 'where':
                                    if len(words) > 1 and words[1] in room_no:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'https://roomparking.cornelltech.io/rooms/{0}.jpg'
                                            .format(words[1]))
                                    else:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Wrong input. Try ```where 375```')

                                elif words[0].lower() == 'cancel':

                                    msft_resp = MSGRAPH.get(
                                        "me/events",
                                        headers=request_headers()).data
                                    # print(msft_resp)
                                    meetings_by_bot = list()
                                    if len(msft_resp.get('value', list())) > 0:
                                        for x in msft_resp['value']:
                                            end_date_time = eastern.localize(
                                                dateutil.parser.parse(
                                                    x['end']['dateTime']))
                                            if x['bodyPreview'] == "This event is created by RoomParking Slackbot, " \
                                                                   "contact Eugene ([email protected]) for help." and end_date_time > datetime.now(eastern):
                                                meetings_by_bot.append(
                                                    get_meeting_info(x))
                                                sc.rtm_send_message(
                                                    member.channel_id,
                                                    get_meeting_info(x))
                                                # print(x)
                                    if len(meetings_by_bot) > 0:
                                        dumped_state = json.dumps({
                                            'state':
                                            'cancel',
                                            'data':
                                            meetings_by_bot
                                        })
                                        if len(dumped_state) > 3000:
                                            raise ValueError(
                                                'Sorry there are too many meetings created that we can\'t handle at once please delete them manually.'
                                            )
                                        member.state = dumped_state
                                        member.update()

                                        response_res = list()
                                        for pos, x in enumerate(
                                                meetings_by_bot):
                                            response_res.append(
                                                '{4}. Meeting at {0}. Starting at {1} until {2} (timezone: {3})'
                                                .format(
                                                    x['location'], x["start"],
                                                    x["end"], x['timeZone'],
                                                    pos + 1))
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Here are the meetings found for your account: \n {0} \nPlease respond with the position of the meeting. Ex: ```1``` If only one meeting present, please still type: 1. To exit the cancelling submenu type exit.'
                                            .format('\n'.join(response_res)))
                                        print(meetings_by_bot)
                                        sc.rtm_send_message(
                                            member.channel_id, meetings_by_bot)
                                    else:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'No meetings created by our bot has been found for your account. Book some now! '
                                        )

                                elif words[0].lower() == 'list':
                                    if len(words[1]) > 1:
                                        floor = int(words[1][0])
                                    else:
                                        floor = int(words[1])
                                    if floor not in [0, 1, 2, 3, 4]:
                                        raise ValueError(
                                            'Floor is wrong. Use: 0, 1, 2, 3, 4'
                                        )
                                    sc.rtm_send_message(
                                        member.channel_id,
                                        'Looking for available rooms...')
                                    rooms = get_available_by_floor(
                                        floor, MSGRAPH, time_start, time_end)
                                    if rooms['result'] == 'success':
                                        if rooms['data']:
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'Available rooms on floor #{0}: \n {1}. \n (VC - Video Conferencing, D - Display)'
                                                .format(
                                                    floor,
                                                    ','.join(rooms['data']))
                                            )  #  \n\nCheck Michael Wilber\'s nice visualization of available rooms: https://cornell-tech-rooms.herokuapp.com
                                        else:
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'There are no available rooms on floor #{0}'
                                                .format(floor))
                                    else:
                                        if rooms['data']['error'][
                                                'message'] == 'Access token has expired.':
                                            member.token = None
                                            member.refresh_token = None
                                            member.update()
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'Token is expired, please login again.'
                                            )
                                        else:
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                rooms['data'])
                                    continue

                                elif words[0].lower() == 'book':

                                    if len(words) == 1:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Please specify room number, like: "book 375".'
                                        )
                                        continue

                                    if len(words) == 3:
                                        time_new = words[2]
                                        if 'pm' == time_new[-2:]:
                                            time_hour = int(time_new[:-2]) + 12
                                        elif 'am' == time_new[-2:]:
                                            time_hour = int(time_new[:-2])
                                        else:
                                            raise ValueError(
                                                'If you want to specify time for booking. Follow this example: ```book 375 11am``` or ```book 375 2pm``` The room will be booked for one hour starting the time you posted.'
                                            )

                                        # sc.rtm_send_message(member.channel_id, time_start.isoformat())
                                        # sc.rtm_send_message(member.channel_id, time_end.isoformat())

                                        time_start = time_start.replace(
                                            microsecond=0,
                                            second=0,
                                            minute=0,
                                            hour=time_hour,
                                            tzinfo=None)
                                        time_end = time_start + timedelta(
                                            hours=1)
                                        # sc.rtm_send_message(member.channel_id, time_start.isoformat())
                                        # sc.rtm_send_message(member.channel_id, time_end.isoformat())

                                    room = words[1]
                                    print(room)
                                    room_full = get_room_by_no(room)
                                    if not room_full:
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Room not found. Try "list {floor_id}" to get rooms.'
                                        )
                                        continue

                                    if room == '367':
                                        sc.rtm_send_message(
                                            member.channel_id,
                                            'Somehow room 367 cannot be booked. It is not in the Outlook Calendar. I will raise a ticket to IT about it. \n Eugene'
                                        )
                                        continue

                                    available = is_available_now(
                                        room_full, time_start, time_end)
                                    if available['result'] == 'success':
                                        if not available['data']:
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'Room is already occupied!')
                                            sc.rtm_send_message(
                                                member.channel_id, available)
                                            continue
                                        else:
                                            book_json = create_booking_json(
                                                user=member.first_name,
                                                room=room_full,
                                                time_start=time_start.
                                                isoformat(),
                                                time_end=time_end.isoformat())
                                            msft_resp = MSGRAPH.post(
                                                "me/calendar/events",
                                                data=book_json,
                                                format='json',
                                                headers=request_headers()).data
                                            if msft_resp.get('error'):
                                                raise SystemError(msft_resp)
                                            print(msft_resp)
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'The room {4} is booked from {0}:{1:02d} to {2}:{3:02d}.'
                                                .format(
                                                    time_start.hour,
                                                    time_start.minute,
                                                    time_end.hour,
                                                    time_end.minute, room))
                                    else:
                                        if available[
                                                'data'] == 'Access token has expired.':
                                            member.token = None
                                            member.expires = None
                                            member.refresh_token = None
                                            member.update()
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                'Token is expired, please login again.'
                                            )
                                        else:
                                            sc.rtm_send_message(
                                                member.channel_id,
                                                available['data'])

                                else:
                                    raise ValueError(
                                        'No commands were matched.')

                                # find_room_json(words[1], str())
                            except Exception as e:
                                print(e)
                                sc.rtm_send_message(member.channel_id,
                                                    e.args[0])
                                sc.rtm_send_message(
                                    member.channel_id,
                                    'Try: ```help``` or ```book 397``` or ```list 4``` or ```book 375 2pm```'
                                )

        else:
            print("Connection Failed")
コード例 #28
0
ファイル: client.py プロジェクト: pinkeen/evebot
class Client:
    METHOD_GET_USER_INFO = 'users.info'
    METHOD_AUTH_TEST = 'auth.test'
    METHOD_DELETE_MSG = 'chat.delete'

    METHOD_GET_CHANNEL_INFO = {
        Channel.TYPE_CHANNEL: 'channels.info',
        Channel.TYPE_GROUP: 'groups.info'
    }

    METHOD_GET_HISTORY = {
        Channel.TYPE_CHANNEL: 'channels.history',
        Channel.TYPE_GROUP: 'groups.history',
        Channel.TYPE_DIRECT: 'im.history',
    }

    users = {}
    channels = {}

    def __init__(self, api_key):
        self._client = SlackClient(api_key)
        self._logger = logging.getLogger(__name__)
        self._me = None

    def connect(self):
        self._client.rtm_connect()

    def send_message(self, channel, text):
        self._logger.debug('Sent message "%s" to channel "%s"' %
                           (text, channel))

        self._client.rtm_send_message(channel.id, text)

    def ping(self):
        self._client.server.ping()

    def get_user(self, id, force=False):
        if not id in self.users or force:
            response = self.call_method(Client.METHOD_GET_USER_INFO, user=id)

            if response:
                self.users[id] = User(response['user'])
            else:
                self._logger.warn('Could not fetch info for user "%s".' % id)
                return None

        return self.users[id]

    def get_me(self):
        if not self._me:
            response = self.call_method(Client.METHOD_AUTH_TEST)

            if response:
                self._me = self.get_user(response['user_id'])
            else:
                return None

        return self._me

    def get_channel(self, id):
        if id not in self.channels:
            type = Channel.get_channel_type(id)

            if type == Channel.TYPE_DIRECT:
                self.channels[id] = Channel({'id': id})
                return self.channels[id]
            elif type == Channel.TYPE_GROUP:
                data_key = 'group'
            elif type == Channel.TYPE_CHANNEL:
                data_key = 'channel'

            response = self.call_method(self.METHOD_GET_CHANNEL_INFO[type],
                                        channel=id)

            if response:
                self.channels[id] = Channel(response[data_key])
            else:
                self._logger.warn('Could not fetch info for channel "%s".' %
                                  id)
                return None

        return self.channels[id]

    def get_channel_history(self, channel):
        response = self.call_method(self.METHOD_GET_HISTORY[channel.type],
                                    channel=channel.id)

        if not response:
            return None

        return response['messages']

    def delete_message(self, channel, timestamp):
        self.call_method(self.METHOD_DELETE_MSG,
                         channel=channel.id,
                         ts=timestamp)

    def call_method(self, method, **kwargs):
        response = json.loads(
            self._client.api_call(method, **kwargs).decode('utf-8'))

        if not 'ok' in response or not response['ok']:
            if 'error' in response:
                self._logger.warn('API call "%s" failed: %s.' %
                                  (method, response['error']))
            else:
                self._logger.warn('API call "%s" failed.' % method)

            return None

        return response

    def process_special_event(self, event):
        if 'user' in event.data and isinstance(event.data['user'], dict):
            new_user = User(event.user)
            event.data['user'] = new_user
            self.users[new_user.id] = new_user

        if 'channel' in event.data and isinstance(event.data['channel'], dict):
            new_channel = Channel(event.channel)
            event.data['channel'] = new_channel
            self.channels[new_channel.id] = new_channel

    def read_events(self):
        events = []

        try:
            event_datas = self._client.rtm_read()
        except BlockingIOError:
            self._logger.debug('Socket is blocked (by another thread?)...')
            return []

        for event_data in event_datas:
            self._logger.debug('Read event: ' + str(event_data))

            if not 'type' in event_data:
                continue

            event = Event.create(self, event_data)

            self.process_special_event(event)

            # store messages in the channel buffer
            if isinstance(event, Message) and event.is_plain():
                event.channel.store_message(event)

            self._logger.debug('Event parsed:\n' + str(event))

            events.append(event)

        return events
コード例 #29
0
ファイル: bot.py プロジェクト: Dav3xor/1louder
          message = response['text']
          user    = get_dict_item(users, 
                                  response['user'], 
                                  sc.server.users).name
          channel = get_dict_item(channels, 
                                  response['channel'], 
                                  sc.server.channels).name
          domain  = get_dict_item(channels, 
                                  response['channel'], 
                                  sc.server.channels).server.domain
        except:
          continue 
        print "%s (%s/%s) -- %s" % (user, domain, channel, message)

        loud_response = louds.add(message, user, domain, channel)

        if loud_response:
          sc.rtm_send_message(response['channel'], loud_response)
          print "           -- %s" % loud_response
          

        command_response = louds.do_commands(message,user,domain,channel)
        if command_response:
          sc.rtm_send_message(response['channel'], command_response)
          print "           -- %s" % command_response

        
    time.sleep(1)
else:
  print "Can't connect to  Slack?!?"
コード例 #30
0
class RepInstance( object ):
    def __init__( self, actor, oid, apiToken, botToken ):
        self.actor = actor
        self.oid = oid
        self.apiToken = apiToken
        self.botToken = botToken
        self.slack = Slacker( self.apiToken )
        self.bot = SlackClient( self.botToken )
        self.botId = None
        self.invId = str( uuid.uuid4() )
        self.taskId = 0
        self.slackLinkRE = re.compile( r'<.+://.+\|(.+)>' )
        resp = self.actor.huntmanager.request( 'reg_inv', { 'uid' : self.actor.name, 'name' : self.invId } )
        if not resp.isSuccess:
            raise Exception( 'failed to register investigation id for tasking: %s' % resp )

        self.history = { 'last_cmd' : [] }

        self.makeChannel( '#detects' )

        if not self.bot.rtm_connect():
            raise Exception( 'failed to connect bot to Slack rtm API' )

        self.actor.newThread( self.botThread )

    def botThread( self, stopEvent ):
        try:
            # Get our ID
            api_call = self.bot.api_call( "users.list" )
            if api_call.get( 'ok' ):
                for user in api_call.get( 'members' ):
                    if user.get( 'name', '' ) == self.bot.server.username:
                        self.botId = user.get( 'id' )
                        break

            self.actor.log( "found our id %s for %s" % ( self.botId, self.bot.server.username ) )
            self.bot.rtm_send_message( '#general', 'Reporting in.' )

            while not stopEvent.wait( 1.0 ):
                for slackMessage in self.tryToRead():
                    message = unicode( slackMessage.get( 'text' ) )
                    fromUser = slackMessage.get( 'user' )
                    channel = slackMessage.get( 'channel' )
                    if not message or not fromUser or ( '<@%s>' % self.botId ) not in message:
                        continue
                    # Fixing silly quotes form unicode to ascii
                    message = message.replace( u'\u201c', '"' )
                    message = message.replace( u'\u201d', '"' )
                    try:
                        ctx = CommandContext( channel, 
                                              fromUser, 
                                              [ self.stripSlackFormatting( x ) for x in shlex.split( message.replace( '<@%s>' % self.botId, '' ) ) ], 
                                              copy.deepcopy( self.history ) )
                    except:
                        self.bot.rtm_send_message( channel, "error parsing command `%s`: %s" % ( message, traceback.format_exc(), ) )
                    self.actor.newThread( self.executeCommand, ctx )

        except:
            self.actor.log( "Excp: %s while parsing %s" % ( traceback.format_exc(), message ) )
            self.bot.rtm_send_message( "#general", "oops I've fallen and I can't get up: %s" % ( traceback.format_exc(), ) )
            del( self.actor.reps[ oid ] )

        self.actor.log( "bot terminating" )

    def tryToRead( self ):
        while True:
            try:
                return self.bot.rtm_read()
            except:
                self.bot = SlackClient( self.botToken )
                self.bot.rtm_connect()

    def executeCommand( self, stopEvent, ctx ):
        try:
            if 'help' == ctx.cmd[ 0 ]:
                self.sendHelp( ctx )
            elif '?' == ctx.cmd[ 0 ] and 2 <= len( ctx.cmd ):
                self.command_objects( ctx )
            elif '*' == ctx.cmd[ 0 ]:
                self.command_status( ctx )
            elif '.' == ctx.cmd[ 0 ] and 2 == len( ctx.cmd ):
                self.command_host_info( ctx )
            elif '!' == ctx.cmd[ 0 ] and 2 < len( ctx.cmd ):
                self.command_task( ctx )
            elif 'close' == ctx.cmd[ 0 ] and ( 1 == len( ctx.cmd ) or 2 == len( ctx.cmd ) ):
                self.command_close( ctx )
            elif '&gt;' == ctx.cmd[ 0 ] and 2 == len( ctx.cmd ):
                self.command_parent_atom( ctx )
            elif '&lt;' == ctx.cmd[ 0 ] and 2 == len( ctx.cmd ):
                self.command_children_atom( ctx )
            elif '~' == ctx.cmd[ 0 ] and ( 2 == len( ctx.cmd ) or  4 <= len( ctx.cmd ) ):
                self.command_traffic( ctx )
            else:
                self.bot.rtm_send_message( ctx.channel, "what are you talking about, need *help*?" )
        except:
            self.bot.rtm_send_message( ctx.channel, "oops I've fallen and I can't get up: %s" % ( traceback.format_exc(), ) )
            self.actor.log( "Excp: %s" % traceback.format_exc() )

        self.history[ 'last_cmd' ] = ctx.cmd

    def isSensorAllowed( self, ctx, sid ):
        aid = AgentId( sid )
        if aid.org_id is None:
            resp = self.actor.model.request( 'get_sensor_info', { 'id_or_host' : aid } )
            if resp.isSuccess:
                aid = AgentId( resp.data[ 'id' ] )
        if aid.org_id == self.oid:
            return True
        self.bot.rtm_send_message( ctx.channel, "sensor not allowed" )
        return False

    def sendHelp( self, ctx ):
        self.bot.rtm_send_message( ctx.channel, self.prettyJson( 
        {
            'help' : 'this help',
            '?' : [ '? <object_name>: lists the objects of any types with that name',
                    '? <object_name> <object_type> . [of_type]: lists the locations where the object was seen',
                    '? <object_name> <object_type> > [of_type]: lists all the parents of the object',
                    '? <object_name> <object_type> < [of_type}: lists all the children of the object' ],
            '!' : [ '! sensor_id command [arguments...]: execute the command on the sensor, investigation sensor if sensor id not specified' ],
            '>' : [ '> atom_id: get the parent event chain starting at this atom_id.' ],
            '<' : [ '< atom_id: get all the direct children of this atom_id.' ],
            '.' : [ '. [hostname | sensor_id]: get information on a host by name or sensor id' ],
            'close' : [ 'close inv_id: closes the specific inv_id with that conclusion.',
                        'close: closes the inv_id from the current channel with that conclusion.' ],
            '~' : [ '~ atom_id: display the event content with that atom_id.',
                    '~ sensor_id from_time to_time [of_type ...]: display event summaries for all events on sensor_id from from_time to to_time, optionally only of types of_type.' ]
        } ) )

    def command_close( self, ctx ):
        if 1 == len( ctx.cmd ):
            #TODO conclude the investigation, tricky a bit because we need the Hunter.
            self.actor.log( "Archiving channel %s" % ctx.channel )
            self.archiveChannel( ctx.channel )
        elif 2 == len( ctx.cmd ):
            #TODO conclude the investigation, tricky a bit because we need the Hunter.
            self.actor.log( "Archiving channel %s" % ctx.cmd[ 1 ] )
            self.archiveChannel( ctx.cmd[ 1 ] )

    def command_objects( self, ctx ):
        if 2 == len( ctx.cmd ):
            # Query for object types that match the name
            data = self.getModelData( 'get_obj_list', { 'orgs' : self.oid, 'name' : ctx.cmd[ 1 ] } )
            if data is not None:
                self.bot.rtm_send_message( ctx.channel, "here are the objects matching:\n%s\n(valid object types: %s)" % 
                                                        ( self.prettyJson( [ x for x in data[ 'objects' ] if 'RELATION' != x[ 2 ] ] ), str( ObjectTypes.forward.keys() ) ) )
        elif 4 <= len( ctx.cmd ):
            # Query for a characteristic of the object
            if '.' == ctx.cmd[ 3 ]:
                # Query the locations of the object
                data = self.getModelData( 'get_obj_view', { 'orgs' : self.oid, 
                                                            'obj_name' : ctx.cmd[ 1 ], 
                                                            'obj_type' : ctx.cmd[ 2 ].upper() } )
                aid = AgentId( '%s.0.0.0.0' % self.oid )
                if data is not None:
                    output = []
                    output.append( '*Globally*: %s hosts' % data[ 'locs' ].get( data[ 'id' ], '-' ) )
                    for loc in data[ 'olocs' ]:
                        output.append( "*%s*" % ( self.getHostname( loc[ 0 ] ) ) )
                        output.append( '  Last Seen: %s' % self.msTsToTime( loc[ 1 ] ) )
                        output.append( '  SID: %s)\n' % loc[ 0 ] )
                    self.bot.rtm_send_message( ctx.channel, "locations of object *%s* (%s):\n%s" % ( ctx.cmd[ 1 ],
                                                                                                     ctx.cmd[ 2 ].upper(),
                                                                                                     "\n".join( output ) ) )
            elif '&gt;' == ctx.cmd[ 3 ]:
                # Query the parents of the object
                typeFilter = None
                if 5 == len( ctx.cmd ):
                    typeFilter = ctx.cmd[ 4 ].upper()
                data = self.getModelData( 'get_obj_view', { 'orgs' : self.oid, 
                                                            'obj_name' : ctx.cmd[ 1 ], 
                                                            'obj_type' : ctx.cmd[ 2 ].upper() } )
                if data is not None:
                    output = []
                    for parent in data[ 'parents' ]:
                        if typeFilter is not None and typeFilter != parent[ 2 ]: 
                            continue
                        output.append( '*%s* (%s)' % ( parent[ 1 ], parent[ 2 ] ) )
                        output.append( '  Hosts w/ object: %s' % data[ 'locs' ].get( parent[ 0 ], '-' ) )
                        output.append( '  Hosts w/ relation: %s\n' % data[ 'rlocs' ].get( parent[ 0 ], '-' ) )
                    self.bot.rtm_send_message( ctx.channel, "parents of object *%s* (%s):\n%s" % ( ctx.cmd[ 1 ],
                                                                                                   ctx.cmd[ 2 ].upper(),
                                                                                                   "\n".join( output ) ) )
            elif '&lt;' == ctx.cmd[ 3 ]:
                # Query the children of the object
                if 5 == len( ctx.cmd ):
                    typeFilter = ctx.cmd[ 4 ].upper()
                data = self.getModelData( 'get_obj_view', { 'orgs' : self.oid, 
                                                            'obj_name' : ctx.cmd[ 1 ], 
                                                            'obj_type' : ctx.cmd[ 2 ].upper() } )
                if data is not None:
                    output = []
                    for child in data[ 'children' ]:
                        if typeFilter is not None and typeFilter != child[ 2 ]: 
                            continue
                        output.append( '*%s* (%s)' % ( child[ 1 ], child[ 2 ] ) )
                        output.append( '  Hosts w/ object: %s' % data[ 'locs' ].get( child[ 0 ], '-' ) )
                        output.append( '  Hosts w/ relation: %s\n' % data[ 'rlocs' ].get( child[ 0 ], '-' ) )
                    self.bot.rtm_send_message( ctx.channel, "children of object *%s* (%s):\n%s" % ( ctx.cmd[ 1 ],
                                                                                                    ctx.cmd[ 2 ].upper(),
                                                                                                    "\n".join( output ) ) )
        else:
            self.sendHelp( ctx )

    def command_status( self, ctx ):
        orgSensors = self.getOrgSensors()
        sensorDir = self.getSensorDir()
        winSensors = 0
        osxSensors = 0
        linSensors = 0
        winOnline = 0
        osxOnline = 0
        linOnline = 0
        onlineSensors = []
        for sid, sensorInfo in orgSensors.iteritems():
            aid = AgentId( sensorInfo[ 'aid' ] )
            isOnline = False
            if sid in sensorDir:
                isOnline = True
                _, _, curBytes, connectedAt = sensorDir[ sid ]
                onlineSensors.append( ( curBytes, connectedAt, sid ) )
            if aid.isWindows():
                winSensors += 1
                if isOnline:
                    winOnline += 1
            if aid.isMacOSX():
                osxSensors += 1
                if isOnline:
                    osxOnline += 1
            if aid.isLinux():
                linSensors += 1
                if isOnline:
                    linOnline += 1

        del( sensorDir )

        output = []
        output.append( 'Sensor Status:' )
        output.append( '  *Windows:* %d (%d online)' % ( winSensors, winOnline ) )
        output.append( '  *MacOS:* %d (%d online)' % ( osxSensors, osxOnline ) )
        output.append( '  *Linux:* %d (%d online)' % ( linSensors, linOnline ) )
        output.append( '' )

        topTraffic = sorted( onlineSensors, key = lambda x: x[ 0 ], reverse = True )[ : 5 ]
        output.append( 'Top online sensors by data received:' )
        output.append( self.prettyJson( [ { "hostname" : self.getHostname( x[ 2 ] ), 
                                            "sid" : x[ 2 ],
                                            "since" : self.sTsToTime( x[ 1 ] ),
                                            "bytes" : x[ 0 ] } for x in topTraffic ] ) )
        
        self.bot.rtm_send_message( ctx.channel, "\n".join( output ) )

    def command_task( self, ctx ):
        dest = self.getHostInfo( ctx.cmd[ 1 ] )[ 'id' ]
        if not self.isSensorAllowed( ctx, dest ): return
        for token in ctx.cmd:
            if token in ( '-!', '-x', '-@' ):
                self.bot.rtm_send_message( ctx.channel, "special CLI flags -x, -! and -@ are not allowed." )
                return
        taskFuture = self.task( ctx, dest, ctx.cmd[ 2 : ] )
        if taskFuture is not None:
            try:
                if taskFuture.wait( 120 ):
                    start = time.time()
                    while time.time() < start + 30:
                        try:
                            resp = taskFuture.responses.pop()
                            data = self.prettyJson( resp )
                            atom = base64.b64decode( _x_( resp, '?/hbs.THIS_ATOM' ) )
                            self.slack.chat.post_message( ctx.channel, 
                                                          attachments = [ { "text" : data, 
                                                                            "pretext" : "Result from *%s* on *%s*" % ( str( ctx.cmd[ 2 : ] ), AgentId( dest ).sensor_id ),
                                                                            "fallback" : "received task response",
                                                                            "mrkdwn_in" : [ "text", "pretext" ],
                                                                            "fields" : [ { "link" : "%s/explore?atid=%s" % ( self.actor.uiDomain, uuid.UUID( bytes = atom ) ) } ] } ] )
                        except IndexError:
                            time.sleep( 1 )
                elif taskFuture.wasReceived:
                    self.actor.log( taskFuture.responses )
                    self.slack.chat.post_message( ctx.channel, "... task was received but no reply received" )
                else:
                    self.slack.chat.post_message( ctx.channel, "... haven't received a reply" )
            finally:
                taskFuture.done()

    def command_parent_atom( self, ctx ):
        interpreter = EventInterpreter()
        data = []
        for evt in self.crawlUpParentTree( None, rootAtom = ctx.cmd[ 1 ] ):
            interpreter.setEvent( evt )
            data.append( { "type" : interpreter.name(),
                           "atom" : interpreter.getAtom(),
                           "narrative" : interpreter.narrative() } )
            
        render = self.sanitizeJson( { "fallback" : "Events going up from: %s." % ctx.cmd[ 1 ],
                                      "pretext" : "Events going up from: %s." % ctx.cmd[ 1 ],
                                      "text" : self.prettyJson( data ),
                                      "mrkdwn_in" : [ "text", "pretext" ] } )
        self.slack.chat.post_message( ctx.channel, attachments = [ render ] )
        

    def command_children_atom( self, ctx ):
        interpreter = EventInterpreter()
        children = self.getChildrenAtoms( ctx.cmd[ 1 ], depth = 1 )
        if children is None:
            self.slack.chat.post_message( ctx.channel, "couldn't fetch children for %s" % ctx.cmd[ 1 ] )
        else:
            data = []
            for evt in children:
                interpreter.setEvent( evt )
                data.append( { "type" : interpreter.name(),
                               "atom" : interpreter.getAtom(),
                               "narrative" : interpreter.narrative() } )
            render = self.sanitizeJson( { "fallback" : "Direct children events of: %s." % ctx.cmd[ 1 ],
                                          "pretext" : "Direct children events of: %s." % ctx.cmd[ 1 ],
                                          "text" : self.prettyJson( data ),
                                          "mrkdwn_in" : [ "text", "pretext" ] } )
            self.slack.chat.post_message( ctx.channel, attachments = [ render ] )

    def command_host_info( self, ctx ):
        hostOrId = ctx.cmd[ 1 ]
        hostInfo = self.getHostInfo( hostOrId )
        if not self.isSensorAllowed( ctx, hostInfo[ 'id' ] ): return
        self.bot.rtm_send_message( ctx.channel, "host info for *%s*: %s" % ( ctx.cmd[ 1 ], self.prettyJson( hostInfo ) ) )

    def command_traffic( self, ctx ):
        if 2 == len( ctx.cmd ):
            self.slack.chat.post_message( ctx.channel, 
                                          attachments = [ { "fallback" : "event",
                                                            "mrkdwn_in" : [ "text", "pretext" ],
                                                            "pretext" : "Event %s" % ctx.cmd[ 1 ],
                                                            "text" : self.prettyJson( self.getSingleAtom( ctx.cmd[ 1 ] ) ) } ] )
        elif 4 <= len( ctx.cmd ):
            self.actor.log( "CMD: %s" % str(ctx.cmd) )
            _, aid, after, before = ctx.cmd[ : 4 ]
            try:
                aid = AgentId( aid )
            except:
                aid = AgentId( self.getHostInfo( aid )[ 'id' ] )
            ofTypes = ctx.cmd[ 4 : ]
            if 0 == len( ofTypes ):
                ofTypes = None
            else:
                ofTypes = [ x if '.' in x else ( 'notification.%s' % x.upper() ) for x in ofTypes ]
            try:
                after = int( after )
            except:
                after = ( dateutil.parser.parse( after ) - datetime.datetime( 1970, 1, 1 ) ).total_seconds()
            try:
                before = int( before )
            except:
                before = ( dateutil.parser.parse( before ) - datetime.datetime( 1970, 1, 1 ) ).total_seconds()
            if not self.isSensorAllowed( ctx, aid ): return
            interpreter = EventInterpreter()
            timeline = self.getModelData( 'get_timeline', { 'id' : aid, 
                                                            'after' : after, 
                                                            'before' : before,
                                                            'types' : ofTypes,
                                                            'is_include_content' : True } )
            if timeline is None: return
            events = []
            for data in timeline[ 'events' ]:
                interpreter.setEvent( data[ 3 ] )
                events.append( { "type" : interpreter.name(),
                                 "atom" : interpreter.getAtom(),
                                 "narrative" : interpreter.narrative() } )
            render = self.sanitizeJson( { "fallback" : "Traffic for %s between %s and %s." % ( aid.sensor_id, after, before ),
                                          "pretext" : "Traffic for %s between %s and %s." % ( aid.sensor_id, after, before ),
                                          "text" : self.prettyJson( events ),
                                          "mrkdwn_in" : [ "text", "pretext" ] } )
            self.slack.chat.post_message( ctx.channel, attachments = [ render ] )

    def getModelData( self, request, requestData = {} ):
        resp = self.actor.model.request( request, requestData, timeout = 10.0 )
        if resp.isSuccess:
            return resp.data
        else:
            self.actor.log( "error getting data from model: %s" % str( resp ) )
            return None

    def getSensorDir( self ):
        directory = {}
        data = self.actor.sensordir.request( 'get_dir', {} )
        if data.isSuccess:
            directory = data.data[ 'dir' ]
        return directory

    def getOrgSensors( self ):
        sensors = {}
        aid = AgentId( '%s.0.0.0.0' % self.oid )
        data = self.getModelData( 'list_sensors', { 'aid' : aid } )
        if data is not None:
            sensors = data
        return sensors

    def sanitizeJson( self, o ):
        if type( o ) is dict:
            for k, v in o.iteritems():
                o[ k ] = self.sanitizeJson( v )
        elif type( o ) is list or type( o ) is tuple:
            o = [ self.sanitizeJson( x ) for x in o ]
        elif type( o ) in ( uuid.UUID, AgentId ):
            o = str( o )
        else:
            try:
                if ( type(o) is str or type(o) is unicode ) and "\x00" in o: raise Exception()
                json.dumps( o )
            except:
                o = base64.b64encode( o )

        return o

    def prettyJson( self, o, indent = 2 ):
        txt = json.dumps( self.sanitizeJson( o ), indent = indent )
        overflow = ''
        if 7000 < len( txt ):
            txt = txt[ : 7000 ]
            overflow = '\n\n*output too large...*'
        return '```%s```%s' % ( txt, overflow )

    def stripSlackFormatting( self, token ):
        res = self.slackLinkRE.match( token )
        if res is not None:
            return res.groups()[ 0 ]
        return token

    def makeChannel( self, name ):
        try:
            self.slack.channels.create( '%s' % name )
        except:
            return False
        return True

    def archiveChannel( self, name ):
        try:
            # Remove the prefix #
            name1 = name.lower()
            name2 = name[ 1 : ].lower()
            cid = None
            for channel in self.slack.channels.list().body[ 'channels' ]:
                if channel[ 'name' ].lower() in ( name1, name2 ) or channel[ 'id' ].lower() in ( name1, name2 ):
                    cid = channel[ 'id' ]
                    break
            if cid is not None:
                self.slack.channels.archive( cid )
        except:
            self.bot.rtm_send_message( name, "error archiving channel (%s): %s" % ( cid, traceback.format_exc(), ) )
            self.actor.log( "Excp: %s" % traceback.format_exc() )
            return False
        return True

    def inviteToChannel( self, name ):
        try:
            name1 = name.lower()
            name2 = name[ 1 : ].lower()
            cid = None
            for channel in self.slack.channels.list().body[ 'channels' ]:
                if channel[ 'name' ].lower() in ( name1, name2 ) or channel[ 'id' ].lower() in ( name1, name2 ):
                    cid = channel[ 'id' ]
                    break
            if cid is not None:
                self.slack.channels.invite( cid, self.botId )
            else:
                self.actor.log( "Channel not found: %s" % name )
        except:
            self.actor.log( 'EXC: %s' % traceback.format_exc() )
            return False
        return True

    def getHostname( self, aid ):
        try:
            return self.actor.model.request( 'get_sensor_info', { 'id_or_host' : str( aid ) } ).data[ 'hostname' ]
        except:
            return '-'

    def getHostInfo( self, aidOrHostnam ):
        try:
            return self.actor.model.request( 'get_sensor_info', { 'id_or_host' : str( aidOrHostnam ) } ).data
        except:
            return None

    def msTsToTime( self, ts ):
        if type( ts ) in ( str, unicode ):
            ts = ts.split( '.' )[ 0 ]
        return datetime.datetime.fromtimestamp( float( ts ) / 1000 ).strftime( '%Y-%m-%d %H:%M:%S.%f' )

    def sTsToTime( self, ts ):
        return self.msTsToTime( ts * 1000 ).split( '.' )[ 0 ]

    def newDetect( self, sources, detect ):
        hostNames = [ self.getHostname( x ) for x in sources ]
        atom = _x_( detect[ 'detect' ], '?/hbs.THIS_ATOM' )
        message = [ 'Detected *%s* on *%s*:' % ( detect[ 'cat' ], ', '.join( hostNames ) ) ]
        message.append( 'Summary: %s.' % detect[ 'summary' ] )
        message.append( 'Link to sensor: %s' % ' '.join( [ ( '%s/sensor?sid=%s' % ( self.actor.uiDomain, x.sensor_id ) ) for x in sources ] ) )
        if atom is not None:
            message.append( 'Link to event: %s/explore?atid=%s' % ( self.actor.uiDomain, uuid.UUID( bytes = atom ) ) )
        detectAttachment = { "text" : self.prettyJson( detect[ 'detect' ] ), 
                             "fallback" : "Detection Data",
                             "mrkdwn_in": [ "text", "pretext" ] }
        self.slack.chat.post_message( '#detects', '\n'.join( message ), attachments = [ detectAttachment ] )

    def renderInvHeader( self, inv, sources ):
        render = { "fallback" : "New investigation (ID: %s) created on %s." % ( inv[ 'inv_id' ], inv[ 'generated' ] ),
                   "pretext" : "New investigation.",
                   "author_name" : inv[ 'hunter' ],
                   "fields" : [],
                   "mrkdwn_in": [ "text", "pretext" ] }
        for source in sources:
            render[ "fields" ].append( { "title" : self.getHostname( source ), "value" : source.sensor_id, "short" : True } )
        return self.sanitizeJson( render )

    def renderNewTasking( self, inv, task ):
        render = { "fallback" : "New tasking sent: %s." % str( task[ 'data' ] ),
                   "pretext" : "New tasking sent: `%s`." % task[ 'why' ],
                   "text" : self.prettyJson( task[ 'data' ], indent = None ),
                   "fields" : [ { "title" : "Sent", "value" : ( "yes" if task[ 'sent' ] else "no" ), "short" : True } ],
                   "mrkdwn_in": [ "text", "pretext" ] }
        return self.sanitizeJson( render )

    def renderNewData( self, inv, data ):
        render = { "fallback" : "Reporting new data.",
                   "pretext" : "Reporting new data: `%s`." % data[ 'why' ],
                   "mrkdwn_in": [ "text", "pretext" ] }
        if 0 != len( data[ 'data' ] ):
            render[ "text" ] = self.prettyJson( data[ 'data' ] )
        return self.sanitizeJson( render )

    def renderInvConclusion( self, inv ):
        render = { "fallback" : "Investigation concluded on %s." % inv[ 'closed' ],
                   "pretext" : "Investigation concluded,",
                   "author_name" : inv[ 'hunter' ],
                   "mrkdwn_in": [ "text", "pretext" ],
                   "fields" : [ { "title" : "Reasoning", "value" : inv[ 'why' ], "short" : True },
                                { "title" : "Nature", "value" : InvestigationNature.lookup[ inv[ 'nature' ] ], "short" : True },
                                { "title" : "Conclusion", "value" : InvestigationConclusion.lookup[ inv[ 'conclusion' ] ], "short" : True },
                                { "title" : "Closed On", "value" : inv[ 'closed' ], "short" : True } ] }
        return self.sanitizeJson( render )

    def newInvestigation( self, sources, investigation ):
        hostNames = [ self.getHostname( x ) for x in sources ]
        channelName = '#inv_%s' % ( investigation[ 'inv_id' ][ : 8 ] )
        self.makeChannel( channelName )
        self.inviteToChannel( channelName )

        self.slack.chat.post_message( channelName, attachments = [ self.renderInvHeader( investigation, sources ) ] )

        for evt in sorted( investigation[ 'data' ] + investigation[ 'tasks' ], key = lambda x: x[ 'generated' ] ):
            if evt.get( 'sent', None ) is not None:
                self.slack.chat.post_message( channelName, attachments = [ self.renderNewTasking( investigation, evt )] )
            else:
                self.slack.chat.post_message( channelName, attachments = [ self.renderNewData( investigation, evt )] )

        self.slack.chat.post_message( channelName, attachments = [ self.renderInvConclusion( investigation ) ] )

        if investigation[ 'nature' ] in ( InvestigationNature.FALSE_POSITIVE, InvestigationNature.DUPLICATE ):
            self.archiveChannel( channelName )

    def task( self, ctx, dest, cmdsAndArgs ):
        ret = None
        if type( cmdsAndArgs[ 0 ] ) not in ( tuple, list ):
            cmdsAndArgs = ( cmdsAndArgs, )
        if not self.isSensorAllowed( ctx, dest ): return
        data = { 'dest' : dest, 'tasks' : cmdsAndArgs }

        # Currently Hunters only operate live
        data[ 'expiry' ] = 0
        trxId = '%s//%s' % ( self.invId, self.taskId )
        self.taskId += 1
        data[ 'inv_id' ] = trxId

        # We start listening for an answer before sending the tasking
        # so that we are sure to beat the race in case an answer comes
        # back really quickly.
        ret = _TaskResp( trxId, self.actor )

        def _syncRecv( msg ):
            routing, event, mtd = msg.data
            ret._add( event )
            return ( True, )

        self.actor.handle( trxId, _syncRecv )

        resp = self.actor.tasking.request( 'task', data, key = dest, timeout = 30, nRetries = 0 )
        if resp.isSuccess:
            msg = "sent for tasking: %s" % ( str(cmdsAndArgs), )
            self.actor.log( msg )
            self.slack.chat.post_message( ctx.channel, msg )
        else:
            if 'usage' == resp.error:
                msg = "```%s```" % resp.data
            else:
                msg = "failed to send tasking: ```%s```" % resp
            self.actor.log( msg )
            self.slack.chat.post_message( ctx.channel, msg )
            # Well we listened for nothing, cleanup.
            ret.done()
            ret = None

        return ret

    def getSingleAtom( self, id ):
        resp = self.actor.model.request( 'get_atoms_from_root', { 'id' : id, 'depth' : 0 } )
        if resp.isSuccess and 0 < len( resp.data ):
            return resp.data[ 0 ]
        else:
            return None

    def getChildrenAtoms( self, id, depth = 5 ):
        resp = self.actor.model.request( 'get_atoms_from_root', { 'id' : id, 'depth' : depth } )
        if resp.isSuccess:
            return resp.data
        else:
            return None

    # This is a generator
    def crawlUpParentTree( self, rootEvent, rootAtom = None ):
        currentEvent = rootEvent
        while True:
            if currentEvent is None and rootAtom is not None:
                parentAtom = rootAtom
            else:
                parentAtom = _x_( currentEvent, '?/hbs.PARENT_ATOM' )
            if parentAtom is None:
                return
            parentEvent = self.getSingleAtom( parentAtom )
            if parentEvent is None:
                return
            currentEvent = parentEvent
            yield parentEvent
コード例 #31
0
 try:
     if last_read[0].get('file') is None or last_read[0].get('file').get('url_private') is None:
         parsed = last_read[0]['text']
         #reply to channel message was found in.
         message_channel = last_read[0]['channel']
         if parsed and 'projects' in parsed.lower():
             msg = get_msg_of_project_lists()
         elif parsed and len(re.compile('\d+').findall(parsed))>0:
             msg = get_msg_by_project(int(re.compile('\d+').findall(parsed)[0]))
         elif parsed and 'today' in parsed.lower():
             msg = get_msg_by_date(date.today())
         elif parsed and 'tomorrow' in parsed.lower():
             msg = get_msg_by_date(date.today() + timedelta(days=1))
         else:
             msg ='Hello naughty tester, I don\'t understand what you want\r\n Please type "projects" to see the project list\r\nType "today" or "tomorrow" to see the deployment of these days'
         client.rtm_send_message(message_channel, msg)
     elif last_read[0].get('file') is not None and last_read[0].get('file').get('url_private') is not None:
         url = str(last_read[0]['file']['url_private'])
         file_type = str(last_read[0]['file']['filetype'])
         response = requests.get(url, headers={'Authorization': 'Bearer %s' % api_key}, stream = True)
         temp_name = 'abc_temp.%s' % file_type
         message_channel = last_read[0]['channel']
         with open(temp_name, 'wb') as out_file:
             response.raw.decode_content = True
             shutil.copyfileobj(response.raw, out_file)
         projects = parse_workbook(temp_name)
         os.remove(holden_xlsx)
         os.rename(temp_name, holden_xlsx)
         client.rtm_send_message(message_channel, 'Thank you for uploading new schedule!')
         del response
 except IOError as e:
コード例 #32
0
 def handle(self, *args, **options):
     team = Team.objects.first()
     client = SlackClient("xoxb-335086709553-AVM6StX7HqYoW1xj0IrjXooN")
     self.mainLobby = Lobby()
     self.mainGame = None
     self.userDict = dict()
     self.gameActive = False
     self.teamID = "C9VNBVCA1"
     if client.rtm_connect():
         while True:
             events = client.rtm_read()
             print("%s----%s" % (team, events))
             for event in events:
                 if 'subtype' in event and event['subtype'] == 'bot_message':
                     continue
                 elif 'type' in event and event['type'] == 'message':
                     userID = event['user']
                     channelID = event['channel']
                     msgText = event['text']
                     username = client.server.users[userID].real_name
                     regex = r'^!set (\w+) (\w+)$'
                     if re.match(regex, msgText):
                         matches = re.match(regex, event['text'])
                         codename, dword = matches[1], matches[2]
                         if userID in self.userDict:
                             if self.userDict[userID].active:
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text=
                                     "Unable to modify character while in game.",
                                     user=userID)
                                 continue
                             else:
                                 self.setName(userID, codename)
                                 self.setDW(userID, dword)
                         else:
                             self.userDict[userID] = Assassin(
                                 userID, username, codename, dword)
                         client.api_call("chat.postEphemeral",
                                         channel=channelID,
                                         text=str(self.userDict[userID]),
                                         user=userID)
                         continue
                     regex = r'^!setname (\w+)$'
                     if re.match(regex, msgText):
                         name = re.match(regex, msgText)[1]
                         if userID in self.userDict:
                             if self.userDict[userID].active:
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text=
                                     "Unable to modify codename while in game.",
                                     user=userID)
                                 continue
                             else:
                                 self.setName(userID, name)
                         else:
                             self.userDict[userID] = Assassin(userID,
                                                              username,
                                                              codeName=name)
                         client.api_call("chat.postEphemeral",
                                         channel=channelID,
                                         text=str(self.userDict[userID]),
                                         user=userID)
                         continue
                     regex = r'^!setdword (\w+)$'
                     if re.match(regex, msgText):
                         dword = re.match(regex, msgText)[1]
                         if userID in self.userDict:
                             if self.userDict[userID].active:
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text=
                                     "Unable to modify deathword while in game.",
                                     user=userID)
                                 continue
                             else:
                                 self.setDW(userID, dword)
                         else:
                             self.userDict[userID] = Assassin(userID,
                                                              username,
                                                              dw=dword)
                         client.api_call("chat.postEphemeral",
                                         channel=channelID,
                                         text=str(self.userDict[userID]),
                                         user=userID)
                         continue
                     regex = r'^!self$'
                     if re.match(regex, msgText):
                         if userID in self.userDict:
                             client.api_call("chat.postEphemeral",
                                             channel=channelID,
                                             text=str(
                                                 self.userDict[userID]),
                                             user=userID)
                         else:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text=
                                 "Please create a character using commands !set, !setname or !setdword",
                                 user=userID)
                         continue
                     regex = r'^!joinlobby$'
                     if re.match(regex, msgText):
                         if self.gameActive:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text=
                                 "Game is already in progress, please wait for the next game.",
                                 user=userID)
                         elif userID in self.userDict:
                             if self.userDict[
                                     userID] in self.mainLobby.players:
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text="You are already in the lobby.",
                                     user=userID)
                             else:
                                 self.joinLobby(userID)
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text="You have joined the lobby.",
                                     user=userID)
                                 client.rtm_send_message(
                                     self.teamID,
                                     self.userDict[userID].codeName +
                                     " has joined the Lobby.")
                                 client.rtm_send_message(
                                     self.teamID, str(self.mainLobby))
                         else:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text=
                                 "Please create a character first by using commands:\n!set, !setname or !setdword",
                                 user=userID)
                         continue
                     regex = r'^!leavelobby$'
                     if re.match(regex, msgText):
                         if self.gameActive:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text="Unable to leave lobby while in game.",
                                 user=userID)
                         elif userID not in self.userDict:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text=
                                 "Please create a character first by using commands:\n!set, !setname or !setdword.",
                                 user=userID)
                         elif self.userDict[
                                 userID] in self.mainLobby.players:
                             self.leaveLobby(userID)
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text="You have left the lobby.",
                                 user=userID)
                             client.rtm_send_message(
                                 self.teamID,
                                 self.userDict[userID].codeName +
                                 " has left the Lobby.")
                             client.rtm_send_message(
                                 self.teamID, str(self.mainLobby))
                         else:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text="You are not in the lobby.",
                                 user=userID)
                         continue
                     regex = r'^!scores$'
                     if re.match(regex, msgText):
                         client.api_call("chat.postEphemeral",
                                         channel=channelID,
                                         text=str(self.mainLobby),
                                         user=userID)
                         continue
                     regex = r'^!startgame$'
                     if re.match(regex, msgText):
                         if self.gameActive:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text="Game has already started.",
                                 user=userID)
                         elif len(self.mainLobby.players) < 1:
                             client.api_call(
                                 "chat.postEphemeral",
                                 channel=channelID,
                                 text="Lobby must have at least 1 player.",
                                 user=userID)
                         else:
                             self.startGame()
                             for p in self.mainLobby.players:
                                 client.api_call("chat.postEphemeral",
                                                 channel=self.teamID,
                                                 text="Your target is: " +
                                                 p.target.realName,
                                                 user=p.userID)
                                 client.api_call("chat.postEphemeral",
                                                 channel=channelID,
                                                 text=str(
                                                     self.userDict[userID]),
                                                 user=userID)
                             client.rtm_send_message(
                                 self.teamID,
                                 "Game has begun.\n\nCurrent Scores:")
                             client.rtm_send_message(
                                 self.teamID, str(self.mainLobby))
                         continue
                     regex = r'!kill (\w+)\s?(.*)?$'
                     if re.match(regex, msgText):
                         if self.gameActive:
                             if userID not in self.userDict:
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text=
                                     "Please create a character first by using commands:\n!set, !setname or !setdword.",
                                     user=userID)
                             elif self.userDict[userID].active:
                                 matches = re.match(regex, msgText)
                                 dw = matches[1]
                                 deathMsg = "\n" + matches[2]
                                 killer = self.userDict[userID]
                                 victim = self.killPlayer(dw, killer)
                                 if victim is not None:
                                     client.api_call(
                                         "chat.postEphemeral",
                                         channel=self.teamID,
                                         text="You have been eliminated by "
                                         + killer.codeName + " (" +
                                         killer.realName + ").",
                                         user=victim.userID)
                                     client.api_call(
                                         "chat.postEphemeral",
                                         channel=channelID,
                                         text="Target eliminated.\nYou have "
                                         + str(killer.kills) +
                                         " confirmed kills.",
                                         user=userID)
                                     client.rtm_send_message(
                                         self.teamID, victim.codeName +
                                         " (" + victim.realName + ")" +
                                         " has been assassinated by " +
                                         killer.codeName + "." + deathMsg)
                                     client.rtm_send_message(
                                         self.teamID, str(self.mainLobby))
                                     if len(self.mainGame.loop) < 2:
                                         client.rtm_send_message(
                                             self.teamID,
                                             "Game over.\n\nFinal Scores:")
                                         client.rtm_send_message(
                                             self.teamID,
                                             str(self.mainLobby))
                                         client.api_call(
                                             "chat.postEphemeral",
                                             channel=channelID,
                                             text=
                                             "Congratulations! You have won the game.",
                                             user=userID)
                                         self.endGame()
                                     else:
                                         client.api_call(
                                             "chat.postEphemeral",
                                             channel=channelID,
                                             text="Your new target is: " +
                                             killer.target.realName,
                                             user=userID)
                                 else:
                                     client.api_call(
                                         "chat.postEphemeral",
                                         channel=channelID,
                                         text="Incorrect death word.",
                                         user=userID)
                             else:
                                 client.api_call(
                                     "chat.postEphemeral",
                                     channel=channelID,
                                     text=
                                     "You cannot kill while eliminated.",
                                     user=userID)
                         else:
                             client.api_call("chat.postEphemeral",
                                             channel=channelID,
                                             text="Game has not yet begun.",
                                             user=userID)
                         continue
                     regex = r'^!help$'
                     if re.match(regex, msgText):
                         client.api_call("chat.postEphemeral",
                                         channel=channelID,
                                         text=self.helpText(),
                                         user=userID)
                         continue
             time.sleep(1)
コード例 #33
0
ファイル: snickybot.py プロジェクト: nickyringland/snickybot
for sourcename in tutors_dict:
    print("added user from db: {} => {}".format(sourcename,
                                                tutors_dict[sourcename]))

# now open it again to append more logs
username_file = open(LOOKUP_FILE, 'a')
reaction_file = open(REACTION_FILE, 'a')

# connect to Slack
sc = SlackClient(SLACK_TOKEN)

# connect to RTM API which feeds us stuff that happens
if not sc.rtm_connect(with_team_state=False, auto_reconnect=True):
    raise Exception("couldn't connect to RTM api")
sc.rtm_send_message("welcome-test", "test")


def is_checked_hour(hour):
    if UTCHOURS_ACTIVE_START > UTCHOURS_ACTIVE_END:
        # start later than end
        return hour >= UTCHOURS_ACTIVE_START or hour < UTCHOURS_ACTIVE_END
    # normal contiguous range
    return hour >= UTCHOURS_ACTIVE_START and hour < UTCHOURS_ACTIVE_END


def format_real_name(real_name):
    if real_name in tutors_dict:
        slackid = tutors_dict[real_name]
        return '<@{}>'.format(slackid)
    return '{}'.format(real_name)
コード例 #34
0
class SpotifySlackBot():
    def __init__(self, api_key, broadcast_channel):
        self.broadcast_channel = broadcast_channel
        self.sc = SlackClient(api_key)

        # Get the user list
        response = self.sc.api_call('users.list')
        self.users = json.loads(response)['members']

    def command_current_song(self, event):
        data = self.run_spotify_script('current-song')
        data = data.strip().split('\n')
        data = {"id": data[0], "name": data[1], "artist": data[2]}
        message = "Hey, the current song is *%s* by *%s*. You can open it on Spotify: %s" % (
            data['name'], data['artist'], data['id'])

        self.sc.rtm_send_message(event['channel'], message)

    def command_playback_play(self, event):
        self.run_spotify_script('playback-play')
        self.sc.rtm_send_message(
            self.broadcast_channel, "*Resumed playback*, as requested by %s." %
            (self.get_username(event['user'])))
        self.sc.rtm_send_message(event['channel'], "Sure, let the music play!")

    def command_playback_pause(self, event):
        self.run_spotify_script('playback-pause')
        self.sc.rtm_send_message(
            self.broadcast_channel, "*Paused playback*, as requested by %s." %
            (self.get_username(event['user'])))
        self.sc.rtm_send_message(event['channel'],
                                 "Alright, let's have some silence for now.")

    def command_playback_skip(self, event):
        self.run_spotify_script('playback-skip')
        self.sc.rtm_send_message(
            self.broadcast_channel,
            "*Skipping this song*, as requested by %s." %
            (self.get_username(event['user'])))
        self.sc.rtm_send_message(event['channel'],
                                 "Sure, let's listen to something else...")

    def command_help(self, event):
        self.sc.rtm_send_message(
            event['channel'],
            "Hey, how are you?  I'm here to help you using our office playlist.\n"
            "I can give you some information about what is playing right now. Just send the command:\n"
            "- `song`: I'll tell you which song is playing and who is the artist.\n"
            "\n"
            "I can also control the playlist, with the following commands:\n"
            "- `play`: I'll resume playback of the playlist, if it is paused.\n"
            "- `pause`: I'll pause the playback of the playlist, if it is playing.\n"
            "- `skip`: I'll skip the current song and play another one.\n"
            "\n"
            "*Please note:* When you give commands to control the playlist, *I'll advertise on #spotify-playlist that you asked me to do it*, just so everyone knows what is going on. Please use these only if you really need to :)"
        )

    def command_unknown(self, event):
        self.sc.rtm_send_message(
            event['channel'],
            "Hey there! I kinda didn't get what you mean, sorry. If you need, just say `help` and I can tell you how I can be of use. ;)"
        )

    def run_spotify_script(self, *args):
        return check_output(['./spotify.applescript'] + list(args))

    def get_username(self, id):
        for user in self.users:
            if user['id'] == id:
                return '@%s' % user['name']
        return 'someone'

    def run(self):
        commands = [('song', self.command_current_song),
                    ('play', self.command_playback_play),
                    ('pause', self.command_playback_pause),
                    ('skip|next', self.command_playback_skip),
                    ('hey|help', self.command_help),
                    ('.+', self.command_unknown)]

        if self.sc.rtm_connect():
            while True:
                events = self.sc.rtm_read()
                for event in events:
                    print event
                    if event.get('type') == 'message' and event.get(
                            'channel')[0] == 'D':
                        for (expression, function) in commands:
                            if re.match(expression, event['text']):
                                function(event)
                                break
                time.sleep(1)
コード例 #35
0
class RtmBot(object):
    """Run plugins and check slack for status periodically"""
    def __init__(self,
                 token,
                 channel="C0LL5MDKN",
                 interval=0.3,
                 ping_interval=5):
        self.channel = channel or "C0LL5MDKN"
        self.interval = interval
        self.ping_interval = min(max(ping_interval, 2), 3600)
        self.first_ping = 0
        self.last_ping = 0
        self.token = token
        self.bot_plugins = []
        self.slack_client = None
        self.last_output = None

    def connect(self):
        """Convenience method that creates Server instance"""
        self.slack_client = SlackClient(self.token)
        self.slack_client.rtm_connect()

    def start(self):
        self.connect()
        self.load_plugins()
        while True:
            for reply in self.slack_client.rtm_read():
                dbg('reply: {}'.format(reply))
                self.input(reply)
            self.crons()
            self.output()
            self.autoping()
            time.sleep(self.interval)
            if DEBUG and (10 < (time.time() - self.first_ping) <
                          (10 + self.interval * 2)) and not self.last_output:
                ans = self.slack_client.rtm_send_message(
                    self.channel, "I'm alive!")
                dbg('Answer to send_message: {}'.format(ans))

    def autoping(self):
        """Automatically ping the server every 3 seconds"""
        now = int(time.time())
        if now > self.last_ping + self.ping_interval:
            self.first_ping = self.first_ping or now
            self.slack_client.server.ping()
            dbg('Next ping in {}s'.format(self.ping_interval))
            self.last_ping = now

    def input(self, data):
        if "type" in data:
            function_name = "process_" + data["type"]
            dbg("got {}".format(function_name))
            for plugin in self.bot_plugins:
                plugin.register_jobs()
                plugin.do(function_name, data)

    def output(self):
        for plugin in self.bot_plugins:
            limiter = False
            for output in plugin.do_output():
                dbg('Found {} output: {}'.format(plugin, output))
                channel = self.slack_client.server.channels.find(output[0])
                if channel is not None and output[1] is None:
                    if limiter is True:
                        time.sleep(.1)
                        limiter = False
                    message = output[1].encode('ascii', 'ignore')
                    channel.send_message("{}".format(message))
                    self.last_output = time.time()
                    limiter = True

    def crons(self):
        for plugin in self.bot_plugins:
            plugin.do_jobs()

    def load_plugins(self):
        for plugin in glob.glob(directory + '/plugins/*'):
            sys.path.insert(0, plugin)
            sys.path.insert(0, directory + '/plugins/')
        for plugin in glob.glob(directory + '/plugins/*.py') + glob.glob(
                directory + '/plugins/*/*.py'):
            logging.info(plugin)
            name = plugin.split('/')[-1][:-3]
            self.bot_plugins.append(Plugin(name))
        print('Loaded: {}'.format(self.bot_plugins))
コード例 #36
0
ファイル: iris.py プロジェクト: theabraxas/SuperSlackBot
class Iris:
    """The Iris Slack bot engine."""

    def __init__(self, slack_token, command_handlers):
        self.sc = SlackClient(slack_token)
        self.command_handlers = command_handlers
        self._signal_handler = ExitOnSignal()

    def run(self):
        """Run the Iris bot using the configured commands."""
        if self.sc.rtm_connect():
            print("> Successfully connected to Slack! Starting the Iris bot...")
            while True:
                # Check the signal handler to make sure we are breaking if necessary.
                if self._signal_handler.kill_now:
                    print("> Terminating the Iris bot...")
                    break

                # Read events from Slack, then parse that list of events into IrisCommand objects.
                events = self.sc.rtm_read()
                commands = self.convert_commands(self.filter_commands(events))

                # Handle each IrisCommand received from Slack.
                for command in commands:
                    self.handle_command(command)

                # Sleep so that we're polite to Slack. There does not seem to be a blocking
                # approach available at this time so this will have to do.
                time.sleep(0.1)
        else:
            print("Failed to connect to Slack. Please verify you have a valid token.")

    @staticmethod
    def _is_command(event):
        """True if the event is a command, false otherwise. Commands are Slack messages that start with '!',
        the command identifier, and contain all required fields."""
        if 'type' in event and 'text' in event and 'user' in event and 'channel' in event:
            return event['type'] == 'message' and str(event['text']).startswith("!")
        else:
            return False

    @staticmethod
    def _command_name(cmd):
        """Extract the name of a command."""
        # We say that the name is any character up until the first space.
        # When we use this command, we already know that the string starts with an '!', the command identifier.
        # We ignore the command identifier with [1:], and then take a single split by space. The single split
        # will produce an array of size two with the first element being to the left of the space, and the second
        # element being to the right of the space. We'll use this same approach to extract the content as well.
        return str(cmd['text'])[1:].split(" ", 1)[0]

    @staticmethod
    def _command_content(cmd):
        """Extract the content of a command."""
        splits = str(cmd['text']).split(" ", 1)
        if len(splits) > 1:
            return splits[1]
        else:
            return ""

    def _to_command(self, cmd):
        """Builds an IrisCommand from the given Slack event."""
        return IrisCommand(self._command_name(cmd), cmd['user'], cmd['channel'], self._command_content(cmd))

    def filter_commands(self, events):
        """Given some list of events, filter such that only the commands remain."""
        return list(filter(lambda evt: self._is_command(evt), events))

    def convert_commands(self, commands):
        """Given some list of commands, convert them into IrisCommand objects."""
        return list(map(lambda cmd: self._to_command(cmd), commands))

    def handle_command(self, command):
        """Given some command, parse it and act upon it if the command is registered."""
        if command.name in self.command_handlers:
            handler = self.command_handlers[command.name]
            handler.handle_command(self.sc, command)
            return True
        else:
            print("No handler exists for command \'" + command.name + "\'.")
            self.sc.rtm_send_message(command.channel,
                                     "No such command \'" + command.name + "\' exists, please type !help for a list.")
            return False
コード例 #37
0
class AA5ROBot:
    """
    A Slack bot for the AARO Slack site.
    """
    def __init__(self):
        # Get the Bot token from the environment.  Raises RunTimeError if the
        # value isn't set because the bot can't run without a token configured.
        slack_bot_token = os.environ.get('SLACK_BOT_TOKEN')
        if slack_bot_token == '':
            raise RuntimeError(
                'SLACK_BOT_TOKEN must be set in the environment.')

        # Create the main SlackClient instance for the bot
        self.slack_client = SlackClient(slack_bot_token)

        # start initial connection to Slack RTM
        if self.slack_client.rtm_connect(with_team_state=False):
            logger.info("AA5ROBot connected to Slack.")
            self.aa5robot_id = self.slack_client.api_call(
                "auth.test")["user_id"]
        else:
            logger.warning("Connection to Slack RTM failed.")
            self.shutdown(1)

        # Load the bot's commands
        self.commands = command.get_commands()

        print('AA5RObot initialized.')

    def start(self):
        reconnects = 0

        # Process events from Slack RTM until ctrl-c
        logger.info('Processing events from Slack...')
        while self.slack_client.server.connected is True:
            try:
                data, channel = self.parse_bot_commands(
                    self.slack_client.rtm_read())
                if data:
                    self.handle_command(data, channel)
                time.sleep(RTM_READ_DELAY)
            except KeyboardInterrupt:
                self.shutdown()

        # If execution gets here, the connection to the server was interrupted.
        # Attempt up to MAX_RECONNECT_ATTEMPTS tries to reconnect to Slack.
        while reconnects < MAX_RECONNECT_ATTEMPTS:
            print(
                'AA5RObot lost connection to Slack.  Attempting reconnect, try {}'
                .format(reconnects + 1))
            if self.slack_client.rtm_connect(with_team_state=False):
                print("AA5ROBot reconnected to Slack.")
                self.aa5robot_id = slack_client.api_call(
                    "auth.test")["user_id"]
                self.start()
            else:
                reconnects += 1
                time.sleep(RECONNECT_WAIT_TIME)

        # Bot was unable to reconnect, so end the process.
        print('Unable to reconnect to Slack.  Exiting.')
        self.shutdown(1)

    def shutdown(self, exit_code=0):
        """
        Execute cleanup tasks before exiting the process.
        """
        # call shutdown method on all command instances
        for instance in self.commands:
            instance[1].shutdown()

        # end the process
        print("AA5ROBot exiting.")
        sys.exit(exit_code)

    def parse_bot_commands(self, slack_events):
        """
        Parses a list of events coming from the Slack RTM API to find bot commands.
        If a bot command is found, this function returns a tuple of command and channel.
        If a command is not found, then this function returns None, None.
        """
        for event in slack_events:
            try:
                if event["type"] == "message" and not "subtype" in event:
                    user_id, message = self.parse_direct_mention(event["text"])
                    if user_id == self.aa5robot_id:
                        return message, event["channel"]
            except KeyError:
                return None, None

        return None, None

    def parse_direct_mention(self, message_text):
        """
        Finds a direct mention (a mention that is at the beginning) in message text
        and returns the user ID which was mentioned. If there is no direct mention, returns None.
        """
        matches = re.search("^<@(|[WU].+?)>(.*)", message_text)
        # the first group contains the username, the second group contains the remaining message
        return (matches.group(1),
                matches.group(2).strip()) if matches else (None, None)

    def handle_command(self, data, channel):
        """
            Executes a bot command.
        """
        logger.debug('channel: {}, data: {}'.format(channel, data))

        # get command string
        try:
            command_str = data.split()[0].lower()
        except IndexError:
            self.send_message(
                channel,
                "Not sure what you mean.  Tell me 'help' for more info.")
            return

        if command_str == '':
            self.send_message(
                channel,
                "Not sure what you mean.  Tell me 'help' for more info.")
            return

        if command_str == 'help' or command_str == '?':
            self.handle_help(channel)
            return

        command_strings = [i[0] for i in self.commands]
        if command_str in command_strings:
            logger.info("Executing command '{}'.".format(command_str))
            method, response = self.commands[command_strings.index(
                command_str)][1].do_command(data)

            if method == command.MessageTypes.RTM_MESSAGE:
                self.send_message(channel, response)

            if method == command.MessageTypes.API_CALL:
                self.chat_post_message(channel, response)

        else:
            self.send_message(
                channel,
                "Not sure what you mean.  Tell me 'help' for more info.")
            return

    def handle_help(self, channel):
        """
        Sends the bot's help message to Slack.
        """
        self.send_message(channel, "Help not implemented yet!")

    def send_message(self, channel, response):
        """
        Send a text-only response via the RTM API.
        """
        self.slack_client.rtm_send_message(channel, response)

    def chat_post_message(self, channel, response):
        """
        Send a chat.postMessage API call.
        """
        self.slack_client.api_call("chat.postMessage",
                                   channel=channel,
                                   as_user=True,
                                   attachments=json.dumps(response))
コード例 #38
0
from slackclient import SlackClient
import time
from parse import filter_message, parse_message, preprocess
from execute import execute_command
from config import SLACK_BOT_TOKEN, BOT_ID, READ_WEBSOCKET_DELAY

slack_client = SlackClient(SLACK_BOT_TOKEN)
if slack_client.rtm_connect():
    print("Bot connected and running!", flush=True)
    last_task = None
    while True:
        filtered = filter(filter_message, slack_client.rtm_read())
        for message in filtered:
            if message['text'] == '닫혀라 참깨': assert False
            try:
                print('message :', message)
                parsed_message = parse_message(message)
                parsed_message = preprocess(parsed_message, last_task)
                print('parsed message :', parsed_message)
                response, last_task = execute_command(parsed_message)
                print('response :', response)
            except Exception as e:
                print(e)
                response = "Sorry, I didn't quite get that. Type 'help' for instruction."
            slack_client.rtm_send_message(message['channel'], response)
        time.sleep(READ_WEBSOCKET_DELAY)
else:
    print("Connection failed. Invalid Slack token or bot ID?")
コード例 #39
0
ファイル: robotson.py プロジェクト: opensanca/socialbot
class Robotson():
    def __init__(self, token):
        self.token = token
        self.slack = SlackClient(token=self.token)
        self.cleverbot = Cleverbot()
        self.botname = settings.BOT_NAME
        self.facebook = Facebook()
        self.twitter = Twitter()
        self.network = SocialNetwork()

    def run(self, interval):
        if self.slack.rtm_connect():
            while True:
                full_message = self.slack.rtm_read()
                if full_message:
                    content = full_message[0]
                    if content.get("type") == 'message':
                        sender = self.username_as_str(content.get("user"))
                        channel = content.get("channel")
                        message = content.get("text")

                        try:
                            match = re.search(r'<@[A-Z0-9]+>', message)
                            bot_mention = match.group() if match else ""

                            if bot_mention:
                                # TODO: Remove hardcoding
                                if settings.BOT_UID in bot_mention:
                                    self.talk(channel, sender, message)
                            elif settings.SHARE_TRIGGER in message.lower():
                                self.share(message)
                        except:
                            pass
                time.sleep(interval)
        else:
            raise SlackNotConnected

    def share(self, message):
        try:
            match_share_trigger = re.search(
                r'%s[\:]?' % settings.SHARE_TRIGGER, message)
            message = message.replace(match_share_trigger.group(), "")

            match_lt_mt = re.search(r'[<]+(.*)[>]+', message)
            message = message.replace(match_lt_mt.group(0),
                                      match_lt_mt.group(1))

            message = message.strip()

            url = re.findall(
                r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',
                message)
            if len(url) > 0:
                if not self.network.already_posted(url[0]):
                    self.facebook.post(message)
                    # self.twitter.post(message)
                    self.network.save_message(message)
        except Exception:
            pass

    def talk(self, channel, user, message):
        try:
            answer = '@%s: %s' % (user, self.cleverbot.ask(message))
            self.slack.rtm_send_message(channel=channel, message=answer)
        except Exception:
            pass

    def username_as_str(self, userid):
        try:
            response = json.loads(
                self.slack.api_call('users.info', user=userid))
            return response.get("user").get("name")
        except:
            return ""
コード例 #40
0
def main():
    sc = SlackClient(SLACK_BOT_TOKEN)

    error_msg = json.dumps([{
        "color":
        "#e74c3c",
        "attachment_type":
        "default",
        "text":
        "",
        "image_url":
        "http://i2.kym-cdn.com/photos/images/original/000/329/784/bd6.jpg"
    }])

    # Connect to slack
    if sc.rtm_connect():
        while True:
            # Listen for any latest events
            for slack_event in sc.rtm_read():

                message = slack_event.get("text")
                user = slack_event.get("user")
                channel = slack_event.get("channel")

                if (message and user):
                    if (SLACK_BOT_NAME in message):

                        movieName = message[13:]
                        if (len(movieName.strip()) == 0):
                            sc.api_call("chat.postMessage",
                                        channel=channel,
                                        text="",
                                        attachments=error_msg,
                                        as_user=True)
                        else:
                            try:
                                url = "http://www.omdbapi.com/?t=" + message[
                                    13:]
                                response = requests.get(url)
                                if response.status_code == 200:
                                    data = response.json()
                                    print "Calling " + url
                                    intro_msg = json.dumps([{
                                        "fallback":
                                        "There seems to be some issue with displaying the data",
                                        "title":
                                        message[13:],
                                        "color":
                                        "#50e043",
                                        "attachment_type":
                                        "default",
                                        "text":
                                        data["Plot"],
                                        "fields": [{
                                            "title": "Title",
                                            "value": data["Title"],
                                            "short": True
                                        }, {
                                            "title": "Actors",
                                            "value": data["Actors"],
                                            "short": True
                                        }, {
                                            "title": "Released",
                                            "value": data["Released"],
                                            "short": True
                                        }, {
                                            "title": "Rated",
                                            "value": data["Rated"],
                                            "short": True
                                        }, {
                                            "title":
                                            "IMDB Ratings",
                                            "value":
                                            data["Ratings"][0]["Value"],
                                            "short":
                                            True
                                        }],
                                        "image_url":
                                        data["Poster"]
                                    }])
                                    sc.api_call(
                                        "chat.postMessage",
                                        channel=channel,
                                        text="Here is some information about "
                                        + message[13:],
                                        attachments=intro_msg,
                                        as_user=True)
                            except:
                                sc.rtm_send_message(
                                    channel, "Hey " + "<@" + user + "> !" +
                                    " I couldn't find this movie")

                    else:
                        sc.rtm_send_message(channel, "")
コード例 #41
0
ファイル: slack_bot.py プロジェクト: philwyettreb/antbs
class DispatcherBot(RedisHash):
    _slack = None

    def __init__(self, name='dispatcher'):
        super().__init__(namespace='slack', prefix='bot', key=name)

        self.attrib_lists.update(
            dict(string=['api_key', 'name'],
                 bool=[],
                 int=[],
                 list=[],
                 set=['watching_events', 'watching_users', 'messages'],
                 path=[]))

        self.__namespaceinit__()

        if not self or not self.name:
            self.__bindattrs__()
            self.name = name

        if self._slack is None:
            self._slack = SlackClient(ET_SLACK_IDENTIFIER)

        if not self.watching_events:
            self.watching_events.extend(['presence_change', 'message'])

    def start(self):
        if self._slack.rtm_connect():
            while True:
                events = self._slack.rtm_read()

                if events:
                    self.handle_events(events)

                gevent.sleep(2)

        else:
            logger.error('Connection Failed!')

    def handle_events(self, events):
        events = [e for e in events if e['type'] in self.watching_events]

        for event in events:
            method = '_{}_handler'.format(event['type'])
            handler = getattr(self, method)

            try:
                handler(event)
            except Exception as err:
                logger.exception(err)

    def _presence_change_handler(self, event):
        if 'active' != event['presence']:
            return

        if not self.watching_users or event['user'] not in self.watching_users:
            return
        elif not self.messages:
            return

        for msg_id in self.messages:
            msg = DispatcherBotMessage(msg_id)

            if msg.delivered or not msg.to_users or event[
                    'user'] not in msg.to_users:
                continue

            channel = self._slack.api_call('im.open', user=event['user'])

            if self._slack.rtm_send_message(channel, msg.content):
                msg.to_users.remove(event['user'])
                self.watching_users.remove(event['user'])

            if not msg.to_users:
                msg.delivered = True
コード例 #42
0
class Slack_bot(SlackClient):
    """slack_bot class."""
    def __init__(self, token, twit_channel, home_channel, bot_id=None):
        self.sc = SlackClient(token)
        self.channel = twit_channel
        self.home = home_channel
        self.start_time = datetime.datetime.now()
        self.bot_id = bot_id
        if not self.bot_id and self.sc.rtm_connect(with_team_state=False):
            response = self.sc.api_call('auth.test')
            self.name = response.get('user')
            self.bot_id = response.get('user_id')
        self.at_bot = '<@' + self.bot_id + '>'

    def __enter__(self):
        """returns slack obj and connects to rtm if not."""
        mess = "PBJTIME is ONLINE!!!! (with a baseball bat)"
        if self.sc.server.connected:
            logger.info('SlackBot connected to rtm stream')
        else:
            logger.info('SlackBot connected to rtm stream')
            self.sc.rtm_connect(with_team_state=False)
        self.post_command_message(mess, self.home)
        return self

    def __exit__(self, type, value, traceback):
        """lets program know that it is exiting slackbot."""
        logger.info('Exiting slack_bot')

    def read_stream(self):
        """reads stream from slack_client connections."""
        return self.sc.rtm_read()

    def parse_stream(self, content):
        """takes in content from stream and looks for pbjtime mentions."""
        for item in content:
            if 'text' in item and item['text'].startswith(self.at_bot):
                text = item['text'].split(self.at_bot)
                chan = item['channel']
                return (text[1].strip(), chan)
        return (None, None)

    def handle_command(self, text, tb):
        """handles commands that are given and returns message to post."""
        global subscr
        global stats
        args = text.lower().split()
        if args:
            cmd = args[0].lower()
            logger.info('{} cmd was issued.'.format(cmd))
        else:
            cmd = ''
        args = args[1:]
        if cmd == 'raise':
            logger.info('raise test exception')
            raise TestException
        elif cmd == 'help':
            return 'these commands are possible:\n\
                {}'.format(pp.pformat(bot_commands))
        elif cmd == 'time':
            logger.info('bot initialized in slack.')
            return "IT'S PEANUT BUTTER JELLY TIME!! \n(help for more options)"
        elif cmd == 'ping':
            uptime = datetime.datetime.now() - self.start_time
            logger.info('current uptime: {}'.format(uptime))
            return 'Peanut Butter Jelly upTime: {}'.format(uptime)
        elif cmd == 'exit':
            tb.close_stream()
            subscr = []
            tb.subscriptions = []
            stats = {}
            logger.info('pbjtime leaving slack.')
            return "peanut butter jelly time :'( (goodbye)"
        elif cmd == 'start':
            subscr = list(set(subscr + args))
            if not subscr:
                logger.info('no subscr. ignoring and not starting stream.')
                return 'Please add subscriptions so I can find tweets.'
            tb.init_stream(subscr)
            logger.info('started stream with subscriptions: {}'.format(subscr))
            for subs in subscr:
                if subs not in stats:
                    stats[subs] = 0
            if args:
                return 'Added subscriptions: {}'.format(args)
            return 'Started with subcriptions: {}'.format(subscr)
        elif cmd == 'add':
            subscr = list(set(subscr + args))
            if not subscr or not args:
                logger.info('no new subscriptions. ignoring')
                return 'Please add new subscriptions so I can find tweets.'
            tb.init_stream(subscr)
            for subs in subscr:
                if subs not in stats:
                    stats[subs] = 0
            logger.info('added new subcriptions; restarting stream.')
            return 'Added subscriptions: {}'.format(args)
        elif cmd == 'remove':
            removed = []
            for arg in args:
                if arg in subscr:
                    subscr.remove(arg)
                    removed.append(arg)
                    if arg in stats:
                        del stats[arg]
            if removed:
                logger.info('removed subcriptions: {}'.format(arg))
                tb.init_stream(subscr)
                logger.info('restarted twitter stream.')
                return 'removed subcriptions: {} and restarted.'.format(arg)
            else:
                logger.info('no subscriptions matching input. ignoring')
                return 'No subscriptions removed. use list to see current.'

        elif cmd == 'removeall':
            subscr = []
            tb.close_stream()
            tb.subscriptions = []
            stats = {}
            logger.info('All subscriptions removed')
            return 'all subscriptions removed!'
        elif cmd == 'list':
            logger.info('channel list: {}'.format(subscr))
            return 'current subscriptons: \n {}'.format(subscr)
        elif cmd == 'stop':
            logger.info('Stopping twitter stream')
            tb.close_stream()
            logger.info('stream closed on slack side.')
            return 'Twitter stream has been stopped.'
        elif cmd == 'channels':
            self.channel_list()
        elif cmd == 'stats':
            logger.info('stats: {}'.format(pp.pformat(stats)))
            return 'subscription stats: {}'.format(pp.pformat(stats))
        elif cmd not in bot_commands:
            logger.info('unknown command issued')
            return 'Peanut Butter Jelly Time??? use help for more options.'
        else:
            logger.warning('made it through if else block: {}'.format(cmd))
            return None

    def post_command_message(self, mess, channel):
        """posts message after command is completed."""
        logger.info('Sent response to channel: {}'.format(channel))
        self.sc.rtm_send_message(channel, mess)

    def post_twit_mess(self, mess):
        """Posts message from twitter bot to initial channel."""
        global stats
        global subscr
        for scr in stats:
            if scr in mess.lower():
                stats[scr] += 1
        self.sc.api_call("chat.postMessage", channel=self.channel, text=mess)

    def channel_list(self):
        logger.info('requesting channel list')
        logger.info(pp.pformat(self.sc.api_call("channels.list")))
コード例 #43
0
class SlackConnection(Borg):
    def __init__(self):
        super().__init__()
        self.log = logging.getLogger(__name__)
        self.initialized = False

    def initialize(self):  # pragma: no cover
        if not self.initialized:
            self.get_slack_token()
            self.connect()
            self.initialized = True

    def get_slack_token(self):  # pragma: no cover
        config_dict = configuration.get()
        self.token = config_dict['main']['slackbot_token']

    def connect(self):  # pragma: no cover
        self.sc = SlackClient(self.token)
        if not self.sc.rtm_connect():
            self.log.critical("Error conecting to Slack - token issue?")
            self.log.critical("--- full stack trace ---")
            self.log.critical(traceback.format_exc())
            sys.exit(1)

    @asyncio.coroutine
    def get_stream_messages(self):
        self.initialize()
        return_messages = []
        try:
            messages = self.sc.rtm_read()
            for msg in messages:
                message_object = self.get_message_type(msg)
                return_messages.append(message_object)
        except TimeoutError as t:
            self.log.error("Error reading from slack socket: %s" % t)
            self.log.error("--- full stack trace ---")
            self.log.error(traceback.format_exc())
            self.log.info("Now attempting to reconnect")
            self.connect()
        except BrokenPipeError as b:
            self.log.critical("Error reading from slack socket: %s" % b)
            self.log.critical("--- full stack trace ---")
            self.log.critical(traceback.format_exc())
            sys.exit(1)
        return return_messages

    def get_message_type(self, msg):
        self.initialize()
        obj_list = [
            "charlesbot.slack.slack_pong.SlackPong",
            "charlesbot.slack.slack_channel_joined.SlackChannelJoined",
            "charlesbot.slack.slack_channel_left.SlackChannelLeft",
            "charlesbot.slack.slack_group_joined.SlackGroupJoined",
            "charlesbot.slack.slack_group_left.SlackGroupLeft",
            "charlesbot.slack.slack_message.SlackMessage",
        ]
        for obj in obj_list:
            module_name, class_name = obj.rsplit(".", 1)
            obj_class = getattr(importlib.import_module(module_name),
                                class_name)  # NOQA
            return_obj = obj_class()

            if getattr(return_obj, 'is_compatible')(msg):
                return_obj.load(msg)
                return return_obj
        return None

    @asyncio.coroutine
    def send_channel_message(self, channel_id, message):  # pragma: no cover
        self.initialize()
        self.sc.rtm_send_message(channel_id, message)

    @asyncio.coroutine
    def send_ping_message(self):  # pragma: no cover
        self.initialize()
        self.sc.server.ping()

    @asyncio.coroutine
    def api_call(self, api_endpoint, **kwargs):
        self.initialize()
        val = self.sc.api_call(api_endpoint, **kwargs)
        json_str = json.loads(val.decode('utf-8'))
        if not json_str['ok']:
            self.log.error("Error fetching %s - response: %s", api_endpoint,
                           str(json_str['ok']))
            self.log.error(json_str)
            return json.dumps("{}")
        return json.dumps(json_str)
コード例 #44
0
ファイル: executor.py プロジェクト: yiching/tfx
    def _fetch_slack_blessing(self, slack_token: Text, channel_id: Text,
                              model_uri: Text) -> _SlackResponse:
        """Send message via Slack channel and wait for response.

    Args:
      slack_token: The user-defined function to obtain token to send and receive
        messages.
      channel_id: The id of the Slack channel to send and receive messages.
      model_uri: The URI of the model waiting for human review.

    Returns:
      A _SlackResponse instance.

    Raises:
      ConnectionError:
        When connection to slack server cannot be established.

    """
        sc = SlackClient(slack_token)
        msg = _NOTIFY_MODEL_REVIEW_TEMPLATE.format(model_uri)
        ts = 0
        if not sc.rtm_connect():
            msg = 'Cannot connect to slack server with given token'
            tf.logging.error(msg)
            raise ConnectionError(msg)  # pylint: disable=undefined-variable

        sc.rtm_send_message(channel=channel_id, message=msg)

        while sc.server.connected:
            payload_list = sc.rtm_read()
            if not payload_list:
                continue

            for payload in payload_list:
                if payload.get('ok') and payload.get(
                        'reply_to') == 0 and not ts:
                    ts = payload['ts']
                    continue
                elif payload.get('type') == 'message' and payload.get(
                        'channel') == channel_id and payload.get(
                            'text') and payload.get('thread_ts') == ts:
                    if payload.get('text').lower() in _APPROVE_TEXT:
                        tf.logging.info(
                            'User %s approves the model located at %s',
                            payload.get('user'), model_uri)
                        return _SlackResponse(True, payload.get('user'),
                                              payload.get('text'), channel_id,
                                              str(ts))
                    elif payload.get('text').lower() in _DECLINE_TEXT:
                        tf.logging.info(
                            'User %s declines the model located at %s',
                            payload.get('user'), model_uri)
                        return _SlackResponse(False, payload.get('user'),
                                              payload.get('text'), channel_id,
                                              str(ts))
                    else:
                        unrecognized_text = payload.get('text')
                        tf.logging.info('Unrecognized response: %s',
                                        unrecognized_text)
                        sc.rtm_send_message(
                            channel=channel_id,
                            message=_NOTIFY_CORRECT_REPLY_TEMPLATE.format(
                                unrecognized_text),
                            thread=ts)
コード例 #45
0
ファイル: stagebot.py プロジェクト: niklasf/lichess-stagebot
class SlackBot:
    def __init__(self):
        self.config = configparser.ConfigParser()
        self.config.read("stagebot.ini")

        self.parser = ArgumentParser()
        self.parser.add_argument("command", choices=["echo", "deploy"])
        self.parser.add_argument("--branch", default="master")

        self.slack = SlackClient(self.config.get("slack", "bot_token"))
        self._connect()

    def _connect(self):
        if not self.slack.rtm_connect():
            raise Exception("rtm connect failed")

        logging.info("Connected.")

    def run(self):
        while True:
            for msg in self.slack.rtm_read():
                logging.debug("%s", msg)

                if msg.get("type") == "message" and "text" in msg:
                    if msg["user"] == self.config.get("slack", "bot_uid"):
                        continue

                    args = msg["text"].split()
                    if args[0].lower() not in [
                            "stagebot", "@stagebot"
                    ] and self.config.get("slack", "bot_uid") not in args[0]:
                        continue

                    try:
                        self.handle(args[1:])
                    except Exception as err:
                        self.post_snippet("build failure", str(err))

            time.sleep(1)

    def send(self, message):
        logging.info(message)
        self.slack.rtm_send_message("bot-testing", message)

    def post_snippet(self, title, snippet):
        self.slack.api_call("files.upload",
                            channels="bot-testing",
                            title=title,
                            content=snippet or "<no output>",
                            filetype="txt")

    def handle(self, args):
        try:
            args = self.parser.parse_args(args)
        except ParserMessage as msg:
            self.send("%s" % msg)
            return
        except ParserError as err:
            self.send(":interrobang: %s" % err)
            return

        if not re.match(r"^[A-Za-z0-9_-]+\Z", args.branch):
            self.send(":interrobang: Invalid branch name")
            return

        if args.command == "echo":
            self.send("echo")
        elif args.command == "deploy":
            self.deploy(args)

    def deploy(self, args):
        start_time = time.time()

        # 0. Pre
        sh(self.config.get("deploy", "pre"))

        # 1. Download server
        download = "%s/lila-server-%s.tar.gz" % (self.config.get(
            "s3", "bucket"), args.branch)
        self.send("Downloading %s ..." % download)
        urllib.urlretrieve(download, "lila-server.tar.gz")

        # 2. Download assets
        download = "%s/lila-assets-%s.tar.gz" % (self.config.get(
            "s3", "bucket"), args.branch)
        self.send("Downloading %s ..." % download)
        urllib.urlretrieve(download, "lila-assets.tar.gz")

        with tarfile.open("lila-server.tar.gz") as tar:
            # 3. Peek server
            with tar.extractfile("commit.txt") as commit_file:
                sha, message = commit_file.readline().decode(
                    "utf-8").strip().split(None, 1)

            self.send(
                "Deploying server: https://github.com/%s/commit/%s (`%s`) ..."
                % (self.config.get("github", "slug"), sha, message))

            # 4. Extract server
            app_files = [
                t for t in tar.getmembers()
                if make_relative("target/universal/stage/", t)
            ]
            tar.extractall(self.config.get("deploy", "app"), members=app_files)

        with tarfile.open("lila-assets.tar.gz") as tar:
            # 5. Peek assets
            with tar.extractfile("commit.txt") as commit_file:
                sha, message = commit_file.readline().decode(
                    "utf-8").strip().split(None, 1)

            self.send(
                "Deploying assets: https://github.com/%s/commit/%s (`%s`) ..."
                % (self.config.get("github", "slug"), sha, message))

            # 6. Extract assets.
            asset_files = [
                t for t in tar.getmembers() if make_relative("public/", t)
            ]
            tar.extractall(self.config.get("deploy", "assets"),
                           members=asset_files)

        # 7. Post
        sh(self.config.get("deploy", "post"))

        end_time = time.time()
        self.send(":white_check_mark: Done in %.1fs" % (end_time - start_time))
コード例 #46
0
ファイル: gaben.py プロジェクト: Agasper/gaben
class Gaben:
    def __init__(self, api_key, rep_directory):
        self.api_key = api_key
        self.slack = SlackClient(api_key)
        self.store = Store()
        self.builder = Builder(rep_directory)

    def run(self):
        if self.slack.rtm_connect(auto_reconnect=True):
            print("Gabe is ready!")
            while True:
                data_list = self.slack.rtm_read()
                for data in data_list:
                    if "type" in data and "subtype" not in data and data[
                            "type"] == "message":
                        self.incoming_im(data)
                time.sleep(1)
        else:
            print("Slack connection failed...")

    def get_user_info(self, data):
        return self.slack.api_call("users.info", user=data["user"])

    def incoming_im(self, data):
        text = data["text"].strip().replace("“", "\"").replace("”", "\"")
        user_info = self.get_user_info(data)
        if user_info["user"]["name"] == self.slack.server.username:
            return

        print("%s: %s" % (user_info["user"]["name"], text))

        if text[:3].lower() == "add":
            self.incoming_add(data, text)
        elif text[:6].lower() == "remove":
            self.incoming_remove(data, text)
        elif text.strip().lower() == "projects":
            self.incoming_projects(data)
        elif text[:5].lower() == "build":
            self.incoming_build(data, text)
        elif text[:5].lower() == "alter":
            self.incoming_alter(data, text)
        elif text[:4].lower() == "jobs":
            self.incoming_jobs(data)
        else:
            if data["channel"] not in config.DONT_PRINT_USAGE_FOR:
                self.send_usage(data)

    def send_usage(self, data):
        self.send_msg(
            data, """Usage:
add - add a new project
remove - remove a project and clean it's data
alter - change parameters of the project
projects - get list of all projects
build - build a project
jobs - show current tasks and projects statuses""")

    def send_msg(self, data, text):
        self.slack.rtm_send_message(data["channel"], text)

    def incoming_alter(self, data, text):
        cmd = shlex.split(text)[1:]
        parser = ArgumentParser(prog="alter",
                                description='Alter an existing project')
        parser.add_argument("name", help="Name or url of the project")
        parser.add_argument(
            "--keystore",
            help="Path of the keystore file relative to the project root",
            default="")
        parser.add_argument("--keystore_pwd",
                            help="Keystore password",
                            default="")
        parser.add_argument("--key", help="Keystore key", default="")
        parser.add_argument("--key_pwd",
                            help="Keystore key password",
                            default="")

        try:
            args = parser.parse_args(cmd)
            project = self.store.search(args.name)

            if len(args.keystore) > 0:
                project.keystore_filename = args.keystore
            if len(args.keystore_pwd) > 0:
                project.keystore_pwd = args.keystore_pwd
            if len(args.key) > 0:
                project.key = args.key
            if len(args.key_pwd) > 0:
                project.key_pwd = args.key_pwd

            self.store.save()
            self.send_msg(data, "Project altered")

        except Exception as ex:
            self.send_msg(data, str(ex))

    def incoming_add(self, data, text):
        cmd = shlex.split(text)[1:]
        parser = ArgumentParser(prog="add", description='Add a new project')
        parser.add_argument("url", help="Git url of the repository")
        parser.add_argument(
            "--keystore",
            help="Path to the keystore file relative to the project root",
            default="")
        parser.add_argument("--keystore_pwd",
                            help="Keystore password",
                            default="")
        parser.add_argument("--key", help="Keystore key", default="")
        parser.add_argument("--key_pwd",
                            help="Keystore key password",
                            default="")
        parser.add_argument("--name",
                            help="Name of the project (optional)",
                            default="")

        try:
            args = parser.parse_args(cmd)
            args.url = re.sub(r"<mailto:(.+)\|(.+)>", lambda m: m.group(1),
                              args.url)

            if self.store.is_url_exists(args.url):
                raise Exception("Project with url %s already exists" %
                                args.url)

            project = Project(args.url, args.keystore, args.keystore_pwd,
                              args.key, args.key_pwd, args.name)
            self.store.add_project(project)
            self.send_msg(
                data, """Project added with parameters:
*Url:* %s
*Keystore file path:* %s
*Keystore password:* %s
*Key:* %s
*Key password:* %s
*Name:* %s
""" % (project.url, project.keystore_filename, project.keystore_pwd,
            project.key, project.key_pwd, project.name))
        except Exception as ex:
            self.send_msg(data, str(ex))

    def incoming_remove(self, data, text):
        cmd = shlex.split(text)[1:]
        parser = ArgumentParser(prog="remove", description='Remove project')
        parser.add_argument("name", help="Name or url of the project")

        try:
            args = parser.parse_args(cmd)
            project = self.store.search(args.name)
            self.builder.clean_project(project)
            self.store.remove_project(project)
            self.send_msg(data, "Project *%s* removed" % str(project))
        except Exception as ex:
            self.send_msg(data, str(ex))
            return

    def incoming_projects(self, data):
        projects = self.store.get_data()
        result = ""
        for project in projects:
            result += "*%s:* %s keystore=%s key=%s\r\n" % (
                project.name, project.url, project.keystore_filename,
                project.key)

        if len(result) == 0:
            self.send_msg(data, "No projects added")
        else:
            self.send_msg(data, result)

    def incoming_build(self, data, text):
        platforms = [
            "Win", "Win64", "OSXUniversal", "Linux", "Linux64",
            "LinuxUniversal", "iOS", "Android"
        ]
        scripting_backengs = ["il2cpp", "mono"]
        cmd = shlex.split(text)[1:]
        parser = ArgumentParser(prog="build", description='Build the project')
        parser.add_argument("name", help="Name or url of the project")
        parser.add_argument("branch", help="Branch of the repositary")
        parser.add_argument("platform",
                            help="Platform: " + ",".join(platforms))
        parser.add_argument("--noupload",
                            action="store_true",
                            help="Don't upload build to Slack")
        parser.add_argument(
            "--log",
            action="store_true",
            help="Always keep log, even if build was successful")
        parser.add_argument("--clean",
                            action="store_true",
                            help="Make a clean build (remove unity cache)")
        parser.add_argument("--backend",
                            help="Override scripting backend: " +
                            ",".join(scripting_backengs),
                            default="")
        parser.add_argument("--build",
                            type=int,
                            help="Override build number",
                            default=-1)
        parser.add_argument("--version",
                            help="Override build version",
                            default="")
        parser.add_argument(
            "--development",
            action="store_true",
            help="Make a developement build (default is Release)")
        parser.add_argument("--profiler",
                            action="store_true",
                            help="Autoconnect profiler")
        parser.add_argument("--donotsign",
                            action="store_true",
                            help="(Android only) Do not sign build")
        parser.add_argument(
            "--split",
            action="store_true",
            help="(Android only) Split APK & OBB (default is single APK)")
        parser.add_argument(
            "--split_arch",
            action="store_true",
            help="(Android only) Split APK  by target architecture")
        parser.add_argument("--build_with_method",
                            default="",
                            help="Set custom building method")
        try:
            args = parser.parse_args(cmd)
            project = self.store.search(args.name)
            if args.platform not in platforms:
                raise Exception("Unknown platform %s. Possible options: %s" %
                                (args.platform, ",".join(platforms)))
            if args.backend not in scripting_backengs and len(
                    args.backend) > 0:
                raise Exception(
                    "Unknown scripting backend %s. Possible options: %s" %
                    (args.backend, ",".join(scripting_backengs)))
            if args.backend == "mono" and args.platform == "iOS":
                raise Exception("%s backend doesn't work on platform %s" %
                                (args.backend, args.platform))
            self.builder.start(project, args.branch, args.platform, args.noupload, args.backend, not args.donotsign, \
                    args.split, args.split_arch, args.log, args.clean, args.build, args.version, args.development, args.profiler, args.build_with_method, data, self.builder_callback)
            self.send_msg(data, config.get_random_quote())
        except Exception as ex:
            self.send_msg(data, str(ex))
            return

    def incoming_jobs(self, data):
        jobs = self.builder.get_jobs()
        if len(jobs) == 0:
            self.send_msg(
                data,
                "No jobs at the moment (uploading your build is not a job)")
            return
        result = "*Current jobs:*\r\n"
        for job in jobs:
            result += "*%s* -> %s\r\n" % (
                job.project.name, str(job.pipeline.get_current_job())
                if job.pipeline is not None else "Finishing")
        self.send_msg(data, result)

    def builder_callback(self, data, project, status, file_path, noupload):
        size = os.path.getsize(file_path)
        MAX_MB = config.MAX_UPLOAD_SIZE_MB
        if noupload:
            self.send_msg(
                data,
                "Build completed! No upload flag is set, so grab your build locally in %s"
                % file_path)
            return

        if size > 1024 * 1024 * MAX_MB:
            self.send_msg(
                data,
                "Build completed, but it's exceeds %dMb size! :neutral_face:\nYou can grab build locally in %s"
                % (MAX_MB, file_path))
            return

        try:
            with open(file_path, "rb") as f:
                self.slack.api_call(
                    'files.upload',
                    channels=data["channel"],
                    as_user=True,
                    filename=os.path.basename(file_path),
                    file=f,
                )
        except Exception as ex:
            print("Failed to upload file to slack: %s" % str(ex))
            self.send_msg(
                data,
                "Failed to upload build to Slack, grab the build locally in %s"
                % file_path)
            return

        if status:
            self.send_msg(data, "Build of %s completed! :+1:" % project.name)
        else:
            self.send_msg(
                data, ":octagonal_sign: Build of %s failed! " % project.name)
コード例 #47
0
ファイル: bot.py プロジェクト: juharris/my-bot
class MySlackBot(object):
    def __init__(self):
        config_path = os.getenv('MYBOT_SLACK_CONFIG_PATH')
        if config_path is None:
            config_path = os.path.join(
                os.path.dirname(os.path.realpath(__file__)), 'config.yaml')

        print("Loading config from " + config_path)
        with io.open(config_path, 'r', encoding='utf8') as f:
            config = yaml.safe_load(f)

        self._logger = logging.getLogger('mybot.slack')
        log_level = config.get('log level', logging.WARN)
        self._logger.setLevel(log_level)
        ch = logging.StreamHandler()
        ch.setLevel(log_level)
        formatter = logging.Formatter(
            '%(asctime)s [%(levelname)s] - %(name)s\n%(message)s')
        ch.setFormatter(formatter)
        self._logger.addHandler(ch)

        slack_token = config["slack API token"]
        self._client = SlackClient(slack_token)
        del slack_token

        # Get current user's ID so that they don't automatically reply to their own messages.
        # TODO Determine is automatically: might need to use OAuth.
        self._current_user_id = config.get('user id')

        self._reply_rules = []
        ReplyRule = namedtuple('ReplyRule', ['pattern', 'replies'])
        for rule in config.get('reply rules', []):
            self._reply_rules.append(
                ReplyRule(re.compile(rule['pattern']), rule['replies']))

        self._check_delay = config.get('check delay', 3)

    def _get_reply(self, received_msg):
        result = None
        for rule in self._reply_rules:
            m = rule.pattern.match(received_msg)
            if m:
                result = random.choice(rule.replies)
                break
        return result

    def handle_messages(self):
        if self._client.rtm_connect():
            self._logger.info("Waiting for messages.")
            while True:
                try:
                    rtm_results = self._client.rtm_read()
                except Exception as e:
                    self._logger.exception(e)
                    raise
                for event in rtm_results:
                    try:
                        if self._logger.isEnabledFor(logging.DEBUG):
                            self._logger.debug("Event: \"%s\"",
                                               json.dumps(event, indent=2))
                        if event.get('type') == 'message' and event.get(
                                'user') != self._current_user_id:
                            channel = event.get('channel', '')
                            if channel.startswith('D'):
                                received_msg = event.get('text')
                                if received_msg:
                                    reply = self._get_reply(received_msg)
                                    if reply:
                                        self._logger.info(
                                            "Replying: \"%s\" in %s", reply,
                                            channel)
                                        self._client.rtm_send_message(
                                            channel, reply)
                    except Exception as e:
                        self._logger.exception(e)
                time.sleep(self._check_delay)
        else:
            raise Exception("Connection failed. Maybe your token is invalid?")
コード例 #48
0
                '\u2019', '\'')  # hacky way of fixing encoding with apostrophe
        # print(len(json.loads(history)['messages']))
        # save_string_as_json_file(filename=office, content=history)

    while True:
        last_read = client.rtm_read()
        if last_read:
            try:
                parsed = last_read[0]['text']
                #reply to channel message was found in.
                message_channel = last_read[0]['channel']
                if message_channel.startswith(
                        'D'
                ) and "update" in parsed:  #TODO: Restrict access with last_read[0]['user']:
                    # print last_read[0]
                    client.rtm_send_message(
                        message_channel,
                        "No problem! Please give me a minute to analyze the latest messages. :clock1:"
                    )

                    r = requests.get(
                        "http://ec2-52-87-240-146.compute-1.amazonaws.com:23001/trigger"
                    )
                    # r = requests.get("http://google.com")
                    client.rtm_send_message(
                        message_channel,
                        "Got the results back! Check them out at http://bit.ly/28cy4vX"
                    )
            except:
                pass
        time.sleep(1)
コード例 #49
0
ファイル: bot.py プロジェクト: T-T-Mochi/amount_slack_bot
def main():
    '''
    UDP通信サーバーのセッティング
    受信データの解析
    解析結果をslack botで送信を行う
    '''

    token = "トークン" # メモしておいたトークンを設定
    sc = SlackClient(token)

    print("bot boot")

    channels_name = "bot_name"

    test = 0

    n = 40

    time_window = 100

    window_list_xyz = []
    time_data = []

    amount = 250

    Decrease_point = [0,0]

    ave_xyz = 0

    udp_data_xyz = 0

    median = 0

    index = 1


    '''
    UDP通信サーバーのセッティング
    '''
    try :
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    except s(ocket.error, msg) :
        print ('Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
        sys.exit()

    try:
        s.bind(('', 3333))
    except (socket.error , msg):
        print ('Bind failed. Error: ' + str(msg[0]) + ': ' + msg[1])
        sys.exit()

    print ('Server listening')

    if sc.rtm_connect():
        while True:
            udp_recv = s.recvfrom(1024)
            udp_data = udp_recv[0].strip()
            udp_data = re.findall(r'[0-9]+', str(udp_data))

            udp_data_xyz = int(udp_data[0])

            window_list_xyz.append(udp_data_xyz)
            time_data.append(udp_data_xyz)

            slack_data = sc.rtm_read()
            test = test + 1

            if len(window_list_xyz) > n:
                window_list_xyz.pop(0)

            if  len(window_list_xyz) == n:
                ''''
                畳み込み積分を行う
                ''''
                ave_xyz = np.convolve(np.array(window_list_xyz, dtype='int64'), np.ones(n)/float(n), 'valid')

            if len(time_data) > time_window:
                time_data.pop(0)

            if len(time_data) == time_window:
                '''
                最頻値を取得
                '''
                median = statistics.median(time_data)
                time_data.pop(0)

            if  len(window_list_xyz) == n:

                if median-ave_xyz > 50 and index - Decrease_point[0] > 50:
                    print("push")
                    print(index - Decrease_point[0])
                    print(median-ave_xyz)
                    Decrease_point[0] = index
                    Decrease_point[1] = Decrease_point[1] + 1

            if len(slack_data) > 0:
                for item in slack_data:
                    message_check = create_message(item)
                    if message_check is True:
                        amount_answer = math.floor(((amount-Decrease_point[1]*5)/amount)*100)
                        print(amount_answer)
                        messagetext = "シャンプーの残りの量は"+str(amount_answer)+"%です"
                        sc.rtm_send_message(item['channel'], messagetext)
                        sc.api_call('files.upload', channels=item['channel'], as_user=True, filename='./image_data/'+str(amount_answer)+'.png', file=open('./image_data/'+str(amount_answer)+'.png', 'rb'))

            index = index + 1
        s.close()
    else:
        print("Connection Failed, invalid token?")
コード例 #50
0
sc = SlackClient(token)
if sc.rtm_connect():
    message = {
        "as_user":
        True,
        "text":
        "TEST1:",
        "attachments":
        json.dumps([{
            "title":
            "App hangs on reboot",
            "title_link":
            "http://domain.com/ticket/123456",
            "text":
            "If I restart my computer without quitting your app, it stops the reboot sequence.\nhttp://domain.com/ticket/123456"
        }]),
    }
    sc.api_call("chat.postMessage", channel="#yuwei", **message)

    while True:
        in_events = sc.rtm_read()
        for event in in_events:
            if 'type' in event:
                if event['type'] == 'message':
                    channel, message = event['channel'], event['text']
                    print(channel, message)
                    sc.rtm_send_message(channel=channel, message=message)

else:
    print("Connection Failed, invalid token?")
コード例 #51
0
									matches.append(v['name'])
									cb=v['callback']
									if m[0].lower() == v['name'].lower():
										exact=cb
									
						if exact:
							log_event( display_name,msg['text'])
							text=exact(sc,userinfo,contexts[chan],*m)
						elif len(matches)==1:
							log_event( display_name,msg['text'])
							text=cb(sc,userinfo,contexts[chan],*m)
						elif len(matches)==0:
							text="Unknown command. Type `help` for help"
						else: 
							text="Ambiguous command: Did you mean "
							text += oxfordlist(matches)
							text += "?\n(`help` for more)"
						
					except BaseException as e:
						text = ":alert: Epic fail: ```"+str(e)+"```"
						log_event( "<Error>",str(e))

					sc.rtm_send_message(msg['channel'],text)
			prune_contexts(contexts)
			sys.stdout.flush()
	else:
		print "Connection Failed"
	time.sleep(2)
	print "RETRY"

コード例 #52
0
 for each in i:
     # process select loop events
     if socketlist[each] == 'tty':
         #  tosend = sys.stdin.readline().rstrip('\r\n')
         msg = teletype.recv(256).rstrip('\r\n')
         tosend = str(msg.decode('ascii', 'ignore'))
         tosend = tosend.replace(
             '^G', '<bell>')  # bell is "not well formed xml" hahaha.
         tosend = tosend.replace(
             '	', '  ')  # tabs make whole message fail silently
         # drop blank lines so we don't make a bogus rtm_send_message() call
         if not tosend:
             continue
         if not tosend.startswith('/'):
             if current_channel:
                 sc.rtm_send_message(channel=current_channel,
                                     message=tosend)
             else:
                 sl_print("not in a channel")
         else:
             # process a / command
             cmd = tosend.split()
             cmd[0] = cmd[0].lower()
             if cmd[0] == '/q' or cmd[0] == '/quit':
                 sl_print("quitting slack")
                 online = False
             # try to send a direct message? this is janky.
             if (cmd[0] == '/m' or cmd[0] == '/msg') and len(cmd) > 2:
                 recip = cmd[1].lower()
                 body = ' '.join(cmd[2:])
                 if recip in uids:
                     try:
コード例 #53
0
ファイル: wget.py プロジェクト: jpbarto/slack_wget_bot
http_get_rqst_pattern = re.compile ('^get\s+<(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)>$')
stop_pattern = re.compile ('^quititsaysame$')

sc = SlackClient (slack_token)

if sc.rtm_connect ():
    while run_flag:
        msgs = sc.rtm_read ()
        if len(msgs) == 0:
            sleep (1)
        else:
            for msg in msgs:
                if 'channel' in msg and msg['channel'] == direct_chan_id:
                    if 'text' in msg:

                        stop_match = stop_pattern.match (msg['text'])
                        http_get_rqst_match = http_get_rqst_pattern.match (msg['text'])

                        if stop_match is not None:
                            run_flag = False
                        elif http_get_rqst_match is not None:
                            uri = http_get_rqst_match.group (1)
                            rqst = requests.get (uri)
                            sc.rtm_send_message (direct_chan_id, "{0} reported status code {1}".format (uri, rqst.status_code))
                        else:
                            sc.rtm_send_message (direct_chan_id, 'Unknown command: '+ repr(msg['text']))
        
else:
    raise Exception ("Unable to connect to slack.com")
コード例 #54
0
ファイル: s.py プロジェクト: IIIIIHIIIII/IndiaBitsBot
    "!register": register,
    "!withdraw": withdraw,
    "!price": price,
    "!market": market,
    "!calc": calc,
    "!help": help
}

while (True):
    try:
        data = sc.rtm_read()
        if (data):
            print(data)
            if ("subtype" in data[0] and "channel_join" in data[0]["subtype"]):
                user = data[0]["channel"]
                sc.rtm_send_message(user, "Welcome")

            if ("text" in data[0] and "C2ACQLM7B" not in data[0]["channel"]):
                message = clean(data[0]["text"])
                channel = data[0]["channel"]
                user = data[0]["user"]
                print(message[0])
                if "!" in message[0]:
                    sc.rtm_send_message(channel, commands[message[0]](message,
                                                                      user))
            elif ("C2ACQLM7B" in data[0]["channel"]
                  and "!" in clean(data[0]["text"])[0]):
                sc.rtm_send_message(data[0]["channel"],
                                    "Please use bot in DM or in #bots-area")
    except:
        pass
コード例 #55
0
ファイル: adapter.py プロジェクト: sumukhballal/slackbot
class SlackAdapter(Adapter):
    def __init__(self, robot):
        super().__init__(robot)

        token = env.get("PYBOT_SLACK_TOKEN")
        if not token:
            raise RuntimeError("Missing environment variable PYBOT_SLACK_TOKEN")

        self.bot_id = None
        self.client = SlackClient(token)

    def send(self, message, text):
        self._send_message(message.room, text)

    def reply(self, message, text):
        thread = None
        if not self._is_direct_message(message.room):
            text = f"<@{message.user.id}>: {text}"
            thread = message.thread_id

        self._send_message(message.room, text, thread)

    def run(self):
        if not self.client.rtm_connect():
            # TODO: use logger once implemented
            print("error: unable to connect to RTM service")
            return

        self._initialize()
        self._loop_forever()

    def _loop_forever(self):
        while True:
            events = self.client.rtm_read()
            if events:
                self._dispatch(events)

            sleep(0.1)

    def _initialize(self):
        name = self.client.server.username
        user = self._find_user(name)

        self.bot_id = user.id
        self.robot.name = user.name

        self.robot.emit("connected")

    def _dispatch(self, events):
        for event in events:
            type = event.get("type")
            if not type:
                continue

            # Ignore any events sent by the bot
            user = self._user_from_event(event)
            if user and user.id == self.bot_id:
                continue

            message = None
            if type == "message":
                # TODO: implement other interesting subtypes
                subtype = event.get("subtype") or "message"
                if subtype == "message":
                    message = self._adapt_message(user, event)

            if message:
                self.receive(message)

    def _adapt_message(self, user, event):
        channel_id = event["channel"]
        text = event["text"]
        ts = event["ts"]
        thread_ts = event.get("thread_ts", ts)

        if self._is_direct_message(channel_id):
            # Pretend they mentioned the robot's name
            text = f"{self.robot.name} {text}"

        # TODO: chat threads
        return Message(user, channel_id, text, ts, thread_ts)

    def _user_from_event(self, event):
        user = event.get("user")
        if isinstance(user, dict):
            # In certain events, the user value of the event
            # will be the entire user instead of an ID.
            user = user.get("id")

        return self._find_user(user)

    def _send_message(self, channel_id, text, thread=None):
        self.client.rtm_send_message(channel_id, text, thread)

    def _find_user(self, name_or_id):
        return self.client.server.users.find(name_or_id)

    @staticmethod
    def _is_direct_message(channel_id):
        return (channel_id or "").startswith("D")
コード例 #56
0
class SlackBackend(ErrBot):
    def __init__(self, config):
        super().__init__(config)
        identity = config.BOT_IDENTITY
        self.token = identity.get('token', None)
        if not self.token:
            log.fatal(
                'You need to set your token (found under "Bot Integration" on Slack) in '
                'the BOT_IDENTITY setting in your configuration. Without this token I '
                'cannot connect to Slack.')
            sys.exit(1)
        self.sc = None  # Will be initialized in serve_once
        self.md = imtext()

    def api_call(self, method, data=None, raise_errors=True):
        """
        Make an API call to the Slack API and return response data.

        This is a thin wrapper around `SlackClient.server.api_call`.

        :param method:
            The API method to invoke (see https://api.slack.com/methods/).
        :param raise_errors:
            Whether to raise :class:`~SlackAPIResponseError` if the API
            returns an error
        :param data:
            A dictionary with data to pass along in the API request.
        :returns:
            The JSON-decoded API response
        :raises:
            :class:`~SlackAPIResponseError` if raise_errors is True and the
            API responds with `{"ok": false}`
        """
        if data is None:
            data = {}
        response = json.loads(
            self.sc.server.api_call(method, **data).decode('utf-8'))
        if raise_errors and not response['ok']:
            raise SlackAPIResponseError("Slack API call to %s failed: %s" %
                                        (method, response['error']),
                                        error=response['error'])
        return response

    def serve_once(self):
        self.sc = SlackClient(self.token)
        log.info("Verifying authentication token")
        self.auth = self.api_call("auth.test", raise_errors=False)
        if not self.auth['ok']:
            raise SlackAPIResponseError(
                error="Couldn't authenticate with Slack. Server said: %s" %
                self.auth['error'])
        log.debug("Token accepted")
        self.bot_identifier = SlackIdentifier(self.sc, self.auth["user_id"])

        log.info("Connecting to Slack real-time-messaging API")
        if self.sc.rtm_connect():
            log.info("Connected")
            self.reset_reconnection_count()
            try:
                while True:
                    for message in self.sc.rtm_read():
                        if 'type' not in message:
                            log.debug("Ignoring non-event message: %s" %
                                      message)
                            continue

                        event_type = message['type']
                        event_handler = getattr(
                            self, '_%s_event_handler' % event_type, None)
                        if event_handler is None:
                            log.debug(
                                "No event handler available for %s, ignoring this event"
                                % event_type)
                            continue
                        try:
                            log.debug("Processing slack event: %s" % message)
                            event_handler(message)
                        except Exception:
                            log.exception(
                                "%s event handler raised an exception" %
                                event_type)
                    time.sleep(1)
            except KeyboardInterrupt:
                log.info("Interrupt received, shutting down..")
                return True
            except:
                log.exception("Error reading from RTM stream:")
            finally:
                log.debug("Triggering disconnect callback")
                self.disconnect_callback()
        else:
            raise Exception('Connection failed, invalid token ?')

    def _hello_event_handler(self, event):
        """Event handler for the 'hello' event"""
        self.connect_callback()
        self.callback_presence(
            Presence(identifier=self.bot_identifier, status=ONLINE))

    def _presence_change_event_handler(self, event):
        """Event handler for the 'presence_change' event"""

        idd = SlackIdentifier(self.sc, event['user'])
        presence = event['presence']
        # According to https://api.slack.com/docs/presence, presence can
        # only be one of 'active' and 'away'
        if presence == 'active':
            status = ONLINE
        elif presence == 'away':
            status = AWAY
        else:
            log.error(
                "It appears the Slack API changed, I received an unknown presence type %s"
                % presence)
            status = ONLINE
        self.callback_presence(Presence(identifier=idd, status=status))

    def _team_join_event_handler(self, event):
        self.sc.parse_user_data((event['user'], ))

    def _message_event_handler(self, event):
        """Event handler for the 'message' event"""
        channel = event['channel']
        if channel.startswith('C'):
            log.debug("Handling message from a public channel")
            message_type = 'groupchat'
        elif channel.startswith('G'):
            log.debug("Handling message from a private group")
            message_type = 'groupchat'
        elif channel.startswith('D'):
            log.debug("Handling message from a user")
            message_type = 'chat'
        else:
            log.warning("Unknown message type! Unable to handle")
            return
        subtype = event.get('subtype', None)

        if subtype == "message_deleted":
            log.debug("Message of type message_deleted, ignoring this event")
            return
        if subtype == "message_changed" and 'attachments' in event['message']:
            # If you paste a link into Slack, it does a call-out to grab details
            # from it so it can display this in the chatroom. These show up as
            # message_changed events with an 'attachments' key in the embedded
            # message. We should completely ignore these events otherwise we
            # could end up processing bot commands twice (user issues a command
            # containing a link, it gets processed, then Slack triggers the
            # message_changed event and we end up processing it again as a new
            # message. This is not what we want).
            log.debug(
                "Ignoring message_changed event with attachments, likely caused "
                "by Slack auto-expanding a link")
            return

        if 'message' in event:
            text = event['message']['text']
            user = event['message']['user']
        else:
            text = event['text']
            user = event['user']

        text = re.sub("<[^>]*>", self.remove_angle_brackets_from_uris, text)

        msg = Message(text, type_=message_type)
        if message_type == 'chat':
            msg.frm = SlackIdentifier(self.sc, user, event['channel'])
            msg.to = SlackIdentifier(
                self.sc, self.username_to_userid(self.sc.server.username),
                event['channel'])
        else:
            msg.frm = SlackMUCOccupant(self.sc, user, event['channel'])
            msg.to = SlackMUCOccupant(
                self.sc, self.username_to_userid(self.sc.server.username),
                event['channel'])

        self.callback_message(msg)

    def userid_to_username(self, id_):
        """Convert a Slack user ID to their user name"""
        user = [user for user in self.sc.server.users if user.id == id_]
        if not user:
            raise UserDoesNotExistError("Cannot find user with ID %s" % id_)
        return user[0].name

    def username_to_userid(self, name):
        """Convert a Slack user name to their user ID"""
        user = [user for user in self.sc.server.users if user.name == name]
        if not user:
            raise UserDoesNotExistError("Cannot find user %s" % name)
        return user[0].id

    def channelid_to_channelname(self, id_):
        """Convert a Slack channel ID to its channel name"""
        channel = [
            channel for channel in self.sc.server.channels if channel.id == id_
        ]
        if not channel:
            raise RoomDoesNotExistError("No channel with ID %s exists" % id_)
        return channel[0].name

    def channelname_to_channelid(self, name):
        """Convert a Slack channel name to its channel ID"""
        if name.startswith('#'):
            name = name[1:]
        channel = [
            channel for channel in self.sc.server.channels
            if channel.name == name
        ]
        if not channel:
            raise RoomDoesNotExistError("No channel named %s exists" % name)
        return channel[0].id

    def channels(self, exclude_archived=True, joined_only=False):
        """
        Get all channels and groups and return information about them.

        :param exclude_archived:
            Exclude archived channels/groups
        :param joined_only:
            Filter out channels the bot hasn't joined
        :returns:
            A list of channel (https://api.slack.com/types/channel)
            and group (https://api.slack.com/types/group) types.

        See also:
          * https://api.slack.com/methods/channels.list
          * https://api.slack.com/methods/groups.list
        """
        response = self.api_call('channels.list',
                                 data={'exclude_archived': exclude_archived})
        channels = [
            channel for channel in response['channels']
            if channel['is_member'] or not joined_only
        ]

        response = self.api_call('groups.list',
                                 data={'exclude_archived': exclude_archived})
        # No need to filter for 'is_member' in this next call (it doesn't
        # (even exist) because leaving a group means you have to get invited
        # back again by somebody else.
        groups = [group for group in response['groups']]

        return channels + groups

    @lru_cache(50)
    def get_im_channel(self, id_):
        """Open a direct message channel to a user"""
        response = self.api_call('im.open', data={'user': id_})
        return response['channel']['id']

    def send_message(self, mess):
        super().send_message(mess)
        to_humanreadable = "<unknown>"
        try:
            if mess.type == 'groupchat':
                to_humanreadable = mess.to.username
                to_channel_id = mess.to.channelid
            else:
                to_humanreadable = mess.to.username
                to_channel_id = mess.to.channelid
                if to_channel_id.startswith('C'):
                    log.debug(
                        "This is a divert to private message, sending it directly to the user."
                    )
                    to_channel_id = self.get_im_channel(
                        self.username_to_userid(to_humanreadable))
            log.debug('Sending %s message to %s (%s)' %
                      (mess.type, to_humanreadable, to_channel_id))
            body = self.md.convert(mess.body)
            log.debug('Message size: %d' % len(body))
            fixed_format = body.startswith(
                '```\n')  # hack to fix the formatting
            for part in split_string_after(
                    body,
                    min(self.bot_config.MESSAGE_SIZE_LIMIT,
                        SLACK_MESSAGE_LIMIT)):
                if fixed_format:
                    if not part.startswith('```\n'):
                        part = '```\n' + part
                    if not part.endswith('```') and not part.endswith('```\n'):
                        part += '\n```\n'
                self.sc.rtm_send_message(to_channel_id, part)
        except Exception:
            log.exception(
                "An exception occurred while trying to send the following message "
                "to %s: %s" % (to_humanreadable, mess.body))

    def build_identifier(self, txtrep):
        """ #channelname/username
            or @username
        """
        log.debug("building an identifier from %s" % txtrep)
        txtrep = txtrep.strip()
        channelname = None

        if txtrep[0] == '@':
            username = txtrep[1:]
        elif txtrep[0] == '#':
            plainrep = txtrep[1:]
            if '/' not in txtrep:
                raise Exception(
                    "Unparseable slack identifier, " +
                    "should be #channelname/username or @username : '******'" %
                    txtrep)
            channelname, username = plainrep.split('/')
        else:
            raise Exception(
                "Unparseable slack identifier, " +
                "should be #channelname/username or @username : '******'" % txtrep)

        userid = self.username_to_userid(username)
        if channelname:
            channelid = self.channelname_to_channelid(channelname)
            return SlackMUCOccupant(self.sc, userid, channelid)

        return SlackIdentifier(self.sc, userid, self.get_im_channel(userid))

    def build_reply(self, mess, text=None, private=False):
        msg_type = mess.type
        response = self.build_message(text)

        response.frm = self.bot_identifier
        response.to = mess.frm
        response.type = 'chat' if private else msg_type

        return response

    def shutdown(self):
        super().shutdown()

    @deprecated
    def join_room(self, room, username=None, password=None):
        return self.query_room(room)

    @property
    def mode(self):
        return 'slack'

    def query_room(self, room):
        """ Room can either be a name or a channelid """
        if room.startswith('C') or room.startswith('G'):
            return SlackRoom(channelid=room, bot=self)

        m = SLACK_CLIENT_CHANNEL_HYPERLINK.match(room)
        if m is not None:
            return SlackRoom(channelid=m.groupdict()['id'], bot=self)

        return SlackRoom(name=room, bot=self)

    def rooms(self):
        """
        Return a list of rooms the bot is currently in.

        :returns:
            A list of :class:`~SlackRoom` instances.
        """
        channels = self.channels(joined_only=True, exclude_archived=True)
        return [
            SlackRoom(channelid=channel['id'], bot=self)
            for channel in channels
        ]

    def prefix_groupchat_reply(self, message, identifier):
        message.body = '@{0}: {1}'.format(identifier.nick, message.body)

    def remove_angle_brackets_from_uris(self, match_object):
        if "://" in match_object.group():
            return match_object.group().strip("<>")
        return match_object.group()
コード例 #57
0
ファイル: slack.py プロジェクト: bolshoibooze/err
class SlackBackend(ErrBot):

    def __init__(self, config):
        super().__init__(config)
        identity = config.BOT_IDENTITY
        self.token = identity.get('token', None)
        if not self.token:
            log.fatal(
                'You need to set your token (found under "Bot Integration" on Slack) in '
                'the BOT_IDENTITY setting in your configuration. Without this token I '
                'cannot connect to Slack.'
            )
            sys.exit(1)
        self.sc = None  # Will be initialized in serve_once

    def api_call(self, method, data=None, raise_errors=True):
        """
        Make an API call to the Slack API and return response data.

        This is a thin wrapper around `SlackClient.server.api_call`.

        :param method:
            The API method to invoke (see https://api.slack.com/methods/).
        :param raise_errors:
            Whether to raise :class:`~SlackAPIResponseError` if the API
            returns an error
        :param data:
            A dictionary with data to pass along in the API request.
        :returns:
            The JSON-decoded API response
        :raises:
            :class:`~SlackAPIResponseError` if raise_errors is True and the
            API responds with `{"ok": false}`
        """
        if data is None:
            data = {}
        response = json.loads(self.sc.server.api_call(method, **data).decode('utf-8'))
        if raise_errors and not response['ok']:
            raise SlackAPIResponseError("Slack API call to %s failed: %s" % (method, response['error']))
        return response

    def serve_once(self):
        self.sc = SlackClient(self.token)
        log.info("Verifying authentication token")
        self.auth = self.api_call("auth.test", raise_errors=False)
        if not self.auth['ok']:
            raise SlackAPIResponseError("Couldn't authenticate with Slack. Server said: %s" % self.auth['error'])
        log.debug("Token accepted")
        self.bot_identifier = SlackIdentifier(self.sc, self.auth["user_id"])

        log.info("Connecting to Slack real-time-messaging API")
        if self.sc.rtm_connect():
            log.info("Connected")
            self.reset_reconnection_count()
            try:
                while True:
                    for message in self.sc.rtm_read():
                        if 'type' not in message:
                            log.debug("Ignoring non-event message: %s" % message)
                            continue

                        event_type = message['type']
                        event_handler = getattr(self, '_%s_event_handler' % event_type, None)
                        if event_handler is None:
                            log.debug("No event handler available for %s, ignoring this event" % event_type)
                            continue
                        try:
                            log.debug("Processing slack event: %s" % message)
                            event_handler(message)
                        except Exception:
                            log.exception("%s event handler raised an exception" % event_type)
                    time.sleep(1)
            except KeyboardInterrupt:
                log.info("Interrupt received, shutting down..")
                return True
            except:
                log.exception("Error reading from RTM stream:")
            finally:
                log.debug("Triggering disconnect callback")
                self.disconnect_callback()
        else:
            raise Exception('Connection failed, invalid token ?')

    def _hello_event_handler(self, event):
        """Event handler for the 'hello' event"""
        self.connect_callback()
        self.callback_presence(Presence(identifier=self.bot_identifier, status=ONLINE))

    def _presence_change_event_handler(self, event):
        """Event handler for the 'presence_change' event"""

        idd = SlackIdentifier(self.sc, event['user'])
        presence = event['presence']
        # According to https://api.slack.com/docs/presence, presence can
        # only be one of 'active' and 'away'
        if presence == 'active':
            status = ONLINE
        elif presence == 'away':
            status = AWAY
        else:
            log.error(
                "It appears the Slack API changed, I received an unknown presence type %s" % presence
            )
            status = ONLINE
        self.callback_presence(Presence(identifier=idd, status=status))

    def _message_event_handler(self, event):
        """Event handler for the 'message' event"""
        channel = event['channel']
        if channel.startswith('C'):
            log.debug("Handling message from a public channel")
            message_type = 'groupchat'
        elif channel.startswith('G'):
            log.debug("Handling message from a private group")
            message_type = 'groupchat'
        elif channel.startswith('D'):
            log.debug("Handling message from a user")
            message_type = 'chat'
        else:
            log.warning("Unknown message type! Unable to handle")
            return
        subtype = event.get('subtype', None)

        if subtype == "message_deleted":
            log.debug("Message of type message_deleted, ignoring this event")
            return
        if subtype == "message_changed" and 'attachments' in event['message']:
            # If you paste a link into Slack, it does a call-out to grab details
            # from it so it can display this in the chatroom. These show up as
            # message_changed events with an 'attachments' key in the embedded
            # message. We should completely ignore these events otherwise we
            # could end up processing bot commands twice (user issues a command
            # containing a link, it gets processed, then Slack triggers the
            # message_changed event and we end up processing it again as a new
            # message. This is not what we want).
            log.debug(
                "Ignoring message_changed event with attachments, likely caused "
                "by Slack auto-expanding a link"
            )
            return

        if 'message' in event:
            text = event['message']['text']
            user = event['message']['user']
        else:
            text = event['text']
            user = event['user']

        msg = Message(text, type_=message_type)
        if message_type == 'chat':
            msg.frm = SlackIdentifier(self.sc, user, event['channel'])
            msg.to = SlackIdentifier(self.sc, self.username_to_userid(self.sc.server.username),
                                     event['channel'])
        else:
            msg.frm = SlackMUCOccupant(self.sc, user, event['channel'])
            msg.to = SlackMUCOccupant(self.sc, self.username_to_userid(self.sc.server.username),
                                      event['channel'])

        msg.nick = msg.frm.userid
        self.callback_message(msg)

    def userid_to_username(self, id):
        """Convert a Slack user ID to their user name"""
        user = [user for user in self.sc.server.users if user.id == id]
        if not user:
            raise UserDoesNotExistError("Cannot find user with ID %s" % id)
        return user[0].name

    def username_to_userid(self, name):
        """Convert a Slack user name to their user ID"""
        user = [user for user in self.sc.server.users if user.name == name]
        if not user:
            raise UserDoesNotExistError("Cannot find user %s" % name)
        return user[0].id

    def channelid_to_channelname(self, id):
        """Convert a Slack channel ID to its channel name"""
        channel = [channel for channel in self.sc.server.channels if channel.id == id]
        if not channel:
            raise RoomDoesNotExistError("No channel with ID %s exists" % id)
        return channel[0].name

    def channelname_to_channelid(self, name):
        """Convert a Slack channel name to its channel ID"""
        if name.startswith('#'):
            name = name[1:]
        channel = [channel for channel in self.sc.server.channels if channel.name == name]
        if not channel:
            raise RoomDoesNotExistError("No channel named %s exists" % name)
        return channel[0].id

    def channels(self, exclude_archived=True, joined_only=False):
        """
        Get all channels and groups and return information about them.

        :param exclude_archived:
            Exclude archived channels/groups
        :param joined_only:
            Filter out channels the bot hasn't joined
        :returns:
            A list of channel (https://api.slack.com/types/channel)
            and group (https://api.slack.com/types/group) types.

        See also:
          * https://api.slack.com/methods/channels.list
          * https://api.slack.com/methods/groups.list
        """
        response = self.api_call('channels.list', data={'exclude_archived': exclude_archived})
        channels = [channel for channel in response['channels']
                    if channel['is_member'] or not joined_only]

        response = self.api_call('groups.list', data={'exclude_archived': exclude_archived})
        # No need to filter for 'is_member' in this next call (it doesn't
        # (even exist) because leaving a group means you have to get invited
        # back again by somebody else.
        groups = [group for group in response['groups']]

        return channels + groups

    @lru_cache(50)
    def get_im_channel(self, id):
        """Open a direct message channel to a user"""
        response = self.api_call('im.open', data={'user': id})
        return response['channel']['id']

    def send_message(self, mess):
        super().send_message(mess)
        to_humanreadable = "<unknown>"
        try:
            if mess.type == 'groupchat':
                to_humanreadable = mess.to.username
                to_channel_id = mess.to.channelid
            else:
                to_humanreadable = mess.to.username
                to_channel_id = mess.to.channelid
            log.debug('Sending %s message to %s (%s)' % (mess.type, to_humanreadable, to_channel_id))
            self.sc.rtm_send_message(to_channel_id, mess.body)
        except Exception:
            log.exception(
                "An exception occurred while trying to send the following message "
                "to %s: %s" % (to_humanreadable, mess.body)
            )

    def build_message(self, text):
        return build_message(text, Message)

    def build_identifier(self, txtrep):
        """ #channelname/username
            or @username
        """
        log.debug("building an identifier from %s" % txtrep)
        txtrep = txtrep.strip()
        channelname = None

        if txtrep[0] == '@':
            username = txtrep[1:]
        elif txtrep[0] == '#':
            plainrep = txtrep[1:]
            if '/' not in txtrep:
                raise Exception("Unparseable slack identifier, " +
                                "should be #channelname/username or @username : '******'" % txtrep)
            channelname, username = plainrep.split('/')
        else:
            raise Exception("Unparseable slack identifier, " +
                            "should be #channelname/username or @username : '******'" % txtrep)

        userid = self.username_to_userid(username)
        if channelname:
            channelid = self.channelname_to_channelid(channelname)
            return SlackMUCOccupant(self.sc, userid, channelid)

        return SlackIdentifier(self.sc, userid, self.get_im_channel(userid))

    def build_reply(self, mess, text=None, private=False):
        msg_type = mess.type
        response = self.build_message(text)

        response.frm = self.bot_identifier
        response.to = mess.frm
        response.type = 'chat' if private else msg_type

        return response

    def is_admin(self, usr):
        return usr.split('@')[0] in self.bot_config.BOT_ADMINS

    def shutdown(self):
        super().shutdown()

    @deprecated
    def join_room(self, room, username=None, password=None):
        return self.query_room(room)

    @property
    def mode(self):
        return 'slack'

    def query_room(self, room):
        """ Room can either be a name or a channelid """
        if room.startswith('C') or room.startswith('G'):
            return SlackRoom(channelid=room, bot=self)

        m = SLACK_CLIENT_CHANNEL_HYPERLINK.match(room)
        if m is not None:
            return SlackRoom(channelid=m.groupdict()['id'], bot=self)

        return SlackRoom(name=room, bot=self)

    def rooms(self):
        """
        Return a list of rooms the bot is currently in.

        :returns:
            A list of :class:`~SlackRoom` instances.
        """
        channels = self.channels(joined_only=True, exclude_archived=True)
        return [SlackRoom(channelid=channel['id'], bot=self) for channel in channels]

    def groupchat_reply_format(self):
        return '@{0}: {1}'
コード例 #58
0
def parcel_help():
    pass


if sc.rtm_connect():
    while sc.server.connected is True:
        msg_from_slack = sc.rtm_read()
        if msg_from_slack:
            print "got something from slack: {} ".format(msg_from_slack)
            if 'text' in msg_from_slack[0].keys(
            ) and msg_from_slack[0]['text'].encode(
                    'ascii', 'ignore').startswith('@mailboy'):
                print msg_from_slack[0]['text'][8::]
                if msg_from_slack[0]['text'][8::].strip() == 'testing':
                    sc.rtm_send_message("CBCK26G31", "I'm fine!")
                elif msg_from_slack[0]['text'][8::].strip() == 'help':
                    print "You need help!"
                    help_msg = '''You can type any of the following to interact with me:\n@mailboy username,\n@mailboy testing,\n@mailboy quicklookid
                    '''
                    sc.rtm_send_message("CBECMBL01", help_msg)
                else:
                    #suppose everything is handled from here
                    parcel_help()

                    #----make slack bot more interesting!

                    question_slack = msg_from_slack[0]['text'][8::].strip()
                    try:
                        question = 'python quepy/examples/dbpedia/main.py ' + question_slack
                        res = os.popen(question).read()
コード例 #59
0
class Bot(object):
    """Slack bot class.
    Handle all basic greeting to member rolling standup, including
    timeframe of each standup.
    """
    """Attributes."""
    token = None
    channels = []
    reports = []
    client = None
    login_data = None
    end_time = None

    def __init__(self, token, timeout, secret=""):
        """Initialize bot instance.
        token: slack bot authorization token
        """
        self.headers = {
            "secret": secret,
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
        self.timeout = timeout
        self.token = token

    def start(self):
        """Boot up slack bot."""
        self.client = SlackClient(self.token)
        if self.client.rtm_connect():
            self.login_data = self.client.get_login_data()
            logging.info("bot running")
            for channel in self.get_all_channels():
                if channel['name'] in self.channels:
                    self.reports.append(self.standup_start(channel))
        return self.reports

    def set_channels(self, channels):
        """Pass list of channel to execute standup.
        :channels array of channels
        """
        self.channels = channels
        return self

    def greet(self, channel):
        """Initial greeting.
        channel: target channel name
        """
        self.client.rtm_send_message(
            channel, "Hello, We'll start the stand up \
soon.")

    def farewell(self, channel):
        """Sum up the standups.
        channel: target channel name
        """
        self.client.rtm_send_message(
            channel, "Looks like that's it for today \
Thanks for your effort today")

    def is_bot(self, member):
        """Check if member is current bot.
        member: specified member id
        """
        return self.login_data['id'] == member

    def extract_slack_message(self, message):
        """Extract slack message body.
        message: response from slack
        """
        text, user, channel = message.get('text'), message.get(
            'user'), message.get('channel')
        if not text or not user or not channel or user == self.login_data['id']:
            return None
        return {'user': user, 'text': text, 'channel': channel}

    def fetch_user_data(self, member):
        """Fetch user data from userid.
        member: userid on slack
        """
        response = self.client.api_call("users.info", user=member)
        result = {
            'email': response['user']['profile']['email'],
            'username': response['user']['name'],
            'real_name': response['user']['real_name']
        }
        return result

    def exec_member(self, member, channel):
        """Loop through every questions, and pass to user.
        member: interacted member.
        """
        ongoing = True
        count = -1
        data = {}
        response = {}
        data['user'] = self.fetch_user_data(member)
        # bot start
        self.client.rtm_send_message(
            channel, """
Hello <@{}> type anything to begin,\
or `skip` if you want to skip for \
today.
            """.format(member))
        member_time_out = datetime.now() + timedelta(seconds=int(self.timeout))
        while ongoing:
            if datetime.now() > member_time_out:
                response['message'] = "timeout"
                self.client.rtm_send_message(
                    channel, "<@{}> is not available \
Let's move to another member.".format(member))
                break
            for slack_message in self.client.rtm_read():
                # Start listening for message
                message = self.extract_slack_message(slack_message)
                if message is None:
                    continue
                if message['channel'] != channel or message['user'] != member:
                    continue
                if message['text'].lower() == 'skip':
                    response['message'] = "skipped"
                    self.client.rtm_send_message(message['channel'], 'okay')
                    ongoing = False
                    break
                elif count < 0 and message['text'].lower(
                ) not in constants.POSITIVE:
                    continue
                if count >= 0:
                    response[self.questions[count]] = message['text']
                else:
                    response['init'] = message['text']
                count += 1
                if count >= len(self.questions):
                    ongoing = False
                    break
                # reset timeout variables after each answer
                member_time_out = datetime.now() + timedelta(
                    seconds=int(self.timeout))
                self.client.rtm_send_message(message['channel'],
                                             self.questions[count])
            data['response'] = response
        self.client.rtm_send_message(channel, "Thanks <@{}>.".format(member))
        return data

    def standup_start(self, channel):
        """Start stand up on channel.
        channel: respective channel
        """
        report = {}
        report['channel'] = channel['name']
        report['members'] = []
        self.greet(channel['id'])
        members = self.get_members(channel['id'])
        for member in members:
            if self.is_bot(member):
                continue
            member_report = self.exec_member(member, channel['id'])
            report['members'].append(member_report)
        self.farewell(channel['id'])
        return report

    def get_all_channels(self):
        """Get all channel associated with current bot."""
        response = self.client.api_call("channels.list")
        return response['channels']

    def get_members(self, channel):
        """Get members of channel.
        channel: channel name
        """
        response = self.client.api_call("channels.info", channel=channel)
        return response['channel']['members']

    def set_questions(self, questions):
        """Set question to be asked.
        questions: array of questions
        """
        self.questions = questions
        return self

    def push_question(self, question):
        """Push question to queue.
        question: Question object to be pushed.
        """
        self.questions.append(question)
        return self

    def send_report(self, hook):
        """Send report to hook.
        hook: endpoint to receive the report
        """
        payload = json.dumps(self.reports)
        try:
            response = requests.post(hook, headers=self.headers, data=payload)
            return response
        except requests.exceptions.RequestException as e:
            logging.warning(e)
            return payload
コード例 #60
0
class PartyQueueBot:

    def __init__(self, config):
        self.client = SlackClient(
            token=config.slack_token, client_id=config.slack_client_id, client_secret=config.slack_client_secret
        )
        self.bot_user_id = self._get_user_id()
        self.bot_mention = '<@{id_}>'.format(id_=self.bot_user_id)
        self.mobile_client = MobileClientWrapper(config)
        self.queue = PartyQueueController(self.mobile_client)
        self.track_controller = TrackController(self.mobile_client)
        self.search_controller = SearchController(self.mobile_client)

    def _get_user_id(self):
        users = self.client.api_call('users.list')
        return [user for user in users['members'] if user['name'] == 'party_queue'][0]['id']

    def start_real_time_messaging(self):
        """
        Starts Real Time Messaging
        """
        if self.client.rtm_connect():
            print('PartyQueue up and listening! Ctrl+C to break.')

            try:
                while True:
                    last_read = self.client.rtm_read()
                    if not last_read:
                        continue
                    last_read = last_read[0]
                    last_read.setdefault('type', '')
                    last_read.setdefault('text', '')
                    if last_read['type'] == 'message' and self.bot_mention in last_read['text']:
                        self.handle_message(last_read)
            except KeyboardInterrupt:
                print('Cleaning up and logging out...')
                self.queue.close_party_queue()
                self.mobile_client.logout()

    def handle_message(self, last_read_message):
        """
        Handles a slack message

        :param last_read_message: dict of last read message
        """
        parsed_text = last_read_message['text']
        origin = last_read_message['channel']
        sender_user_id = last_read_message['user']
        if 'queue' in parsed_text.lower():
            self.get_queue_contents(origin)
        elif 'search' in parsed_text.lower():
            self.search_songs(origin, self.get_query(parsed_text.lower(), 'search'))
        elif 'add' in parsed_text.lower():
            self.add_song_by_name_and_title(origin, self.get_query(parsed_text.lower(), 'add'), sender_user_id)
        else:
            self.client.rtm_send_message(origin, 'I don\'t understand your stupid request.')

    @staticmethod
    def get_query(message, command):
        """
        Pulls out actual query from message string

        :param message: the message string
        :param command: the PartyQueue command string used in the message

        :return: query string
        """
        return message[message.index(command)+len(command)+1:]

    def get_queue_contents(self, origin):
        """
        Posts PartyQueue Entries to chat

        :param origin: channel where request originated
        """
        queue_tracks = self.queue.get_party_queue_tracks()
        if len(queue_tracks):
            text = '*Songs in the PartyQueue ({share}):*' \
                   '\n*-------------------------*\n'.format(share=self.queue.share_url())
            for index, track in enumerate(queue_tracks, start=1):
                text += '{count}. {artist} | {title}\n'.format(count=index, artist=track.artist, title=track.title)
        else:
            text = 'No Songs Currently in the Queue ({share})'.format(share=self.queue.share_url())
        self.client.rtm_send_message(origin, text)

    def search_songs(self, origin, query):
        """
        Posts results of search made on given query to chat

        :param origin: channel where request originated
        :param query: search query
        """
        text = '*Search Results for \'{query}\'*\n*-------------------------*\n'.format(**locals())
        for index, track in enumerate(self.search_controller.get_search_results(query), start=1):
            self.track_controller.add_track_to_repo(track)
            track_text = '{count}. {artist} | {title}\n'.format(count=index, artist=track.artist, title=track.title)
            text += track_text
        self.client.rtm_send_message(origin, text)

    def add_song_by_name_and_title(self, origin, artist_song_string, slack_user_id):
        """
        Adds a Song to the PartyQueue and Posts a notification

        :param origin: channel where request originated
        :param artist_song_string: Name of the song to add
        :param slack_user_id: ID of the slack user who requested the song
        """
        split_list = artist_song_string.split('|')
        artist = split_list[0].strip()
        track_name = split_list[1].strip()
        track = self.track_controller.get_track_by_artist_and_name(artist, track_name)
        if track is None:
            text = '*Could not find song {title}, try searching for it first*'.format(title=track_name.title())
        else:
            self.queue.add_to_play_list(track.store_id, slack_user_id)
            text = '*Added {title} to the Party Queue*'.format(title=track.title)
        self.client.rtm_send_message(origin, text)