Fix unread notification indicator
[bloat] / main.go
1 package main
2
3 import (
4         "errors"
5         "fmt"
6         "log"
7         "net"
8         "net/http"
9         "os"
10         "path/filepath"
11         "strings"
12         "time"
13
14         "bloat/config"
15         "bloat/renderer"
16         "bloat/repo"
17         "bloat/service"
18         "bloat/util"
19 )
20
21 var (
22         configFile = "/etc/bloat.conf"
23 )
24
25 func errExit(err error) {
26         fmt.Fprintln(os.Stderr, err.Error())
27         os.Exit(1)
28 }
29
30 func setupHttp() {
31         tr := http.DefaultTransport.(*http.Transport)
32         tr.MaxIdleConnsPerHost = 30
33         tr.MaxIdleConns = 300
34         tr.ForceAttemptHTTP2 = false
35         tr.DialContext = (&net.Dialer{
36                 Timeout:   30 * time.Second,
37                 KeepAlive: 3 * time.Minute,
38                 DualStack: true,
39         }).DialContext
40         client := http.DefaultClient
41         client.Transport = tr
42 }
43
44 func main() {
45         opts, _, err := util.Getopts(os.Args, "f:")
46         if err != nil {
47                 errExit(err)
48         }
49
50         for _, opt := range opts {
51                 switch opt.Option {
52                 case 'f':
53                         configFile = opt.Value
54                 }
55         }
56
57         config, err := config.ParseFile(configFile)
58         if err != nil {
59                 errExit(err)
60         }
61
62         if !config.IsValid() {
63                 errExit(errors.New("invalid config"))
64         }
65
66         templatesGlobPattern := filepath.Join(config.TemplatesPath, "*")
67         renderer, err := renderer.NewRenderer(templatesGlobPattern)
68         if err != nil {
69                 errExit(err)
70         }
71
72         err = os.Mkdir(config.DatabasePath, 0755)
73         if err != nil && !os.IsExist(err) {
74                 errExit(err)
75         }
76
77         sessionDBPath := filepath.Join(config.DatabasePath, "session")
78         sessionDB, err := util.NewDatabse(sessionDBPath)
79         if err != nil {
80                 errExit(err)
81         }
82
83         appDBPath := filepath.Join(config.DatabasePath, "app")
84         appDB, err := util.NewDatabse(appDBPath)
85         if err != nil {
86                 errExit(err)
87         }
88
89         sessionRepo := repo.NewSessionRepo(sessionDB)
90         appRepo := repo.NewAppRepo(appDB)
91
92         customCSS := config.CustomCSS
93         if len(customCSS) > 0 && !strings.HasPrefix(customCSS, "http://") &&
94                 !strings.HasPrefix(customCSS, "https://") {
95                 customCSS = "/static/" + customCSS
96         }
97
98         var logger *log.Logger
99         if len(config.LogFile) < 1 {
100                 logger = log.New(os.Stdout, "", log.LstdFlags)
101         } else {
102                 lf, err := os.OpenFile(config.LogFile,
103                         os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
104                 if err != nil {
105                         errExit(err)
106                 }
107                 defer lf.Close()
108                 logger = log.New(lf, "", log.LstdFlags)
109         }
110
111         setupHttp()
112
113         s := service.NewService(config.ClientName, config.ClientScope,
114                 config.ClientWebsite, customCSS, config.PostFormats, renderer,
115                 sessionRepo, appRepo, config.SingleInstance)
116         handler := service.NewHandler(s, logger, config.StaticDirectory)
117
118         logger.Println("listening on", config.ListenAddress)
119         err = http.ListenAndServe(config.ListenAddress, handler)
120         if err != nil {
121                 errExit(err)
122         }
123 }