gdrive_server_node.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import datetime
4 import os.path
5 import sys
6 
7 from httplib2 import ServerNotFoundError
8 from pydrive.auth import GoogleAuth
9 from pydrive.drive import GoogleDrive
10 from pydrive.files import ApiRequestError
11 import rospy
12 
13 from gdrive_ros.srv import MultipleUpload
14 from gdrive_ros.srv import MultipleUploadResponse
15 from gdrive_ros.srv import Upload
16 from gdrive_ros.srv import UploadResponse
17 
18 
19 class GDriveServerNode(object):
20  folder_mime_type = 'application/vnd.google-apps.folder'
21  folder_url_format = 'https://drive.google.com/drive/folders/{}'
22  file_url_format = 'https://drive.google.com/uc?id={}'
23 
24  def __init__(self):
25  settings_yaml = rospy.get_param('~settings_yaml', None)
26  self.share_type = rospy.get_param('~share_type', 'anyone')
27  self.share_value = rospy.get_param('~share_value', 'anyone')
28  self.share_role = rospy.get_param('~share_role', 'reader')
29  self.share_with_link = rospy.get_param('~share_with_link', True)
30  if settings_yaml is not None:
31  self.gauth = GoogleAuth(settings_yaml)
32  else:
33  rospy.logerr('param: ~settings_yaml is not correctly set.')
34  sys.exit(1)
35 
36  rospy.loginfo('Google drive authentication starts.')
37  self.gauth.LocalWebserverAuth()
38  self.gdrive = GoogleDrive(self.gauth)
39  rospy.loginfo('Google drive authentication finished.')
40  self.upload_server = rospy.Service('~upload', Upload, self._upload_cb)
41  self.upload_multi_server = rospy.Service(
42  '~upload_multi', MultipleUpload, self._upload_multi_cb)
43 
44  def _upload_cb(self, req):
45  timestamp = '{0:%Y%m%d%H%M%S}'.format(datetime.datetime.now())
46  parents_path = req.parents_path
47  parents_id = req.parents_id
48 
49  # response initialization
50  res = UploadResponse()
51  res.success = False
52  res.file_id = ''
53  res.file_url = ''
54 
55  if parents_id and parents_path:
56  rospy.logerr('parents_path and parents_id is both set.')
57  rospy.logerr('parents_id: {} is selected to upload.'.format(parents_id))
58  parents_path = ''
59 
60  if parents_path:
61  try:
62  parents_id = self._get_parents_id(
63  parents_path, mkdir=True)
64  except (ValueError, ApiRequestError, ServerNotFoundError) as e:
65  rospy.logerr(e)
66  rospy.logerr(
67  'Failed to get parents_id: {}'.format(parents_path))
68  return res
69  # root
70  elif parents_id == '' and parents_path == '':
71  parents_id = ''
72 
73  if req.use_timestamp_folder:
74  try:
75  parents_id = self._get_parents_id(
76  [timestamp], parents_id=parents_id, mkdir=True)
77  except (ValueError, ApiRequestError, ServerNotFoundError) as e:
78  rospy.logerr(e)
79  rospy.logerr(
80  'Failed to get parents_id: {} in {}'.format(
81  timestamp, self.folder_url_format.format(parents_id)))
82  return res
83 
84  success, file_id, file_url = self._upload_step(
85  req.file_path, req.file_title, parents_id,
86  req.use_timestamp_file_title, timestamp)
87  res.success = success
88  res.file_id = file_id
89  res.file_url = file_url
90  res.parents_id = parents_id
91  res.parents_url = self.folder_url_format.format(parents_id)
92  return res
93 
94  def _upload_multi_cb(self, req):
95  timestamp = '{0:%Y%m%d%H%M%S}'.format(datetime.datetime.now())
96  parents_path = req.parents_path
97  parents_id = req.parents_id
98 
99  # response initialization
100  res = MultipleUploadResponse()
101  res.successes = [False] * len(req.file_titles)
102  res.file_ids = [''] * len(req.file_titles)
103  res.file_urls = [''] * len(req.file_titles)
104 
105  if parents_id and parents_path:
106  rospy.logerr('parents_path and parents_id is both set.')
107  rospy.logerr('parents_id: {} is selected to upload.'.format(parents_id))
108  parents_path = ''
109 
110  if parents_path:
111  try:
112  parents_id = self._get_parents_id(
113  parents_path, mkdir=True)
114  except (ValueError, ApiRequestError, ServerNotFoundError) as e:
115  rospy.logerr(e)
116  rospy.logerr(
117  'Failed to get parents_id: {}'.format(parents_path))
118  return res
119  # root
120  elif parents_id == '' and parents_path == '':
121  parents_id = ''
122 
123  if req.use_timestamp_folder:
124  try:
125  parents_id = self._get_parents_id(
126  [timestamp], parents_id=parents_id, mkdir=True)
127  except (ValueError, ApiRequestError, ServerNotFoundError) as e:
128  rospy.logerr(e)
129  rospy.logerr(
130  'Failed to get parents_id: {} in {}'.format(
131  timestamp, self.folder_url_format.format(parents_id)))
132  return res
133 
134  for i, (file_path, file_title) in enumerate(
135  zip(req.file_paths, req.file_titles)):
136  success, file_id, file_url = self._upload_step(
137  file_path, file_title, parents_id,
138  req.use_timestamp_file_title, timestamp)
139  res.successes[i] = success
140  res.file_ids[i] = file_id
141  res.file_urls[i] = file_url
142  res.parents_id = parents_id
143  res.parents_url = self.folder_url_format.format(parents_id)
144  return res
145 
146  def _upload_step(self, file_path, file_title, parents_id,
147  use_timestamp_file_title=False, timestamp=None):
148  file_title = file_title if file_title else file_path.split('/')[-1]
149  file_path = os.path.expanduser(file_path)
150  if use_timestamp_file_title:
151  file_title = '{}_{}'.format(timestamp, file_title)
152 
153  success = False
154  file_id = ''
155  file_url = ''
156  folder_url = self.folder_url_format.format(parents_id)
157  try:
158  file_id = self._upload_file(
159  file_path, file_title, parents_id=parents_id)
160  file_url = self.file_url_format.format(file_id)
161  success = True
162  rospy.loginfo(
163  'Success to upload: {} -> {}'.format(file_path, file_url))
164  except (OSError, ApiRequestError, ServerNotFoundError) as e:
165  rospy.logerr(e)
166  rospy.logerr(
167  'Failed to upload: {} -> {}'.format(file_path, folder_url))
168  return success, file_id, file_url
169 
170  def _upload_file(self, file_path, file_title, parents_id=None):
171  if not os.path.exists(file_path):
172  raise OSError('File not found: {}'.format(file_path))
173  rospy.loginfo('Start uploading a file: {}'.format(file_title))
174  if parents_id:
175  gfile = self.gdrive.CreateFile(
176  {'parents': [{'id': parents_id}]})
177  else:
178  gfile = self.gdrive.CreateFile()
179  gfile.SetContentFile(file_path)
180  gfile['title'] = file_title
181  gfile.Upload()
182  gfile.InsertPermission({
183  'type': self.share_type,
184  'value': self.share_value,
185  'role': self.share_role,
186  'withLink': self.share_with_link,
187  })
188  rospy.loginfo('Finish uploading a file: {}'.format(file_title))
189  return gfile['id']
190 
191  def _upload_folder(self, folder_title, parents_id=None):
192  rospy.loginfo('Start making a folder: {}'.format(folder_title))
193  if parents_id:
194  gfolder = self.gdrive.CreateFile(
195  {'title': folder_title,
196  'parents': [{'id': parents_id}],
197  'mimeType': 'application/vnd.google-apps.folder'})
198  else:
199  gfolder = self.gdrive.CreateFile(
200  {'title': folder_title,
201  'mimeType': 'application/vnd.google-apps.folder'})
202  gfolder.Upload()
203  rospy.loginfo('Finish making a folder: {}'.format(folder_title))
204  return gfolder['id']
205 
206  def _get_parents_id(self, parents_path, parents_id=None, mkdir=False):
207  if parents_path == '':
208  return None
209 
210  if not isinstance(parents_path, list):
211  parents_path = [p for p in parents_path.split('/') if p != '']
212 
213  folder_title = parents_path[0]
214  parent = parents_id if parents_id else 'root'
215  gfiles = self.gdrive.ListFile(
216  {'q': "'{}' in parents and trashed=false".format(parent)})
217  gfiles = gfiles.GetList()
218  gfolders = []
219  for gf in gfiles:
220  if (gf['mimeType'] == self.folder_mime_type
221  and gf['title'] == folder_title):
222  gfolders.append(gf)
223 
224  if len(parents_path) == 1:
225  if len(gfolders) > 0:
226  return gfolders[0]['id']
227  if mkdir:
228  folder_id = self._upload_folder(
229  folder_title, parents_id=parents_id)
230  return folder_id
231  else:
232  raise ValueError(
233  'Folder is not found: {}'.format(folder_title))
234  else:
235  if len(gfolders) > 0 or mkdir:
236  if len(gfolders) > 0:
237  next_parents_id = gfolders[0]['id']
238  elif mkdir:
239  next_parents_id = self._upload_folder(
240  folder_title, parents_id=parents_id)
241  folder_id = self._get_parents_id(
242  parents_path[1:], parents_id=next_parents_id,
243  mkdir=mkdir)
244  return folder_id
245  else:
246  raise ValueError('folder is not found: {}', folder_title)
247 
248 
249 if __name__ == '__main__':
250  rospy.init_node('gdrive_server')
252  rospy.spin()
def _upload_folder(self, folder_title, parents_id=None)
def _upload_file(self, file_path, file_title, parents_id=None)
def _upload_step(self, file_path, file_title, parents_id, use_timestamp_file_title=False, timestamp=None)
def _get_parents_id(self, parents_path, parents_id=None, mkdir=False)


gdrive_ros
Author(s): Shingo Kitagawa
autogenerated on Tue May 11 2021 02:55:33