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