tdryer / hangups

the first third-party instant messaging client for Google Hangouts
https://hangups.readthedocs.io/
MIT License
1.71k stars 191 forks source link

How to use the send_message.py code within another code? #415

Open masterchop opened 6 years ago

masterchop commented 6 years ago

Hello i have been using this software alot for my home security system but i have struggle with the send_message.py script i cant figure out how to use it in another code. i tried using its code on the interactive shell:

` import hangups

from common import run_example

async def send_message(client): request = hangups.hangouts_pb2.SendChatMessageRequest( request_header=client.get_request_header(), event_request_header=hangups.hangouts_pb2.EventRequestHeader( conversation_id=hangups.hangouts_pb2.ConversationId( id="Ugz1TPwdoBnYwNq9RXN4AaABAagB-YGbAQ" ), client_generated_id=client.get_client_generated_id(), ), message_content=hangups.hangouts_pb2.MessageContent( segment=[ hangups.ChatMessageSegment("Test").serialize() ], ), ) await client.send_chat_message(request)`

But i am not able to call it to send a message i have tried all this sequenses:

` run_example(send_message, '--conversation-id Ugz1TPwdoBn9RXN4AaABAagB-YGbAQ', '--message-text hola')

run_example(send_message, '--conversation-id', 'Ugz1TPwdoBnq9RXN4AaABAagB-YGbAQ', '--message-text', 'hola')

run_example(send_message, '--conversation-id:Ugz1TPwdoBNq9RXN4AaABAagB-YGbAQ', '--message-text:hola')

run_example(send_message, 'Ugz1TPwdoBnq9R4AaABAagB-YGbAQ', 'hola')`

Any help is welcome

IamSierraCharlie commented 6 years ago

whats the error when you try to run it this way?

masterchop commented 6 years ago

I got the following error :+1:

error: the following arguments are required: --conversation-id Ugz1TPwdoBn9RXN4AaABAagB-YGbAQ, --message-text hola

it always complain about the arguments so i am not sure how to pass them inside a script.

Terrance commented 6 years ago

The example code defines script command arguments; it doesn't send the actual conversation ID because that's read from the argument list (i.e. as given from your shell) as per common.run_example.

If you're interacting with hangups from another script then don't go via the examples -- they're exactly that: simple examples under an independent wrapper. You should work with the client directly, which means creating a client, adding a handler for on_connect that starts whatever tasks you need to do, and running your client in an asyncio event loop:

async def callback():
    # Do your tasks here.

client = hangups.Client(...)
client.on_connect.add_observer(callback)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(client.connect(), loop=loop)
try:
    loop.run_until_complete(task)
except KeyboardInterrupt:
    task.cancel()
    loop.run_until_complete(task)
finally:
    loop.close()
masterchop commented 6 years ago

OllieTerrance, thanks for the response but i am too new to python so i am not sure were to go from there but thanks that will help others with better knowledge.

masterchop commented 6 years ago

is there any chance you could create a quick sample to send msg? i am using 'import os' to run the send_message.py and this is taking alot of resources, i am running PI3B with Opencv with MobileNet SSD neural network and sending screenshot results through hangups works great but pi is to resource limited.

ubaid4j commented 6 years ago

masterchop, can you please share the code of sending sms (of your work)..

masterchop commented 6 years ago

I am not doing anything special, i am just importing the os module and do a system command:

os.system("send_message.py --conversation-id Ugz1TPwdoBn9RXN4AaABAagB-YGbAQ, --message-text hello ")

But this code probably creates a session everytime and i would like to have the session open like the chat client.

ubaid4j commented 6 years ago

ok

Maillouski commented 6 years ago

I have the same question. I am really new to python and would like an example of a basic .py that would simply repeat the received text to the sender.

I would then be able to work from there.

umop3plsdn commented 6 years ago

tritto

ghost commented 5 years ago

@Synoptic2 Same here

Terrance commented 5 years ago

I am really new to python

Then this probably isn't a good place for you to start off. Working with hangups directly requires knowledge of using the asyncio module correctly, which itself requires a strong understanding of Python. You should make yourself familiar with the language (and programming in general, if applicable) -- this guide lists plenty of places to make a start.

From there, you should learn how to make a simple asyncio program before continuing. The docs cover all the details, but it's not the easiest thing to pick up from there -- a tutorial like this one may be easier to digest.

