ó
O'—^c           @   sk  d  Z  d d l Z d d l Z d d l Z d d l Z d d l Z d d l Z d d l m Z d d l	 m
 Z
 d d l m Z d d l m Z d d l m Z d	 e f d
 „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d „  Z d „  Z d „  Z d „  Z d „  Z d d d e d d g  i  d d d d d „ Z d „  Z d „  Z d „  Z d „  Z  d „  Z! d S(   sã   
Apple Push Notification Service
Documentation is available on the iOS Developer Library:
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html
iÿÿÿÿN(   t   closing(   t	   unhexlify(   t   ImproperlyConfiguredi   (   t   NotificationError(   t   PUSH_NOTIFICATIONS_SETTINGSt	   APNSErrorc           B   s   e  Z RS(    (   t   __name__t
   __module__(    (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyR      s   t   APNSServerErrorc           B   s   e  Z d  „  Z RS(   c         C   s/   t  t |  ƒ j | | ƒ | |  _ | |  _ d  S(   N(   t   superR   t   __init__t   statust
   identifier(   t   selfR   R   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyR
      s    	(   R   R   R
   (    (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyR      s   t   APNSDataOverflowc           B   s   e  Z RS(    (   R   R   (    (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyR      s   c      	   C   sÆ   t  j d ƒ } | s$ t d ƒ ‚ n  y& t | d ƒ  } | j ƒ  Wd  QXWn) t k
 ru } t d | | f ƒ ‚ n Xt  j d ƒ } t j ƒ  } t j | d t j	 d | d | ƒ} | j
 |  ƒ | S(	   Nt   APNS_CERTIFICATEs^   You need to set PUSH_NOTIFICATIONS_SETTINGS["APNS_CERTIFICATE"] to send messages through APNS.t   rs3   The APNS certificate file at %r is not readable: %st   APNS_CA_CERTIFICATESt   ssl_versiont   certfilet   ca_certs(   t   SETTINGSt   getR   t   opent   readt	   Exceptiont   sockett   sslt   wrap_sockett   PROTOCOL_TLSv1t   connect(   t   address_tupleR   t   ft   eR   t   sock(    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_create_socket#   s    $c           C   s   t  t d t d f ƒ S(   Nt	   APNS_HOSTt	   APNS_PORT(   R#   R   (    (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_create_socket_to_push9   s    c           C   s   t  t d t d f ƒ S(   Nt   APNS_FEEDBACK_HOSTt   APNS_FEEDBACK_PORT(   R#   R   (    (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_create_socket_to_feedback=   s    c   	      C   s    t  |  ƒ } d t | ƒ t | ƒ d d d } d t | ƒ t | ƒ f } t j | d | d t | ƒ | d t | ƒ | d d | d d | d d | ƒ } | S(   Ni   i   i   i   s   !BIBH%ssBH%ssBHIBHIBHBi   i   (   R   t   lent   structt   pack(	   t	   token_hext   payloadR   t
   expirationt   priorityt   tokent	   frame_lent	   frame_fmtt   frame(    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_pack_frameA   s    &		c         C   sú   t  d } | d  k r d  S|  j ƒ  } z¿ yz |  j | ƒ |  j d ƒ } | r¢ t j d | ƒ \ } } } | d k s t d ƒ ‚ | d k r¢ t | | ƒ ‚ q¢ n  Wn> t	 j
 k
 r¹ n+ t j k
 rã } d | j k rä ‚  qä n XWd  |  j | ƒ Xd  S(   Nt   APNS_ERROR_TIMEOUTi   s   !BBIi   s   Command must be 8!i    s	   timed out(   R   t   Nonet
   gettimeoutt
   settimeoutt   recvR+   t   unpackt   AssertionErrorR   R   t   timeoutR   t   SSLErrort   message(   R"   R=   t   saved_timeoutt   datat   commandR   R   R!   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_check_errorsR   s&    
 i    i
   c         C   sÝ  i  } i  } | s | s | rs | r1 i | d 6n i  } | rJ | | d <n  | r] | | d <n  | rs | | d <qs n  | d  k	 rŒ | | d <n  | d  k	 r¥ | | d <n  | d  k	 r¾ | | d <n  | d  k	 r× | | d <n  | rê d	 | d
 <n  | | d <| j |	 ƒ t j | d d d t ƒj d ƒ } t d } t | ƒ | k rTt d | ƒ ‚ n  | d  k	 rf| n t	 t
 j
 ƒ  ƒ d } t |  | |
 | | ƒ } | rª| j | ƒ n/ t t ƒ  ƒ  } | j | ƒ t | ƒ Wd  QXd  S(   Nt   bodys   action-loc-keys   loc-keys   loc-argst   alertt   badget   soundt   categoryi   s   content-availablet   apst
   separatorst   ,t   :t	   sort_keyss   utf-8t   APNS_MAX_NOTIFICATION_SIZEs(   Notification body cannot exceed %i bytesi ' (   RK   RL   (   R7   t   updatet   jsont   dumpst   Truet   encodeR   R*   R   t   intt   timeR5   t   writeR    R&   RC   (   R1   RE   RF   RG   RH   t   content_availablet   action_loc_keyt   loc_keyt   loc_argst   extraR   R/   R0   R   RA   t   aps_datat	   json_datat   max_sizet   expiration_timeR4   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt
   _apns_sendi   sB    
$
(c         C   s?   t  j | ƒ } |  j | ƒ } | r7 t  j | | d ƒ Sd  Sd  S(   Ni    (   R+   t   calcsizeR:   t   unpack_fromR7   (   R   t   data_formatt   lengthRA   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_read_and_unpackž   s
    c   
      C   s×   g  } d } t  } x¾ | rÒ ys t |  | ƒ } | d  k	 r‡ | \ } } d | } t |  | ƒ } | d  k	 r | j | | d f ƒ q n t } Wq |  j k
 r¤ q t j k
 rÎ }	 d |	 j k rÏ ‚  qÏ q Xq W| S(   Ns   !LHs   %ssi    s	   timed out(	   RR   Re   R7   t   appendt   FalseR=   R   R>   R?   (
   R   t   expired_token_listt   header_formatt   has_datat   header_datat	   timestampt   token_lengtht   token_formatt   device_tokenR!   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   _apns_receive_feedback§   s&    	

c         K   s   t  |  | |  d S(   ss  
	Sends an APNS notification to a single registration_id.
	This will send the notification as form data.
	If sending multiple notifications, it is more efficient to use
	apns_send_bulk_message()

	Note that if set alert should always be a string. If it is not set,
	it won't be included in the notification. You will need to pass None
	to this for silent notifications.
	N(   R`   (   t   registration_idRE   t   kwargs(    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   apns_send_messageÅ   s    c         K   s_   t  t ƒ  ƒ J } x6 t |  ƒ D]( \ } } t | | d | d | | q Wt | ƒ Wd QXd S(   s!  
	Sends an APNS notification to one or more registration_ids.
	The registration_ids argument needs to be a list.

	Note that if set alert should always be a string. If it is not set,
	it won't be included in the notification. You will need to pass None
	to this for silent notifications.
	R   R   N(   R    R&   t	   enumerateR`   RC   (   t   registration_idsRE   Rr   R   R   Rq   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   apns_send_bulk_messageÔ   s    	 c       	   C   s\   t  t ƒ  ƒ G }  g  } x3 t |  ƒ D]% \ } } | j t j | d ƒ ƒ q% W| SWd QXd S(   sT   
	Queries the APNS server for id's that are no longer active since
	the last fetch
	t	   hex_codecN(   R    R)   Rp   Rf   t   codecsRS   (   R   t   inactive_idst   tStampRq   (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   apns_fetch_inactive_idsã   s
    ("   t   __doc__Rx   RP   R   R+   R   RU   t
   contextlibR    t   binasciiR   t   django.core.exceptionsR   t    R   t   settingsR   R   R   R   R   R#   R&   R)   R5   RC   R7   Rg   R`   Re   Rp   Rs   Rv   R{   (    (    (    s9   /tmp/pip-unpacked-wheel-MTFMX_/push_notifications/apns.pyt   <module>   s6   					3					