chiark / gitweb /
Add youmagine uploader (inactive, no API urls filled)
[cura.git] / Cura / util / youmagine.py
1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
3
4 import sys
5 import json
6 import httplib as httpclient
7 import urllib
8 import cStringIO as StringIO
9
10 class Youmagine(object):
11         def __init__(self, authToken):
12                 self._hostUrl = ''
13                 self._viewUrl = ''
14                 self._authUrl = ''
15                 self._authToken = authToken
16                 self._userName = None
17                 self._userID = None
18                 self._http = None
19                 self._hostReachable = True
20                 self._categories = [
21                         ('Art', 2),
22                         ('Fashion', 3),
23                         ('For your home', 4),
24                         ('Gadget', 5),
25                         ('Games', 6),
26                         ('Jewelry', 7),
27                         ('Maker/DIY', 8),
28                         ('Miniatures', 9),
29                         ('Other', 1),
30                 ]
31                 self._licenses = [
32                         ('Creative Commons - Share Alike', 'cc'),
33                         ('Creative Commons - Attribution-NonCommerical-ShareAlike', 'ccnc'),
34                         ('GPLv3', 'gplv3'),
35                 ]
36
37         def getAuthorizationUrl(self):
38                 return self._authUrl
39
40         def getCategories(self):
41                 return map(lambda n: n[0], self._categories)
42
43         def getLicenses(self):
44                 return map(lambda n: n[0], self._licenses)
45
46         def setAuthToken(self, token):
47                 self._authToken = token
48                 self._userName = None
49                 self._userID = None
50
51         def getAuthToken(self):
52                 return self._authToken
53
54         def isHostReachable(self):
55                 return self._hostReachable
56
57         def viewUrlForDesign(self, id):
58                 return 'https://%s/designs/%d' % (self._viewUrl, id)
59
60         def editUrlForDesign(self, id):
61                 return 'https://%s/designs/%d/edit' % (self._viewUrl, id)
62
63         def isAuthorized(self):
64                 if self._authToken is None:
65                         return False
66                 if self._userName is None:
67                         #No username yet, try to request the username to see if the authToken is valid.
68                         result = self._request('GET', '/authorized_integrations/%s/whoami.json' % (self._authToken))
69
70                         if 'error' in result:
71                                 self._authToken = None
72                                 return False
73                         self._userName = result['screen_name']
74                         self._userID = result['id']
75                 return True
76
77         def createDesign(self, name, description, category, license):
78                 res = self._request('POST', '/designs.json', {'design[name]': name, 'design[excerpt]': description, 'design[design_category_id]': filter(lambda n: n[0] == category, self._categories)[0][1], 'design[license]': filter(lambda n: n[0] == license, self._licenses)[0][1]})
79                 if 'id' in res:
80                         return res['id']
81                 print res
82                 return None
83
84         def publishDesign(self, id):
85                 res = self._request('PUT', '/designs/%d/mark_as/publish.json' % (id), {'ignore': 'me'})
86                 if res is not None:
87                         print res
88                         return False
89                 return True
90
91         def createDocument(self, designId, name, contents):
92                 res = self._request('POST', '/designs/%d/documents.json' % (designId), {'document[name]': name, 'document[description]': 'Uploaded from Cura'}, {'document[file]': (name, contents)})
93                 if 'id' in res:
94                         return res['id']
95                 print res
96                 return None
97
98         def createImage(self, designId, name, contents):
99                 res = self._request('POST', '/designs/%d/images.json' % (designId), {'image[name]': name, 'image[description]': 'Uploaded from Cura'}, {'image[file]': (name, contents)})
100                 if 'id' in res:
101                         return res['id']
102                 print res
103                 return None
104
105         def listDesigns(self):
106                 res = self._request('GET', '/users/%s/designs.json' % (self._userID))
107                 return res
108
109         def _request(self, method, url, postData = None, files = None):
110                 retryCount = 2
111                 if self._authToken is not None:
112                         url += '?auth_token=%s' % (self._authToken)
113                 error = 'Failed to connect to %s' % self._hostUrl
114                 for n in xrange(0, retryCount):
115                         if self._http is None:
116                                 self._http = httpclient.HTTPSConnection(self._hostUrl)
117                         try:
118                                 if files is not None:
119                                         boundary = 'wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T'
120                                         s = StringIO.StringIO()
121                                         for k, v in files.iteritems():
122                                                 filename = v[0]
123                                                 fileContents = v[1]
124                                                 s.write('--%s\r\n' % (boundary))
125                                                 s.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (k, filename))
126                                                 s.write('Content-Type: application/octet-stream\r\n')
127                                                 s.write('Content-Transfer-Encoding: binary\r\n')
128                                                 s.write('\r\n')
129                                                 s.write(fileContents)
130                                                 s.write('\r\n')
131
132                                         for k, v in postData.iteritems():
133                                                 s.write('--%s\r\n' % (boundary))
134                                                 s.write('Content-Disposition: form-data; name="%s"\r\n' % (k))
135                                                 s.write('\r\n')
136                                                 s.write(str(v))
137                                                 s.write('\r\n')
138                                         s.write('--%s--\r\n' % (boundary))
139
140                                         s = s.getvalue()
141                                         self._http.request(method, url, StringIO.StringIO(s), {"Content-type": "multipart/form-data; boundary=%s" % (boundary), "Content-Length": len(s)})
142                                 elif postData is not None:
143                                         self._http.request(method, url, urllib.urlencode(postData), {"Content-type": "application/x-www-form-urlencoded"})
144                                 else:
145                                         self._http.request(method, url)
146                         except IOError:
147                                 self._http.close()
148                                 continue
149                         try:
150                                 response = self._http.getresponse()
151                                 responseText = response.read()
152                         except:
153                                 self._http.close()
154                                 continue
155                         try:
156                                 if responseText == '':
157                                         return None
158                                 return json.loads(responseText)
159                         except ValueError:
160                                 print response.getheaders()
161                                 error = 'Failed to decode JSON response'
162                 self._hostReachable = False
163                 return {'error': error}
164
165
166 #Fake Youmagine class to test without internet
167 class FakeYoumagine(Youmagine):
168         def __init__(self, authToken):
169                 super(FakeYoumagine, self).__init__(authToken)
170                 self._authUrl = 'file:///C:/Models/output.html'
171                 self._authToken = None
172
173         def isAuthorized(self):
174                 if self._authToken is None:
175                         return False
176                 if self._userName is None:
177                         self._userName = 'FakeYoumagine'
178                         self._userID = '1'
179                 return True
180
181         def isHostReachable(self):
182                 return True
183
184         def createDesign(self, name, description, category, license):
185                 return 1
186
187         def publishDesign(self, id):
188                 pass
189
190         def createDocument(self, designId, name, contents):
191                 print "Create document: %s" % (name)
192                 f = open("C:/models/%s" % (name), "wb")
193                 f.write(contents)
194                 f.close()
195                 return 1
196
197         def createImage(self, designId, name, contents):
198                 print "Create image: %s" % (name)
199                 f = open("C:/models/%s" % (name), "wb")
200                 f.write(contents)
201                 f.close()
202                 return 1
203
204         def listDesigns(self):
205                 return []
206
207         def _request(self, method, url, postData = None, files = None):
208                 print "Err: Tried to do request: %s %s" % (method, url)
209
210 def main():
211         ym = Youmagine('j3rY9kQF62ptuZF7vqbR')
212         if not ym.isAuthorized():
213                 print "Failed to authorize"
214                 return
215         for design in ym.listDesigns():
216                 print design['name']