├── go.mod ├── config.json.example ├── .gitignore ├── Makefile ├── README.md ├── cmd └── retriever │ └── main.go └── pkg └── doccle └── doccle.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jonaswouters/go-doccle 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /config.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "Username": "", 3 | "Password": "" 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | config.json 2 | 3 | doccle-document-retriever 4 | /retriever.exe 5 | /retriever 6 | /.idea 7 | *.pdf 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /usr/bin/env bash 2 | 3 | export PROJECT = go-doccle 4 | 5 | all: retriever-build 6 | 7 | retriever-run: 8 | go run ./cmd/retriever 9 | 10 | retriever-build: 11 | go build ./cmd/retriever 12 | 13 | test: 14 | go test ./... 15 | 16 | run: retriever-run -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | ## What is go-doccle 4 | 5 | In the /pkg/doccle folder, there is a simple library that allows you to get all your documents, get all your new documents, download them and archive them. 6 | 7 | The retriever is a simple implementation of the library that allows you to download and archive your documents. 8 | 9 | ## Simple usage example 10 | 11 | *Make sure you create a configuration file `config.json` with your credentials for doccle.* 12 | 13 | `./retriever -path="~/Desktop/doccledocuments/" -archive -new` 14 | 15 | * The -new parameter only downloads the documents in the new queue 16 | * The -archive parameter will archive the documents after downloading (Only useful in combination with the -new parameter) 17 | * The -path parameter supports the home folder with ~, Make sure to always close with a / 18 | 19 | ## Contributions 20 | 21 | This is only a simple downloader script. It won't get a lot of attention as long as it's working for me. 22 | Any contributions are welcome. 23 | -------------------------------------------------------------------------------- /cmd/retriever/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "github.com/jonaswouters/go-doccle/pkg/doccle" 7 | "os/user" 8 | "strings" 9 | ) 10 | 11 | func main() { 12 | // Parameters 13 | archivePtr := flag.Bool("archive", false, "Archive the downloaded documents") 14 | newPtr := flag.Bool("new", false, "Only download new documents") 15 | pathPtr := flag.String("path", "", "Path where the files should be downloaded") 16 | flag.Parse() 17 | 18 | // Get documents 19 | var configuration = doccle.GetConfiguration() 20 | var documentsResult doccle.DocumentsResult 21 | if *newPtr { 22 | documentsResult = doccle.GetNewDocuments(configuration) 23 | } else { 24 | documentsResult = doccle.GetDocuments(configuration) 25 | } 26 | 27 | // Home folder 28 | usr, _ := user.Current() 29 | dir := usr.HomeDir 30 | path := *pathPtr 31 | if path[:2] == "~/" { 32 | *pathPtr = strings.Replace(*pathPtr, "~", dir, 1) 33 | } 34 | 35 | for _, document := range documentsResult.Documents { 36 | var filename = strings.Join([]string{strings.Replace(document.Name, "/", "-", 999), ".pdf"}, "") 37 | filename = strings.Join([]string{document.Sender.Label, filename}, " - ") 38 | n, err := document.Download(configuration, *pathPtr, filename) 39 | 40 | if err != nil { 41 | fmt.Println("error:", err) 42 | } 43 | 44 | fmt.Printf("Downloaded %s (%d)\n", filename, n) 45 | 46 | if *archivePtr { 47 | fmt.Printf("Archiving document %s\n", filename) 48 | document.Archive(configuration) 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /pkg/doccle/doccle.go: -------------------------------------------------------------------------------- 1 | package doccle 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "os" 10 | "strings" 11 | ) 12 | 13 | const ( 14 | // API_URL Url of the API 15 | API_URL = "https://secure.doccle.be/doccle-euui" 16 | ) 17 | 18 | type ( 19 | DocumentsResult struct { 20 | CurrentPage int `json:"currentPage",xml:"username"` 21 | HasMore bool `json:"hasMore"` 22 | NextPage int `json:"nextPage"` 23 | PageSize int `json:"pageSize"` 24 | PreviousPage interface{} `json:"previousPage"` 25 | Results int `json:"results"` 26 | SortField string `json:"sortField"` 27 | SortFieldType string `json:"sortFieldType"` 28 | SortOrder string `json:"sortOrder"` 29 | TotalPages int `json:"totalPages"` 30 | TotalResults int `json:"totalResults"` 31 | Documents []Document `json:"documents"` 32 | } 33 | 34 | Document struct { 35 | Actions []Action `json:"actions"` 36 | Categories []string `json:"categories"` 37 | ContentURL string `json:"contentUrl"` 38 | CreationDate string `json:"creationDate"` 39 | Name string `json:"name"` 40 | Payment interface{} `json:"payment"` 41 | PresentationType string `json:"presentationType"` 42 | Sender Sender `json:"sender"` 43 | SenderDocumentType string `json:"senderDocumentType"` 44 | ShortName interface{} `json:"shortName"` 45 | URI string `json:"uri"` 46 | } 47 | 48 | Action struct { 49 | Enabled bool `json:"enabled"` 50 | ID int `json:"id"` 51 | Label string `json:"label"` 52 | URL string `json:"url"` 53 | } 54 | 55 | Sender struct { 56 | ID string `json:"id"` 57 | Label string `json:"label"` 58 | } 59 | 60 | EndUser struct { 61 | ID int `json:"id"` 62 | FirstName string `json:"firstName"` 63 | LastName string `json:"lastName"` 64 | } 65 | 66 | Configuration struct { 67 | Username string 68 | Password string 69 | } 70 | ) 71 | 72 | // DoRequest makes a request 73 | func DoRequest(configuration Configuration, url string, method string) *http.Response { 74 | req, err := http.NewRequest(method, url, nil) 75 | 76 | req.SetBasicAuth(configuration.Username, configuration.Password) 77 | client := &http.Client{} 78 | resp, err := client.Do(req) 79 | if err != nil { 80 | panic(err) 81 | } 82 | 83 | return resp 84 | } 85 | 86 | // GetConfiguration retrieves the config.json file and parses it 87 | func GetConfiguration() Configuration { 88 | configuration := Configuration{} 89 | file, _ := os.Open("config.json") 90 | decoder := json.NewDecoder(file) 91 | err := decoder.Decode(&configuration) 92 | if err != nil { 93 | fmt.Println("error:", err) 94 | } 95 | return configuration 96 | } 97 | 98 | // GetDocuments retrieves and returns an DocumentsResult struct 99 | func GetDocuments(configuration Configuration) DocumentsResult { 100 | url := strings.Join([]string{API_URL, "/rest/v1/documents?lang=en&order=DESC&page=1&pageSize=50&sort=date"}, "") 101 | 102 | var resp = DoRequest(configuration, url, "GET") 103 | defer resp.Body.Close() 104 | 105 | var data = DocumentsResult{} 106 | 107 | dec := json.NewDecoder(resp.Body) 108 | if err := dec.Decode(&data); err != nil { 109 | log.Println(err) 110 | } 111 | 112 | return data 113 | } 114 | 115 | // GetNewDocuments retrieves and returns an DocumentsResult struct with new documents only 116 | func GetNewDocuments(configuration Configuration) DocumentsResult { 117 | url := strings.Join([]string{API_URL, "/rest/v1/documents/new?lang=en&order=DESC&page=1&pageSize=50&sort=date"}, "") 118 | 119 | var resp = DoRequest(configuration, url, "GET") 120 | defer resp.Body.Close() 121 | 122 | var data = DocumentsResult{} 123 | 124 | dec := json.NewDecoder(resp.Body) 125 | if err := dec.Decode(&data); err != nil { 126 | log.Println(err) 127 | } 128 | 129 | return data 130 | } 131 | 132 | // Download the document's file 133 | func (document Document) Download(configuration Configuration, path string, filename string) (int64, error) { 134 | url := strings.Join([]string{API_URL, document.ContentURL}, "") 135 | var resp = DoRequest(configuration, url, "GET") 136 | defer resp.Body.Close() 137 | 138 | out, err := os.Create(strings.Join([]string{path, filename}, "")) 139 | defer out.Close() 140 | 141 | if err != nil { 142 | return 0, err 143 | } 144 | 145 | n, err := io.Copy(out, resp.Body) 146 | 147 | return n, err 148 | } 149 | 150 | // Archive the document 151 | func (document Document) Archive(configuration Configuration) { 152 | for _, action := range document.Actions { 153 | if action.Label == "ARCHIVE" { 154 | url := strings.Join([]string{API_URL, action.URL}, "") 155 | var resp = DoRequest(configuration, url, "PUT") 156 | defer resp.Body.Close() 157 | } 158 | } 159 | } 160 | --------------------------------------------------------------------------------