mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-15 20:26:53 +02:00
command line options
This commit is contained in:
parent
424e77e4b5
commit
ff07f13cd6
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
|||
DC = dmd
|
||||
DFLAGS = -debug -g -gs -od./bin -of./bin/$@ -L-lcurl -L-lsqlite3 -L-ldl
|
||||
DFLAGS = -unittest -debug -g -gs -od./bin -of./bin/$@ -L-lcurl -L-lsqlite3 -L-ldl
|
||||
|
||||
SOURCES = \
|
||||
/usr/include/dlang/dmd/core/sys/posix/poll.d \
|
||||
|
|
19
src/config.d
19
src/config.d
|
@ -1,6 +1,6 @@
|
|||
import std.regex, std.stdio, std.file;
|
||||
import std.file, std.regex, std.stdio;
|
||||
|
||||
final class Config
|
||||
struct Config
|
||||
{
|
||||
private string filename;
|
||||
private string[string] values;
|
||||
|
@ -8,12 +8,16 @@ final class Config
|
|||
this(string filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
load();
|
||||
}
|
||||
|
||||
string get(string key)
|
||||
{
|
||||
return values[key];
|
||||
import core.exception;
|
||||
try {
|
||||
return values[key];
|
||||
} catch (RangeError e) {
|
||||
throw new Exception("Missing config value: " ~ key);
|
||||
}
|
||||
}
|
||||
|
||||
void set(string key, string value)
|
||||
|
@ -24,16 +28,17 @@ final class Config
|
|||
void load()
|
||||
{
|
||||
values = null;
|
||||
scope (failure) return;
|
||||
auto file = File(filename, "r");
|
||||
auto r = regex("(?:^\\s*)(\\w+)(?:\\s*=\\s*\")(.*)(?:\"\\s*$)");
|
||||
foreach (line; file.byLine()) {
|
||||
auto c = matchFirst(line, r);
|
||||
if (!c.empty) {
|
||||
c.popFront(); // skip whole match
|
||||
c.popFront(); // skip the whole match
|
||||
string key = c.front.dup;
|
||||
c.popFront();
|
||||
values[key] = c.front.dup;
|
||||
} else {
|
||||
writeln("Malformed config line: ", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +58,7 @@ final class Config
|
|||
|
||||
unittest
|
||||
{
|
||||
auto cfg = new Config("/tmp/test.conf");
|
||||
auto cfg = Config(tempDir() ~ "/test.conf");
|
||||
cfg.set("test1", "1");
|
||||
cfg.set("test2", "2");
|
||||
cfg.set("test1", "3");
|
||||
|
|
105
src/main.d
105
src/main.d
|
@ -1,46 +1,89 @@
|
|||
import std.file;
|
||||
import std.getopt, std.file, std.process, std.stdio;
|
||||
import config, monitor, onedrive, sync;
|
||||
|
||||
private string configFile = "./onedrive.conf";
|
||||
private string refreshTokenFile = "refresh_token";
|
||||
string ver = "1.0";
|
||||
|
||||
void main()
|
||||
void main(string[] args)
|
||||
{
|
||||
auto cfg = new Config(configFile);
|
||||
|
||||
auto onedrive = new OneDriveApi(cfg.get("client_id"), cfg.get("client_secret"));
|
||||
onedrive.onRefreshToken = (string refreshToken) { std.file.write(refreshTokenFile, refreshToken); };
|
||||
bool monitor, resync, resetLocal, resetRemote, verbose;
|
||||
try {
|
||||
string refreshToken = readText(refreshTokenFile);
|
||||
writeln("OneDrive Client for Linux v", ver);
|
||||
auto opt = getopt(
|
||||
args,
|
||||
"monitor|m", "Keep monitoring for local and remote changes.", &monitor,
|
||||
"resync", "Perform a full synchronization.", &resync,
|
||||
"verbose|v", "Print more details, useful for debugging.", &verbose
|
||||
);
|
||||
if (opt.helpWanted) {
|
||||
defaultGetoptPrinter("Available options:", opt.options);
|
||||
return;
|
||||
}
|
||||
} catch (GetOptException e) {
|
||||
writeln(e.msg);
|
||||
writeln("Try 'onedrive -h' for more information.");
|
||||
return;
|
||||
}
|
||||
|
||||
string homeDirName = environment["HOME"];
|
||||
string configDirName = environment.get("XDG_CONFIG_HOME", homeDirName ~ "/.config") ~ "/onedrive";
|
||||
string configFilePath = configDirName ~ "/config";
|
||||
string refreshTokenFilePath = configDirName ~ "/refresh_token";
|
||||
string statusTokenFilePath = configDirName ~ "/status_token";
|
||||
string databaseFilePath = configDirName ~ "/database";
|
||||
|
||||
if (resync || resetLocal || resetRemote) {
|
||||
if (verbose) writeln("Deleting the current status ...");
|
||||
if (exists(databaseFilePath)) remove(databaseFilePath);
|
||||
if (exists(statusTokenFilePath)) remove(statusTokenFilePath);
|
||||
}
|
||||
|
||||
if (verbose) writeln("Loading config ...");
|
||||
auto cfg = config.Config(configFilePath);
|
||||
cfg.load();
|
||||
|
||||
if (verbose) writeln("Initializing the OneDrive API ...");
|
||||
auto onedrive = new OneDriveApi(cfg, verbose);
|
||||
onedrive.onRefreshToken = (string refreshToken) {
|
||||
std.file.write(refreshTokenFilePath, refreshToken);
|
||||
};
|
||||
try {
|
||||
string refreshToken = readText(refreshTokenFilePath);
|
||||
onedrive.setRefreshToken(refreshToken);
|
||||
} catch (FileException e) {
|
||||
onedrive.authorize();
|
||||
}
|
||||
// TODO check if the token is valid
|
||||
|
||||
if (verbose) writeln("Initializing the Synchronization Engine ...");
|
||||
auto sync = new SyncEngine(cfg, onedrive);
|
||||
sync.applyDifferences();
|
||||
sync.uploadDifferences();
|
||||
|
||||
Monitor m;
|
||||
import std.stdio;
|
||||
m.onDirCreated = delegate(string path) {
|
||||
writeln("Directory created: ", path);
|
||||
sync.createFolderItem(path);
|
||||
sync.uploadDifferences(path);
|
||||
};
|
||||
m.onFileChanged = delegate(string path) {
|
||||
writeln("File changed: ", path);
|
||||
sync.uploadDifference2(path);
|
||||
};
|
||||
m.onDelete = delegate(string path) {
|
||||
sync.deleteByPath(path);
|
||||
};
|
||||
m.onMove = delegate(string from, string to) {
|
||||
sync.moveItem(from, to);
|
||||
};
|
||||
m.init();
|
||||
string syncDir = cfg.get("sync_dir");
|
||||
chdir(syncDir);
|
||||
m.addRecursive("test");
|
||||
while (true) m.update();
|
||||
if (monitor) {
|
||||
if (verbose) writeln("Monitoring for changes ...");
|
||||
Monitor m;
|
||||
m.onDirCreated = delegate(string path) {
|
||||
if (verbose) writeln("[M] Directory created: ", path);
|
||||
sync.createFolderItem(path);
|
||||
sync.uploadDifferences(path);
|
||||
};
|
||||
m.onFileChanged = delegate(string path) {
|
||||
if (verbose) writeln("[M] File changed: ", path);
|
||||
sync.uploadDifference2(path);
|
||||
};
|
||||
m.onDelete = delegate(string path) {
|
||||
if (verbose) writeln("[M] Item deleted: ", path);
|
||||
sync.deleteByPath(path);
|
||||
};
|
||||
m.onMove = delegate(string from, string to) {
|
||||
if (verbose) writeln("[M] Item moved: ", from, " -> ", to);
|
||||
sync.moveItem(from, to);
|
||||
};
|
||||
m.init();
|
||||
string syncDir = cfg.get("sync_dir");
|
||||
chdir(syncDir);
|
||||
m.addRecursive("test");
|
||||
while (true) m.update();
|
||||
// TODO download changes
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
module onedrive;
|
||||
|
||||
import std.datetime, std.json, std.net.curl, std.path, std.string, std.uni, std.uri;
|
||||
import config;
|
||||
|
||||
private immutable {
|
||||
string authUrl = "https://login.live.com/oauth20_authorize.srf";
|
||||
|
@ -30,18 +29,14 @@ final class OneDriveApi
|
|||
private SysTime accessTokenExpiration;
|
||||
private HTTP http;
|
||||
|
||||
void function(string) onRefreshToken; // called when a new refresh_token is received
|
||||
void delegate(string) onRefreshToken; // called when a new refresh_token is received
|
||||
|
||||
this(string clientId, string clientSecret)
|
||||
this(Config cfg, bool verbose)
|
||||
{
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.clientId = cfg.get("client_id");
|
||||
this.clientSecret = cfg.get("client_secret");
|
||||
http = HTTP();
|
||||
//debug http.verbose = true;
|
||||
// HACK: prevent SIGPIPE
|
||||
//import etc.c.signal, etc.c.curl;
|
||||
//http.handle.set(CurlOption.nosignal, 0);
|
||||
//signal(/*SIGPIPE*/ 13, /*SIG_IGN*/ cast(void function(int)) 1);
|
||||
http.verbose = verbose;
|
||||
}
|
||||
|
||||
~this()
|
||||
|
@ -53,8 +48,8 @@ final class OneDriveApi
|
|||
{
|
||||
import std.stdio, std.regex;
|
||||
string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=wl.offline_access onedrive.readwrite&response_type=code&redirect_url=" ~ redirectUrl;
|
||||
writeln("Authorize this app visiting:");
|
||||
writeln(url);
|
||||
writeln("Authorize this app visiting:\n");
|
||||
writeln(url, "\n");
|
||||
|
||||
while (true) {
|
||||
char[] response;
|
||||
|
@ -62,7 +57,7 @@ final class OneDriveApi
|
|||
readln(response);
|
||||
auto c = matchFirst(response, r"(?:code=)(([\w\d]+-){4}[\w\d]+)");
|
||||
if (!c.empty) {
|
||||
c.popFront(); // skip whole match
|
||||
c.popFront(); // skip the whole match
|
||||
redeemToken(c.front);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue