tgalal / yowsup

The WhatsApp lib
GNU General Public License v3.0
7.07k stars 2.23k forks source link

[HELP] Getting iq group list results and using it in other functions #1857

Closed SweetShyGirl closed 5 years ago

SweetShyGirl commented 7 years ago
class RequestGroupList(YowProtocolLayer):
    def getMyGroups(self):
        self._sendIq(ListGroupsIqProtocolEntity(), self.onGroupsResult, self.onGroupsError)

    def onGroupsResult(self, protocolTreeNode, listGroupsIqProtocolEntity):
         self.toUpper(ListGroupsResultIqProtocolEntity.fromProtocolTreeNode(protocolTreeNode))

    def onGroupsError(self, protocolTreeNode, listGroupsIqProtocolEntity):
        self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(protocolTreeNode))

I would like to find a way to return only the successful results and use back the results in a message_entity class, for example, to check if the bot is admin by requesting the groupinfo results and check it, etc

I want to do this without adding everything under the same class or function as the request

SweetShyGirl commented 7 years ago

@jlguardi here?

decieved commented 7 years ago

You want to check if the bot is admin before removing and adding users via commands?

SweetShyGirl commented 7 years ago

@KyleJr Yes, I want to check if the bot is admin first before but Idk how to return true from the iq results in a class or nested function, then check the function/variable in my command parser core.

It's hard to explain, I want to check if the bot is admin before doing any sort of adding or removing users.

And I want to check if a number is in a group before adding or removing them too, please help

SweetShyGirl commented 7 years ago

@tgalal help please

SweetShyGirl commented 7 years ago

how to set iq results on a global function to be accessed else where

SweetShyGirl commented 7 years ago

@jlguardi hi

jlguardi commented 7 years ago

Do something like:

... # somewhere in your loop
     successFn = lambda successEntity, originalEntity: yourGlobalFunction(successEntity, originalEntity, otherParams)   
     Self._sendIq(ListGroupsIqProtocolEntity(), successFn)
SweetShyGirl commented 7 years ago

@jlguardi

In my loop? I don't understand, do you mean each time I receive a text message or something?

For example, I would put it in my layers.py and define the global function in another file then each time I want to check if the bot is admin, i would call the global function, correct?

Assuming if it's each time I receive a text message, then the bot would keep checking group info, which wouldn't be the best idea I might add (requesting group info on every message)

SweetShyGirl commented 7 years ago

Also

Does this applies to group info? because to check if the bot is admin, i need to use the GroupInfo entity so I was wondering if I could use this same method for group list, group info and other iq requests

SweetShyGirl commented 7 years ago

@jlguardi

This is just an example, not my actual code but, this is how I'm trying to do it with your code

layers.py

import group

successFn = lambda successEntity, originalEntity: group.list(successEntity, originalEntity)   
self._sendIq(ListGroupsIqProtocolEntity(), successFn)

@protocolentity("message") 
def onmsg(self, entity):
    if "list" in entity.getBody():
        print(group.list(successEntity, originalEntity))

group.py


def list(successEntity, originalEntity)
    results = successEntity
    return results

# That's how you meant?
jlguardi commented 7 years ago

@SweetShyGirl No, it isn't. I meant something like:

layers.py
import group

def getGroupsInfo(self, messageEntity):
    successFn = lambda successEntity, originalEntity: group.list(successEntity, originalEntity, messageEntity)   
    self._sendIq(ListGroupsIqProtocolEntity(), successFn)

@protocolentity("message") 
def onmsg(self, entity):
    if "list" in entity.getBody():
        self.getGroupsInfo(entity) #if you need to use incoming message later

group.py

def list(successEntity, originalEntity, messageEntity):
    results = successEntity
    print(results)
SweetShyGirl commented 7 years ago

This is what I'm actually trying to achieve with group results, to be able to parse from them and use them

layers.py
import group

