package promote import ( "bytes" "fmt" "gitea-page/internal/config" "github.com/rs/zerolog/log" "html/template" "os" "os/exec" "time" ) type Promote struct { Config config.GiteaPagesConfig } type PromoterData struct { Config config.GiteaPagesConfig Repo string Owner string Domain string Path string SSL struct{ Active bool Cert string Key string } } func (p Promote) PromoteRepo(name, owner string) { log.Debug().Str("name", name).Str("owner", owner).Msg("Promote") url := p.getDefaultURL(name, owner) log.Debug().Str("url", url).Msg("Promote URL") content := p.getContent(name, owner, url) updated := p.updateContent(url, content) if updated { p.reloadServer() } log.Debug().Bool("Need to Reload", updated).Msg("File Created") } func (p Promote) reloadServer() { reload, err := exec.Command(p.Config.Promoter.Reload.Name, p.Config.Promoter.Reload.Args...).Output() if err != nil { log.Error().Err(err).Msg("Cant reload Server") } log.Debug().Str("output", string(reload)).Msg("Reloaded Server") } func (p Promote) getSSL(domain, path string) (cert, key string, active bool) { if _, err := os.Stat(p.getCertPath(domain, "cer")); err == nil { return p.getCertPath(domain, "cer"), p.getCertPath(domain, "key"), true } return "", "", false } func (p Promote) requestSSL(domain, path, name, owner string) { log.Debug().Msg("Try to get SSL Zertifikat") output, err := exec.Command("/root/.acme.sh/acme.sh", "--issue", "-d", domain, "-w", path).Output() if err != nil { log.Error().Str("output", string(output)).Err(err).Msg("Cant issue ssl certificat") } else { log.Info().Str("output", string(output)).Msg("Got SSL zertifikat") p.PromoteRepo(name, owner) } } func (p Promote) updateContent(domain, content string) bool { fileName := fmt.Sprintf("%s/%s.conf", p.Config.Promoter.Path, domain) log.Debug().Str("filename", fileName).Msg("Promote to File") if _, err := os.Stat(fileName); err == nil { c, _ := os.ReadFile(fileName) if string(c) == content { return false } } os.WriteFile(fileName, []byte(content), 0644) return true } func (p Promote) getContent(name, owner, domain string) string { templateContent, err := os.ReadFile(p.Config.Promoter.Template) if err != nil { log.Panic().Err(err).Msg("Cant get promoter template") } var b bytes.Buffer templ, err := template.New("").Parse(string(templateContent)) if err != nil { log.Panic().Err(err).Msg("Cant parse Prmoter Template") } path := fmt.Sprintf("%s/%s/%s", p.Config.RootPath, owner, name) promoterData := PromoterData{ Config: p.Config, Repo: name, Owner: owner, Domain: domain, Path: path, } cert, key, active := p.getSSL(domain, path) promoterData.SSL.Active = active promoterData.SSL.Cert = cert promoterData.SSL.Key = key err = templ.Execute(&b, promoterData) if err != nil { log.Panic().Err(err).Msg("Cant parse Promoter Template") } if active == false { go func() { time.Sleep(10*time.Second) p.requestSSL(domain, path, name, owner) }() } return b.String() } func (p Promote) getCertPath(domain, typ string) string { var b bytes.Buffer templ, err := template.New("").Parse(p.Config.Promoter.CertPath) if err != nil { log.Panic().Err(err).Msg("Cant parse Cert Path String") } err = templ.Execute(&b, map[string]interface{}{ "domain": domain, "typ": typ, }) if err != nil { log.Panic().Err(err).Msg("Cant get cert path") } return b.String() } func (p Promote) getDefaultURL(name, owner string) string { log.Debug().Str("domain", p.Config.Domain).Msg("get Default URL") var b bytes.Buffer templ, err := template.New("").Parse(p.Config.Domain) if err != nil { log.Panic().Err(err).Msg("Cant parse Config String") } err = templ.Execute(&b, map[string]interface{}{ "repro": name, "owner": owner, }) if err != nil { log.Panic().Err(err).Msg("Cant get default URL") } return b.String() }