]> BookStack Code Mirror - api-scripts/blob - go-export-page-content/export.go
Added community section to readme
[api-scripts] / go-export-page-content / export.go
1 package main
2
3 import (
4         "flag"
5         "fmt"
6         "os"
7         "path/filepath"
8         "time"
9 )
10
11 func main() {
12
13         baseUrlPtr := flag.String("baseurl", "", "The base URL of your BookStack instance")
14         tokenId := flag.String("tokenid", "", "Your BookStack API Token ID")
15         tokenSecret := flag.String("tokensecret", "", "Your BookStack API Token Secret")
16         exportDir := flag.String("exportdir", "./page-export", "The directory to store exported data")
17
18         flag.Parse()
19
20         if *baseUrlPtr == "" || *tokenId == "" || *tokenSecret == "" {
21                 panic("baseurl, tokenid and tokensecret arguments are required")
22         }
23
24         api := NewBookStackApi(*baseUrlPtr, *tokenId, *tokenSecret)
25
26         // Grab all content from BookStack
27         fmt.Println("Fetching books...")
28         bookIdMap := getBookMap(api)
29         fmt.Printf("Fetched %d books\n", len(bookIdMap))
30         fmt.Println("Fetching chapters...")
31         chapterIdMap := getChapterMap(api)
32         fmt.Printf("Fetched %d chapters\n", len(chapterIdMap))
33         fmt.Println("Fetching pages...")
34         pageIdMap := getPageMap(api)
35         fmt.Printf("Fetched %d pages\n", len(pageIdMap))
36
37         // Track progress when going through our pages
38         pageCount := len(pageIdMap)
39         currentCount := 1
40
41         // Cycle through each of our fetches pages
42         for _, p := range pageIdMap {
43                 fmt.Printf("Exporting page %d/%d [%s]\n", currentCount, pageCount, p.Name)
44                 // Get the full page content
45                 fullPage := api.GetPage(p.Id)
46
47                 // Work out a book+chapter relative path
48                 book := bookIdMap[fullPage.BookId]
49                 path := book.Slug
50                 if chapter, ok := chapterIdMap[fullPage.ChapterId]; ok {
51                         path += "/" + chapter.Slug
52                 }
53
54                 // Get the html, or markdown, content from our page along with the file name
55                 // based upon the page slug
56                 content := fullPage.Html
57                 fName := fullPage.Slug + ".html"
58                 if fullPage.Markdown != "" {
59                         content = fullPage.Markdown
60                         fName = fullPage.Slug + ".md"
61                 }
62
63                 // Create our directory path
64                 absExportPath, err := filepath.Abs(*exportDir)
65                 if err != nil {
66                         panic(err)
67                 }
68
69                 absPath := filepath.Join(absExportPath, path)
70                 err = os.MkdirAll(absPath, 0744)
71                 if err != nil {
72                         panic(err)
73                 }
74
75                 // Write the content to the filesystem
76                 fPath := filepath.Join(absPath, fName)
77                 go writeOutPageContent(fPath, content)
78
79                 // Wait to avoid hitting rate limits
80                 time.Sleep(time.Second / 6)
81                 currentCount++
82         }
83
84 }
85
86 func writeOutPageContent(path string, content string) {
87         err := os.WriteFile(path, []byte(content), 0644)
88         if err != nil {
89                 panic(err)
90         }
91 }