use view.delta instead of view.changes

removed dependency on client_secret
This commit is contained in:
skilion 2016-06-27 19:23:14 +02:00
parent a927f74626
commit 0efc2fe382
4 changed files with 31 additions and 28 deletions

View file

@ -31,7 +31,7 @@ cp /usr/local/etc/onedrive.conf ~/.config/onedrive/config
Available options: Available options:
* `client_id` & `client_secret`: application identifiers necessary during the [authentication][2] * `client_id`: application identifier necessary for the [authentication][2]
* `sync_dir`: directory where the files will be synced * `sync_dir`: directory where the files will be synced
* `skip_file`: any files that match this pattern will be skipped during sync * `skip_file`: any files that match this pattern will be skipped during sync
* `skip_dir`: any directories that match this pattern will be skipped during sync * `skip_dir`: any directories that match this pattern will be skipped during sync

View file

@ -1,5 +1,4 @@
client_id = "000000004C15842F" client_id = "000000004C15842F"
client_secret = "5vWj5xi6rYZM61X81Z9OyXAmjGhVS6Py"
sync_dir = "~/OneDrive" sync_dir = "~/OneDrive"
skip_file = ".*|~*" skip_file = ".*|~*"
skip_dir = ".*" skip_dir = ".*"

View file

@ -6,7 +6,7 @@ import config;
private immutable { private immutable {
string authUrl = "https://login.live.com/oauth20_authorize.srf"; string authUrl = "https://login.live.com/oauth20_authorize.srf";
string redirectUrl = "https://login.live.com/oauth20_desktop.srf"; string redirectUrl = "https://login.live.com/oauth20_desktop.srf"; // "urn:ietf:wg:oauth:2.0:oob";
string tokenUrl = "https://login.live.com/oauth20_token.srf"; string tokenUrl = "https://login.live.com/oauth20_token.srf";
string itemByIdUrl = "https://api.onedrive.com/v1.0/drive/items/"; string itemByIdUrl = "https://api.onedrive.com/v1.0/drive/items/";
string itemByPathUrl = "https://api.onedrive.com/v1.0/drive/root:/"; string itemByPathUrl = "https://api.onedrive.com/v1.0/drive/root:/";
@ -32,7 +32,7 @@ class OneDriveException: Exception
final class OneDriveApi final class OneDriveApi
{ {
private string clientId, clientSecret; private string clientId;
private string refreshToken, accessToken; private string refreshToken, accessToken;
private SysTime accessTokenExpiration; private SysTime accessTokenExpiration;
/* private */ HTTP http; /* private */ HTTP http;
@ -42,7 +42,6 @@ final class OneDriveApi
this(Config cfg, bool verbose) this(Config cfg, bool verbose)
{ {
this.clientId = cfg.get("client_id"); this.clientId = cfg.get("client_id");
this.clientSecret = cfg.get("client_secret");
http = HTTP(); http = HTTP();
//http.verbose = verbose; //http.verbose = verbose;
} }
@ -50,7 +49,7 @@ final class OneDriveApi
void authorize() void authorize()
{ {
import std.stdio, std.regex; import std.stdio, std.regex;
string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=wl.offline_access%20onedrive.readwrite&response_type=code&redirect_uri=" ~ redirectUrl; string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=onedrive.readwrite%20offline_access&response_type=code&redirect_uri=" ~ redirectUrl;
writeln("Authorize this app visiting:\n"); writeln("Authorize this app visiting:\n");
writeln(url, "\n"); writeln(url, "\n");
@ -72,21 +71,22 @@ final class OneDriveApi
this.refreshToken = refreshToken; this.refreshToken = refreshToken;
} }
// https://dev.onedrive.com/items/view_changes.htm // https://dev.onedrive.com/items/view_delta.htm
JSONValue viewChangesById(const(char)[] id, const(char)[] statusToken) JSONValue viewChangesById(const(char)[] id, const(char)[] statusToken)
{ {
checkAccessTokenExpired(); checkAccessTokenExpired();
char[] url = itemByIdUrl ~ id ~ "/view.changes"; const(char)[] url = itemByIdUrl ~ id ~ "/view.delta";
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,fileSystemInfo,remoteItem,parentReference";
if (statusToken) url ~= "?token=" ~ statusToken; if (statusToken) url ~= "?token=" ~ statusToken;
return get(url); return get(url);
} }
// https://dev.onedrive.com/items/view_changes.htm // https://dev.onedrive.com/items/view_delta.htm
JSONValue viewChangesByPath(const(char)[] path, const(char)[] statusToken) JSONValue viewChangesByPath(const(char)[] path, const(char)[] statusToken)
{ {
checkAccessTokenExpired(); checkAccessTokenExpired();
string url = itemByPathUrl ~ encodeComponent(path) ~ ":/view.changes"; string url = itemByPathUrl ~ encodeComponent(path) ~ ":/view.delta";
url ~= "?select=id,name,eTag,cTag,deleted,file,folder,fileSystemInfo,parentReference"; url ~= "?select=id,name,eTag,cTag,deleted,file,folder,fileSystemInfo,remoteItem,parentReference";
if (statusToken) url ~= "&token=" ~ statusToken; if (statusToken) url ~= "&token=" ~ statusToken;
return get(url); return get(url);
} }
@ -99,7 +99,7 @@ final class OneDriveApi
import std.file; import std.file;
if (exists(saveToPath)) remove(saveToPath); if (exists(saveToPath)) remove(saveToPath);
} }
char[] url = itemByIdUrl ~ id ~ "/content?AVOverride=1"; const(char)[] url = itemByIdUrl ~ id ~ "/content";
download(url, saveToPath); download(url, saveToPath);
} }
@ -183,15 +183,21 @@ final class OneDriveApi
private void redeemToken(const(char)[] authCode) private void redeemToken(const(char)[] authCode)
{ {
string postData = "client_id=" ~ clientId ~ "&redirect_uri=" ~ redirectUrl ~ "&client_secret=" ~ clientSecret; const(char)[] postData =
postData ~= "&code=" ~ authCode ~ "&grant_type=authorization_code"; "client_id=" ~ clientId ~
"&redirect_uri=" ~ redirectUrl ~
"&code=" ~ authCode ~
"&grant_type=authorization_code";
acquireToken(postData); acquireToken(postData);
} }
private void newToken() private void newToken()
{ {
string postData = "client_id=" ~ clientId ~ "&redirect_uri=" ~ redirectUrl ~ "&client_secret=" ~ clientSecret; string postData =
postData ~= "&refresh_token=" ~ refreshToken ~ "&grant_type=refresh_token"; "client_id=" ~ clientId ~
"&redirect_uri=" ~ redirectUrl ~
"&refresh_token=" ~ refreshToken ~
"&grant_type=refresh_token";
acquireToken(postData); acquireToken(postData);
} }

