github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/backend/jottacloud/api/types.go (about) 1 package api 2 3 import ( 4 "encoding/xml" 5 "fmt" 6 "time" 7 8 "github.com/pkg/errors" 9 ) 10 11 const ( 12 // default time format for almost all request and responses 13 timeFormat = "2006-01-02-T15:04:05Z0700" 14 // the API server seems to use a different format 15 apiTimeFormat = "2006-01-02T15:04:05Z07:00" 16 ) 17 18 // Time represents time values in the Jottacloud API. It uses a custom RFC3339 like format. 19 type Time time.Time 20 21 // UnmarshalXML turns XML into a Time 22 func (t *Time) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 23 var v string 24 if err := d.DecodeElement(&v, &start); err != nil { 25 return err 26 } 27 if v == "" { 28 *t = Time(time.Time{}) 29 return nil 30 } 31 newTime, err := time.Parse(timeFormat, v) 32 if err == nil { 33 *t = Time(newTime) 34 } 35 return err 36 } 37 38 // MarshalXML turns a Time into XML 39 func (t *Time) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 40 return e.EncodeElement(t.String(), start) 41 } 42 43 // Return Time string in Jottacloud format 44 func (t Time) String() string { return time.Time(t).Format(timeFormat) } 45 46 // APIString returns Time string in Jottacloud API format 47 func (t Time) APIString() string { return time.Time(t).Format(apiTimeFormat) } 48 49 // LoginToken is struct representing the login token generated in the WebUI 50 type LoginToken struct { 51 Username string `json:"username"` 52 Realm string `json:"realm"` 53 WellKnownLink string `json:"well_known_link"` 54 AuthToken string `json:"auth_token"` 55 } 56 57 // WellKnown contains some configuration parameters for setting up endpoints 58 type WellKnown struct { 59 Issuer string `json:"issuer"` 60 AuthorizationEndpoint string `json:"authorization_endpoint"` 61 TokenEndpoint string `json:"token_endpoint"` 62 TokenIntrospectionEndpoint string `json:"token_introspection_endpoint"` 63 UserinfoEndpoint string `json:"userinfo_endpoint"` 64 EndSessionEndpoint string `json:"end_session_endpoint"` 65 JwksURI string `json:"jwks_uri"` 66 CheckSessionIframe string `json:"check_session_iframe"` 67 GrantTypesSupported []string `json:"grant_types_supported"` 68 ResponseTypesSupported []string `json:"response_types_supported"` 69 SubjectTypesSupported []string `json:"subject_types_supported"` 70 IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"` 71 UserinfoSigningAlgValuesSupported []string `json:"userinfo_signing_alg_values_supported"` 72 RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported"` 73 ResponseNodesSupported []string `json:"response_modes_supported"` 74 RegistrationEndpoint string `json:"registration_endpoint"` 75 TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"` 76 TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported"` 77 ClaimsSupported []string `json:"claims_supported"` 78 ClaimTypesSupported []string `json:"claim_types_supported"` 79 ClaimsParameterSupported bool `json:"claims_parameter_supported"` 80 ScopesSupported []string `json:"scopes_supported"` 81 RequestParameterSupported bool `json:"request_parameter_supported"` 82 RequestURIParameterSupported bool `json:"request_uri_parameter_supported"` 83 CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"` 84 TLSClientCertificateBoundAccessTokens bool `json:"tls_client_certificate_bound_access_tokens"` 85 IntrospectionEndpoint string `json:"introspection_endpoint"` 86 } 87 88 // TokenJSON is the struct representing the HTTP response from OAuth2 89 // providers returning a token in JSON form. 90 type TokenJSON struct { 91 AccessToken string `json:"access_token"` 92 ExpiresIn int32 `json:"expires_in"` // at least PayPal returns string, while most return number 93 RefreshExpiresIn int32 `json:"refresh_expires_in"` 94 RefreshToken string `json:"refresh_token"` 95 TokenType string `json:"token_type"` 96 IDToken string `json:"id_token"` 97 NotBeforePolicy int32 `json:"not-before-policy"` 98 SessionState string `json:"session_state"` 99 Scope string `json:"scope"` 100 } 101 102 // JSON structures returned by new API 103 104 // AllocateFileRequest to prepare an upload to Jottacloud 105 type AllocateFileRequest struct { 106 Bytes int64 `json:"bytes"` 107 Created string `json:"created"` 108 Md5 string `json:"md5"` 109 Modified string `json:"modified"` 110 Path string `json:"path"` 111 } 112 113 // AllocateFileResponse for upload requests 114 type AllocateFileResponse struct { 115 Name string `json:"name"` 116 Path string `json:"path"` 117 State string `json:"state"` 118 UploadID string `json:"upload_id"` 119 UploadURL string `json:"upload_url"` 120 Bytes int64 `json:"bytes"` 121 ResumePos int64 `json:"resume_pos"` 122 } 123 124 // UploadResponse after an upload 125 type UploadResponse struct { 126 Name string `json:"name"` 127 Path string `json:"path"` 128 Kind string `json:"kind"` 129 ContentID string `json:"content_id"` 130 Bytes int64 `json:"bytes"` 131 Md5 string `json:"md5"` 132 Created int64 `json:"created"` 133 Modified int64 `json:"modified"` 134 Deleted interface{} `json:"deleted"` 135 Mime string `json:"mime"` 136 } 137 138 // DeviceRegistrationResponse is the response to registering a device 139 type DeviceRegistrationResponse struct { 140 ClientID string `json:"client_id"` 141 ClientSecret string `json:"client_secret"` 142 } 143 144 // CustomerInfo provides general information about the account. Required for finding the correct internal username. 145 type CustomerInfo struct { 146 Username string `json:"username"` 147 Email string `json:"email"` 148 Name string `json:"name"` 149 CountryCode string `json:"country_code"` 150 LanguageCode string `json:"language_code"` 151 CustomerGroupCode string `json:"customer_group_code"` 152 BrandCode string `json:"brand_code"` 153 AccountType string `json:"account_type"` 154 SubscriptionType string `json:"subscription_type"` 155 Usage int64 `json:"usage"` 156 Qouta int64 `json:"quota"` 157 BusinessUsage int64 `json:"business_usage"` 158 BusinessQouta int64 `json:"business_quota"` 159 WriteLocked bool `json:"write_locked"` 160 ReadLocked bool `json:"read_locked"` 161 LockedCause interface{} `json:"locked_cause"` 162 WebHash string `json:"web_hash"` 163 AndroidHash string `json:"android_hash"` 164 IOSHash string `json:"ios_hash"` 165 } 166 167 // XML structures returned by the old API 168 169 // Flag is a hacky type for checking if an attribute is present 170 type Flag bool 171 172 // UnmarshalXMLAttr sets Flag to true if the attribute is present 173 func (f *Flag) UnmarshalXMLAttr(attr xml.Attr) error { 174 *f = true 175 return nil 176 } 177 178 // MarshalXMLAttr : Do not use 179 func (f *Flag) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { 180 attr := xml.Attr{ 181 Name: name, 182 Value: "false", 183 } 184 return attr, errors.New("unimplemented") 185 } 186 187 /* 188 GET http://www.jottacloud.com/JFS/<account> 189 190 <user time="2018-07-18-T21:39:10Z" host="dn-132"> 191 <username>12qh1wsht8cssxdtwl15rqh9</username> 192 <account-type>free</account-type> 193 <locked>false</locked> 194 <capacity>5368709120</capacity> 195 <max-devices>-1</max-devices> 196 <max-mobile-devices>-1</max-mobile-devices> 197 <usage>0</usage> 198 <read-locked>false</read-locked> 199 <write-locked>false</write-locked> 200 <quota-write-locked>false</quota-write-locked> 201 <enable-sync>true</enable-sync> 202 <enable-foldershare>true</enable-foldershare> 203 <devices> 204 <device> 205 <name xml:space="preserve">Jotta</name> 206 <display_name xml:space="preserve">Jotta</display_name> 207 <type>JOTTA</type> 208 <sid>5c458d01-9eaf-4f23-8d3c-2486fd9704d8</sid> 209 <size>0</size> 210 <modified>2018-07-15-T22:04:59Z</modified> 211 </device> 212 </devices> 213 </user> 214 */ 215 216 // DriveInfo represents a Jottacloud account 217 type DriveInfo struct { 218 Username string `xml:"username"` 219 AccountType string `xml:"account-type"` 220 Locked bool `xml:"locked"` 221 Capacity int64 `xml:"capacity"` 222 MaxDevices int `xml:"max-devices"` 223 MaxMobileDevices int `xml:"max-mobile-devices"` 224 Usage int64 `xml:"usage"` 225 ReadLocked bool `xml:"read-locked"` 226 WriteLocked bool `xml:"write-locked"` 227 QuotaWriteLocked bool `xml:"quota-write-locked"` 228 EnableSync bool `xml:"enable-sync"` 229 EnableFolderShare bool `xml:"enable-foldershare"` 230 Devices []JottaDevice `xml:"devices>device"` 231 } 232 233 /* 234 GET http://www.jottacloud.com/JFS/<account>/<device> 235 236 <device time="2018-07-23-T20:21:50Z" host="dn-158"> 237 <name xml:space="preserve">Jotta</name> 238 <display_name xml:space="preserve">Jotta</display_name> 239 <type>JOTTA</type> 240 <sid>5c458d01-9eaf-4f23-8d3c-2486fd9704d8</sid> 241 <size>0</size> 242 <modified>2018-07-15-T22:04:59Z</modified> 243 <user>12qh1wsht8cssxdtwl15rqh9</user> 244 <mountPoints> 245 <mountPoint> 246 <name xml:space="preserve">Archive</name> 247 <size>0</size> 248 <modified>2018-07-15-T22:04:59Z</modified> 249 </mountPoint> 250 <mountPoint> 251 <name xml:space="preserve">Shared</name> 252 <size>0</size> 253 <modified></modified> 254 </mountPoint> 255 <mountPoint> 256 <name xml:space="preserve">Sync</name> 257 <size>0</size> 258 <modified></modified> 259 </mountPoint> 260 </mountPoints> 261 <metadata first="" max="" total="3" num_mountpoints="3"/> 262 </device> 263 */ 264 265 // JottaDevice represents a Jottacloud Device 266 type JottaDevice struct { 267 Name string `xml:"name"` 268 DisplayName string `xml:"display_name"` 269 Type string `xml:"type"` 270 Sid string `xml:"sid"` 271 Size int64 `xml:"size"` 272 User string `xml:"user"` 273 MountPoints []JottaMountPoint `xml:"mountPoints>mountPoint"` 274 } 275 276 /* 277 GET http://www.jottacloud.com/JFS/<account>/<device>/<mountpoint> 278 279 <mountPoint time="2018-07-24-T20:35:02Z" host="dn-157"> 280 <name xml:space="preserve">Sync</name> 281 <path xml:space="preserve">/12qh1wsht8cssxdtwl15rqh9/Jotta</path> 282 <abspath xml:space="preserve">/12qh1wsht8cssxdtwl15rqh9/Jotta</abspath> 283 <size>0</size> 284 <modified></modified> 285 <device>Jotta</device> 286 <user>12qh1wsht8cssxdtwl15rqh9</user> 287 <folders> 288 <folder name="test"/> 289 </folders> 290 <metadata first="" max="" total="1" num_folders="1" num_files="0"/> 291 </mountPoint> 292 */ 293 294 // JottaMountPoint represents a Jottacloud mountpoint 295 type JottaMountPoint struct { 296 Name string `xml:"name"` 297 Size int64 `xml:"size"` 298 Device string `xml:"device"` 299 Folders []JottaFolder `xml:"folders>folder"` 300 Files []JottaFile `xml:"files>file"` 301 } 302 303 /* 304 GET http://www.jottacloud.com/JFS/<account>/<device>/<mountpoint>/<folder> 305 306 <folder name="test" time="2018-07-24-T20:41:37Z" host="dn-158"> 307 <path xml:space="preserve">/12qh1wsht8cssxdtwl15rqh9/Jotta/Sync</path> 308 <abspath xml:space="preserve">/12qh1wsht8cssxdtwl15rqh9/Jotta/Sync</abspath> 309 <folders> 310 <folder name="t2"/>c 311 </folders> 312 <files> 313 <file name="block.csv" uuid="f6553cd4-1135-48fe-8e6a-bb9565c50ef2"> 314 <currentRevision> 315 <number>1</number> 316 <state>COMPLETED</state> 317 <created>2018-07-05-T15:08:02Z</created> 318 <modified>2018-07-05-T15:08:02Z</modified> 319 <mime>application/octet-stream</mime> 320 <size>30827730</size> 321 <md5>1e8a7b728ab678048df00075c9507158</md5> 322 <updated>2018-07-24-T20:41:10Z</updated> 323 </currentRevision> 324 </file> 325 </files> 326 <metadata first="" max="" total="2" num_folders="1" num_files="1"/> 327 </folder> 328 */ 329 330 // JottaFolder represents a JottacloudFolder 331 type JottaFolder struct { 332 XMLName xml.Name 333 Name string `xml:"name,attr"` 334 Deleted Flag `xml:"deleted,attr"` 335 Path string `xml:"path"` 336 CreatedAt Time `xml:"created"` 337 ModifiedAt Time `xml:"modified"` 338 Updated Time `xml:"updated"` 339 Folders []JottaFolder `xml:"folders>folder"` 340 Files []JottaFile `xml:"files>file"` 341 } 342 343 /* 344 GET http://www.jottacloud.com/JFS/<account>/<device>/<mountpoint>/.../<file> 345 346 <file name="block.csv" uuid="f6553cd4-1135-48fe-8e6a-bb9565c50ef2"> 347 <currentRevision> 348 <number>1</number> 349 <state>COMPLETED</state> 350 <created>2018-07-05-T15:08:02Z</created> 351 <modified>2018-07-05-T15:08:02Z</modified> 352 <mime>application/octet-stream</mime> 353 <size>30827730</size> 354 <md5>1e8a7b728ab678048df00075c9507158</md5> 355 <updated>2018-07-24-T20:41:10Z</updated> 356 </currentRevision> 357 </file> 358 */ 359 360 // JottaFile represents a Jottacloud file 361 type JottaFile struct { 362 XMLName xml.Name 363 Name string `xml:"name,attr"` 364 Deleted Flag `xml:"deleted,attr"` 365 PublicSharePath string `xml:"publicSharePath"` 366 State string `xml:"currentRevision>state"` 367 CreatedAt Time `xml:"currentRevision>created"` 368 ModifiedAt Time `xml:"currentRevision>modified"` 369 Updated Time `xml:"currentRevision>updated"` 370 Size int64 `xml:"currentRevision>size"` 371 MimeType string `xml:"currentRevision>mime"` 372 MD5 string `xml:"currentRevision>md5"` 373 } 374 375 // Error is a custom Error for wrapping Jottacloud error responses 376 type Error struct { 377 StatusCode int `xml:"code"` 378 Message string `xml:"message"` 379 Reason string `xml:"reason"` 380 Cause string `xml:"cause"` 381 } 382 383 // Error returns a string for the error and statistifes the error interface 384 func (e *Error) Error() string { 385 out := fmt.Sprintf("error %d", e.StatusCode) 386 if e.Message != "" { 387 out += ": " + e.Message 388 } 389 if e.Reason != "" { 390 out += fmt.Sprintf(" (%+v)", e.Reason) 391 } 392 return out 393 }