Giter Club home page Giter Club logo

python-gcm's Introduction

python-gcm

Join the chat at https://gitter.im/geeknam/python-gcm

image

image

Build Status

Code Health

image

image

Python client for Google Cloud Messaging for Android (GCM)

Installation

pip install python-gcm

Features

  • Supports multicast message
  • Resend messages using exponential back-off
  • Proxy support
  • Easily handle errors
  • Uses requests from version > 0.2
  • Topic Messaging
  • TCP connection pooling and Keep-Alive when passing an explict requests.Session object to the used GCM request call

Usage

Read about Google Cloud Messaging

from gcm import GCM

gcm = GCM(API_KEY)
data = {'param1': 'value1', 'param2': 'value2'}

# Downstream message using JSON request
reg_ids = ['token1', 'token2', 'token3']
response = gcm.json_request(registration_ids=reg_ids, data=data)

# Downstream message using JSON request with extra arguments
res = gcm.json_request(
    registration_ids=reg_ids, data=data,
    collapse_key='uptoyou', delay_while_idle=True, time_to_live=3600
)

# Topic Messaging
topic = 'topic name'
gcm.send_topic_message(topic=topic, data=data)

See examples directory for more usage details, including error handling.

Contributing ========== See CONTRIBUTING.md

Licensing ======= See LICENSE

python-gcm's People

Contributors

akaz00 avatar alibitek avatar anthonysutardja avatar chernando avatar codebutler avatar dahlia avatar dkong avatar dokterbob avatar free1002 avatar gabriel-laet avatar geeknam avatar gitter-badger avatar imankulov avatar jacobcr avatar javaguirre avatar jnorton001 avatar kudo avatar mikelambert avatar networksaremadeofstring avatar orblivion avatar pagles avatar sergeybe avatar sssbox avatar suzaku avatar sylvainde avatar uniite avatar vbabiy avatar vivekhub avatar youknowone avatar ziima avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-gcm's Issues

file gcm.py (for module gcm) not found in python-gcm-0.1.3

sudo pip install python-gcm
[
Downloading/unpacking python-gcm
Downloading python-gcm-0.1.3.tar.gz
Running setup.py egg_info for package python-gcm

file gcm.py (for module gcm) not found

Installing collected packages: python-gcm
Running setup.py install for python-gcm
file gcm.py (for module gcm) not found
file gcm.py (for module gcm) not found

file gcm.py (for module gcm) not found
file gcm.py (for module gcm) not found

Successfully installed python-gcm
Cleaning up...

error on running the sample

I get

./http_gcm_server.py: line 4: syntax error near unexpected token (' ./http_gcm_server.py: line 4:gcm = GCM("1234")'

nothing modified.

get blank dictionary in response after sending data to registration id

I am using gcm from pip install python-gcm, whenever i send an data to reg id i get blank dictionary in response i.e {} but it gives me proper errors if i try wrong id like NotRegistered, MisMatchSenderID etc...Please help me out there..for right reg id it gives me blank dictionary

a way to have the list of successful sents?

Hi,

In the info object that is returned when calling json_request(), "errors" and "canonical" are useful to know wich registration_id has failed or should be updated. that's cool.

But is there a way to have the list of successful ids?

I guess i could change handle_json_response to create a group_response for the "message_id" result form google and that should do the trick?

Am I right ?
Is there a reason why it's not implemented in you version?

If yes, I think it could be cool to have it in the pip package ;)
thanks for your work

License

Please add a license to this project. Thanks. :)

plaintext_request fails

plaintext_request calls make_request with is_json=False, which then runs the data through urlencode_utf8 to get a urlencoded string. The data param of requests.post requires a dictionary (this is a difference from urllib2), so the regid and other parameters are not passed to GCM, which then errors out.

Exception not raised

In handle_plaintext_response, self.raise_error() gets called. Why is not called from json_request?

using the gcm multicast feature