View file

@ -95,9 +95,9 @@ final class SyncEngine
foreach (item; changes["value"].array) { foreach (item; changes["value"].array) {
applyDifference(item); applyDifference(item);
} }
statusToken = changes["@changes.token"].str; statusToken = changes["@delta.token"].str;
onStatusToken(statusToken); onStatusToken(statusToken);
} while (changes["@changes.hasMoreChanges"].type == JSON_TYPE.TRUE); } while (("@odata.nextLink" in changes.object) !is null);
} catch (ErrnoException e) { } catch (ErrnoException e) {
throw new SyncException(e.msg, e); throw new SyncException(e.msg, e);
} catch (FileException e) { } catch (FileException e) {
@ -146,11 +146,9 @@ final class SyncEngine
} }
// compute the path of the item // compute the path of the item
string path; string path = ".";
if (parentId) { if (parentId) {
path = itemdb.computePath(parentId) ~ "/" ~ name; path = itemdb.computePath(parentId) ~ "/" ~ name;
} else {
path = ".";
} }
ItemType type; ItemType type;
@ -181,13 +179,13 @@ final class SyncEngine
} }
string cTag; string cTag;
try { try {
cTag = item["cTag"].str; cTag = item["cTag"].str;
} catch (JSONException e) { } catch (JSONException e) {
// cTag is not returned if the Item is a folder // cTag is not returned if the Item is a folder
// https://dev.onedrive.com/resources/item.htm // https://dev.onedrive.com/resources/item.htm
cTag = ""; cTag = "";
} }
string mtime = item["fileSystemInfo"]["lastModifiedDateTime"].str; string mtime = item["fileSystemInfo"]["lastModifiedDateTime"].str;