2022-08-03 14:55:48 +00:00
|
|
|
package owl
|
2022-07-20 17:17:42 +00:00
|
|
|
|
|
|
|
import (
|
2022-07-23 07:11:25 +00:00
|
|
|
_ "embed"
|
2022-07-20 17:17:42 +00:00
|
|
|
"fmt"
|
2022-07-24 18:29:31 +00:00
|
|
|
"io/ioutil"
|
2022-07-20 17:17:42 +00:00
|
|
|
"os"
|
|
|
|
"path"
|
2022-07-27 19:53:56 +00:00
|
|
|
|
|
|
|
"gopkg.in/yaml.v2"
|
2022-07-20 17:17:42 +00:00
|
|
|
)
|
|
|
|
|
2022-07-24 13:34:52 +00:00
|
|
|
//go:embed embed/initial/base.html
|
2022-07-23 07:11:25 +00:00
|
|
|
var base_template string
|
2022-07-24 13:34:52 +00:00
|
|
|
|
2022-07-23 13:17:14 +00:00
|
|
|
var VERSION = "0.0.1"
|
2022-07-23 07:11:25 +00:00
|
|
|
|
2022-07-20 17:17:42 +00:00
|
|
|
type Repository struct {
|
2022-09-05 18:50:46 +00:00
|
|
|
name string
|
|
|
|
HttpClient HttpClient
|
|
|
|
Parser HtmlParser
|
2022-07-20 17:17:42 +00:00
|
|
|
}
|
|
|
|
|
2022-08-13 13:32:26 +00:00
|
|
|
type RepoConfig struct {
|
2022-09-05 18:50:46 +00:00
|
|
|
Domain string `yaml:"domain"`
|
|
|
|
SingleUser string `yaml:"single_user"`
|
|
|
|
AllowRawHtml bool `yaml:"allow_raw_html"`
|
2022-08-13 13:32:26 +00:00
|
|
|
}
|
|
|
|
|
2022-09-05 18:50:46 +00:00
|
|
|
func CreateRepository(name string, config RepoConfig) (Repository, error) {
|
2022-09-06 18:32:21 +00:00
|
|
|
newRepo := Repository{name: name, Parser: OwlHtmlParser{}, HttpClient: &OwlHttpClient{}}
|
2022-07-20 17:17:42 +00:00
|
|
|
// check if repository already exists
|
2022-07-20 17:33:22 +00:00
|
|
|
if dirExists(newRepo.Dir()) {
|
2022-07-20 17:17:42 +00:00
|
|
|
return Repository{}, fmt.Errorf("Repository already exists")
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:34:52 +00:00
|
|
|
os.Mkdir(newRepo.Dir(), 0755)
|
|
|
|
os.Mkdir(newRepo.UsersDir(), 0755)
|
|
|
|
os.Mkdir(newRepo.StaticDir(), 0755)
|
|
|
|
|
2022-09-05 18:50:46 +00:00
|
|
|
// create config file
|
|
|
|
if config.Domain == "" {
|
|
|
|
config.Domain = "http://localhost:8080"
|
|
|
|
}
|
|
|
|
config_data, _ := yaml.Marshal(config)
|
|
|
|
os.WriteFile(path.Join(newRepo.Dir(), "config.yml"), config_data, 0644)
|
|
|
|
|
2022-07-24 13:34:52 +00:00
|
|
|
// copy all files from static_files embed.FS to StaticDir
|
2022-08-18 19:06:01 +00:00
|
|
|
staticFiles, _ := embed_files.ReadDir("embed/initial/static")
|
2022-07-24 13:34:52 +00:00
|
|
|
for _, file := range staticFiles {
|
|
|
|
if file.IsDir() {
|
|
|
|
continue
|
|
|
|
}
|
2022-08-18 19:06:01 +00:00
|
|
|
src_data, _ := embed_files.ReadFile("embed/initial/static/" + file.Name())
|
2022-07-24 13:34:52 +00:00
|
|
|
os.WriteFile(newRepo.StaticDir()+"/"+file.Name(), src_data, 0644)
|
|
|
|
}
|
2022-07-24 18:29:31 +00:00
|
|
|
|
2022-08-13 13:32:26 +00:00
|
|
|
// copy repo/ to newRepo.Dir()
|
2022-08-18 19:06:01 +00:00
|
|
|
init_files, _ := embed_files.ReadDir("embed/initial/repo")
|
2022-08-13 13:32:26 +00:00
|
|
|
for _, file := range init_files {
|
|
|
|
if file.IsDir() {
|
|
|
|
continue
|
|
|
|
}
|
2022-08-18 19:06:01 +00:00
|
|
|
src_data, _ := embed_files.ReadFile("embed/initial/repo/" + file.Name())
|
2022-08-13 13:32:26 +00:00
|
|
|
os.WriteFile(newRepo.Dir()+"/"+file.Name(), src_data, 0644)
|
|
|
|
}
|
2022-07-20 17:33:22 +00:00
|
|
|
return newRepo, nil
|
2022-07-20 17:17:42 +00:00
|
|
|
}
|
|
|
|
|
2022-07-23 07:00:10 +00:00
|
|
|
func OpenRepository(name string) (Repository, error) {
|
|
|
|
|
2022-09-06 18:32:21 +00:00
|
|
|
repo := Repository{name: name, Parser: OwlHtmlParser{}, HttpClient: &OwlHttpClient{}}
|
2022-07-23 07:00:10 +00:00
|
|
|
if !dirExists(repo.Dir()) {
|
2022-07-23 15:19:47 +00:00
|
|
|
return Repository{}, fmt.Errorf("Repository does not exist: " + repo.Dir())
|
2022-07-23 07:00:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return repo, nil
|
2022-08-03 18:34:42 +00:00
|
|
|
}
|
2022-07-23 07:00:10 +00:00
|
|
|
|
2022-07-20 17:17:42 +00:00
|
|
|
func (repo Repository) Dir() string {
|
|
|
|
return repo.name
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:34:52 +00:00
|
|
|
func (repo Repository) StaticDir() string {
|
|
|
|
return path.Join(repo.Dir(), "static")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (repo Repository) UsersDir() string {
|
|
|
|
return path.Join(repo.Dir(), "users")
|
|
|
|
}
|
|
|
|
|
2022-08-03 18:34:42 +00:00
|
|
|
func (repo Repository) UserUrlPath(user User) string {
|
2022-09-05 18:50:46 +00:00
|
|
|
config, _ := repo.Config()
|
|
|
|
if config.SingleUser != "" {
|
2022-08-03 18:34:42 +00:00
|
|
|
return "/"
|
|
|
|
}
|
|
|
|
return "/user/" + user.name + "/"
|
|
|
|
}
|
|
|
|
|
2022-08-13 16:47:27 +00:00
|
|
|
func (repo Repository) FullUrl() string {
|
2022-08-13 13:32:26 +00:00
|
|
|
config, _ := repo.Config()
|
2022-08-13 16:47:27 +00:00
|
|
|
return config.Domain
|
2022-08-13 13:32:26 +00:00
|
|
|
}
|
|
|
|
|
2022-07-24 18:29:31 +00:00
|
|
|
func (repo Repository) Template() (string, error) {
|
|
|
|
// load base.html
|
|
|
|
path := path.Join(repo.Dir(), "base.html")
|
|
|
|
base_html, err := ioutil.ReadFile(path)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return string(base_html), nil
|
|
|
|
}
|
|
|
|
|
2022-07-20 17:35:31 +00:00
|
|
|
func (repo Repository) Users() ([]User, error) {
|
2022-09-05 18:50:46 +00:00
|
|
|
config, _ := repo.Config()
|
|
|
|
if config.SingleUser != "" {
|
|
|
|
return []User{{repo: &repo, name: config.SingleUser}}, nil
|
2022-08-03 18:34:42 +00:00
|
|
|
}
|
|
|
|
|
2022-07-24 14:19:21 +00:00
|
|
|
userNames := listDir(repo.UsersDir())
|
2022-07-20 17:35:31 +00:00
|
|
|
users := make([]User, len(userNames))
|
|
|
|
for i, name := range userNames {
|
2022-08-05 20:04:03 +00:00
|
|
|
users[i] = User{repo: &repo, name: name}
|
2022-07-20 17:35:31 +00:00
|
|
|
}
|
|
|
|
return users, nil
|
2022-07-20 17:17:42 +00:00
|
|
|
}
|
|
|
|
|
2022-08-05 20:04:03 +00:00
|
|
|
func (repo *Repository) CreateUser(name string) (User, error) {
|
2022-07-20 17:17:42 +00:00
|
|
|
new_user := User{repo: repo, name: name}
|
|
|
|
// check if user already exists
|
2022-07-20 17:33:22 +00:00
|
|
|
if dirExists(new_user.Dir()) {
|
2022-07-20 17:17:42 +00:00
|
|
|
return User{}, fmt.Errorf("User already exists")
|
|
|
|
}
|
|
|
|
|
|
|
|
// creates repo/name folder if it doesn't exist
|
|
|
|
user_dir := new_user.Dir()
|
|
|
|
os.Mkdir(user_dir, 0755)
|
|
|
|
os.Mkdir(path.Join(user_dir, "meta"), 0755)
|
|
|
|
// create public folder
|
|
|
|
os.Mkdir(path.Join(user_dir, "public"), 0755)
|
|
|
|
|
|
|
|
// create Meta files
|
2022-07-23 13:17:14 +00:00
|
|
|
os.WriteFile(path.Join(user_dir, "meta", "VERSION"), []byte(VERSION), 0644)
|
2022-07-21 17:44:07 +00:00
|
|
|
os.WriteFile(path.Join(user_dir, "meta", "base.html"), []byte(base_template), 0644)
|
2022-07-20 17:17:42 +00:00
|
|
|
|
2022-07-27 19:53:56 +00:00
|
|
|
meta, _ := yaml.Marshal(UserConfig{
|
|
|
|
Title: name,
|
|
|
|
SubTitle: "",
|
|
|
|
HeaderColor: "#bdd6be",
|
|
|
|
})
|
|
|
|
os.WriteFile(new_user.ConfigFile(), meta, 0644)
|
|
|
|
|
2022-07-20 17:17:42 +00:00
|
|
|
return new_user, nil
|
|
|
|
}
|
2022-07-23 15:19:47 +00:00
|
|
|
|
|
|
|
func (repo Repository) GetUser(name string) (User, error) {
|
2022-08-05 20:04:03 +00:00
|
|
|
user := User{repo: &repo, name: name}
|
2022-07-23 15:19:47 +00:00
|
|
|
if !dirExists(user.Dir()) {
|
|
|
|
return User{}, fmt.Errorf("User does not exist")
|
|
|
|
}
|
|
|
|
return user, nil
|
|
|
|
}
|
2022-08-06 17:38:13 +00:00
|
|
|
|
|
|
|
func (repo Repository) PostAliases() (map[string]*Post, error) {
|
|
|
|
users, err := repo.Users()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
aliases := make(map[string]*Post)
|
|
|
|
for _, user := range users {
|
|
|
|
user_aliases, err := user.PostAliases()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for alias, post := range user_aliases {
|
|
|
|
aliases[alias] = post
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aliases, nil
|
|
|
|
}
|
2022-08-13 13:32:26 +00:00
|
|
|
|
|
|
|
func (repo Repository) Config() (RepoConfig, error) {
|
|
|
|
config_path := path.Join(repo.Dir(), "config.yml")
|
|
|
|
config_data, err := ioutil.ReadFile(config_path)
|
|
|
|
if err != nil {
|
|
|
|
return RepoConfig{}, err
|
|
|
|
}
|
|
|
|
var meta RepoConfig
|
|
|
|
err = yaml.Unmarshal(config_data, &meta)
|
|
|
|
if err != nil {
|
|
|
|
return RepoConfig{}, err
|
|
|
|
}
|
|
|
|
return meta, nil
|
|
|
|
}
|