Is there a way to make a Discord Dadbot that can find "I'm" later in a message?

Viewed 70

So I'm working on a personal bot in Python on my Discord server that can do a variety of things, one of which being mimicking the common Dadbot. Here's the code that does that:

if any(word in msg for word in imlist):      
    resp = message.content.split(" ",1)[1]
    await message.channel.send("Hi "+ resp +", I'm Pigeonbot")

if any(word in msg for word in iamlist):
    resp = message.content.split(" ",2)[2]
    await message.channel.send("Hi "+ resp +", I'm Pigeonbot")

And here are the two lists:

imlist = ["I'm", "Im", "im", "i'm", "IM", "I'M"]
iamlist = ["i am", "I am", "I AM"]

If you type a message in discord like "I'm hungry", it will respond with "Hi hungry, I'm Pigeonbot". However if you say something before the "I'm", such as "It's hot outside, and I'm hungry", it will return "Hi hot outside, and I'm hungry, I'm Pigeonbot". Is there a way to make it so that the bot will find where in the message the imlist or iamlist is and start the "Hi [], I'm Pigeonbot" from there? Thank you :)

2 Answers

Try something like.

all_list = imlist+iamlist
message_word_text = message.content.split(" ")
indices = []
for word in all_list:
      try:
       indices.append(message_word_text[word])
      except:
       indices.append(100)
noun = message_word_text[message_word_text.index(all_list[indices.index(min(indices)])+1]
print(f'Hi {noun}')




Essentially what we're doing in this program is appending the index of each word in the I'm list relating to the message words. The Lowest of those indices means the word that is first. Then we find the noun by taking the index of the lowest value, passing that in the I'm list, then finding that in the message content, and finally we find the word after that.

This is a good use-case for regular expressions

You can use the regex I(?:'| a)?m ([^\s]*) Demo

Explanation:

  • I: Match a literal I.
  • (?:...)?: Makes the contents an optional non-capturing group.
  • '| a: Contents of the non-capturing group: match an apostrophe, or a space and a.
  • m : Match a m and then a space.
  • (...): Create a capturing group
  • [^\s]*: Match any character except a space, any number of times

As you can see from the demo, this will only capture a single word after I'm. If you want to capture everything after I'm, you can change the regex to I(?:'| a)m (.*) Demo. Here, the contents of the capture group match any character, any number of times.

import re

expr1 = re.compile(r"I(?:'| a)m ([^\s]*)", re.IGNORECASE) # Use the re.IGNORECASE flag for case-insensitive match

expr2 = re.compile(r"I(?:'| a)m (.*)", re.IGNORECASE)

test_texts = ["I'm hungry", "It's hot and I'm parched", "I'm not stupid", "I'm going to go to bed now, see you tomorrow"]

for s in test_texts:
    print(f"text: {s}")
    match = re.search(expr1, s)
    if match:
        resp = match.group(1)
        print(f"\texpr1: Hi {resp}, I'm pigeonbot")

    match2 = re.search(expr2, s)
    if match2:
        resp2 = match2.group(1)
        print(f"\texpr2: Hi {resp2}, I'm pigeonbot")

And this gives us the output:

text: I'm hungry
    expr1: Hi hungry, I'm pigeonbot
    expr2: Hi hungry, I'm pigeonbot
text: It's hot and I'm parched
    expr1: Hi parched, I'm pigeonbot
    expr2: Hi parched, I'm pigeonbot
text: I'm not stupid
    expr1: Hi not, I'm pigeonbot
    expr2: Hi not stupid, I'm pigeonbot
text: I'm going to go to bed now, see you tomorrow
    expr1: Hi going, I'm pigeonbot
    expr2: Hi going to go to bed now, see you tomorrow, I'm pigeonbot
Related