At that point you should be able to take the sample code above and adjust the callback to your needs, or wrap it up into something a bit more usable. Note that the client here isn't really suited for one-shot style invocation, as there's a lot of startup overhead -- ideally you would have a long-running client along with a way to pass messages into a running instance.

Kop3sh commented 5 years ago

ERROR:asyncio:SSL error in data received protocol: <asyncio.sslproto.SSLProtocol object at 0x7fe15c5c30f0> transport: <_SelectorSocketTransport fd=24 read=polling write=<idle, bufsize=0>> Traceback (most recent call last): File "/home/mark/miniconda3/envs/HSenv/lib/python3.7/asyncio/sslproto.py", line 526, in data_received ssldata, appdata = self._sslpipe.feed_ssldata(data) File "/home/mark/miniconda3/envs/HSenv/lib/python3.7/asyncio/sslproto.py", line 207, in feed_ssldata self._sslobj.unwrap() File "/home/mark/miniconda3/envs/HSenv/lib/python3.7/ssl.py", line 767, in unwrap return self._sslobj.shutdown() ssl.SSLError: [SSL: KRB5_S_INIT] application data after close notify (_ssl.c:2605) Terminated This is the error that I get when I run send_message.py with common.py

This my code; this function is called when a certain button is selected using urwid itemchosen() and is passed these params (conversation.id , 'lorem ipusm')

def send_message_func(conv_id, text='hello world'): run_example(send_message, conv_id, text) can anyone help me... Thanks in advance

IamSierraCharlie commented 5 years ago

@masterchop is this still an issue for you? Did you get this to work for your home security system?

IamSierraCharlie commented 5 years ago

It seems a few people want to use hangups as part of a bigger project - perhaps as part of a notification system for home security for example. I had many issues initially trying to get hangups to work, but I did have some success in the end. I agree with the statement above comment about asyncio. You really need to understand how it works to get a better overall understanding of the workings of hangups itself. I'm not quote there myself, but have managed to fumble my way through. I have extracted the code that I use from my home security program that sends messages to my phone every time a person is detected on the camera at the front door. I hope that it will be useful for a few of you. The code provides a basic function to send a hangouts message and then 2 scenarios. 1 with an image and 1 without.

import datetime
import asyncio
import hangups

CLIENT_SECRET_FILE = '/home/scarter/.google/sb_client_secrets.json'
APPLICATION_NAME = 'Gmail API Python Send Email'
MY_CONVERSATION_ID = '???????????????' # todo use your own conversation_id
IMG_NAME = 'bee-closeup.jpeg' # todo use your own image here
REFRESH_TOKEN = '/home/scarter/.cache/hangups/refresh_token.txt' # todo this path must exist - if the file is empty, you will be asked to log in

class HangupsExample(object):
    def __init__(self):
        self.conversation_id = MY_CONVERSATION_ID
        self.refresh_token_path = REFRESH_TOKEN
        self.client = None
        self.notifier = {'start date': None, 'detection': False, 'counter': 0}
        self.test_hangups()

    def test_hangups(self):
        now_time = datetime.datetime.now()
        self.notifier['start date'] = now_time.strftime('%Y%m%d%H%M')
        incident_time = now_time.strftime('%Y%m%d @ %H:%M')
        cookies = hangups.auth.get_auth_stdin(self.refresh_token_path)
        self.client = hangups.Client(cookies)
        self.client.on_connect.add_observer(lambda: asyncio.async(self.hangout_notifier(hclient=self.client,
                                                                                        image=None,
                                                                                        time_of_incident=incident_time)))
        loop = asyncio.get_event_loop()
        loop.run_until_complete(self.client.connect())
        self.client = hangups.Client(cookies)
        self.client.on_connect.add_observer(lambda: asyncio.async(self.hangout_notifier(hclient=self.client,
                                                                                        image=open(IMG_NAME,'rb'),
                                                                                        time_of_incident=incident_time)))
        loop = asyncio.get_event_loop()
        loop.run_until_complete(self.client.connect())

    async def hangout_notifier(self, hclient, image, time_of_incident):
        notification_message = 'SOMEONE IS AT THE FRONT DOOR -> ' + time_of_incident
        user_list, conversation_list = await hangups.build_user_conversation_list(hclient)
        this_conversation = conversation_list.get(self.conversation_id)
        if image is None:
            await this_conversation.send_message([hangups.ChatMessageSegment(notification_message)], image_file=None)  # a message only
        else:
            await this_conversation.send_message([], image_file=image)  #  a pic only
        await hclient.disconnect()

