Squashed into initial commit

This commit is contained in:
Victor Lacasse-Beaudoin 2023-03-06 14:01:18 -05:00
commit c74e093a3b
19 changed files with 1728 additions and 0 deletions

53
cmd/import.go Normal file
View file

@ -0,0 +1,53 @@
package cmd
import (
"log"
"os"
"git.agecem.com/agecem/bottin/bottin"
"git.agecem.com/agecem/bottin/data"
"github.com/spf13/cobra"
)
// importCmd represents the import command
var importCmd = &cobra.Command{
Use: "import",
Short: "Import content into the database",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
log.Fatal("Not enough arguments, needs at least 1 path")
} else {
data.OpenDatabase()
data.MigrateDatabase()
bottin.UpdateFlags()
var valid_args []string
for _, arg := range args {
_, err := os.Stat(arg)
if !os.IsNotExist(err) {
log.Printf("Adding %s to valid_args", arg)
valid_args = append(valid_args, arg)
}
}
// Import from valid args
if len(valid_args) == 1 {
// Do once
bottin.InsertJson(valid_args[0])
} else {
// Do multiple times
for _, path := range valid_args {
bottin.InsertJson(path)
}
}
}
},
}
func init() {
rootCmd.AddCommand(importCmd)
}

86
cmd/root.go Normal file
View file

@ -0,0 +1,86 @@
/*
Copyright © 2022 AGECEM & Victor Lacasse-Beaudoin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var cfgFile string
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "bottin",
Short: "Bottin de la masse étudiante.",
// Uncomment the following line if your bare application
// has an action associated with it:
//
// Run: func(cmd *cobra.Command, args []string) {
// },
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig)
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.bottin.yaml)")
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)
// Search config in home directory with name ".bottin" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".bottin")
}
viper.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
}
}

145
cmd/server.go Normal file
View file

@ -0,0 +1,145 @@
/*
Copyright © 2022 Victor Lacasse-Beaudoin <victor.lacassebeaudoin@gmail.com>
*/
package cmd
import (
"git.agecem.com/agecem/bottin/bottin"
"git.agecem.com/agecem/bottin/data"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"log"
"time"
)
var (
json_insert_path string
)
// serverCmd represents the server command
var serverCmd = &cobra.Command{
Use: "server",
Short: "Run the bottin server",
Run: func(cmd *cobra.Command, args []string) {
// Timer
db_retry_timer := time.Duration(viper.GetInt("db.retry-timer"))
// Open and migrate db
for {
err := data.OpenDatabase()
if err != nil {
log.Println(err)
time.Sleep(db_retry_timer * time.Second)
continue
}
err = data.MigrateDatabase()
if err != nil {
log.Println(err)
time.Sleep(db_retry_timer * time.Second)
continue
}
break
}
bottin.UpdateFlags()
// Import from flag
if json_insert_path != "" {
bottin.InsertJson(json_insert_path)
}
// Run web app
bottin.RunServer()
},
}
func init() {
declareFlags()
rootCmd.AddCommand(serverCmd)
}
func declareFlags() {
// db.type
serverCmd.PersistentFlags().String(
"db-type", "",
"Database type (config: 'db.type')")
viper.BindPFlag(
"db.type",
serverCmd.PersistentFlags().Lookup("db-type"))
serverCmd.MarkPersistentFlagRequired("db.type")
// db.sqlite.path
serverCmd.PersistentFlags().String(
"db-sqlite-path", "",
"Path to sqlite database (config: 'db.sqlite.path')")
viper.BindPFlag(
"db.sqlite.path",
serverCmd.PersistentFlags().Lookup("db-sqlite-path"))
// server.port
serverCmd.PersistentFlags().Int(
"server-port", 1312,
"The port on which the web application will server content (config: 'server.port')")
viper.BindPFlag(
"server.port",
serverCmd.PersistentFlags().Lookup("server-port"))
// server.static_dir
serverCmd.PersistentFlags().String(
"static-dir", "/var/lib/bottin/static",
"The directory containing static assets (config: 'server.static_dir')")
viper.BindPFlag(
"server.static_dir",
serverCmd.PersistentFlags().Lookup("static-dir"))
// login.username
serverCmd.PersistentFlags().String(
"login-username", "bottin",
"The username to login to the web ui. (config: 'login.username')")
viper.BindPFlag(
"login.username",
serverCmd.PersistentFlags().Lookup("login-username"))
// login.password
serverCmd.PersistentFlags().String(
"login-password", "bottin",
"The password to login to the web ui. (config: 'login.password')")
viper.BindPFlag(
"login.password",
serverCmd.PersistentFlags().Lookup("login-password"))
// import.insert-batch-size
serverCmd.PersistentFlags().Int(
"insert-batch-size", 500,
"The amount of inserts to do per batch (config: 'import.insert_batch_size')")
viper.BindPFlag(
"import.insert_batch_size",
serverCmd.PersistentFlags().Lookup("insert-batch-size"))
// json-insert-path
serverCmd.PersistentFlags().StringVar(
&json_insert_path, "json-insert-path", "",
"The location of a json file containing Membres to insert.")
/*
// Not using viper for json-insert-path since it would make it too easy
// to forget to remove from the config every time, which heavily risks
// doubling values.
//
// It would at least need to check for doubles before importing the file,
// for it to be a kind of automatic differential update of the database.
viper.BindPFlag(
"import.json-insert-path",
serverCmd.PersistentFlags().Lookup("json-insert-path"))
*/
// db.retry-timer
serverCmd.PersistentFlags().Int(
"db-retry-timer", 2,
"Time between failed database connection retries, in seconds.")
viper.BindPFlag(
"db.retry-timer",
serverCmd.PersistentFlags().Lookup("db-retry-timer"))
}