def getGroupsInfo(self, messageEntity):
    successFn = lambda successEntity, originalEntity: group.list(successEntity, originalEntity, messageEntity)   
    self._sendIq(ListGroupsIqProtocolEntity(), successFn)

@protocolentity("message") 
def onmsg(self, entity):
    """
        Under here would be where i execute commands
    """
    if "list" in entity.getBody():
        send_msg(self.getGroupsInfo(entity), target)

    if "@groupid " in entity.getBody():
        id = entity.getBody.split("@groupid ")[1] # Splitting the id, this isn't how i parse commands
        if id in self.getGroupsInfo(entity):      # just giving you an idea
            send_msg("That group exist", target)

group.py

def list(successEntity, originalEntity, messageEntity):
    return successEntity

That code is 100% but I'm trying to make you understand what I want to do

SweetShyGirl commented 7 years ago

@jlguardi

I know it's possible by piling up everything under the list function, but I want to get the iq results to also use in tons of other functions throughout the bot, not only there. That's my initial issue which I've been trying to do for days

jlguardi commented 7 years ago

@SweetShyGirl You can't use send_msg(self.getGroupsInfo(entity), target) due to self.getGroupsInfo returns nothing! _sendIq sends an Iq to WA server and returns to you the control (so nothing but exceptions is returned). Some time after, the Iq answers is received from WA and then managed by interface layer executing success callback and error callback. So, whenever you execute send_msg(self.getGroupsInfo(entity), target) you are waiting for an asynchronous event and you lock main thread. This will not work.

I recommend to you something like:

I attach a draft of code (not tested):

class myLayer(...):
  myGroups = {} # class variable with your groups of interest
  def onGroupList(successEntity, originalEntity):
    for child in successEntity.getChildren(): # this is a brochure of code
        myGroups[group.name] = group.id 

  def getGroupsInfo(self):
    successFn = lambda successEntity, originalEntity: self.onGroupList(successEntity, originalEntity)
    errorFn = lambda successEntity, originalEntity: self.getGroupsInfo() #try again if failed but you should check to avoid too much calls
    self._sendIq(ListGroupsIqProtocolEntity(), successFn, errorFn)

@ProtocolEntityCallback("success")
 def onSuccess(self):
    ....
    self.getGroupsInfo()

 @ProtocolEntityCallback("message")
  def onMessage(self, ,entity):
    if "list" in entity.getBody():
        groupName = split(...)
        send_msg(myGroups[groupName], target)

@ProtocolEntityCallback("notification")
  def onNotification(self, entity):
    if isinstance(entity, CreateGroupsNotificationProtocolEntity):
        myGroups[group.name] = group.id
SweetShyGirl commented 7 years ago

Yes I like the idea of that, I'll let you know in 24 hours

SweetShyGirl commented 7 years ago

Okay, I've been busy preparing for christmas..

@jlguardi

I'm lost, but what's more important in all this is to check group participants, and know when they are admin or not

Could I get group participants info of each groups on start and update each time a group notification got called?

So when I need to remove someone, this way I'll just use the variable (or a file that stores each participants) and check if that number is in the stored participants list before attempting to remove them. And hopefully, it'll be stored as a dictionary along with JID of each number and item as admin/None.

I could do all this on my own but I need your assistance on getting groups participants of each group on startup, if that's possible. Since you're able to get the group names

Perhaps I could store each group participants to a file using the group id as the file name (easy to do) but getting the information is the problem

SweetShyGirl commented 7 years ago

@jlguardi Thanks, got it working by group notifications

So i did in fact create new files saved as group ids with participants stored, and updated per notifications I'm more worried about how often can I send iq requests before getting banned? And also, is it possible to know when a number was given admin? And have you found a way to join group links yet? I believe the group link is like a group id, hashed with a base64, and you could use the join protocol entity modified to send a iq request, then join the group on prompt after getting info of the group link.. Let me know when you're available, thanks

SweetShyGirl commented 7 years ago

Also, how can I ignore messages when yowsup starts up? I hate when my bot triggers to previously entered offline commands and leads to late responding and possibly spam