private void AuthenticateClient(DownloadStationSettings settings) { var arguments = new Dictionary <string, object> { { "api", "SYNO.API.Auth" }, { "version", "1" }, { "method", "login" }, { "account", settings.Username }, { "passwd", settings.Password }, { "format", "cookie" }, { "session", "DownloadStation" }, }; var authLoginRequest = BuildRequest(settings, DiskStationApi.Auth, arguments, HttpMethod.GET); authLoginRequest.StoreResponseCookie = true; var response = _httpClient.Execute(authLoginRequest); var downloadStationResponse = Json.Deserialize <DiskStationResponse <DiskStationAuthResponse> >(response.Content); var authResponse = Json.Deserialize <DiskStationResponse <DiskStationAuthResponse> >(response.Content); _authenticated = authResponse.Success; if (!_authenticated) { throw new DownloadClientAuthenticationException(downloadStationResponse.Error.GetMessage(DiskStationApi.Auth)); } }
private DiskStationApiInfo GetApiInfo(DiskStationApi api, DownloadStationSettings settings) { if (api == DiskStationApi.Info) { return(_apiInfo); } var key = GenerateInfoCacheKey(settings, api); var info = _infoCache.Find(key); if (info == null) { UpdateApiInfo(settings); info = _infoCache.Find(key); if (info == null) { if (api == DiskStationApi.DownloadStation2Task) { _logger.Warn("Info of {0} not found on {1}:{2}", api, settings.Host, settings.Port); } else { throw new DownloadClientException("Info of {0} not found on {1}:{2}", api, settings.Host, settings.Port); } } } return(info); }
private void UpdateApiInfo(DownloadStationSettings settings) { var apis = new Dictionary <string, DiskStationApi>() { { "SYNO.API.Auth", DiskStationApi.Auth }, { _apiName, _apiType } }; var requestBuilder = BuildRequest(settings, _apiInfo, "query", _apiInfo.MinVersion); requestBuilder.AddQueryParam("query", string.Join(",", apis.Keys)); var infoResponse = ProcessRequest <DiskStationApiInfoResponse>(requestBuilder, "get api info", _apiInfo.Type, settings); foreach (var data in infoResponse.Data) { if (apis.ContainsKey(data.Key)) { data.Value.Name = data.Key; data.Value.Type = apis[data.Key]; data.Value.NeedsAuthentication = apis[data.Key] != DiskStationApi.Auth; _infoCache.Set(GenerateInfoCacheKey(settings, apis[data.Key]), data.Value, TimeSpan.FromHours(1)); } } }
protected DiskStationResponse <T> ProcessRequest <T>(HttpRequestBuilder requestBuilder, string operation, DownloadStationSettings settings) where T : new() { return(ProcessRequest <T>(requestBuilder, operation, _apiType, settings)); }
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings) { var requestBuilder = BuildRequest(settings, "create", 2); requestBuilder.AddQueryParam("type", "url"); requestBuilder.AddQueryParam("url", url); requestBuilder.AddQueryParam("create_list", "false"); if (downloadDirectory.IsNotNullOrWhiteSpace()) { requestBuilder.AddQueryParam("destination", downloadDirectory); } else { _logger.Trace("No directory configured in settings; falling back to client default destination folder."); string defaultDestination = _defaultDestinationProxy.GetDefaultDestination(settings); if (defaultDestination.IsNotNullOrWhiteSpace()) { _logger.Trace($"Default destination folder found: {defaultDestination}."); requestBuilder.AddQueryParam("destination", $"\"{defaultDestination}\""); } else { _logger.Error("Unable to get default destination folder from DownloadStation."); } } ProcessRequest <object>(requestBuilder, $"add task from url {url}", settings); }
private DiskStationResponse <T> ProcessRequest <T>(HttpRequestBuilder requestBuilder, string operation, DiskStationApi api, DownloadStationSettings settings) where T : new() { var request = requestBuilder.Build(); HttpResponse response; try { response = _httpClient.Execute(request); } catch (HttpException ex) { throw new DownloadClientException("Unable to connect to Diskstation, please check your settings", ex); } catch (WebException ex) { if (ex.Status == WebExceptionStatus.TrustFailure) { throw new DownloadClientUnavailableException("Unable to connect to Diskstation, certificate validation failed.", ex); } throw new DownloadClientUnavailableException("Unable to connect to Diskstation, please check your settings", ex); } _logger.Debug("Trying to {0}", operation); if (response.StatusCode == HttpStatusCode.OK) { var responseContent = Json.Deserialize <DiskStationResponse <T> >(response.Content); if (responseContent.Success) { return(responseContent); } else { var msg = $"Failed to {operation}. Reason: {responseContent.Error.GetMessage(api)}"; _logger.Error(msg); if (responseContent.Error.SessionError) { _sessionCache.Remove(GenerateSessionCacheKey(settings)); if (responseContent.Error.Code == 105) { throw new DownloadClientAuthenticationException(msg); } } throw new DownloadClientException(msg); } } else { throw new HttpException(request, response); } }
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = null) { httpVerb ??= HttpMethod.Get; var info = GetApiInfo(_apiType, settings); return(BuildRequest(settings, info, methodName, apiVersion, httpVerb)); }
public SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings) { var info = GetInfoFileOrDirectory(sharedFolder, settings); var physicalPath = info.Additional["real_path"].ToString(); return(new SharedFolderMapping(sharedFolder, physicalPath)); }
public Dictionary <string, object> GetConfig(DownloadStationSettings settings) { var requestBuilder = BuildRequest(settings, "getConfig", 1); var response = ProcessRequest <Dictionary <string, object> >(requestBuilder, "get config", settings); return(response.Data); }
protected DiskStationResponse <object> ProcessRequest(DiskStationApi api, Dictionary <string, object> arguments, DownloadStationSettings settings, string operation, HttpMethod method = HttpMethod.GET) { return(ProcessRequest <object>(api, arguments, settings, operation, method)); }
public void RemoveTask(string downloadId, DownloadStationSettings settings) { var requestBuilder = BuildRequest(settings, "delete", 2); requestBuilder.AddQueryParam("id", downloadId); requestBuilder.AddQueryParam("force_complete", "false"); ProcessRequest <object>(requestBuilder, $"remove item {downloadId}", settings); }
public string GetDefaultDestination(DownloadStationSettings settings) { var info = GetApiInfo(settings); var requestBuilder = BuildRequest(settings, "get", info.MinVersion); var response = ProcessRequest <DownloadStation2SettingsLocationResponse>(requestBuilder, "get default destination folder", settings); return(response.Data.Default_Destination); }
public string GetSerialNumber(DownloadStationSettings settings) { var info = GetApiInfo(settings); var requestBuilder = BuildRequest(settings, "getinfo", info.MinVersion); var response = ProcessRequest <DSMInfoResponse>(requestBuilder, "get serial number", settings); return(response.Data.SerialNumber); }
protected DiskStationResponse <T> ProcessRequest <T>(DiskStationApi api, Dictionary <string, object> arguments, DownloadStationSettings settings, string operation, HttpMethod method = HttpMethod.GET, int retries = 0) where T : new() { if (retries == 5) { throw new DownloadClientException("Try to process request to {0} with {1} more than 5 times", api, arguments.ToJson().ToString()); } if (!_authenticated && api != DiskStationApi.Info && api != DiskStationApi.DSMInfo) { AuthenticateClient(settings); } var request = BuildRequest(settings, api, arguments, method); var response = _httpClient.Execute(request); _logger.Debug("Trying to {0}", operation); if (response.StatusCode == HttpStatusCode.OK) { var responseContent = Json.Deserialize <DiskStationResponse <T> >(response.Content); if (responseContent.Success) { return(responseContent); } else { var msg = $"Failed to {operation}. Reason: {responseContent.Error.GetMessage(api)}"; _logger.Error(msg); if (responseContent.Error.SessionError) { _authenticated = false; if (responseContent.Error.Code == 105) { throw new DownloadClientAuthenticationException(msg); } return(ProcessRequest <T>(api, arguments, settings, operation, method, ++retries)); } throw new DownloadClientException(msg); } } else { throw new HttpException(request, response); } }
public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings) { var requestBuilder = BuildRequest(settings, "getinfo", 2); requestBuilder.AddQueryParam("path", new[] { path }.ToJson()); requestBuilder.AddQueryParam("additional", "[\"real_path\"]"); var response = ProcessRequest <FileStationListResponse>(requestBuilder, $"get info of {path}", settings); return(response.Data.Files.First()); }
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings) { var requestBuilder = BuildRequest(settings, "create", 3); requestBuilder.AddQueryParam("uri", url); if (downloadDirectory.IsNotNullOrWhiteSpace()) { requestBuilder.AddQueryParam("destination", downloadDirectory); } var response = ProcessRequest <object>(requestBuilder, $"add task from url {url}", settings); }
public void RemoveTask(string downloadId, DownloadStationSettings settings) { var arguments = new Dictionary <string, object> { { "api", "SYNO.DownloadStation.Task" }, { "version", "1" }, { "method", "delete" }, { "id", downloadId }, { "force_complete", false } }; var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"remove item {downloadId}"); }
public string GetSerialNumber(DownloadStationSettings settings) { var arguments = new Dictionary <string, object>() { { "api", "SYNO.DSM.Info" }, { "version", "2" }, { "method", "getinfo" } }; var response = ProcessRequest <DSMInfoResponse>(DiskStationApi.DSMInfo, arguments, settings, "get serial number"); return(response.Data.SerialNumber); }
public Dictionary <string, object> GetConfig(DownloadStationSettings settings) { var arguments = new Dictionary <string, object> { { "api", "SYNO.DownloadStation.Info" }, { "version", "1" }, { "method", "getconfig" } }; var response = ProcessRequest <Dictionary <string, object> >(DiskStationApi.DownloadStationInfo, arguments, settings, "get config"); return(response.Data); }
public IEnumerable <DownloadStationTask> GetTasks(DownloadStationSettings settings) { try { var result = new List <DownloadStationTask>(); var requestBuilder = BuildRequest(settings, "list", 1); requestBuilder.AddQueryParam("additional", "detail"); var response = ProcessRequest <DownloadStation2TaskInfoResponse>(requestBuilder, "get tasks with additional detail", settings); if (response.Success && response.Data.Total > 0) { requestBuilder.AddQueryParam("additional", "transfer"); var responseTransfer = ProcessRequest <DownloadStation2TaskInfoResponse>(requestBuilder, "get tasks with additional transfer", settings); if (responseTransfer.Success) { foreach (var task in response.Data.Task) { var taskTransfer = responseTransfer.Data.Task.Where(t => t.Id == task.Id).First(); var combinedTask = new DownloadStationTask { Username = task.Username, Id = task.Id, Title = task.Title, Size = task.Size, Status = (DownloadStationTaskStatus)task.Status, Type = task.Type, Additional = new DownloadStationTaskAdditional { Detail = task.Additional.Detail, Transfer = taskTransfer.Additional.Transfer } }; result.Add(combinedTask); } } } return(result); } catch (DownloadClientException e) { _logger.Error(e); return(new List <DownloadStationTask>()); } }
protected void Setup() { _sharedFolder = new OsPath("/myFolder"); _physicalPath = new OsPath("/mnt/sda1/folder"); _settings = new DownloadStationSettings(); Mocker.GetMock <IFileStationProxy>() .Setup(f => f.GetSharedFolderMapping(It.IsAny <string>(), It.IsAny <DownloadStationSettings>())) .Throws(new DownloadClientException("There is no shared folder")); Mocker.GetMock <IFileStationProxy>() .Setup(f => f.GetSharedFolderMapping(_sharedFolder.FullPath, It.IsAny <DownloadStationSettings>())) .Returns(new SharedFolderMapping(_sharedFolder.FullPath, _physicalPath.FullPath)); }
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = null) { httpVerb ??= HttpMethod.Get; var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}"); requestBuilder.Method = httpVerb; requestBuilder.LogResponseContent = true; requestBuilder.SuppressHttpError = true; requestBuilder.AllowAutoRedirect = false; requestBuilder.Headers.ContentType = "application/json"; if (apiVersion < apiInfo.MinVersion || apiVersion > apiInfo.MaxVersion) { throw new ArgumentOutOfRangeException(nameof(apiVersion)); } if (httpVerb == HttpMethod.Post) { if (apiInfo.NeedsAuthentication) { if (_apiType == DiskStationApi.DownloadStation2Task) { requestBuilder.AddQueryParam("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6))); } else { requestBuilder.AddFormParameter("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6))); } } requestBuilder.AddFormParameter("api", apiInfo.Name); requestBuilder.AddFormParameter("version", apiVersion); requestBuilder.AddFormParameter("method", methodName); } else { if (apiInfo.NeedsAuthentication) { requestBuilder.AddQueryParam("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6))); } requestBuilder.AddQueryParam("api", apiInfo.Name); requestBuilder.AddQueryParam("version", apiVersion); requestBuilder.AddQueryParam("method", methodName); } return(requestBuilder); }
public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings) { var arguments = new Dictionary <string, object> { { "api", "SYNO.FileStation.List" }, { "version", "2" }, { "method", "getinfo" }, { "path", new [] { path }.ToJson() }, { "additional", $"[\"real_path\"]" } }; var response = ProcessRequest <FileStationListResponse>(DiskStationApi.FileStationList, arguments, settings, $"get info of {path}"); return(response.Data.Files.First()); }
private string AuthenticateClient(DownloadStationSettings settings) { var authInfo = GetApiInfo(DiskStationApi.Auth, settings); var requestBuilder = BuildRequest(settings, authInfo, "login", 2); requestBuilder.AddQueryParam("account", settings.Username); requestBuilder.AddQueryParam("passwd", settings.Password); requestBuilder.AddQueryParam("format", "sid"); requestBuilder.AddQueryParam("session", "DownloadStation"); var authResponse = ProcessRequest <DiskStationAuthResponse>(requestBuilder, "login", DiskStationApi.Auth, settings); return(authResponse.Data.SId); }
private HttpRequest BuildRequest(DownloadStationSettings settings, DiskStationApi api, Dictionary <string, object> arguments, HttpMethod method) { if (!Resources.ContainsKey(api)) { GetApiVersion(settings, api); } var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{Resources[api]}"); requestBuilder.Method = method; requestBuilder.LogResponseContent = true; requestBuilder.SuppressHttpError = true; requestBuilder.AllowAutoRedirect = false; if (requestBuilder.Method == HttpMethod.POST) { if (api == DiskStationApi.DownloadStationTask && arguments.ContainsKey("file")) { requestBuilder.Headers.ContentType = "multipart/form-data"; foreach (var arg in arguments) { if (arg.Key == "file") { Dictionary <string, object> file = (Dictionary <string, object>)arg.Value; requestBuilder.AddFormUpload(arg.Key, file["name"].ToString(), (byte[])file["data"]); } else { requestBuilder.AddFormParameter(arg.Key, arg.Value); } } } else { requestBuilder.Headers.ContentType = "application/json"; } } else { foreach (var arg in arguments) { requestBuilder.AddQueryParam(arg.Key, arg.Value); } } return(requestBuilder.Build()); }
private IDownloadStationTaskProxy FetchProxy(DownloadStationSettings settings) { if (_proxyV2.IsApiSupported(settings)) { _logger.Trace("Using DownloadStation Task API v2"); return(_proxyV2); } if (_proxyV1.IsApiSupported(settings)) { _logger.Trace("Using DownloadStation Task API v1"); return(_proxyV1); } throw new DownloadClientException("Unable to determine DownloadStations Task API version"); }
protected IEnumerable <int> GetApiVersion(DownloadStationSettings settings, DiskStationApi api) { var arguments = new Dictionary <string, object> { { "api", "SYNO.API.Info" }, { "version", "1" }, { "method", "query" }, { "query", "SYNO.API.Auth, SYNO.DownloadStation.Info, SYNO.DownloadStation.Task, SYNO.FileStation.List, SYNO.DSM.Info" }, }; var infoResponse = ProcessRequest <DiskStationApiInfoResponse>(DiskStationApi.Info, arguments, settings, "Get api version"); //TODO: Refactor this into more elegant code var infoResponeDSAuth = infoResponse.Data["SYNO.API.Auth"]; var infoResponeDSInfo = infoResponse.Data["SYNO.DownloadStation.Info"]; var infoResponeDSTask = infoResponse.Data["SYNO.DownloadStation.Task"]; var infoResponseFSList = infoResponse.Data["SYNO.FileStation.List"]; var infoResponseDSMInfo = infoResponse.Data["SYNO.DSM.Info"]; Resources[DiskStationApi.Auth] = infoResponeDSAuth.Path; Resources[DiskStationApi.DownloadStationInfo] = infoResponeDSInfo.Path; Resources[DiskStationApi.DownloadStationTask] = infoResponeDSTask.Path; Resources[DiskStationApi.FileStationList] = infoResponseFSList.Path; Resources[DiskStationApi.DSMInfo] = infoResponseDSMInfo.Path; switch (api) { case DiskStationApi.Auth: return(Enumerable.Range(infoResponeDSAuth.MinVersion, infoResponeDSAuth.MaxVersion - infoResponeDSAuth.MinVersion + 1)); case DiskStationApi.DownloadStationInfo: return(Enumerable.Range(infoResponeDSInfo.MinVersion, infoResponeDSInfo.MaxVersion - infoResponeDSInfo.MinVersion + 1)); case DiskStationApi.DownloadStationTask: return(Enumerable.Range(infoResponeDSTask.MinVersion, infoResponeDSTask.MaxVersion - infoResponeDSTask.MinVersion + 1)); case DiskStationApi.FileStationList: return(Enumerable.Range(infoResponseFSList.MinVersion, infoResponseFSList.MaxVersion - infoResponseFSList.MinVersion + 1)); case DiskStationApi.DSMInfo: return(Enumerable.Range(infoResponseDSMInfo.MinVersion, infoResponseDSMInfo.MaxVersion - infoResponseDSMInfo.MinVersion + 1)); default: throw new DownloadClientException("Api not implemented"); } }
public IEnumerable <DownloadStationTask> GetTasks(DownloadStationSettings settings) { try { var requestBuilder = BuildRequest(settings, "list", 1); requestBuilder.AddQueryParam("additional", "detail,transfer"); var response = ProcessRequest <DownloadStationTaskInfoResponse>(requestBuilder, "get tasks", settings); return(response.Data.Tasks); } catch (DownloadClientException e) { _logger.Error(e); return(new List <DownloadStationTask>()); } }
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings) { var arguments = new Dictionary <string, object> { { "api", "SYNO.DownloadStation.Task" }, { "version", "3" }, { "method", "create" }, { "uri", url } }; if (downloadDirectory.IsNotNullOrWhiteSpace()) { arguments.Add("destination", downloadDirectory); } var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from url {url}"); }
private DiskStationResponse <T> ProcessRequest <T>(HttpRequestBuilder requestBuilder, string operation, DiskStationApi api, DownloadStationSettings settings) where T : new() { var request = requestBuilder.Build(); var response = _httpClient.Execute(request); _logger.Debug("Trying to {0}", operation); if (response.StatusCode == HttpStatusCode.OK) { var responseContent = Json.Deserialize <DiskStationResponse <T> >(response.Content); if (responseContent.Success) { return(responseContent); } else { var msg = $"Failed to {operation}. Reason: {responseContent.Error.GetMessage(api)}"; _logger.Error(msg); if (responseContent.Error.SessionError) { _sessionCache.Remove(GenerateSessionCacheKey(settings)); if (responseContent.Error.Code == 105) { throw new DownloadClientAuthenticationException(msg); } } throw new DownloadClientException(msg); } } else { throw new HttpException(request, response); } }