if __name__ == '__main__':
    HangupsExample()

I hope this is useful to someone.

masterchop commented 5 years ago

dude, i have been waiting for this for while, how do i use it. i am kinda new to python, i used the smtp solution as this one disconnected to much for me but i am interested into test yours.

Please tell me how to use it!

IamSierraCharlie commented 5 years ago

Hi,
Here are some tips You need your own MY_CONVERSATION_ID Research how to find the conversation ID using hangups. No one can provide this for you, you need your own from a conversation between your hangouts ID and another party. Secondly, you just need to set a path to your REFRESH_TOKEN. When you log in for the first time, the refresh token should be written. It takes away the need for you to log onto google hangouts every time you run the program . Finally, set the path to a jpeg you want to test with (IMG_NAME).

Everything I have learned in Python is through research & review of other peoples code, but I honestly believe I have learned more through my own mistakes (and fixing them) than anyone simply giving me the code and telling me how to use it. I'd suggest you run it first and look at any errors to understand what you might be missing. Its only my opinion, but you really need to understand it yourself to make sense of it. I've found looking at other peoples code to be helpful in making a start, but you will need to do some research here first yourself to truly understand what you are looking at here.

masterchop commented 5 years ago

Yes, i understand what you are saying for the variables but wont this one disconnects from the session too? Can i send multiple messages in a row? Also have you been able to read a message and respond ?

IamSierraCharlie commented 5 years ago

Yes, it could send multiple messages - given it is incorporated into your own code properly. I can read the message on my phone. I guess I could respond. This code is out of a program for finding people in a security camera. There is a counter - once the counter hits a certain number, it sends a message and a picture - in both hangouts and to my gmail account. The counter resets and then will alarm again if the counter hits that number. It works, but is not without its bugs that I need to fix. The code I have provided simply shows how to send a message in hangouts using hangups. You can use it as an example and incorporate it into your own code to send as many messages as you want to as many people as you want or to a group chat. All you need to do is take the functions and call them as necessary. Its fair to say its not simple to do, but again, once you understand the code, you can send messages at will. If you want to set up some sort of security system as your first post advises, then this is but a very small snippet of code in a much larger more complex program. The code I provided is from my project probably doing something similar to what I presume you are trying to achieve...

  1. Connect to some sort of camera stream
  2. Use a neural network to detect a person inside the image
  3. Report via hangouts that someone is at the door
  4. Save the images as evidence (perhaps)
  5. Repeat as necessary again

This is what I see in hangouts sent from the program. The code I provided is responsible for getting that information into hangouts.

image

masterchop commented 5 years ago

yes. something like that. My main goal is to have the hangups as a chatbot that i can write back and forward. I can request updates and stuff without port forwarding. I tell him to do stuff inside my network like patterns of activity when noone is home. i had it ready with my crappy workaround but unfortunately it disconnected to much been inconsistent and i had to switch to SMTP emails. Ill give it a go to your code and see if this works as expected. Thanks for sharing :)

masterchop commented 5 years ago

I am not able to send images, i get the following error:

Failed to send message: Request failed with status 3: 'Unexpected error'
Task exception was never retrieved
future: <Task finished coro=<HangupsExample.hangout_notifier() done, defined at hangups_example.py:40> exception=NetworkError("Request failed with status 3: 'Unexpected error'",)>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "hangups_example.py", line 47, in hangout_notifier
    await this_conversation.send_message([], image_file=image)  #  a pic only
  File "/home/chop/.local/lib/python3.5/site-packages/hangups/conversation.py", line 445, in send_message
    yield from self._client.send_chat_message(request)
  File "/home/chop/.local/lib/python3.5/site-packages/hangups/client.py", line 611, in send_chat_message
    send_chat_message_request, response)
  File "/home/chop/.local/lib/python3.5/site-packages/hangups/client.py", line 442, in _pb_request
    .format(status, description)
hangups.exceptions.NetworkError: Request failed with status 3: 'Unexpected error'

The message does arrived and i make sure the image existed, i also replace the image with None to see if i could just send a txt msg but that hang too.

IamSierraCharlie commented 5 years ago

Hmm, Are you just using the code provided above?
If you send no image and end up with the same error, then there is something else at play there - not just an image problem. Looks like a timeout of some sort. Are you saying you get some messages but not others or you have not received ANY messages?

