0

I have a facebook messenger chatbot I programmed in python. There are a few dozen commands it handles, mostly via a ton of if/then statements as follows

if state == "state1":
    if "command1" in message:
         (do stuff)
    elif "command2" in message:
         (do other stuff)

         state = "waiting_command2_resp"
    elif ...
elif state == "waiting_command2_resp":
    if message == "response1":
         (stuff)
    elif message == "response2":
         (you get the idea)

elif...

You get the idea. As the capabilities of the bot have grown and become more complex, the code has become ridiculously confusing to navigate.

I'm looking for a way to refactor the code so it's cleaner. I can potentially make each action a method, but the mass of if/else statements will remain to determine which method to call

What's a good, maintainable way of assigning a string to each method, and running the appropriate method where its assigned string matches the message string?

I know Flask runs methods in response to URL path strings above the method definition. For example:

@app.route('/')
def index():
    do stuff

@app.route('/endpoint')
def method():
    do other stuff

Is there any way I can potentially do this via similar behavior?

Edit: This is not a duplicate of the question it's marked as a duplicate of. That question is about if you have a string with the exact name of the function. That is not the case here

quantumbutterfly
  • 1,815
  • 4
  • 23
  • 38
  • 1
    You could use a dict mapping from command string to function. – Vivek Pabani Jun 14 '18 at 01:04
  • 1
    The first step is to build a dict mapping strings to functions. And ideally a `command, *args = parse(message)` so you can just look up `functions[command]`, instead of having to iterate `for function in functions: if function in message: …`. – abarnert Jun 14 '18 at 01:06
  • If you want to have a single dict shared by all the states, there's nothing stopping you from having a dict keyed off a tuple of two strings, so you can look up `functions[state, command]`. – abarnert Jun 14 '18 at 01:07
  • Then you just have to write the decorator that registers a function by just adding it to the appropriate dict (and then returns the function unchanged). The linked question won't show you how to do that part, but if you get stuck on that, you can ask a new question. (Try writing it not as a decorator at first, but as a function you explicitly call: `register('state1', 'command1', method)`. Then, after it's working, worry about how to give it the nice decorator syntax.) – abarnert Jun 14 '18 at 01:09
  • "That question is about if you have a string with the exact name of the function. That is not the case here" The linked duplicate applies to your question in exactly the same way: it maps arbitrary strings to some functions. – juanpa.arrivillaga Jun 14 '18 at 19:15

0 Answers0