replace zxq.co/ripple/hanayo
This commit is contained in:
134
modules/doc/documentation.go
Normal file
134
modules/doc/documentation.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package doc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const referenceLanguage = "en"
|
||||
|
||||
var docFiles []Document
|
||||
|
||||
// File represents the single documentation file of a determined language.
|
||||
type File struct {
|
||||
IsUpdated bool
|
||||
Title string
|
||||
referencesFile string
|
||||
}
|
||||
|
||||
// Data retrieves data from file's actual file on disk.
|
||||
func (f File) Data() (string, error) {
|
||||
data, err := ioutil.ReadFile(f.referencesFile)
|
||||
updateIPs()
|
||||
res := strings.NewReplacer(
|
||||
"{ipmain}", ipMain,
|
||||
"{ipmirror}", ipMirror,
|
||||
).Replace(string(data))
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Document represents a documentation file, providing its old ID, its slug,
|
||||
// and all its variations in the various languages.
|
||||
type Document struct {
|
||||
Slug string
|
||||
OldID int
|
||||
Languages map[string]File
|
||||
}
|
||||
|
||||
// File retrieves a Document's File based on the passed language, and returns
|
||||
// the values for the referenceLanguage (en) if in the passed language they are
|
||||
// not available
|
||||
func (d Document) File(lang string) File {
|
||||
if vals, ok := d.Languages[lang]; ok {
|
||||
return vals
|
||||
}
|
||||
return d.Languages[referenceLanguage]
|
||||
}
|
||||
|
||||
// LanguageDoc has the only purpose to be returned by GetDocs.
|
||||
type LanguageDoc struct {
|
||||
Title string
|
||||
Slug string
|
||||
}
|
||||
|
||||
// GetDocs retrieves a list of documents in a certain language, with titles and
|
||||
// slugs.
|
||||
func GetDocs(lang string) []LanguageDoc {
|
||||
var docs []LanguageDoc
|
||||
|
||||
for _, file := range docFiles {
|
||||
docs = append(docs, LanguageDoc{
|
||||
Slug: file.Slug,
|
||||
Title: file.File(lang).Title,
|
||||
})
|
||||
}
|
||||
|
||||
return docs
|
||||
}
|
||||
|
||||
// SlugFromOldID gets a doc file's slug from its old ID
|
||||
func SlugFromOldID(i int) string {
|
||||
for _, d := range docFiles {
|
||||
if d.OldID == i {
|
||||
return d.Slug
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetFile retrieves a file, given a slug and a language.
|
||||
func GetFile(slug, language string) File {
|
||||
for _, f := range docFiles {
|
||||
if f.Slug != slug {
|
||||
continue
|
||||
}
|
||||
if val, ok := f.Languages[language]; ok {
|
||||
return val
|
||||
}
|
||||
return f.Languages[referenceLanguage]
|
||||
}
|
||||
return File{}
|
||||
}
|
||||
|
||||
var (
|
||||
ipMain = "163.172.71.251"
|
||||
ipMirror = "51.15.222.176"
|
||||
ipLastUpdated = time.Date(2018, 5, 13, 11, 45, 0, 0, time.UTC)
|
||||
ipRegex = regexp.MustCompile(`^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$`)
|
||||
)
|
||||
|
||||
func updateIPs() {
|
||||
if time.Now().Sub(ipLastUpdated) < time.Hour*24*14 {
|
||||
return
|
||||
}
|
||||
ipLastUpdated = time.Now()
|
||||
|
||||
resp, err := http.Get("https://ip.ripple.moe")
|
||||
if err != nil {
|
||||
fmt.Println("error updating IPs", err)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Println("error updating IPs", err)
|
||||
return
|
||||
}
|
||||
|
||||
ips := strings.SplitN(string(data), "\n", 3)
|
||||
if len(ips) < 2 || !ipRegex.MatchString(ips[0]) || !ipRegex.MatchString(ips[1]) {
|
||||
return
|
||||
}
|
||||
ipMain = ips[0]
|
||||
ipMirror = ips[1]
|
||||
}
|
||||
|
||||
func init() {
|
||||
go updateIPs()
|
||||
}
|
137
modules/doc/loader.go
Normal file
137
modules/doc/loader.go
Normal file
@@ -0,0 +1,137 @@
|
||||
// Package doc handles documentation.
|
||||
package doc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// When we start the program, we should load the documentation files.
|
||||
err := loadDocFiles()
|
||||
if err != nil {
|
||||
fmt.Println("error while loading documentation:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// rawFile represents the data that may be provided at the top of files.
|
||||
type rawFile struct {
|
||||
Title string `yaml:"title"`
|
||||
OldID int `yaml:"old_id"`
|
||||
ReferenceVersion string `yaml:"reference_version"`
|
||||
}
|
||||
|
||||
func loadDocFiles() error {
|
||||
langs, err := loadLanguagesAvailable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir("website-docs/" + referenceLanguage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
data, err := ioutil.ReadFile("website-docs/" + referenceLanguage + "/" + file.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header := loadHeader(data)
|
||||
md5sum := fmt.Sprintf("%x", md5.Sum(data))
|
||||
|
||||
doc := Document{
|
||||
OldID: header.OldID,
|
||||
Slug: strings.TrimSuffix(file.Name(), ".md"),
|
||||
}
|
||||
|
||||
doc.Languages, err = loadLanguages(langs, file.Name(), md5sum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
docFiles = append(docFiles, doc)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadHeader(b []byte) rawFile {
|
||||
s := bufio.NewScanner(bytes.NewReader(b))
|
||||
var (
|
||||
isConf bool
|
||||
conf string
|
||||
)
|
||||
|
||||
for s.Scan() {
|
||||
line := s.Text()
|
||||
if !isConf {
|
||||
if line == "---" {
|
||||
isConf = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
if line == "---" {
|
||||
break
|
||||
}
|
||||
conf += line + "\n"
|
||||
}
|
||||
|
||||
var f rawFile
|
||||
err := yaml.Unmarshal([]byte(conf), &f)
|
||||
if err != nil {
|
||||
fmt.Println("Error unmarshaling yaml:", err)
|
||||
return rawFile{}
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func loadLanguagesAvailable() ([]string, error) {
|
||||
files, err := ioutil.ReadDir("website-docs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
langs := make([]string, 0, len(files))
|
||||
for _, f := range files {
|
||||
if !f.IsDir() {
|
||||
continue
|
||||
}
|
||||
langs = append(langs, f.Name())
|
||||
}
|
||||
|
||||
return langs, nil
|
||||
}
|
||||
|
||||
func loadLanguages(langs []string, fname string, referenceMD5 string) (map[string]File, error) {
|
||||
m := make(map[string]File, len(langs))
|
||||
|
||||
for _, lang := range langs {
|
||||
data, err := ioutil.ReadFile("website-docs/" + lang + "/" + fname)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header := loadHeader(data)
|
||||
|
||||
m[lang] = File{
|
||||
IsUpdated: lang == referenceLanguage || header.ReferenceVersion == referenceMD5,
|
||||
Title: header.Title,
|
||||
referencesFile: "website-docs/" + lang + "/" + fname,
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
Reference in New Issue
Block a user