Amanda Amanda - 5 months ago 11
Python Question

Why is my code printing the "if" result and the "else" result?

I'm trying to write a pretty basic slackbot, starting by looking up the bot's
user_id, which is already harder than I was expecting. The only way I can figure from the documentation is to pull a list of every user and then search that list for my bot user. That already seems kind of bizarre, so if anyone can suggest a better approach, I'm all ears.

But right now what is happening is that it finds the user_id and then proceeds to choke:

Ready to look for REDACTED
<type 'dict'>
2016-06-27 20:22:05.380408 DEBUG REDACTED : ABC123
2016-06-27 20:22:05.381173 DEBUG No user found named REDACTED
2016-06-27 20:22:05.385158 DEBUG ABC123


This is my code:

from slackclient import SlackClient
import time
import re
import datetime


class Bot(object):

def __init__(self, token, username):
self.client = SlackClient(token)
self.username = username
self.user_id = {}

def _log(self, message, level=' DEBUG '):
"""
TODO this should actually put logs somewhere useful.
for now writing to the stream is useful.
"""
print str(datetime.datetime.utcnow()) + level + message


def run(self):
if self.client.rtm_connect():
self.user_id = self.whoami(self.client.server.username)
while True:
self.process_messages(self.client.rtm_read())
time.sleep(1)
else:
self._log("Connection failed.")

def whoami(self, username):
"""
finds the ID for this username.
"""
all_users = self.client.api_call("users.list")
print "Ready to look for " + username

for user in all_users['members']:
if re.match(username, user['name']):
self._log(user['name'] + " : " + user['id'])
user_id = user['id']
if (user_id not in locals()):
self._log("No user found named " + username)
else:
self._log(user_id)
return user_id


And then I call it with:

api_token = 'redacted'
username = 'redacted'

first_bot = Bot(api_token, username)
first_bot.run()


I am trying to figure out why it finds the user and then immediately says "No user found" -- and then prints the
user_id
-- I expected it to print one or the other.

Answer

I think if ("user_id" not in locals()): (note the quotes around user_id) would do the trick, but I'd strongly recommend not using locals().

Here's one of many possible fixes:

def whoami(self, username):
    """
    finds the ID for this username.
    """
    all_users = self.client.api_call("users.list")
    print "Ready to look for " + username

    user_id = None

    for user in all_users['members']:
        if re.match(username, user['name']):
            self._log(user['name'] + " : " + user['id'])
            user_id = user['id']

    if user_id is None:
        self._log("No user found named ") 

    return user_id

EDIT

Also, completely untested, but here's a better way to get the bot's user ID:

def whoami(self):
    """
    finds the bot's user ID
    """

    return self.client.api_call("auth.test")["user_id"]
Comments