2024-10-02 23:53:21 +00:00
|
|
|
// MediNET - Session repository and community portal for Meditation Assistant
|
|
|
|
// https://code.rocket9labs.com/tslocum/medinet
|
2017-09-29 04:14:47 +00:00
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-10-02 23:53:21 +00:00
|
|
|
"flag"
|
2017-09-29 04:14:47 +00:00
|
|
|
"fmt"
|
2019-04-26 12:03:08 +00:00
|
|
|
"io/ioutil"
|
2017-09-29 04:14:47 +00:00
|
|
|
"log"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
|
|
|
"regexp"
|
2018-08-10 01:12:03 +00:00
|
|
|
"time"
|
2018-08-10 01:01:50 +00:00
|
|
|
|
2020-01-28 23:30:52 +00:00
|
|
|
"gopkg.in/yaml.v2"
|
2017-09-29 04:14:47 +00:00
|
|
|
)
|
|
|
|
|
2020-10-20 20:08:00 +00:00
|
|
|
type configuration struct {
|
2019-04-26 11:44:43 +00:00
|
|
|
TimeZone string
|
|
|
|
DBDriver string
|
|
|
|
DBSource string
|
|
|
|
Om string
|
2020-10-20 20:03:53 +00:00
|
|
|
Web string
|
2017-09-29 04:14:47 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 20:08:00 +00:00
|
|
|
type statistics struct {
|
2018-06-08 02:30:37 +00:00
|
|
|
AccountsCreated int
|
|
|
|
ActiveAccounts []int
|
|
|
|
|
|
|
|
SessionsPosted int
|
|
|
|
TopStreak int
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2020-10-20 20:08:00 +00:00
|
|
|
db *database
|
|
|
|
config *configuration
|
|
|
|
printDebug bool
|
|
|
|
stats *statistics
|
2018-06-08 02:30:37 +00:00
|
|
|
serverLocation *time.Location
|
2018-08-10 00:45:36 +00:00
|
|
|
|
|
|
|
regexpNumbers = regexp.MustCompile("[0-9]+")
|
|
|
|
regexpMarket = regexp.MustCompile(".*?([a-zA-Z]+)$")
|
2018-06-08 02:30:37 +00:00
|
|
|
)
|
2017-09-29 04:14:47 +00:00
|
|
|
|
2018-06-08 01:13:23 +00:00
|
|
|
func logDebug(message string) {
|
2020-10-20 20:08:00 +00:00
|
|
|
if printDebug {
|
2018-06-08 01:13:23 +00:00
|
|
|
log.Println(message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-08 02:30:37 +00:00
|
|
|
func logDebugf(format string, a ...interface{}) {
|
2019-01-21 14:02:20 +00:00
|
|
|
logDebug(fmt.Sprintf(format, a...))
|
2018-06-08 01:13:23 +00:00
|
|
|
}
|
|
|
|
|
2019-01-21 14:02:20 +00:00
|
|
|
func atWindowStart(t time.Time, streakBuffer int) time.Time {
|
2017-09-29 04:14:47 +00:00
|
|
|
year, month, day := t.Date()
|
2019-01-21 14:02:20 +00:00
|
|
|
return time.Date(year, month, day, streakBuffer/3600, (streakBuffer%3600)/60, streakBuffer%60, 0, t.Location())
|
|
|
|
}
|
|
|
|
|
|
|
|
func beforeWindowStart(t time.Time, streakBuffer int) bool {
|
|
|
|
return t.Before(atWindowStart(t, streakBuffer))
|
2017-09-29 04:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func failOnError(err error) {
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-08 02:30:37 +00:00
|
|
|
func trackActiveAccount(accountID int) {
|
|
|
|
active := false
|
|
|
|
for _, aID := range stats.ActiveAccounts {
|
|
|
|
if aID == accountID {
|
|
|
|
active = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !active {
|
|
|
|
stats.ActiveAccounts = append(stats.ActiveAccounts, accountID)
|
|
|
|
}
|
2019-04-26 11:44:43 +00:00
|
|
|
err := db.updateLastActive(accountID)
|
|
|
|
failOnError(err)
|
2018-06-08 02:30:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func printStatistics() {
|
|
|
|
for {
|
|
|
|
stats.ActiveAccounts = nil
|
|
|
|
stats.AccountsCreated, stats.SessionsPosted, stats.TopStreak = 0, 0, 0
|
|
|
|
|
|
|
|
now := time.Now().In(serverLocation)
|
|
|
|
fourAM := time.Date(now.Year(), now.Month(), now.Day(), 4, 0, 0, 0, serverLocation)
|
|
|
|
if !fourAM.After(now) {
|
|
|
|
fourAM = fourAM.AddDate(0, 0, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(time.Until(fourAM))
|
|
|
|
log.Printf("%d accounts (%d new) posted %d sessions (top streak %d)", len(stats.ActiveAccounts), stats.AccountsCreated, stats.SessionsPosted, stats.TopStreak)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-29 04:14:47 +00:00
|
|
|
func main() {
|
|
|
|
var opts struct {
|
2024-10-02 23:53:21 +00:00
|
|
|
ConfigFile string
|
|
|
|
Debug bool
|
2017-09-29 04:14:47 +00:00
|
|
|
}
|
2024-10-02 23:53:21 +00:00
|
|
|
flag.StringVar(&opts.ConfigFile, "config", "", "Configuration file")
|
|
|
|
flag.BoolVar(&opts.Debug, "debug", false, "Print debug information")
|
|
|
|
flag.Parse()
|
2017-09-29 04:14:47 +00:00
|
|
|
|
|
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
|
|
|
|
|
|
if opts.ConfigFile == "" {
|
|
|
|
log.Fatal("Please specify configuration file with: medinet -c <config file>")
|
|
|
|
}
|
2024-10-02 23:53:21 +00:00
|
|
|
_, err := os.Stat(opts.ConfigFile)
|
|
|
|
if err != nil {
|
2017-09-29 04:14:47 +00:00
|
|
|
log.Fatalf("Configuration file %s does not exist: %s", opts.ConfigFile, err)
|
|
|
|
}
|
|
|
|
|
2019-04-26 12:03:08 +00:00
|
|
|
configData, err := ioutil.ReadFile(opts.ConfigFile)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to read %s: %v", opts.ConfigFile, err)
|
|
|
|
}
|
|
|
|
|
2020-10-20 20:08:00 +00:00
|
|
|
config = new(configuration)
|
2019-04-26 12:03:08 +00:00
|
|
|
err = yaml.Unmarshal(configData, config)
|
|
|
|
if err != nil {
|
2017-09-29 04:14:47 +00:00
|
|
|
log.Fatalf("Failed to read %s: %v", opts.ConfigFile, err)
|
2019-04-26 12:03:08 +00:00
|
|
|
} else if config.DBDriver == "" {
|
|
|
|
log.Fatal("Specify database driver in configuration file")
|
|
|
|
} else if config.Om == "" {
|
|
|
|
log.Fatal("Specify Om host:port in configuration file")
|
2020-10-20 20:03:53 +00:00
|
|
|
} else if config.Web == "" {
|
|
|
|
log.Fatal("Specify Web directory in configuration file")
|
2017-09-29 04:14:47 +00:00
|
|
|
}
|
|
|
|
|
2024-10-02 23:53:21 +00:00
|
|
|
tz := "UTC"
|
2018-06-08 02:30:37 +00:00
|
|
|
if config.TimeZone != "" {
|
|
|
|
tz = config.TimeZone
|
|
|
|
}
|
|
|
|
loc, err := time.LoadLocation(tz)
|
|
|
|
failOnError(err)
|
|
|
|
serverLocation = loc
|
|
|
|
|
2020-10-20 20:08:00 +00:00
|
|
|
printDebug = opts.Debug
|
2018-06-08 01:13:23 +00:00
|
|
|
|
2020-10-20 20:08:00 +00:00
|
|
|
stats = new(statistics)
|
2018-06-08 02:30:37 +00:00
|
|
|
go printStatistics()
|
|
|
|
|
2020-10-20 20:08:00 +00:00
|
|
|
db, err = connect(config.DBDriver, config.DBSource)
|
2017-09-29 04:14:47 +00:00
|
|
|
failOnError(err)
|
|
|
|
|
2020-10-20 20:03:53 +00:00
|
|
|
initWeb()
|
|
|
|
listenWeb()
|
2024-10-02 23:53:21 +00:00
|
|
|
|
|
|
|
log.Printf("Listening on %+v", config.Om)
|
2017-09-29 04:14:47 +00:00
|
|
|
}
|