tomer8007 / kik-bot-api-unofficial

Python API for writing unoffical Kik bots that act like humans
MIT License
126 stars 76 forks source link

obtaining name of user in group that sent message #177

Closed aspwil closed 3 years ago

aspwil commented 3 years ago

Is there any way to obtain the name of the user that sends a message in a group from inside of

on_group_message_received(self, chat_message: IncomingGroupChatMessage):

calling chat_message.from_jid as is done in the interactive client example just returns a long string of numbers and letters.

Is it possible to get the actual display name (or #name) of said user? thank you

tomer8007 commented 3 years ago

Yes, I guess you probably want request_info_of_users.

aspwil commented 3 years ago

Thanks, I ended up using client.request_info_of_users(jid) i was originally trying to call .diplay_name upon the object generated by on_peer_info_received() but that made the program start acting weird and being unable to get group names (weird) so I ended up just using str(user_object).split("display_name=")[1][0:-2] to directly extract it from its string representation.

aspwil commented 3 years ago

I thought I would include the exact code I used to get it (in case anyone comes across the same problem)

group_mates = {}
user_object = None
waiting = False

    def on_peer_info_received(self, response: PeersInfoResponse):
        global waiting, user_object
        user_object = response.users
        waiting = False

def jid_to_group_display_name(jid):
    global waiting, user_object
    if jid in group_mates:
        return group_mates[jid]
    else:
        waiting = True
        client.request_info_of_users(jid)
        while waiting:
            time.sleep(1)
        name = str(user_object).split("display_name=")[1][0:-2]
        if len(name) < 10:
            group_mates[jid] = name
        else:
            group_mates[jid] = name[0:10] + "..."
        return group_mates[jid]

the reason for the waiting boolean is to force the getting of name from group_mates to wait until we actually receive the display name from client.request_info_of_users(jid) (so we don't try to get the name from group_mates before the name is added to group_mates) and the reason for user_object is to forward the info back to be added to group_mates and then the last little bit is for truncation (cause some people have names that are way too long)

aspwil commented 3 years ago

I have now realized that the above code can cause a multitude of problems. due to it being dependent on shuffling back and forth the variables user_object and waiting between threads. I have since replaced it with this (much simpler and less error-prone) code, this also allows you to get more than just the name of the user, and do other things.

users = {}

    def on_peer_info_received(self, response: PeersInfoResponse):
        users[response.users[0].jid] = response.users[0]

def query_user(jid):
    if jid in users:
        return users[jid]
    else:
        client.request_info_of_users(jid)
        while jid not in users:
            pass
        return users[jid]

def jid_to_group_display_name(jid):
    return query_user(jid).display_name

upon getting the info of a peer we add the user object to the users dictionary based on its jid

when querying a user's info, if they're already in the dictionary we return the user object.

if they are not in the dictionary we request the info (which will be added to the dictionary by the on_peer_info_received call back)

we then enter a loop of waiting for the info to be added to the dictionary

once the entry is added to the dictionary we return the info object.

then jid_to_group_display_name(jid) just returns the display name from the user object