Thanks for the GCM code!

To take advantage of the multicast feature of GCM (sending the same notification to up to 1000 devices), I forked and created:

https://github.com/larham/python-gcm

The changes are not backwards-compatible, and they introduce complexity to the JSON request that isn't necessary unless you want multicast.

This seems more like a fork than something appropriate for a pull request, unless the additional feature is worth the complexity for most users.

Let me know what you think.

Larry

client?

Is it really a client? When I read client I am thinking of an Android Application.

Sending non-blocking requests to GCM

I noticed that I had to wait for the json_request call to return before I could be able to send my next messge to GCM. In other words, the following call is a blocking call.

    res = gcm.json_request(registration_ids=reg_ids, data=data,)

It would be nice to have an async_json_request function that sends the message to GCM and returns immediately so that we can send our next message.

I think there might be need to to use CCS (XMPP) for this instead of HTTP based GCM, but I am not completely aware of the implementation details.

Add oAuth Support

as per the Google apis page:

API Access
To prevent abuse, Google places limits on API requests. Using a valid OAuth token or API key allows you to exceed anonymous limits by connecting requests back to your project.

It would be beneficial if this was included in the library.

Issue in README

Another issue in the readme sample, which I found to be clearer than the documentation but got me wrong here:

for canonical_id, reg_id in response['canonical'].items():
# Repace reg_id with canonical_id in your database
entry = entity.filter(registration_id=reg_id)
entry.registration_id = canonical_id
entry.save()

This looks wrong: the new id is reg_id and the old one is canonical_id!
Having something like "for reg_id, new_reg_id in response['canonical']..." would be clearer.

python gcm also for IOS

Currently we can only use this wrapper for push notifications to Android devices. Can this also be done for IOS ? is there any difference in the procedure?

local variable response referenced before the assignment

Hello,

GCM results in the following python error for some unknown reason to me at this time:
local variable response referenced before the assignment at line 174: return response

I double checked the code, and it seems like it's not raising any exceptions, otherwise we wouldn't have got this far with the execution.

I'll try to re-produce the issue but i think your experience on the matter might help discover what response is being returned to cause such an issue.

Thanks

w/Collapse key... getting 'int' object has no attribute 'encode'

If I make the call:

data = { 'param1': 'value1', 'param2': 'value2' }
response = gcm.plaintext_request( registration_id=token, data=data )

it works, but if I modify the call to:

data = { 'param1': 'value1', 'param2': 'value2' }
response = gcm.plaintext_request( registration_id=token, collapse_key='Updated Steps', data=data, time_to_live=86400 )

then I get the following error:

ERROR log_traceback ==== Exception: AttributeError | 'int' object has no attribute 'encode' ====
DEBUG log_traceback 

  File "/home/idbill/workspace/OPT/common/functions/send_GCM_notification.py", line 30, in send_GCM_notification
    response = gcm.plaintext_request( registration_id=token, collapse_key='Updated Steps', data=data, time_to_live=86400 )

  File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/gcm/gcm.py", line 244, in plaintext_request
    response = self.make_request(payload, is_json=False)

  File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/gcm/gcm.py", line 155, in make_request
    data = urlencode_utf8(data)

  File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/gcm/gcm.py", line 67, in urlencode_utf8
    return '&'.join(params)

  File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/gcm/gcm.py", line 64, in <genexpr>
    )) for k, v in params

'Error'

It would appear in the urlencode_utf8 function, it is trying to url encode the TTL.

Bill

RTFM link is broken

