Module bluevia_helpers
[hide private]
[frames] | no frames]

Source Code for Module bluevia_helpers

  1  #  
  2  # The MIT license 
  3  # 
  4  # Copyright (C) 2011 by Bernhard Walter ( @bernhard42 ) 
  5  #  
  6  # Permission is hereby granted, free of charge, to any person obtaining a copy 
  7  # of this software and associated documentation files (the "Software"), to deal 
  8  # in the Software without restriction, including without limitation the rights 
  9  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 10  # copies of the Software, and to permit persons to whom the Software is 
 11  # furnished to do so, subject to the following conditions: 
 12   
 13  # The above copyright notice and this permission notice shall be included in 
 14  # all copies or substantial portions of the Software. 
 15   
 16  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 17  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 18  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 19  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 20  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 21  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 22  # THE SOFTWARE. 
 23  # 
 24   
 25  # 
 26  # Version 01.08.2011 
 27  # 
 28   
 29   
 30   
 31  # # # # # # # # # # # # # # # #  
 32  # Simple XML to JSON Class 
 33  # # # # # # # # # # # # # # # # 
 34   
 35  from xml.dom.minidom import parseString 
 36   
37 -def _parseAdResponse(xmlString):
38 """ 39 Parses the XML respponse of a BlueVia Adsvertising requests and constructs a JSON object as result 40 41 Internal method 42 """ 43 44 dom = parseString(xmlString) 45 arId = dom.getElementsByTagName ("NS1:adResponse")[0].attributes.getNamedItem("id").value 46 arVersion = dom.getElementsByTagName ("NS1:adResponse")[0].attributes.getNamedItem("version").value 47 adId = dom.getElementsByTagName ("NS1:ad")[0].attributes.getNamedItem("id").value 48 adPlace = dom.getElementsByTagName ("NS1:ad")[0].attributes.getNamedItem("ad_placement").value 49 adCampaign = dom.getElementsByTagName ("NS1:ad")[0].attributes.getNamedItem("campaign").value 50 adFlight = dom.getElementsByTagName ("NS1:ad")[0].attributes.getNamedItem("flight").value 51 adPresent = dom.getElementsByTagName ("NS1:resource")[0].attributes.getNamedItem("ad_presentation").value 52 ce = dom.getElementsByTagName ("NS1:creative_element")[0] 53 ceType = ce.attributes.items()[0] 54 ceAttrs = [(n.attributes.items(), n.childNodes[0].nodeValue) for n in ce.childNodes if n.nodeName == "NS1:attribute"] 55 ceInter = dom.getElementsByTagName ("NS1:interaction")[0] 56 ciType = ceInter.attributes.items()[0] 57 ciAttrs = [(n.attributes.items(), n.childNodes[0].nodeValue) for n in ceInter.childNodes if n.nodeName == "NS1:attribute"] 58 59 60 creativeElement = { 61 ceType[0]:ceType[1], 62 "attributes":[{x[0][0][0]:x[0][0][1],"value":x[1]} for x in ceAttrs], 63 "interaction":{ciType[0]:ciType[1], 64 "attributes":[{x[0][0][0]:x[0][0][1],"value":x[1]} for x in ciAttrs]} 65 } 66 fullAd = {"adResponse": { \ 67 "id":arId, \ 68 "version":arVersion, \ 69 "ad": { \ 70 "id":adId, \ 71 "ad_place_ment":adPlace, \ 72 "campaign":adCampaign, \ 73 "flight":adFlight, \ 74 "resource":{ \ 75 "ad_representation":adPresent, \ 76 "creative_element": creativeElement}}}} 77 return fullAd 78 79 80 # # # # # # # # # # # # # # # # 81 # Simple Multipart POST body 82 # # # # # # # # # # # # # # # # 83 84 import random, string, sys, mimetypes, base64, email, os 85
86 -def _random_string (length):
87 return ''.join (random.choice (string.letters) for ii in range (length + 1))
88
89 -def _encodeMultipart (root, messages = None, files = None):
90 """ 91 Encodes messages and files in Multipart MIME format fitting for BlueVia Send MMS API 92 93 Internal method 94 """ 95 96 # to comply with blueVia format, some adaptation to email.mime.multipart results would have to be applied 97 # so just do it manually 98 boundary1 = _random_string (32) 99 boundary2 = _random_string (32) 100 101 def get_content_type (filename): 102 return mimetypes.guess_type (filename)[0] or 'application/octet-stream'
103 104 def encode_message (num, message, boundary): 105 return ('--' + boundary, 106 'Content-Disposition: attachment; name="message%d.txt"' % num, 107 'Content-Type: text/plain', 108 'Content-Transfer-Encoding: 8bit;charset=UTF-8', 109 '', str(message)) 110 111 def encode_file (field_name, boundary): 112 filename = files [field_name] 113 return ('\r\n--' + boundary, 114 'Content-Disposition: attachment; filename="%s"' % filename, 115 'Content-Type: %s' % get_content_type(filename), 116 'Content-Transfer-Encoding: base64', 117 '', base64.encodestring(open (filename, 'rb').read ())) 118 119 lines = ['\r\n--' + boundary1, 120 'Content-Disposition: form-data; name="root-fields"', 121 'Content-Type: application/json;charset=UTF-8', 122 'Content-Transfer-Encoding: 8bit', 123 '', str(root)] 124 125 if messages or files: 126 att = ('\r\n--' + boundary1, 127 'Content-Disposition: form-data; name="attachments"', 128 'Content-Type: multipart/mixed; boundary=%s' % boundary2, 129 '') 130 lines.extend(att) 131 132 if messages: 133 i=0 134 for msg in messages: 135 lines.extend (encode_message(i, msg, boundary2)) 136 i += 1 137 if files: 138 for name in files: 139 lines.extend (encode_file (name, boundary2)) 140 141 lines.extend (('--%s--' % boundary2, '')) 142 lines.extend (('--%s--' % boundary1, '')) 143 body = '\r\n'.join (lines) 144 145 headers = {'content-type': 'multipart/form-data; boundary=' + boundary1, 146 'content-length': str (len (body))} 147 148 return body, headers 149
150 -def _decodeMultipart(msgId, body):
151 """ 152 Decodes the BlueVia Multipart MIME body from retrieving MMS attachemnts into a folder with message and file objects 153 154 Internal method 155 """ 156 157 common_ext = { 'image/jpg': '.jpg', 158 'image/jpeg': '.jpg', 159 'image/png': '.png', 160 'application/json': '.json', 161 'application/xml': '.xml', 162 'text/plain': '.txt', 163 'text/html': '.html' 164 } 165 166 result = [] 167 directory = msgId 168 os.mkdir(directory) 169 170 # add the multipart header, unfortunately missing in BlueVia response 171 boundary = body[:200].split("\r\n")[1][2:] 172 fullbody = 'Content-Type: multipart/mixed; boundary="%s"\r\n%s\r\n"' % (boundary, body) 173 174 msg = email.message_from_string(fullbody) 175 counter = 1 176 for part in msg.walk(): 177 # multipart/* are just containers 178 if part.get_content_maintype() == 'multipart': 179 continue 180 filename = part.get_filename() 181 ext = common_ext.get(part.get_content_type()) 182 if not ext: 183 ext = mimetypes.guess_extension(part.get_content_type()) 184 if not ext: 185 ext = '.bin' 186 if filename: 187 if not os.path.splitext(filename)[1]: 188 filename += ext 189 else: 190 filename = 'part-%03d%s' % (counter, ext) 191 counter += 1 192 193 fp = open(os.path.join(directory, filename), 'wb') 194 fp.write(part.get_payload(decode=True)) 195 fp.close() 196 197 print "%d files saved to %s" % (counter, msgId) 198 return (counter, msgId)
199