Python client library for the iPhone/iPod Touch "Notifications" app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

notifications.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright (c) 2009, 2010, Thomas Jost <thomas.jost@gmail.com>
  4. #
  5. # Permission to use, copy, modify, and/or distribute this software for any
  6. # purpose with or without fee is hereby granted, provided that the above
  7. # copyright notice and this permission notice appear in all copies.
  8. #
  9. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  10. # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  14. # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. # PERFORMANCE OF THIS SOFTWARE.
  16. """Client for the iPhone/iPod Touch `Notifications' app.
  17. This module helps scripts to use the HTTP REST API of the `Notifications'
  18. application, which is available for the iPhone and the iPod Touch. It supports
  19. finding the user's credentials token, and then sending notification in a
  20. synchronous or asynchronous way. This modules provides three functions:
  21. get_credentials() -- Get the user's credentials token
  22. send() -- Send a notification, waiting for it to be sent.
  23. send_async() -- Send a notification, returning immediately, without waiting for
  24. the message to be sent.
  25. """
  26. __author__ = "Thomas Jost <thomas.jost@gmail.com>"
  27. __version__ = "0.2"
  28. import sys
  29. import threading
  30. import urllib
  31. import xml.dom.minidom
  32. CREDENTIALS_URL = "https://www.appnotifications.com/user_session.xml"
  33. SEND_URL = "https://www.appnotifications.com/account/notifications.xml"
  34. def get_credentials(email, password):
  35. """Get the user's credentials token."""
  36. # Create data to POST
  37. data = {
  38. 'user_session[email]': email,
  39. 'user_session[password]': password
  40. }
  41. data = urllib.urlencode(data)
  42. # Send them
  43. u = urllib.urlopen(CREDENTIALS_URL, data)
  44. success = (u.getcode() == 200)
  45. if not success:
  46. return False
  47. # Parse the XML response
  48. response = u.read()
  49. u.close()
  50. doc = xml.dom.minidom.parseString(response)
  51. token = doc.getElementsByTagName("single-access-token")
  52. if len(token) == 0:
  53. return False
  54. return token[0].firstChild.data
  55. def send(credentials, message, title=None, subtitle=None, long_message=None,
  56. long_message_preview=None, icon_url=None, message_level=0, silent=False,
  57. action_loc_key=None, run_command=None, sound=1, debug=False):
  58. """Send a notification, waiting for the message to be sent.
  59. The first two arguments (credentials and message) are mandatory, all of the
  60. others are optional. They are the same as the various identifiers described
  61. in the documentation of the Notifications HTTP REST API
  62. (http://developer.appnotifications.com/p/user_notifications.html).
  63. When `debug` is set to `True`, the XML result of the HTTP request is
  64. displayed on `sys.stderr`.
  65. This function returns a boolean indicating if the message was sent
  66. successfuly.
  67. """
  68. # Create data to POST
  69. data = {}
  70. if credentials is None or credentials == "":
  71. raise ValueError("Invalid user credentials")
  72. if message is None or message == "":
  73. raise ValueError("Invalid message")
  74. data['user_credentials'] = credentials
  75. data['notification[message]'] = message
  76. for key in ("title", "subtitle", "long_message", "long_message_preview",
  77. "icon_url", "message_level", "action_loc_key", "run_command"):
  78. value = locals()[key]
  79. if value is not None:
  80. data['notification[%s]' % key] = value
  81. if silent:
  82. data['notification[silent]'] = 1
  83. else:
  84. data['notification[silent]'] = 0
  85. if not 1 <= sound <= 7:
  86. raise ValueError("sound must be an integer between 1 and 7")
  87. data['notification[sound]'] = "%d.caf" % sound
  88. # Encode the data, trying to deal with Unicode
  89. for k in data:
  90. if type(data[k]) is unicode:
  91. data[k] = data[k].encode('utf-8')
  92. data = urllib.urlencode(data)
  93. # Send the notification
  94. u = urllib.urlopen(SEND_URL, data)
  95. success = (u.getcode() == 200)
  96. if debug:
  97. print >> sys.stderr, u.read()
  98. u.close()
  99. return success
  100. def send_async(*args, **kwargs):
  101. """Send a notification, returning immediately, without waiting for the
  102. message to be sent.
  103. This function does return the ID of the thread that does the HTTP request.
  104. """
  105. thr = threading.Thread(target=send, args=args, kwargs=kwargs)
  106. thr.daemon = True
  107. thr.start()
  108. return thr
  109. if __name__ == '__main__':
  110. import sys
  111. if len(sys.argv) != 3:
  112. print >> sys.stderr, "Syntax: %s credentials message" % sys.argv[0]
  113. else:
  114. send(sys.argv[1], sys.argv[2], debug=True)