I want to use this module but I am way to dumb to figure it out and the RTFM link (http://developer.android.com/guide/google/gcm/gcm.html) resolves to https://developers.google.com/cloud-messaging/.

What is "registration_id" and how do you obtain one? Very few of the current GCM docs mention this item or where it can be sourced from and the example GCM app contains no mention of it. Is it legacy/deprecated verbage? No matter what I put in that field it doesn't work.

Is there anyone out there who know how to use this lib correctly or at least how to obtain the necessary keys/id's to get it to work with the GCM example app ( https://developers.google.com/cloud-messaging/android/start )?

Example Documentation Error

The check:

if error is 'NotRegistered'

Can cause problems. If 'NotRegistered' comes back as unicode, this check will fail. Many times JSON comes back as exclusively unicode depending on libraries that are used. The correct syntax that will work in both cases (unicode and non-unicode) is:

if error == 'NotRegistered'

Thanks!

python-gcm does not support connection pooling

Hello! I observe that an SSL connection is being created for each request. This was true at least in 0.1.5 and was still true in 0.2. This appears to be a consequence of using requests.post which creates and closes an internal Session object. In Requests, connection pooling is bound to the Session object (http://docs.python-requests.org/en/latest/user/advanced/#keep-alive).

I tested a monkey patched version of python-gcm where gcm.gcm.requests is replaced with a gcm.gcm.requests.Session() object and observed that connections are reused. From my test server in AWS us-east-1, each GCM POST request took avg ~140ms without the patch and avg ~40ms with (7 qps vs 25) which at our volume is a significant help.

It wasn't clear to me how best to integrate connection pooling into python-gcm so I thought I'd post the issue for comment before sending a PR. Also, the thread safety of requests.Session is an open question so that's a trade-off to consider: https://github.com/kennethreitz/requests/issues/1871.

"retries" on json_response is a bit misleading

I'd call it "tries". But, since you probably don't want to change your interface, I'd say, throw an exception there if 0 is passed in, somehow explaining that "retries" actually means the number of tries.

If you put in 0 now, you get:

Exception: local variable 'info' referenced before assignment (<type 'exceptions.UnboundLocalError'>)

Which doesn't make sense unless you examine the source code.

And maybe mention it in your README for confusion for cases > 0, though the difference between 2 and 3 tries may not be as big a deal as the difference between 1 and 2. The reason I personally want 1 try only is that I don't want to call sleep, I'd rather have Celery kick off a new task in 2 seconds if I decide I want retries.

GCM returns 400 for issues other than bad JSON

In particular if you have a key named "from" in your data, it will reject it as a reserved word, even though its quoted:

{"data": {"body": "test", "from": "boss", "type": "test"}, "registration_ids": ["APA91bGELb0bXFnXeFvWZnRNKaHXVH5sfBuNkEO5vGJGHy3b8BToVqLa2qyRB6InjwKpZmyD1R0UXaqYnsTxdgyQ2bePk3f9L5XEMnxvT8NfFgfPO1vXcXUtaLgpOqHiOx7jMz9yEsVHc91qBBcIMx8YBSmb_KHj8w"]}

GCMUnavailableException handling on json_request

def json_request(self, registration_ids, data=None, collapse_key=None,
                     delay_while_idle=False, time_to_live=None, retries=5, dry_run=False):
        ...
            response = self.make_request(payload, is_json=True)

this will raise GCMUnavailableException and it couldn't be failover.
please put try/exception phrase like this,

        try:
            response = self.make_request(payload, is_json=True)
        except GCMUnavailableException:
            unsent_reg_ids = registration_ids

Plaintext response appends data to dictionary keys

See code!

python
custom_params = dict(message='News alert!', **{'title': 'Hello', 'body': 'This is a cool news', 'datetime': 1377551230})

gcm.plaintext_request(
... registration_id=p.android,
... data=custom_params
... )
def william():
... gcm.plaintext_request(
... registration_id=p.android,
... data=custom_params
... )
...
william()
william()
william()
william()
william()
custom_params
{'data.data.data.data.data.data.body': 'This is a cool news', 'data.data.data.data.data.data.message': 'News alert!', 'data.data.data.data.data.data.title': 'Hello', 'data.data.data.data.data.data.datetime': 1377551230}

Multiple Resends

I'm having an issue where I send one notification but am receiving 5 of them on my device.

retrying to handle 503 error

Handling 503 error (service is not available.) is yet implemented. It is still working well without retrying request, but It would be better to implement it for the future.

There is a java implementation in the android sdk and the source is written with an exponential back-off algorithm. We could check that source.

Honor the Retry-After header

As per https://developers.google.com/cloud-messaging/http-server-ref#error-codes

Timeout     5xx or 200 + error:Unavailable  

The server couldn't process the request in time. Retry the same request, but you must:

    Honor the Retry-After header if it is included in the response from the GCM Connection Server.
    Implement exponential back-off in your retry mechanism. (e.g. if you waited one second before the first retry, wait at least two second before the next one, then 4 seconds and so on). If you're sending multiple messages, delay each one independently by an additional random amount to avoid issuing a new request for all messages at the same time.

Senders that cause problems risk being blacklisted.

MySQL database management?

Is it possible to add to this project a MySQL database management class to read/write registrationIds?
I'm developing a python script that reads data from a MySQL table and uses gcm.py to send messages.
I'm still finishing it up, but I can share my script with you... Let me know what you think about this

ImportError in Python3

Did #57 make it onto PyPI? I'm getting:

Python 3.4.0 (default, Apr 11 2014, 13:05:11) [GCC 4.8.2] on linux
import gcm
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python3.4/dist-packages/gcm/init.py", line 4, in
GCM = gcm.GCM
AttributeError: 'module' object has no attribute 'GCM'

when I do 'import gcm' from the Python3.4 console on a fresh installation, Ubuntu Trusty on AWS. dist-packages shows python-gcm version 0.2. This was the same error I got locally before #57 was merged.

Receiving a None response

When doing

    reg_id = sample_reg_id
    response = gcm.plaintext_request(registration_id=reg_id, data=data)

The response variable comes as "None". Why so?

python-gcm causes MissingRegistration error

This is how I use the library:

x = self.gcm.plaintext_request(id, {"amount": str(transaction.amount), "address": transaction.to})

When messages didn't reach my phone, I tried to debug this a bit:

The variable x contains a NoneType value.

When I used pdb to analyse why it doesn't throw an exception, I found out that it calls self.raise_error(value) in base.py:253. But value somehow contains MissingRegistration which doesn't get handled by raise_error.

This seems to be unlikely as this error should only occur when the request doesn't contain any registration id.

The data that is sent (constructed in base.py:184) contains this value:

(Pdb) p data
'data.amount=36.11628274&registration_id=fUxwjeZSVR0%3AAPA91bFfRy0DcYw_gxsMd86FEUdwhR6SrvAV46AHhSeWydnYtLMCvza055jXW-e-j-ETDGGCbVaMBN7TdKR8VvdkqLr_pofWkQcsb1o9FE7kqciPvXxYrxYvp98jZttDZSxe3f8dvuM7&data.address=9GWXR4aD6JSb6DMPxAKH9GeGrBDjhRyxuf'

I don't know if that is how the request data should look like and I don't have any other idea to debug this further.

MissingRegistration error not handled

Or rather, it's partially handled. This error may be returned by GCM if registration_id is missing. Normally this is checked upon entry to plaintext_request/json_request, but because of #66, the registration_id isn't being encoded correctly and so GCM errors out silently. It should at least be checked in raise_error so that a failure doesn't pass silently to the rest of the app.

Unable to generate rpm from dist-utils

Hi,

Trying to generate a rpm package from dist-utils ends with error because setup.py license line don't follow the standards.

From https://docs.python.org/2/distutils/setupscript.html#additional-meta-data:
"license, license for the package, short string".
In this context short string is "A single line of text, not more than 200 characters.", but currently this field is filled with the content of LICENSE file which is a multiline text.

python setup.py bdist_rpm
......
error: line 14: Unknown tag: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
error: query of specfile build/bdist.linux-x86_64/rpm/SPECS/python-gcm.spec failed, can't parse
error: Failed to execute: "rpm -q --qf '%{name}-%{version}-%{release}.src.rpm %{arch}/%{name}-%{version}-%{release}.%{arch}.rpm\\n' --specfile 'build/bdist.linux-x86_64/rpm/SPECS/python-gcm.spec'"

Readme: error handling usage issue

Noticed a little issue in the Readme examples:

response.items() should be response['errors'].items() or response['canonical'].items()

Thanks for sharing this lib!

Python-gcm not handling 5xx errors other than 503.

Hi there,
according to Google:
http://developer.android.com/google/gcm/http.html#response
GCM may return any 5xx error.
When 5xx is different than 503, the library is not handling it correctly, it does not realize that 501 is an error and tries to load the response body as json.
This is the stack trace:

Traceback (most recent call last):
  File "android_dispatcher.py", line 347, in _handle_device_recvrs
    response = gcm_for_msg.json_request(tokens_to_send, **json_request)
  File "/usr/lib/python2.7/site-packages/gcm/gcm.py", line 256, in json_request
    response = self.make_request(payload, is_json=True)
  File "/usr/lib/python2.7/site-packages/gcm/gcm.py", line 151, in make_request
    response = json.loads(response)
UnboundLocalError: local variable 'response' referenced before assignment

FIX proposal
change gcm.py#165 : https://github.com/geeknam/python-gcm/blob/master/gcm/gcm.py#L165

elif 500 <= e.code <= 599:
    raise GCMUnavailableException("GCM service is unavailable")

I can push a pull-request if you prefer it.
Thank you in advance.

Release new version with packaging fix

The currently version on pypi doesn't work as advertised, if you could please release a new version so we can install from pypi and not have to use git.

Thanks.

handle_response is not correct

  1. When I tried send a message using plaintext_request, a response format was like this :

<< success case >>

res : id=0:1342406578446357%24fa77d8f9fd7ecd

<< failure case >>

res : Error=InvalidRegistration

But, current handle_response has a assumption that the type of response is dict. This assumption is not true.

  1. When I tried json_request, the response was like this : ( res_ids has 3 items. First and third reg_ids are wrong register id and second reg_id is right register id)
{u'failure': 2, u'canonical_ids': 0, u'success': 1, u'multicast_id': 6941921051371432547, u'results': [{u'error': u'InvalidRegistration'}, {u'message_id': u'0:1342406147892805%24fa77d8f9fd7ecd'}, {u'error': u'InvalidRegistration'}]}

But, in handle_response, 'error' is set like this :

error = response['results']['error']

In conclusion, handle_response is not right implementation for both of plaintext_request and json_request.

Not able to access data in service worker

I have called gcm api using following code:

from gcm import GCM

gcm = GCM(API_KEY)
data = {'param1': 'value1', 'param2': 'value2'}
reg_id = '12'
gcm.plaintext_request(registration_id=reg_id, data=data)

But in serviceworker file I am not getting data sent via gcm api.
event.data is empty in service worker file

Topic Messaging Support

Dear Sir/Madam,

I am writing to inquire if python-gcm to support Topic Messaging.
Currently, there are no way to custom payload outside of data field.
So I am not able to add the "to": "/topics/foo-bar".

Do you have any plans to add such feature?
If you need help to contribute the code and create a PR, please feel free to let me know.
My thought is simple to add an topic=None parameter to both json_request() and plaintext_request() interfaces.

Thanks.

Best practice for utf-8 messages?

Hi Nam -

what is the best practice for using utf-8 encoded messages? Should we always do data.encode("utf-8") before passing the data?

Otherwise, the urlencoder chokes

"You got a message"

I'm using pip install python-gcm
data = {"alert": "a test"}
canonical_id = gcm.json_request(registration_ids=ids, data=data, collapse_key="test test")

but, On the device "You got message" only is notified. Plz help me!!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.