masterchop commented 5 years ago

I got the text msg, then the error and terminal hang. Same behavior without image. I didnt supply this CLIENT_SECRET_FILE = '/home/scarter/.google/sb_client_secrets.json' As it wasnt called anywhere in the script and i never had to setup that before. The image never arrives.

IamSierraCharlie commented 5 years ago

yeah you don't need that. Whats is the image that you are trying to send? And what is its name, and what type of image is it? Can you give me some info about it?

masterchop commented 5 years ago

I tried wit ha PNG and a JPEG file both with the same result.

PATH: /home/chop/Scripts/images/2.jpeg

The path is the home folder of the user executing the script.

IamSierraCharlie commented 5 years ago

Hmm, I can't replicate that issue here.
What is the conversation ID you are using?

masterchop commented 5 years ago

That conversation id works on the send_message.py sample

IamSierraCharlie commented 5 years ago

Not sure there is anything else I can do to help you here. The code I provided works for me - I can send message after message without any issue with or without an image. You might want to do some research on hangups.exceptions.NetworkError: Request failed with status 3: 'Unexpected error' or parts of that error to understand your issue a little better, but I don't believe its the actual code that is causing your problem.

Kop3sh commented 5 years ago

I really appreciate your help @IamSierraCharlie , thank you I was running your code to analyze it and understand it more but the lines containing lambda expressions give me an invalid syntax error and the program wouldn't run in vs code although I properly changed the REFRESH_TOKEN_PATH and the conversation_id

I've read multiple threads in asyncio and I know roughly how it works but it's still a new concept for me but from my understanding I can't use a lambda expression with async functions

IamSierraCharlie commented 5 years ago

what version of python are you running? I have that code running on 3.6.3

Kop3sh commented 5 years ago

3.7.2 I'll try to make a new env a run it again

IamSierraCharlie commented 5 years ago

Do you us an IDE - like pycharm?

Kop3sh commented 5 years ago

vs code

IamSierraCharlie commented 5 years ago

so is it the IDE complaining about invalid syntax? or do you see an error when you attempt to run the code?

Kop3sh commented 5 years ago

yes when I type: python example.py from the terminal i get the same error File "example.py", line 27 self.client.on_connect.add_observer(lambda: asyncio.async(self.hangout_notifier(hclient=self.client,hclient=self.client, image=None, time_of_incident=incident_time)))

Kop3sh commented 5 years ago

@IamSierraCharlie I made a new python env with 3.6.3 and hangups using the git method (cloning then 'python setup.py install) using conda... Now the first error disappeared and this is the error now (in the same line though) Module 'asyncio' has no 'async' member; maybe 'async_'?pylint(no-member)

IamSierraCharlie commented 5 years ago

okay - great to see you are moving along a little. I think its fair to say that hangups is particular about modules that are installed. Do you know what version of hangups you are running? Did you install it using pip or did you build it from source? Could you tell me your process? I'll try and replicate your setup here. To be honest, I set this up a while back and I probably need to go through it again myself so why not follow your setup process and see if I end up with the same issue.

What I can tell you is that my IDE complains about async reference missing from asyncio, but it still works

Kop3sh commented 5 years ago

I used the github source cloning then cd hangups then python setup.py install I used this approach because manual-login didn't work for me with the pip installation...

IamSierraCharlie commented 5 years ago

hmm okay. I used pip and run hangups 0.4.6 (0.4.4) also works. Was there an open issue for manual login not working? What is the motive for using this?

I'll try build this from source and see if I get the same result - standby

Kop3sh commented 5 years ago

my installed hangups version is 0.4.6

IamSierraCharlie commented 5 years ago

Okay, I created a new environment (using anaconda) in Ubuntu 16.04 using python 3.6.3 and I've just built from source and it works fine. What can you tell me about your asynchio module? What version is it? Just to be certain, you are running this in Linux or MAC OS?

Kop3sh commented 5 years ago

So I made a new conda env on Ubuntu 18.04.1 LTS and using python=3.6.3 and installing hangups using pip this time in that env and it ran and it magically worked although vs code is still highlighting the first error of invald syntax mentioned above... I'm really greatefull for your help Thanks You @IamSierraCharlie

IamSierraCharlie commented 5 years ago

Glad that it is working for you.
👍

masterchop commented 4 years ago

It was easier to move to telegram. Simple api if Hangouts is not mandatory