repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

pico / shared
Antonio Mika · 22 Nov 24

config.go

  1package shared
  2
  3import (
  4	"context"
  5	"fmt"
  6	"html/template"
  7	"log/slog"
  8	"net/http"
  9	"net/url"
 10	"os"
 11	"path"
 12	"strings"
 13	"time"
 14
 15	"github.com/picosh/pico/db"
 16	"github.com/picosh/utils"
 17
 18	pipeLogger "github.com/picosh/utils/pipe/log"
 19)
 20
 21var DefaultEmail = "hello@pico.sh"
 22
 23type SitePageData struct {
 24	Domain  template.URL
 25	HomeURL template.URL
 26}
 27
 28type PageData struct {
 29	Site SitePageData
 30}
 31
 32type ConfigSite struct {
 33	Debug              bool
 34	SendgridKey        string
 35	Domain             string
 36	Port               string
 37	PortOverride       string
 38	Protocol           string
 39	DbURL              string
 40	StorageDir         string
 41	MinioURL           string
 42	MinioUser          string
 43	MinioPass          string
 44	Space              string
 45	Issuer             string
 46	Secret             string
 47	SecretWebhook      string
 48	AllowedExt         []string
 49	HiddenPosts        []string
 50	MaxSize            uint64
 51	MaxAssetSize       int64
 52	MaxSpecialFileSize int64
 53	Logger             *slog.Logger
 54}
 55
 56func NewConfigSite() *ConfigSite {
 57	return &ConfigSite{}
 58}
 59
 60type CreateURL struct {
 61	Subdomain       bool
 62	UsernameInRoute bool
 63	HostDomain      string
 64	AppDomain       string
 65	Username        string
 66	Cfg             *ConfigSite
 67}
 68
 69func NewCreateURL(cfg *ConfigSite) *CreateURL {
 70	return &CreateURL{
 71		Cfg:       cfg,
 72		Subdomain: cfg.IsSubdomains(),
 73	}
 74}
 75
 76func CreateURLFromRequest(cfg *ConfigSite, r *http.Request) *CreateURL {
 77	hostDomain := strings.Split(r.Host, ":")[0]
 78	appDomain := strings.Split(cfg.Domain, ":")[0]
 79
 80	onSubdomain := cfg.IsSubdomains() && strings.Contains(hostDomain, appDomain)
 81	withUserName := !cfg.IsCustomdomains() || (!onSubdomain && hostDomain == appDomain)
 82
 83	return &CreateURL{
 84		Cfg:             cfg,
 85		AppDomain:       appDomain,
 86		HostDomain:      hostDomain,
 87		Subdomain:       onSubdomain,
 88		UsernameInRoute: withUserName,
 89	}
 90}
 91
 92func (c *ConfigSite) GetSiteData() *SitePageData {
 93	return &SitePageData{
 94		Domain:  template.URL(c.Domain),
 95		HomeURL: template.URL(c.HomeURL()),
 96	}
 97}
 98
 99func (c *ConfigSite) IsSubdomains() bool {
100	return true
101}
102
103func (c *ConfigSite) IsCustomdomains() bool {
104	return true
105}
106
107func (c *ConfigSite) HomeURL() string {
108	if c.IsSubdomains() || c.IsCustomdomains() {
109		return fmt.Sprintf("//%s", c.Domain)
110	}
111
112	return "/"
113}
114
115func (c *ConfigSite) ReadURL() string {
116	if c.IsSubdomains() || c.IsCustomdomains() {
117		return fmt.Sprintf("%s://%s", c.Protocol, c.Domain)
118	}
119
120	return "/"
121}
122
123func (c *ConfigSite) StaticPath(fname string) string {
124	return path.Join(c.Space, fname)
125}
126
127func (c *ConfigSite) BlogURL(username string) string {
128	if c.IsSubdomains() {
129		return fmt.Sprintf("%s://%s.%s", c.Protocol, username, c.Domain)
130	}
131
132	return fmt.Sprintf("/%s", username)
133}
134
135func (c *ConfigSite) CssURL(username string) string {
136	if c.IsSubdomains() || c.IsCustomdomains() {
137		return "/_styles.css"
138	}
139
140	return fmt.Sprintf("/%s/styles.css", username)
141}
142
143func (c *ConfigSite) PostURL(username, slug string) string {
144	fname := url.PathEscape(slug)
145	if c.IsSubdomains() {
146		return fmt.Sprintf("%s://%s.%s/%s", c.Protocol, username, c.Domain, fname)
147	}
148
149	return fmt.Sprintf("/%s/%s", username, fname)
150
151}
152
153func (c *ConfigSite) RawPostURL(username, slug string) string {
154	fname := url.PathEscape(slug)
155	if c.IsSubdomains() {
156		return fmt.Sprintf("%s://%s.%s/raw/%s", c.Protocol, username, c.Domain, fname)
157	}
158
159	return fmt.Sprintf("/raw/%s/%s", username, fname)
160}
161
162func (c *ConfigSite) ImgFullURL(username, slug string) string {
163	fname := url.PathEscape(strings.TrimLeft(slug, "/"))
164	return fmt.Sprintf("%s://%s.%s/%s", c.Protocol, username, c.Domain, fname)
165}
166
167func (c *ConfigSite) FullBlogURL(curl *CreateURL, username string) string {
168	if c.IsSubdomains() && curl.Subdomain {
169		return fmt.Sprintf("%s://%s.%s", c.Protocol, username, c.Domain)
170	}
171
172	if curl.UsernameInRoute {
173		return fmt.Sprintf("/%s", username)
174	}
175
176	return fmt.Sprintf("%s://%s", c.Protocol, curl.HostDomain)
177}
178
179func (c *ConfigSite) FullPostURL(curl *CreateURL, username, slug string) string {
180	fname := url.PathEscape(strings.TrimLeft(slug, "/"))
181
182	if curl.Subdomain && c.IsSubdomains() {
183		return fmt.Sprintf("%s://%s.%s/%s", c.Protocol, username, c.Domain, fname)
184	}
185
186	if curl.UsernameInRoute {
187		return fmt.Sprintf("%s://%s/%s/%s", c.Protocol, c.Domain, username, fname)
188	}
189
190	return fmt.Sprintf("%s://%s/%s", c.Protocol, curl.HostDomain, fname)
191}
192
193func (c *ConfigSite) RssBlogURL(curl *CreateURL, username, tag string) string {
194	url := ""
195	if c.IsSubdomains() && curl.Subdomain {
196		url = fmt.Sprintf("%s://%s.%s/rss", c.Protocol, username, c.Domain)
197	} else if curl.UsernameInRoute {
198		url = fmt.Sprintf("/%s/rss", username)
199	} else {
200		url = "/rss"
201	}
202
203	if tag != "" {
204		return fmt.Sprintf("%s?tag=%s", url, tag)
205	}
206
207	return url
208}
209
210func (c *ConfigSite) ImgURL(curl *CreateURL, username string, slug string) string {
211	fname := url.PathEscape(strings.TrimLeft(slug, "/"))
212	if c.IsSubdomains() && curl.Subdomain {
213		return fmt.Sprintf("%s://%s.%s/%s", c.Protocol, username, c.Domain, fname)
214	}
215
216	if curl.UsernameInRoute {
217		return fmt.Sprintf("/%s/%s", username, fname)
218	}
219
220	return fmt.Sprintf("/%s", fname)
221}
222
223func (c *ConfigSite) ImgPostURL(curl *CreateURL, username string, slug string) string {
224	fname := url.PathEscape(strings.TrimLeft(slug, "/"))
225	if c.IsSubdomains() && curl.Subdomain {
226		return fmt.Sprintf("%s://%s.%s/p/%s", c.Protocol, username, c.Domain, fname)
227	}
228
229	if curl.UsernameInRoute {
230		return fmt.Sprintf("/%s/p/%s", username, fname)
231	}
232
233	return fmt.Sprintf("/p/%s", fname)
234}
235
236func (c *ConfigSite) ImgOrigURL(curl *CreateURL, username string, slug string) string {
237	fname := url.PathEscape(strings.TrimLeft(slug, "/"))
238	if c.IsSubdomains() && curl.Subdomain {
239		return fmt.Sprintf("%s://%s.%s/o/%s", c.Protocol, username, c.Domain, fname)
240	}
241
242	if curl.UsernameInRoute {
243		return fmt.Sprintf("/%s/o/%s", username, fname)
244	}
245
246	return fmt.Sprintf("/o/%s", fname)
247}
248
249func (c *ConfigSite) TagURL(curl *CreateURL, username, tag string) string {
250	tg := url.PathEscape(tag)
251	return fmt.Sprintf("%s?tag=%s", c.FullBlogURL(curl, username), tg)
252}
253
254func (c *ConfigSite) AssetURL(username, projectName, fpath string) string {
255	if username == projectName {
256		return fmt.Sprintf(
257			"%s://%s.%s/%s",
258			c.Protocol,
259			username,
260			c.Domain,
261			fpath,
262		)
263	}
264
265	return fmt.Sprintf(
266		"%s://%s-%s.%s/%s",
267		c.Protocol,
268		username,
269		projectName,
270		c.Domain,
271		fpath,
272	)
273}
274
275func CreateLogger(space string) *slog.Logger {
276	opts := &slog.HandlerOptions{
277		AddSource: true,
278	}
279	log := slog.New(
280		slog.NewTextHandler(os.Stdout, opts),
281	)
282
283	newLogger := log
284
285	if strings.ToLower(utils.GetEnv("PICO_PIPE_ENABLED", "true")) == "true" {
286		conn := NewPicoPipeClient()
287		newLogger = pipeLogger.RegisterReconnectLogger(context.Background(), log, conn, 100, 10*time.Millisecond)
288	}
289
290	return newLogger.With("service", space)
291}
292
293func LoggerWithUser(logger *slog.Logger, user *db.User) *slog.Logger {
294	return logger.With("user", user.Name, "userId", user.ID)
295}