<commit_before>// Package main defines a command line interface for the sqlboiler package
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/kat-co/vala"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/vattle/sqlboiler/bdb/drivers"
	"github.com/vattle/sqlboiler/boilingcore"
)

const sqlBoilerVersion = "2.2.0"

var (
	cmdState  *boilingcore.State
	cmdConfig *boilingcore.Config
)

func main() {
	var err error

	// Too much happens between here and cobra's argument handling, for
	// something so simple just do it immediately.
	for _, arg := range os.Args {
		if arg == "--version" {
			fmt.Println("SQLBoiler v" + sqlBoilerVersion)
			return
		}
	}

	viper.SetConfigName("sqlboiler")

	configHome := os.Getenv("XDG_CONFIG_HOME")
	homePath := os.Getenv("HOME")
	wd, err := os.Getwd()
	if err != nil {
		wd = "./"
	}

	configPaths := []string{wd}
	if len(configHome) > 0 {
		configPaths = append(configPaths, filepath.Join(configHome, "sqlboiler"))
	} else {
		configPaths = append(configPaths, filepath.Join(homePath, ".config/sqlboiler"))
	}

	for _, p := range configPaths {
		viper.AddConfigPath(p)
	}

	// Ignore errors here, fallback to other validation methods.
	// Users can use environment variables if a config is not found.
	_ = viper.ReadInConfig()

	// Set up the cobra root command
	var rootCmd = &cobra.Command{
		Use:   "sqlboiler [flags] <driver>",
		Short: "SQL Boiler generates an ORM tailored to your database schema.",
		Long: "SQL Boiler generates a Go ORM from template files, tailored to your database schema.\n" +
			`Complete documentation is available at http://github.com/vattle/sqlboiler`,
		Example:       `sqlboiler postgres`,
		PreRunE:       preRun,
		RunE:          run,
		PostRunE:      postRun,
		SilenceErrors: true,
		SilenceUsage:  true,
	}

	// Set up the cobra root command flags
	rootCmd.PersistentFlags().StringP("output", "o", "models", "The name of the folder to output to")
	rootCmd.PersistentFlags().StringP("schema", "s", "public", "The name of your database schema, for databases that support real schemas")
	rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")
	rootCmd.PersistentFlags().StringP("basedir", "", "", "The base directory has the templates and templates_test folders")
	rootCmd.PersistentFlags().StringSliceP("blacklist", "b", nil, "Do not include these tables in your generated package")
	rootCmd.PersistentFlags().StringSliceP("whitelist", "w", nil, "Only include these tables in your generated package")
	rootCmd.PersistentFlags().StringSliceP("tag", "t", nil, "Struct tags to be included on your models in addition to json, yaml, toml")
	rootCmd.PersistentFlags().StringSliceP("replace", "", nil, "Replace templates by directory: relpath/to_file.tpl:relpath/to_replacement.tpl")
	rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug mode prints stack traces on error")
	rootCmd.PersistentFlags().BoolP("no-tests", "", false, "Disable generated go test files")
	rootCmd.PersistentFlags().BoolP("no-hooks", "", false, "Disable hooks feature for your models")
	rootCmd.PersistentFlags().BoolP("no-auto-timestamps", "", false, "Disable automatic timestamps for created_at/updated_at")
	rootCmd.PersistentFlags().BoolP("version", "", false, "Print the version")
	rootCmd.PersistentFlags().BoolP("tinyint-as-bool", "", false, "Map MySQL tinyint(1) in Go to bool instead of int8")
	rootCmd.PersistentFlags().BoolP("wipe", "", false, "Delete the output folder (rm -rf) before generation to ensure sanity")

	// hide flags not recommended for use
	rootCmd.PersistentFlags().MarkHidden("replace")

	viper.SetDefault("postgres.sslmode", "require")
	viper.SetDefault("postgres.port", "5432")
	viper.SetDefault("mysql.sslmode", "true")
	viper.SetDefault("mysql.port", "3306")

	viper.BindPFlags(rootCmd.PersistentFlags())
	viper.AutomaticEnv()

	if err := rootCmd.Execute(); err != nil {
		if e, ok := err.(commandFailure); ok {
			fmt.Printf("Error: %v\n\n", string(e))
			rootCmd.Help()
		} else if !viper.GetBool("debug") {
			fmt.Printf("Error: %v\n", err)
		} else {
			fmt.Printf("Error: %+v\n", err)
		}

		os.Exit(1)
	}
}

type commandFailure string

func (c commandFailure) Error() string {
	return string(c)
}

func preRun(cmd *cobra.Command, args []string) error {
	var err error

	if len(args) == 0 {
		return commandFailure("must provide a driver name")
	}

	driverName := args[0]

	cmdConfig = &boilingcore.Config{
		DriverName:       driverName,
		OutFolder:        viper.GetString("output"),
		Schema:           viper.GetString("schema"),
		PkgName:          viper.GetString("pkgname"),
		BaseDir:          viper.GetString("basedir"),
		Debug:            viper.GetBool("debug"),
		NoTests:          viper.GetBool("no-tests"),
		NoHooks:          viper.GetBool("no-hooks"),
		NoAutoTimestamps: viper.GetBool("no-auto-timestamps"),
		Wipe:             viper.GetBool("wipe"),
	}

	// BUG: https://github.com/spf13/viper/issues/200
	// Look up the value of blacklist, whitelist & tags directly from PFlags in Cobra if we
	// detect a malformed value coming out of viper.
	// Once the bug is fixed we'll be able to move this into the init above
	cmdConfig.BlacklistTables = viper.GetStringSlice("blacklist")
	if len(cmdConfig.BlacklistTables) == 1 && strings.ContainsRune(cmdConfig.BlacklistTables[0], ',') {
		cmdConfig.BlacklistTables, err = cmd.PersistentFlags().GetStringSlice("blacklist")
		if err != nil {
			return err
		}
	}

	cmdConfig.WhitelistTables = viper.GetStringSlice("whitelist")
	if len(cmdConfig.WhitelistTables) == 1 && strings.ContainsRune(cmdConfig.WhitelistTables[0], ',') {
		cmdConfig.WhitelistTables, err = cmd.PersistentFlags().GetStringSlice("whitelist")
		if err != nil {
			return err
		}
	}

	cmdConfig.Tags = viper.GetStringSlice("tag")
	if len(cmdConfig.Tags) == 1 && strings.ContainsRune(cmdConfig.Tags[0], ',') {
		cmdConfig.Tags, err = cmd.PersistentFlags().GetStringSlice("tag")
		if err != nil {
			return err
		}
	}

	cmdConfig.Replacements = viper.GetStringSlice("replace")
	if len(cmdConfig.Replacements) == 1 && strings.ContainsRune(cmdConfig.Replacements[0], ',') {
		cmdConfig.Replacements, err = cmd.PersistentFlags().GetStringSlice("replace")
		if err != nil {
			return err
		}
	}

	if driverName == "postgres" {
		cmdConfig.Postgres = boilingcore.PostgresConfig{
			User:    viper.GetString("postgres.user"),
			Pass:    viper.GetString("postgres.pass"),
			Host:    viper.GetString("postgres.host"),
			Port:    viper.GetInt("postgres.port"),
			DBName:  viper.GetString("postgres.dbname"),
			SSLMode: viper.GetString("postgres.sslmode"),
		}

		// BUG: https://github.com/spf13/viper/issues/71
		// Despite setting defaults, nested values don't get defaults
		// Set them manually
		if cmdConfig.Postgres.SSLMode == "" {
			cmdConfig.Postgres.SSLMode = "require"
			viper.Set("postgres.sslmode", cmdConfig.Postgres.SSLMode)
		}

		if cmdConfig.Postgres.Port == 0 {
			cmdConfig.Postgres.Port = 5432
			viper.Set("postgres.port", cmdConfig.Postgres.Port)
		}

		err = vala.BeginValidation().Validate(
			vala.StringNotEmpty(cmdConfig.Postgres.User, "postgres.user"),
			vala.StringNotEmpty(cmdConfig.Postgres.Host, "postgres.host"),
			vala.Not(vala.Equals(cmdConfig.Postgres.Port, 0, "postgres.port")),
			vala.StringNotEmpty(cmdConfig.Postgres.DBName, "postgres.dbname"),
			vala.StringNotEmpty(cmdConfig.Postgres.SSLMode, "postgres.sslmode"),
		).Check()

		if err != nil {
			return commandFailure(err.Error())
		}
	}

	if driverName == "mysql" {
		cmdConfig.MySQL = boilingcore.MySQLConfig{
			User:    viper.GetString("mysql.user"),
			Pass:    viper.GetString("mysql.pass"),
			Host:    viper.GetString("mysql.host"),
			Port:    viper.GetInt("mysql.port"),
			DBName:  viper.GetString("mysql.dbname"),
			SSLMode: viper.GetString("mysql.sslmode"),
		}

		// Set MySQL TinyintAsBool global var. This flag only applies to MySQL.
		drivers.TinyintAsBool = viper.GetBool("tinyint-as-bool")

		// MySQL doesn't have schemas, just databases
		cmdConfig.Schema = cmdConfig.MySQL.DBName

		// BUG: https://github.com/spf13/viper/issues/71
		// Despite setting defaults, nested values don't get defaults
		// Set them manually
		if cmdConfig.MySQL.SSLMode == "" {
			cmdConfig.MySQL.SSLMode = "true"
			viper.Set("mysql.sslmode", cmdConfig.MySQL.SSLMode)
		}

		if cmdConfig.MySQL.Port == 0 {
			cmdConfig.MySQL.Port = 3306
			viper.Set("mysql.port", cmdConfig.MySQL.Port)
		}

		err = vala.BeginValidation().Validate(
			vala.StringNotEmpty(cmdConfig.MySQL.User, "mysql.user"),
			vala.StringNotEmpty(cmdConfig.MySQL.Host, "mysql.host"),
			vala.Not(vala.Equals(cmdConfig.MySQL.Port, 0, "mysql.port")),
			vala.StringNotEmpty(cmdConfig.MySQL.DBName, "mysql.dbname"),
			vala.StringNotEmpty(cmdConfig.MySQL.SSLMode, "mysql.sslmode"),
		).Check()

		if err != nil {
			return commandFailure(err.Error())
		}
	}

	if driverName == "mssql" {
		cmdConfig.MSSQL = boilingcore.MSSQLConfig{
			User:    viper.GetString("mssql.user"),
			Pass:    viper.GetString("mssql.pass"),
			Host:    viper.GetString("mssql.host"),
			Port:    viper.GetInt("mssql.port"),
			DBName:  viper.GetString("mssql.dbname"),
			SSLMode: viper.GetString("mssql.sslmode"),
		}

		// BUG: https://github.com/spf13/viper/issues/71
		// Despite setting defaults, nested values don't get defaults
		// Set them manually
		if cmdConfig.MSSQL.SSLMode == "" {
			cmdConfig.MSSQL.SSLMode = "true"
			viper.Set("mssql.sslmode", cmdConfig.MSSQL.SSLMode)
		}

		if cmdConfig.MSSQL.Port == 0 {
			cmdConfig.MSSQL.Port = 1433
			viper.Set("mssql.port", cmdConfig.MSSQL.Port)
		}

		err = vala.BeginValidation().Validate(
			vala.StringNotEmpty(cmdConfig.MSSQL.User, "mssql.user"),
			vala.StringNotEmpty(cmdConfig.MSSQL.Host, "mssql.host"),
			vala.Not(vala.Equals(cmdConfig.MSSQL.Port, 0, "mssql.port")),
			vala.StringNotEmpty(cmdConfig.MSSQL.DBName, "mssql.dbname"),
			vala.StringNotEmpty(cmdConfig.MSSQL.SSLMode, "mssql.sslmode"),
		).Check()

		if err != nil {
			return commandFailure(err.Error())
		}
	}

	cmdState, err = boilingcore.New(cmdConfig)
	return err
}

func run(cmd *cobra.Command, args []string) error {
	return cmdState.Run(true)
}

func postRun(cmd *cobra.Command, args []string) error {
	return cmdState.Cleanup()
}
<commit_msg>Default MS SQL sslmode and port for viper<commit_after>// Package main defines a command line interface for the sqlboiler package
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/kat-co/vala"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/vattle/sqlboiler/bdb/drivers"
	"github.com/vattle/sqlboiler/boilingcore"
)

const sqlBoilerVersion = "2.2.0"

var (
	cmdState  *boilingcore.State
	cmdConfig *boilingcore.Config
)

func main() {
	var err error

	// Too much happens between here and cobra's argument handling, for
	// something so simple just do it immediately.
	for _, arg := range os.Args {
		if arg == "--version" {
			fmt.Println("SQLBoiler v" + sqlBoilerVersion)
			return
		}
	}

	viper.SetConfigName("sqlboiler")

	configHome := os.Getenv("XDG_CONFIG_HOME")
	homePath := os.Getenv("HOME")
	wd, err := os.Getwd()
	if err != nil {
		wd = "./"
	}

	configPaths := []string{wd}
	if len(configHome) > 0 {
		configPaths = append(configPaths, filepath.Join(configHome, "sqlboiler"))
	} else {
		configPaths = append(configPaths, filepath.Join(homePath, ".config/sqlboiler"))
	}

	for _, p := range configPaths {
		viper.AddConfigPath(p)
	}

	// Ignore errors here, fallback to other validation methods.
	// Users can use environment variables if a config is not found.
	_ = viper.ReadInConfig()

	// Set up the cobra root command
	var rootCmd = &cobra.Command{
		Use:   "sqlboiler [flags] <driver>",
		Short: "SQL Boiler generates an ORM tailored to your database schema.",
		Long: "SQL Boiler generates a Go ORM from template files, tailored to your database schema.\n" +
			`Complete documentation is available at http://github.com/vattle/sqlboiler`,
		Example:       `sqlboiler postgres`,
		PreRunE:       preRun,
		RunE:          run,
		PostRunE:      postRun,
		SilenceErrors: true,
		SilenceUsage:  true,
	}

	// Set up the cobra root command flags
	rootCmd.PersistentFlags().StringP("output", "o", "models", "The name of the folder to output to")
	rootCmd.PersistentFlags().StringP("schema", "s", "public", "The name of your database schema, for databases that support real schemas")
	rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")
	rootCmd.PersistentFlags().StringP("basedir", "", "", "The base directory has the templates and templates_test folders")
	rootCmd.PersistentFlags().StringSliceP("blacklist", "b", nil, "Do not include these tables in your generated package")
	rootCmd.PersistentFlags().StringSliceP("whitelist", "w", nil, "Only include these tables in your generated package")
	rootCmd.PersistentFlags().StringSliceP("tag", "t", nil, "Struct tags to be included on your models in addition to json, yaml, toml")
	rootCmd.PersistentFlags().StringSliceP("replace", "", nil, "Replace templates by directory: relpath/to_file.tpl:relpath/to_replacement.tpl")
	rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug mode prints stack traces on error")
	rootCmd.PersistentFlags().BoolP("no-tests", "", false, "Disable generated go test files")
	rootCmd.PersistentFlags().BoolP("no-hooks", "", false, "Disable hooks feature for your models")
	rootCmd.PersistentFlags().BoolP("no-auto-timestamps", "", false, "Disable automatic timestamps for created_at/updated_at")
	rootCmd.PersistentFlags().BoolP("version", "", false, "Print the version")
	rootCmd.PersistentFlags().BoolP("tinyint-as-bool", "", false, "Map MySQL tinyint(1) in Go to bool instead of int8")
	rootCmd.PersistentFlags().BoolP("wipe", "", false, "Delete the output folder (rm -rf) before generation to ensure sanity")

	// hide flags not recommended for use
	rootCmd.PersistentFlags().MarkHidden("replace")

	viper.SetDefault("postgres.sslmode", "require")
	viper.SetDefault("postgres.port", "5432")
	viper.SetDefault("mysql.sslmode", "true")
	viper.SetDefault("mysql.port", "3306")
	viper.SetDefault("mssql.sslmode", "true")
	viper.SetDefault("mssql.port", "1433")

	viper.BindPFlags(rootCmd.PersistentFlags())
	viper.AutomaticEnv()

	if err := rootCmd.Execute(); err != nil {
		if e, ok := err.(commandFailure); ok {
			fmt.Printf("Error: %v\n\n", string(e))
			rootCmd.Help()
		} else if !viper.GetBool("debug") {
			fmt.Printf("Error: %v\n", err)
		} else {
			fmt.Printf("Error: %+v\n", err)
		}

		os.Exit(1)
	}
}

type commandFailure string

func (c commandFailure) Error() string {
	return string(c)
}

func preRun(cmd *cobra.Command, args []string) error {
	var err error

	if len(args) == 0 {
		return commandFailure("must provide a driver name")
	}

	driverName := args[0]

	cmdConfig = &boilingcore.Config{
		DriverName:       driverName,
		OutFolder:        viper.GetString("output"),
		Schema:           viper.GetString("schema"),
		PkgName:          viper.GetString("pkgname"),
		BaseDir:          viper.GetString("basedir"),
		Debug:            viper.GetBool("debug"),
		NoTests:          viper.GetBool("no-tests"),
		NoHooks:          viper.GetBool("no-hooks"),
		NoAutoTimestamps: viper.GetBool("no-auto-timestamps"),
		Wipe:             viper.GetBool("wipe"),
	}

	// BUG: https://github.com/spf13/viper/issues/200
	// Look up the value of blacklist, whitelist & tags directly from PFlags in Cobra if we
	// detect a malformed value coming out of viper.
	// Once the bug is fixed we'll be able to move this into the init above
	cmdConfig.BlacklistTables = viper.GetStringSlice("blacklist")
	if len(cmdConfig.BlacklistTables) == 1 && strings.ContainsRune(cmdConfig.BlacklistTables[0], ',') {
		cmdConfig.BlacklistTables, err = cmd.PersistentFlags().GetStringSlice("blacklist")
		if err != nil {
			return err
		}
	}

	cmdConfig.WhitelistTables = viper.GetStringSlice("whitelist")
	if len(cmdConfig.WhitelistTables) == 1 && strings.ContainsRune(cmdConfig.WhitelistTables[0], ',') {
		cmdConfig.WhitelistTables, err = cmd.PersistentFlags().GetStringSlice("whitelist")
		if err != nil {
			return err
		}
	}

	cmdConfig.Tags = viper.GetStringSlice("tag")
	if len(cmdConfig.Tags) == 1 && strings.ContainsRune(cmdConfig.Tags[0], ',') {
		cmdConfig.Tags, err = cmd.PersistentFlags().GetStringSlice("tag")
		if err != nil {
			return err
		}
	}

	cmdConfig.Replacements = viper.GetStringSlice("replace")
	if len(cmdConfig.Replacements) == 1 && strings.ContainsRune(cmdConfig.Replacements[0], ',') {
		cmdConfig.Replacements, err = cmd.PersistentFlags().GetStringSlice("replace")
		if err != nil {
			return err
		}
	}

	if driverName == "postgres" {
		cmdConfig.Postgres = boilingcore.PostgresConfig{
			User:    viper.GetString("postgres.user"),
			Pass:    viper.GetString("postgres.pass"),
			Host:    viper.GetString("postgres.host"),
			Port:    viper.GetInt("postgres.port"),
			DBName:  viper.GetString("postgres.dbname"),
			SSLMode: viper.GetString("postgres.sslmode"),
		}

		// BUG: https://github.com/spf13/viper/issues/71
		// Despite setting defaults, nested values don't get defaults
		// Set them manually
		if cmdConfig.Postgres.SSLMode == "" {
			cmdConfig.Postgres.SSLMode = "require"
			viper.Set("postgres.sslmode", cmdConfig.Postgres.SSLMode)
		}

		if cmdConfig.Postgres.Port == 0 {
			cmdConfig.Postgres.Port = 5432
			viper.Set("postgres.port", cmdConfig.Postgres.Port)
		}

		err = vala.BeginValidation().Validate(
			vala.StringNotEmpty(cmdConfig.Postgres.User, "postgres.user"),
			vala.StringNotEmpty(cmdConfig.Postgres.Host, "postgres.host"),
			vala.Not(vala.Equals(cmdConfig.Postgres.Port, 0, "postgres.port")),
			vala.StringNotEmpty(cmdConfig.Postgres.DBName, "postgres.dbname"),
			vala.StringNotEmpty(cmdConfig.Postgres.SSLMode, "postgres.sslmode"),
		).Check()

		if err != nil {
			return commandFailure(err.Error())
		}
	}

	if driverName == "mysql" {
		cmdConfig.MySQL = boilingcore.MySQLConfig{
			User:    viper.GetString("mysql.user"),
			Pass:    viper.GetString("mysql.pass"),
			Host:    viper.GetString("mysql.host"),
			Port:    viper.GetInt("mysql.port"),
			DBName:  viper.GetString("mysql.dbname"),
			SSLMode: viper.GetString("mysql.sslmode"),
		}

		// Set MySQL TinyintAsBool global var. This flag only applies to MySQL.
		drivers.TinyintAsBool = viper.GetBool("tinyint-as-bool")

		// MySQL doesn't have schemas, just databases
		cmdConfig.Schema = cmdConfig.MySQL.DBName

		// BUG: https://github.com/spf13/viper/issues/71
		// Despite setting defaults, nested values don't get defaults
		// Set them manually
		if cmdConfig.MySQL.SSLMode == "" {
			cmdConfig.MySQL.SSLMode = "true"
			viper.Set("mysql.sslmode", cmdConfig.MySQL.SSLMode)
		}

		if cmdConfig.MySQL.Port == 0 {
			cmdConfig.MySQL.Port = 3306
			viper.Set("mysql.port", cmdConfig.MySQL.Port)
		}

		err = vala.BeginValidation().Validate(
			vala.StringNotEmpty(cmdConfig.MySQL.User, "mysql.user"),
			vala.StringNotEmpty(cmdConfig.MySQL.Host, "mysql.host"),
			vala.Not(vala.Equals(cmdConfig.MySQL.Port, 0, "mysql.port")),
			vala.StringNotEmpty(cmdConfig.MySQL.DBName, "mysql.dbname"),
			vala.StringNotEmpty(cmdConfig.MySQL.SSLMode, "mysql.sslmode"),
		).Check()

		if err != nil {
			return commandFailure(err.Error())
		}
	}

	if driverName == "mssql" {
		cmdConfig.MSSQL = boilingcore.MSSQLConfig{
			User:    viper.GetString("mssql.user"),
			Pass:    viper.GetString("mssql.pass"),
			Host:    viper.GetString("mssql.host"),
			Port:    viper.GetInt("mssql.port"),
			DBName:  viper.GetString("mssql.dbname"),
			SSLMode: viper.GetString("mssql.sslmode"),
		}

		// BUG: https://github.com/spf13/viper/issues/71
		// Despite setting defaults, nested values don't get defaults
		// Set them manually
		if cmdConfig.MSSQL.SSLMode == "" {
			cmdConfig.MSSQL.SSLMode = "true"
			viper.Set("mssql.sslmode", cmdConfig.MSSQL.SSLMode)
		}

		if cmdConfig.MSSQL.Port == 0 {
			cmdConfig.MSSQL.Port = 1433
			viper.Set("mssql.port", cmdConfig.MSSQL.Port)
		}

		err = vala.BeginValidation().Validate(
			vala.StringNotEmpty(cmdConfig.MSSQL.User, "mssql.user"),
			vala.StringNotEmpty(cmdConfig.MSSQL.Host, "mssql.host"),
			vala.Not(vala.Equals(cmdConfig.MSSQL.Port, 0, "mssql.port")),
			vala.StringNotEmpty(cmdConfig.MSSQL.DBName, "mssql.dbname"),
			vala.StringNotEmpty(cmdConfig.MSSQL.SSLMode, "mssql.sslmode"),
		).Check()

		if err != nil {
			return commandFailure(err.Error())
		}
	}

	cmdState, err = boilingcore.New(cmdConfig)
	return err
}

func run(cmd *cobra.Command, args []string) error {
	return cmdState.Run(true)
}

func postRun(cmd *cobra.Command, args []string) error {
	return cmdState.Cleanup()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/bfirsh/whalebrew/cmd"
)

func main() {
	// HACK: if first argument starts with "/", prefix the subcommand run.
	// This allows us to use this command as a shebang, because we can't pass
	// the argument "run" in the shebang on Linux.
	if len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "/") {
		cmd.RootCmd.SetArgs(append([]string{"run"}, os.Args[1:]...))
	}

	if err := cmd.RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}
<commit_msg>Fix checking args (for working on windows)<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/bfirsh/whalebrew/cmd"
)

func main() {

	if len(os.Args) > 1 {
		// Check if not command exists
		if _, _, err := cmd.RootCmd.Find(os.Args); err != nil {
			// Check if file exists
			if _, err := os.Stat(os.Args[1]); err == nil {
				cmd.RootCmd.SetArgs(append([]string{"run"}, os.Args[1:]...))
			}
		}
	}

	if err := cmd.RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"path"
	"time"

	"github.com/gorilla/mux"
	_ "github.com/mattn/go-sqlite3"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var DB *sql.DB

type Item struct {
	ID          string `json:"id"`
	Description string `json:"description"`
	User        string `json:"user,omitempty"`
}

func addHeaders(rw http.ResponseWriter) {
	rw.Header().Add("Access-Control-Allow-Origin", "http://localhost:8080")
	rw.Header().Add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS")
	rw.Header().Add("Access-Control-Allow-Headers", "Content-Type")
	rw.Header().Add("Access-Control-Allow-Credentials", "true")
	rw.Header().Add("Content-Type", "application/json")
}

func GetHandler(rw http.ResponseWriter, req *http.Request) {
	addHeaders(rw)
	if req.Method == "OPTIONS" {
		return
	}

	tx, err := DB.Begin()
	if err != nil {
		log.Printf("Error begining transaction: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		return
	}
	defer tx.Rollback()

	cur, err := tx.Query("SELECT * FROM items")
	if err != nil {
		log.Printf("Error retrieving list: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		return
	}

	items := []*Item{}

	for cur.Next() {
		item := &Item{}
		if err := cur.Scan(&item.ID, &item.Description, &item.User); err != nil {
			log.Printf("Error retrieving item: %v", err)
			rw.WriteHeader(500)
			rw.Write([]byte("oops"))
			return
		}
		items = append(items, item)
	}

	resp := &struct {
		List []*Item `json:"list"`
	}{List: items}
	body, err := json.Marshal(resp)
	if err != nil {
		log.Printf("Error marshalling items: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		return
	}
	rw.WriteHeader(200)
	rw.Write(body)
}

func AddHandler(rw http.ResponseWriter, req *http.Request) {
	addHeaders(rw)
	if req.Method == "OPTIONS" {
		return
	}

	tx, err := DB.Begin()
	if err != nil {
		log.Printf("Error begining transaction: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		return
	}

	item := &Item{}
	if err := json.NewDecoder(req.Body).Decode(item); err != nil {
		log.Printf("Error decoding request: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		tx.Rollback()
		return
	}

	item.ID = fmt.Sprintf("%x", rand.Int63())
	_, err = tx.Exec(
		"INSERT INTO items (id, description) VALUES (?, ?)",
		item.ID, item.Description,
	)
	if err != nil {
		log.Printf("Error inserting item: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		tx.Rollback()
		return
	}

	if err := tx.Commit(); err != nil {
		log.Printf("Error committing item: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		tx.Rollback()
		return
	}
	req.URL.RawQuery = ""
	req.URL.Fragment = ""
	rw.Header().Add("Location", req.URL.String()+"/"+item.ID)
	rw.WriteHeader(201)
	json.NewEncoder(rw).Encode(item)
}

func UpdateHandler(rw http.ResponseWriter, req *http.Request) {
	addHeaders(rw)
	if req.Method == "OPTIONS" {
		return
	}

	tx, err := DB.Begin()
	if err != nil {
		log.Printf("Error begining transaction: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		return
	}

	newitem := &Item{}
	if err := json.NewDecoder(req.Body).Decode(newitem); err != nil {
		log.Printf("Error decoding request: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		tx.Rollback()
		return
	}
	vars := mux.Vars(req)
	newitem.ID = vars["id"]
	if newitem.ID == "" {
		log.Printf("Empty ID: %v", vars)
		rw.WriteHeader(400)
		rw.Write([]byte("missing id id"))
		tx.Rollback()
		return
	}

	{
		olditem := &Item{ID: "id"}
		row := tx.QueryRow("SELECT * FROM items WHERE id = ? LIMIT 1", newitem.ID)
		if err := row.Scan(&olditem.ID, &olditem.Description, &olditem.User); err != nil {
			log.Printf("Error querying item: %v", err)
			rw.WriteHeader(500)
			rw.Write([]byte("oops"))
			tx.Rollback()
			return
		}
		newitem.Description = olditem.Description
	}

	_, err = tx.Exec(
		"UPDATE items SET description = ?, user = ? WHERE id = ?",
		newitem.Description, newitem.User, newitem.ID,
	)
	if err != nil {
		log.Printf("Error updating item: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		tx.Rollback()
		return
	}

	if err := tx.Commit(); err != nil {
		log.Printf("Error committing item: %v", err)
		rw.WriteHeader(500)
		rw.Write([]byte("oops"))
		tx.Rollback()
		return
	}
	req.URL.RawQuery = ""
	req.URL.Fragment = ""
	rw.Header().Add("Location", req.URL.String()+"/"+newitem.ID)
	rw.WriteHeader(201)
	json.NewEncoder(rw).Encode(newitem)
}

func createTable(table, create string) {
	create = fmt.Sprintf(create, table)

	tx, err := DB.Begin()
	if err != nil {
		log.Fatalf("Error beginning transaction: %v", err)
	}

	row := tx.QueryRow("SELECT COUNT(1) FROM sqlite_master WHERE type = ? AND name = ?", "table", table)
	count := 0
	if err := row.Scan(&count); err != nil {
		log.Fatalf("Error reading results of '%s' table check: %v", table, err)
	}

	if count > 0 {
		tx.Rollback()
		return
	}
	if _, err := tx.Exec(create); err != nil {
		log.Fatalf("Error creating table %s: %v", table, err)
	}
	if err := tx.Commit(); err != nil {
		log.Fatalf("Error commiting table creation %s: %v", table, err)
	}
}

func main() {
	log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
	bind := flag.String("bind", "localhost:8000", "host:port to listen on")
	dbFile := flag.String("db", "signup.sqlite3", "filename for db")
	staticPath := flag.String("path", "www", "path to static www assests")
	flag.Parse()

	router, err := setup(*staticPath, *dbFile)
	if err != nil {
		log.Fatalf("Error starting up: %v", err)
	}
	m := http.NewServeMux()
	m.Handle("/", router)

	log.Printf("Starting %s on http://%s", path.Base(os.Args[0]), *bind)
	log.Fatal(http.ListenAndServe(*bind, m))
}

func initDB() {
	createTable("items", "CREATE TABLE %s ( id TEXT PRIMARY KEY, description TEXT NOT NULL DEFAULT '', user TEXT NOT NULL DEFAULT '' )")
}

func setup(staticPath, dbFile string) (*mux.Router, error) {
	var err error
	if DB, err = sql.Open("sqlite3", dbFile); err != nil {
		return nil, fmt.Errorf("Error opening database: %v", err)
	}

	initDB()

	r := mux.NewRouter()
	r.HandleFunc("/api/list", GetHandler).Methods("GET", "OPTIONS")
	r.HandleFunc("/api/list", AddHandler).Methods("POST", "OPTIONS")
	r.HandleFunc("/api/list/{id}", UpdateHandler).Methods("POST", "OPTIONS")
	r.PathPrefix("/").Handler(http.FileServer(http.Dir(staticPath)))

	return r, nil
}
<commit_msg>@pietvanzoen loves json responses.<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"path"
	"time"

	"github.com/gorilla/mux"
	_ "github.com/mattn/go-sqlite3"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var DB *sql.DB

type Item struct {
	ID          string `json:"id"`
	Description string `json:"description"`
	User        string `json:"user,omitempty"`
}

type Error struct {
	Error string `json:"error"`
}

func errorResponse(rw http.ResponseWriter, msg string, code int) {
	rw.WriteHeader(code)
	json.NewEncoder(rw).Encode(&Error{Error: msg})
	return
}

func addHeaders(rw http.ResponseWriter) {
	rw.Header().Add("Access-Control-Allow-Origin", "http://localhost:8080")
	rw.Header().Add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS")
	rw.Header().Add("Access-Control-Allow-Headers", "Content-Type")
	rw.Header().Add("Access-Control-Allow-Credentials", "true")
	rw.Header().Add("Content-Type", "application/json")
}

func GetHandler(rw http.ResponseWriter, req *http.Request) {
	addHeaders(rw)
	if req.Method == "OPTIONS" {
		return
	}

	tx, err := DB.Begin()
	if err != nil {
		log.Printf("Error begining transaction: %v", err)
		errorResponse(rw, "internal error", 500)
		return
	}
	defer tx.Rollback()

	cur, err := tx.Query("SELECT * FROM items")
	if err != nil {
		log.Printf("Error retrieving list: %v", err)
		errorResponse(rw, "internal error", 500)
		return
	}

	items := []*Item{}

	for cur.Next() {
		item := &Item{}
		if err := cur.Scan(&item.ID, &item.Description, &item.User); err != nil {
			log.Printf("Error retrieving item: %v", err)
			errorResponse(rw, "internal error", 500)
			return
		}
		items = append(items, item)
	}

	resp := &struct {
		List []*Item `json:"list"`
	}{List: items}
	body, err := json.Marshal(resp)
	if err != nil {
		log.Printf("Error marshalling items: %v", err)
		errorResponse(rw, "internal error", 500)
		return
	}
	rw.WriteHeader(200)
	rw.Write(body)
}

func AddHandler(rw http.ResponseWriter, req *http.Request) {
	addHeaders(rw)
	if req.Method == "OPTIONS" {
		return
	}

	tx, err := DB.Begin()
	if err != nil {
		log.Printf("Error begining transaction: %v", err)
		errorResponse(rw, "internal error", 500)
		return
	}

	item := &Item{}
	if err := json.NewDecoder(req.Body).Decode(item); err != nil {
		log.Printf("Error decoding request: %v", err)
		errorResponse(rw, "internal error", 500)
		tx.Rollback()
		return
	}

	item.ID = fmt.Sprintf("%x", rand.Int63())
	_, err = tx.Exec(
		"INSERT INTO items (id, description) VALUES (?, ?)",
		item.ID, item.Description,
	)
	if err != nil {
		log.Printf("Error inserting item: %v", err)
		errorResponse(rw, "internal error", 500)
		tx.Rollback()
		return
	}

	if err := tx.Commit(); err != nil {
		log.Printf("Error committing item: %v", err)
		errorResponse(rw, "internal error", 500)
		tx.Rollback()
		return
	}
	req.URL.RawQuery = ""
	req.URL.Fragment = ""
	rw.Header().Add("Location", req.URL.String()+"/"+item.ID)
	rw.WriteHeader(201)
	json.NewEncoder(rw).Encode(item)
}

func UpdateHandler(rw http.ResponseWriter, req *http.Request) {
	addHeaders(rw)
	if req.Method == "OPTIONS" {
		return
	}

	tx, err := DB.Begin()
	if err != nil {
		log.Printf("Error begining transaction: %v", err)
		errorResponse(rw, "internal error", 500)
		return
	}

	newitem := &Item{}
	if err := json.NewDecoder(req.Body).Decode(newitem); err != nil {
		log.Printf("Error decoding request: %v", err)
		errorResponse(rw, "invalid json in request", 400)
		tx.Rollback()
		return
	}
	vars := mux.Vars(req)
	newitem.ID = vars["id"]
	if newitem.ID == "" {
		log.Printf("Empty ID: %v", vars)
		errorResponse(rw, "empty ID", 400)
		tx.Rollback()
		return
	}

	{
		olditem := &Item{ID: "id"}
		row := tx.QueryRow("SELECT * FROM items WHERE id = ? LIMIT 1", newitem.ID)
		if err := row.Scan(&olditem.ID, &olditem.Description, &olditem.User); err != nil {
			log.Printf("Error querying item: %v", err)
			errorResponse(rw, "internal error", 500)
			tx.Rollback()
			return
		}
		newitem.Description = olditem.Description
	}

	_, err = tx.Exec(
		"UPDATE items SET description = ?, user = ? WHERE id = ?",
		newitem.Description, newitem.User, newitem.ID,
	)
	if err != nil {
		log.Printf("Error updating item: %v", err)
		errorResponse(rw, "internal error", 500)
		tx.Rollback()
		return
	}

	if err := tx.Commit(); err != nil {
		log.Printf("Error committing item: %v", err)
		errorResponse(rw, "internal error", 500)
		tx.Rollback()
		return
	}
	req.URL.RawQuery = ""
	req.URL.Fragment = ""
	rw.Header().Add("Location", req.URL.String()+"/"+newitem.ID)
	rw.WriteHeader(201)
	json.NewEncoder(rw).Encode(newitem)
}

func createTable(table, create string) {
	create = fmt.Sprintf(create, table)

	tx, err := DB.Begin()
	if err != nil {
		log.Fatalf("Error beginning transaction: %v", err)
	}

	row := tx.QueryRow("SELECT COUNT(1) FROM sqlite_master WHERE type = ? AND name = ?", "table", table)
	count := 0
	if err := row.Scan(&count); err != nil {
		log.Fatalf("Error reading results of '%s' table check: %v", table, err)
	}

	if count > 0 {
		tx.Rollback()
		return
	}
	if _, err := tx.Exec(create); err != nil {
		log.Fatalf("Error creating table %s: %v", table, err)
	}
	if err := tx.Commit(); err != nil {
		log.Fatalf("Error commiting table creation %s: %v", table, err)
	}
}

func main() {
	log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
	bind := flag.String("bind", "localhost:8000", "host:port to listen on")
	dbFile := flag.String("db", "signup.sqlite3", "filename for db")
	staticPath := flag.String("path", "www", "path to static www assests")
	flag.Parse()

	router, err := setup(*staticPath, *dbFile)
	if err != nil {
		log.Fatalf("Error starting up: %v", err)
	}
	m := http.NewServeMux()
	m.Handle("/", router)

	log.Printf("Starting %s on http://%s", path.Base(os.Args[0]), *bind)
	log.Fatal(http.ListenAndServe(*bind, m))
}

func initDB() {
	createTable("items", "CREATE TABLE %s ( id TEXT PRIMARY KEY, description TEXT NOT NULL DEFAULT '', user TEXT NOT NULL DEFAULT '' )")
}

func setup(staticPath, dbFile string) (*mux.Router, error) {
	var err error
	if DB, err = sql.Open("sqlite3", dbFile); err != nil {
		return nil, fmt.Errorf("Error opening database: %v", err)
	}

	initDB()

	r := mux.NewRouter()
	r.HandleFunc("/api/list", GetHandler).Methods("GET", "OPTIONS")
	r.HandleFunc("/api/list", AddHandler).Methods("POST", "OPTIONS")
	r.HandleFunc("/api/list/{id}", UpdateHandler).Methods("POST", "OPTIONS")
	r.PathPrefix("/").Handler(http.FileServer(http.Dir(staticPath)))

	return r, nil
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type service struct {
	path string
}

func (s *service) render() ([]byte, error) {
	f, err := os.Open(s.path)
	if err != nil {
		return nil, err
	}
	response, err := http.Post("https://api.github.com/markdown/raw", "text/plain", f)
	if err != nil {
		return nil, err
	}
	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return b, nil
}

func (s *service) hRoot(w http.ResponseWriter, r *http.Request) {
	b, err := s.render()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	w.Header().Set("Content-Type", "text/html")
	w.Write(b)
}

func main() {
	s := service{
		path: os.Args[1],
	}
	http.HandleFunc("/", s.hRoot)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>use websockets for updating<commit_after>package main

import (
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/gorilla/websocket"
)

const indexHTML = `
<!DOCTYPE html>

        <title>Markdown Preview</title>

	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="https://rawgit.com/sindresorhus/github-markdown-css/gh-pages/github-markdown.css">

{{.Data}}

`

type service struct {
	path          string
	indexTemplate *template.Template
	upgrader      websocket.Upgrader
}

func (s *service) serveHome(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	rendered, _ := s.render()
	var v = struct {
		Host string
		Data template.HTML
	}{
		r.Host,
		template.HTML(rendered),
	}
	s.indexTemplate.Execute(w, &v)
}

func (s *service) serveWs(w http.ResponseWriter, r *http.Request) {
	ws, err := s.upgrader.Upgrade(w, r, nil)
	if err != nil {
		if _, ok := err.(websocket.HandshakeError); !ok {
			log.Println(err)
		}
		return
	}

	go s.writer(ws)
	s.reader(ws)
}

func (s *service) render() ([]byte, error) {
	f, err := os.Open(s.path)
	if err != nil {
		return nil, err
	}
	response, err := http.Post("https://api.github.com/markdown/raw", "text/plain", f)
	if err != nil {
		return nil, err
	}
	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return b, nil
}

func (s *service) watcher(changes chan<- struct{}) {
	w, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-w.Events:
				if event.Op&fsnotify.Write == fsnotify.Write {
					changes <- struct{}{}
				}
			case err := <-w.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = w.Add(s.path)
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

func (s *service) writer(ws *websocket.Conn) {
	defer func() {
		ws.Close()
	}()

	changes := make(chan struct{})
	go s.watcher(changes)
	for {
		select {
		case <-changes:
			rendered, _ := s.render()
			ws.SetWriteDeadline(time.Now().Add(10 * time.Second))
			if err := ws.WriteMessage(websocket.TextMessage, rendered); err != nil {
				return
			}
		case <-time.After(2 * time.Second):
			ws.SetWriteDeadline(time.Now().Add(10 * time.Second))
			if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}

func (s *service) reader(ws *websocket.Conn) {
	defer ws.Close()
	ws.SetReadLimit(512)
	ws.SetReadDeadline(time.Now().Add(60 * time.Second))
	ws.SetPongHandler(func(string) error {
		ws.SetReadDeadline(time.Now().Add(60 * time.Second))
		return nil
	})
	for {
		_, _, err := ws.ReadMessage()
		if err != nil {
			break
		}
	}
}

func main() {
	s := service{
		path:          os.Args[1],
		indexTemplate: template.Must(template.New("").Parse(indexHTML)),
		upgrader: websocket.Upgrader{
			ReadBufferSize:  1024,
			WriteBufferSize: 1024,
		},
	}
	http.HandleFunc("/", s.serveHome)
	http.HandleFunc("/ws", s.serveWs)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Gary Burd
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Package talksapp implements the go-talks.appspot.com server.
package talksapp

import (
	"appengine"
	"appengine/memcache"
	"appengine/urlfetch"
	"bytes"
	"code.google.com/p/go.tools/present"
	"errors"
	"fmt"
	"github.com/garyburd/gosrc"
	"html/template"
	"io"
	"net/http"
	"os"
	"path"
	"sync"
	"time"
)

var (
	presentTemplates = map[string]*template.Template{
		".article": parsePresentTemplate("article.tmpl"),
		".slide":   parsePresentTemplate("slides.tmpl"),
	}
	homeArticle  = loadHomeArticle()
	contactEmail = "unknown@example.com"
)

func init() {
	http.Handle("/", handlerFunc(serveRoot))
	http.Handle("/compile", handlerFunc(serveCompile))
	http.Handle("/bot.html", handlerFunc(serveBot))
	present.PlayEnabled = true
}

func parsePresentTemplate(name string) *template.Template {
	t := present.Template()
	if _, err := t.ParseFiles("present/templates/"+name, "present/templates/action.tmpl"); err != nil {
		panic(err)
	}
	t = t.Lookup("root")
	if t == nil {
		panic("root template not found for " + name)
	}
	return t
}

func loadHomeArticle() []byte {
	const fname = "assets/home.article"
	f, err := os.Open(fname)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	doc, err := present.Parse(f, fname, 0)
	if err != nil {
		panic(err)
	}
	var buf bytes.Buffer
	if err := renderPresentation(&buf, fname, doc); err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func renderPresentation(w io.Writer, fname string, doc *present.Doc) error {
	t := presentTemplates[path.Ext(fname)]
	if t == nil {
		return errors.New("unknown template extension")
	}
	data := struct {
		*present.Doc
		Template    *template.Template
		PlayEnabled bool
	}{
		doc,
		t,
		true,
	}
	return t.Execute(w, &data)
}

type presFileNotFoundError string

func (s presFileNotFoundError) Error() string { return fmt.Sprintf("File %s not found.", string(s)) }

func writeHTMLHeader(w http.ResponseWriter, status int) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.WriteHeader(status)
}

func writeTextHeader(w http.ResponseWriter, status int) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(status)
}

var setupOnce sync.Once

func setup(r *http.Request) {
	c := appengine.NewContext(r)
	c.Infof("Contact email: %s", contactEmail)
	gosrc.SetUserAgent(fmt.Sprintf("%s (+http://%s/bot.html)", appengine.AppID(c), r.Host))
}

type handlerFunc func(http.ResponseWriter, *http.Request) error

func (f handlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	setupOnce.Do(func() { setup(r) })
	c := appengine.NewContext(r)
	err := f(w, r)
	if err == nil {
		return
	} else if gosrc.IsNotFound(err) {
		writeTextHeader(w, 400)
		io.WriteString(w, "Not Found.")
	} else if e, ok := err.(*gosrc.RemoteError); ok {
		writeTextHeader(w, 500)
		fmt.Fprintf(w, "Error accessing %s.", e.Host)
	} else if e, ok := err.(presFileNotFoundError); ok {
		writeTextHeader(w, 200)
		io.WriteString(w, e.Error())
	} else if err != nil {
		writeTextHeader(w, 500)
		io.WriteString(w, "Internal server error.")
		c.Errorf("Internal error %v", err)
	}
}

func serveRoot(w http.ResponseWriter, r *http.Request) error {
	switch {
	case r.Method != "GET":
		writeTextHeader(w, 405)
		_, err := io.WriteString(w, "Method not supported.")
		return err
	case r.URL.Path == "/":
		writeHTMLHeader(w, 200)
		_, err := w.Write(homeArticle)
		return err
	default:
		return servePresentation(w, r)
	}
}

func servePresentation(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	importPath := r.URL.Path[1:]

	item, err := memcache.Get(c, importPath)
	if err == nil {
		writeHTMLHeader(w, 200)
		w.Write(item.Value)
		return nil
	} else if err != memcache.ErrCacheMiss {
		return err
	}

	c.Infof("Fetching presentation %s.", importPath)
	pres, err := gosrc.GetPresentation(urlfetch.Client(c), importPath)
	if err != nil {
		return err
	}

	ctx := &present.Context{
		ReadFile: func(name string) ([]byte, error) {
			if p, ok := pres.Files[name]; ok {
				return p, nil
			}
			return nil, presFileNotFoundError(name)
		},
	}

	doc, err := ctx.Parse(bytes.NewReader(pres.Files[pres.Filename]), pres.Filename, 0)
	if err != nil {
		return err
	}

	var buf bytes.Buffer
	if err := renderPresentation(&buf, importPath, doc); err != nil {
		return err
	}

	if err := memcache.Add(c, &memcache.Item{
		Key:        importPath,
		Value:      buf.Bytes(),
		Expiration: time.Hour,
	}); err != nil {
		return err
	}

	writeHTMLHeader(w, 200)
	_, err = w.Write(buf.Bytes())
	return err
}

func serveCompile(w http.ResponseWriter, r *http.Request) error {
	client := urlfetch.Client(appengine.NewContext(r))
	if err := r.ParseForm(); err != nil {
		return err
	}
	resp, err := client.PostForm("http://play.golang.org/compile", r.Form)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
	_, err = io.Copy(w, resp.Body)
	return err
}

func serveBot(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	writeTextHeader(w, 200)
	_, err := fmt.Fprintf(w, "Contact %s for help with the %s bot.", contactEmail, appengine.AppID(c))
	return err
}
<commit_msg>Allow HEAD requests.<commit_after>// Copyright 2013 Gary Burd
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Package talksapp implements the go-talks.appspot.com server.
package talksapp

import (
	"appengine"
	"appengine/memcache"
	"appengine/urlfetch"
	"bytes"
	"code.google.com/p/go.tools/present"
	"errors"
	"fmt"
	"github.com/garyburd/gosrc"
	"html/template"
	"io"
	"net/http"
	"os"
	"path"
	"sync"
	"time"
)

var (
	presentTemplates = map[string]*template.Template{
		".article": parsePresentTemplate("article.tmpl"),
		".slide":   parsePresentTemplate("slides.tmpl"),
	}
	homeArticle  = loadHomeArticle()
	contactEmail = "unknown@example.com"
)

func init() {
	http.Handle("/", handlerFunc(serveRoot))
	http.Handle("/compile", handlerFunc(serveCompile))
	http.Handle("/bot.html", handlerFunc(serveBot))
	present.PlayEnabled = true
}

func parsePresentTemplate(name string) *template.Template {
	t := present.Template()
	if _, err := t.ParseFiles("present/templates/"+name, "present/templates/action.tmpl"); err != nil {
		panic(err)
	}
	t = t.Lookup("root")
	if t == nil {
		panic("root template not found for " + name)
	}
	return t
}

func loadHomeArticle() []byte {
	const fname = "assets/home.article"
	f, err := os.Open(fname)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	doc, err := present.Parse(f, fname, 0)
	if err != nil {
		panic(err)
	}
	var buf bytes.Buffer
	if err := renderPresentation(&buf, fname, doc); err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func renderPresentation(w io.Writer, fname string, doc *present.Doc) error {
	t := presentTemplates[path.Ext(fname)]
	if t == nil {
		return errors.New("unknown template extension")
	}
	data := struct {
		*present.Doc
		Template    *template.Template
		PlayEnabled bool
	}{
		doc,
		t,
		true,
	}
	return t.Execute(w, &data)
}

type presFileNotFoundError string

func (s presFileNotFoundError) Error() string { return fmt.Sprintf("File %s not found.", string(s)) }

func writeHTMLHeader(w http.ResponseWriter, status int) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.WriteHeader(status)
}

func writeTextHeader(w http.ResponseWriter, status int) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(status)
}

var setupOnce sync.Once

func setup(r *http.Request) {
	c := appengine.NewContext(r)
	c.Infof("Contact email: %s", contactEmail)
	gosrc.SetUserAgent(fmt.Sprintf("%s (+http://%s/bot.html)", appengine.AppID(c), r.Host))
}

type handlerFunc func(http.ResponseWriter, *http.Request) error

func (f handlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	setupOnce.Do(func() { setup(r) })
	c := appengine.NewContext(r)
	err := f(w, r)
	if err == nil {
		return
	} else if gosrc.IsNotFound(err) {
		writeTextHeader(w, 400)
		io.WriteString(w, "Not Found.")
	} else if e, ok := err.(*gosrc.RemoteError); ok {
		writeTextHeader(w, 500)
		fmt.Fprintf(w, "Error accessing %s.", e.Host)
	} else if e, ok := err.(presFileNotFoundError); ok {
		writeTextHeader(w, 200)
		io.WriteString(w, e.Error())
	} else if err != nil {
		writeTextHeader(w, 500)
		io.WriteString(w, "Internal server error.")
		c.Errorf("Internal error %v", err)
	}
}

func serveRoot(w http.ResponseWriter, r *http.Request) error {
	switch {
	case r.Method != "GET" && r.Method != "HEAD":
		writeTextHeader(w, 405)
		_, err := io.WriteString(w, "Method not supported.")
		return err
	case r.URL.Path == "/":
		writeHTMLHeader(w, 200)
		_, err := w.Write(homeArticle)
		return err
	default:
		return servePresentation(w, r)
	}
}

func servePresentation(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	importPath := r.URL.Path[1:]

	item, err := memcache.Get(c, importPath)
	if err == nil {
		writeHTMLHeader(w, 200)
		w.Write(item.Value)
		return nil
	} else if err != memcache.ErrCacheMiss {
		return err
	}

	c.Infof("Fetching presentation %s.", importPath)
	pres, err := gosrc.GetPresentation(urlfetch.Client(c), importPath)
	if err != nil {
		return err
	}

	ctx := &present.Context{
		ReadFile: func(name string) ([]byte, error) {
			if p, ok := pres.Files[name]; ok {
				return p, nil
			}
			return nil, presFileNotFoundError(name)
		},
	}

	doc, err := ctx.Parse(bytes.NewReader(pres.Files[pres.Filename]), pres.Filename, 0)
	if err != nil {
		return err
	}

	var buf bytes.Buffer
	if err := renderPresentation(&buf, importPath, doc); err != nil {
		return err
	}

	if err := memcache.Add(c, &memcache.Item{
		Key:        importPath,
		Value:      buf.Bytes(),
		Expiration: time.Hour,
	}); err != nil {
		return err
	}

	writeHTMLHeader(w, 200)
	_, err = w.Write(buf.Bytes())
	return err
}

func serveCompile(w http.ResponseWriter, r *http.Request) error {
	client := urlfetch.Client(appengine.NewContext(r))
	if err := r.ParseForm(); err != nil {
		return err
	}
	resp, err := client.PostForm("http://play.golang.org/compile", r.Form)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
	_, err = io.Copy(w, resp.Body)
	return err
}

func serveBot(w http.ResponseWriter, r *http.Request) error {
	c := appengine.NewContext(r)
	writeTextHeader(w, 200)
	_, err := fmt.Fprintf(w, "Contact %s for help with the %s bot.", contactEmail, appengine.AppID(c))
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/hansrodtang/runcom/backends"
	"github.com/hansrodtang/runcom/core"
	"github.com/hansrodtang/runcom/plugins"
	// Backend
	_ "github.com/hansrodtang/runcom/backends/directory"
	_ "github.com/hansrodtang/runcom/backends/git"
	// Plugins
	_ "github.com/hansrodtang/runcom/plugins/dotfiles"
	_ "github.com/hansrodtang/runcom/plugins/packages/homebrew"
	_ "github.com/hansrodtang/runcom/plugins/scripts"
	// Other dependencies
	"github.com/hansrodtang/viper"
	"github.com/spf13/cobra"
	//"golang.org/x/crypto/ssh/terminal"
)

const defaultBackend = "directory"

func main() {
	viper.SetDefault("backend", defaultBackend)

	var mainCmd = &cobra.Command{
		Use:   core.BinaryName,
		Short: core.Name + " is a simple and flexible configuration manager",
		Long: `A Simple and Flexible Configuration Manager..
Complete documentation is available at http:/runcom.github.io`,
	}

	mainCmd.PersistentFlags().String("backend", defaultBackend, "Storage backend to use for saving configuration")
	viper.BindPFlag("backend", mainCmd.PersistentFlags().Lookup("backend"))

	print := core.NewPrinter(core.BinaryName)

	backendErr := backends.Select(viper.GetString("backend"))
	if backendErr != nil {
		answer := print.Ask("Backend '"+viper.GetString("backend")+"' not found. Use default? ["+defaultBackend+"]", true)
		if !answer {
			fmt.Println("No storage backend chosen. Exiting")
			os.Exit(0)
		}
		backendErr = backends.Select(defaultBackend)
		if backendErr != nil {
			panic("Could not load default backend.")
		}

	}

	plugs := plugins.GetAll()

	for _, plugin := range plugs {
		mainCmd.AddCommand(plugin.Command)
	}

	mainCmd.AddCommand(
		core.ConnectCommand,
		core.PushCommand,
		core.GetCommand,
		core.UnpackCommand,
		core.PackCommand)

	// if !terminal.IsTerminal(int(os.Stdout.Fd())) {
	// 	var test io.Writer
	// 	test = bufio.NewWriter(test)
	// 	mainCmd.SetOutput(test)
	// }

	mainCmd.Execute()
}
<commit_msg>Removed unused code.<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/hansrodtang/runcom/backends"
	"github.com/hansrodtang/runcom/core"
	"github.com/hansrodtang/runcom/plugins"
	// Backend
	_ "github.com/hansrodtang/runcom/backends/directory"
	_ "github.com/hansrodtang/runcom/backends/git"
	// Plugins
	_ "github.com/hansrodtang/runcom/plugins/dotfiles"
	_ "github.com/hansrodtang/runcom/plugins/packages/homebrew"
	_ "github.com/hansrodtang/runcom/plugins/scripts"
	// Other dependencies
	"github.com/hansrodtang/viper"
	"github.com/spf13/cobra"
)

const defaultBackend = "directory"

func main() {
	viper.SetDefault("backend", defaultBackend)

	var mainCmd = &cobra.Command{
		Use:   core.BinaryName,
		Short: core.Name + " is a simple and flexible configuration manager",
		Long: `A Simple and Flexible Configuration Manager..
Complete documentation is available at http:/runcom.github.io`,
	}

	mainCmd.PersistentFlags().String("backend", defaultBackend, "Storage backend to use for saving configuration")
	viper.BindPFlag("backend", mainCmd.PersistentFlags().Lookup("backend"))

	print := core.NewPrinter(core.BinaryName)

	backendErr := backends.Select(viper.GetString("backend"))
	if backendErr != nil {
		answer := print.Ask("Backend '"+viper.GetString("backend")+"' not found. Use default? ["+defaultBackend+"]", true)
		if !answer {
			fmt.Println("No storage backend chosen. Exiting")
			os.Exit(0)
		}
		backendErr = backends.Select(defaultBackend)
		if backendErr != nil {
			panic("Could not load default backend.")
		}

	}

	plugs := plugins.GetAll()

	for _, plugin := range plugs {
		mainCmd.AddCommand(plugin.Command)
	}

	mainCmd.AddCommand(
		core.ConnectCommand,
		core.PushCommand,
		core.GetCommand,
		core.UnpackCommand,
		core.PackCommand)

	mainCmd.Execute()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/mkideal/cli"
	"github.com/snabb/isoweek"
)

const yearOffset = 1996

type serial struct {
	serialNum     string
	year, weekNum int
	mfgDate       time.Time
}

// Splits out the year and week number out of a serial number
func (s *serial) splitNums() {
	if len(s.serialNum) != 11 {
		log.Fatal("Serial number must be exactly 11 characters")
	}

	parts := strings.Split(s.serialNum, "")
	s.year, _ = strconv.Atoi(parts[3] + parts[4])
	s.weekNum, _ = strconv.Atoi(parts[5] + parts[6])
	if s.weekNum > 52 {
		log.Fatal("Week number must not be higher than 52")
	}
}

// Parses the given serial and prints out its manufactured date
func (s *serial) parseSerial() {
	fmt.Println(s.serialNum)
	s.splitNums()
	s.year = s.year + yearOffset // Add our year offset
	s.mfgDate = isoweek.StartTime(s.year, s.weekNum, time.UTC)
	fmt.Println(s.mfgDate.Format("2006-01-02"))
}

type argT struct {
	cli.Helper
	Serial   string `cli:"s,serial"   usage:"serial to parse"`
	Filename string `cli:"f,filename" usage:"filename with serials to parse"`
}

var (
	helptext = `
Parses provided cisco serial and returns manufactured date

Examples:
./serial_to_date --serial FAA04459FNI
./serial_to_date --filename serials.txt
`
)

func main() {
	cli.Run(new(argT), func(ctx *cli.Context) error {
		argv := ctx.Argv().(*argT)

		// Read single serial
		if argv.Serial != "" {
			s := serial{serialNum: argv.Serial}
			s.parseSerial()
		}

		// Read filename
		if argv.Filename != "" {
			file, err := os.Open(argv.Filename)
			if err != nil {
				log.Fatal(err)
			}
			defer file.Close()

			scanner := bufio.NewScanner(file)
			for scanner.Scan() {
				s := serial{serialNum: scanner.Text()}
				s.parseSerial()
				fmt.Println("")
			}
		}

		// If neither flag, print help
		if argv.Serial == "" && argv.Filename == "" {
			log.Fatal(helptext)
		}

		return nil
	})
}
<commit_msg>Add location parsing<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/mkideal/cli"
	"github.com/snabb/isoweek"
)

const yearOffset = 1996

type serial struct {
	serialNum, location string
	year, weekNum       int
	mfgDate             time.Time
}

// Splits out the year and week number out of a serial number
func (s *serial) splitChars() {
	if len(s.serialNum) != 11 {
		log.Fatal("Serial number must be exactly 11 characters")
	}
	// year is numbers 4 & 5 in string
	// week is numbers 6 & 7 in string
	parts := strings.Split(s.serialNum, "")
	s.year, _ = strconv.Atoi(parts[3] + parts[4])
	s.weekNum, _ = strconv.Atoi(parts[5] + parts[6])
	if s.weekNum > 52 {
		log.Fatal("Week number must not be higher than 52")
	}
}

// Parses the given serial and prints out extracted info
func (s *serial) parseSerial() {
	fmt.Println(s.serialNum)
	s.getLocation()

	s.splitChars()
	s.year = s.year + yearOffset // Add our year offset
	s.mfgDate = isoweek.StartTime(s.year, s.weekNum, time.UTC)

	fmt.Println("Manufatured on: " + s.mfgDate.Format("2006-01-02"))
	fmt.Println("Manufatured in: " + s.location)
}

func (s *serial) getLocation() {
	// locationCode is first 3 characters
	locationCode := s.serialNum[0:3]

	// Location codes
	locations := map[string]string{
		"CTH": "Celestica - Thailand",
		"FAA": "Flextronics - San Jose, CA.",
		"FOC": "Foxconn - Shenzhen China",
		"JAB": "Jabil - Florida",
		"JPE": "Jabil - Malaysia",
		"JSH": "Jabil - Shanghai China",
		"PEN": "Solectron - Malaysia",
		"TAU": "Solectron - Texas",
	}

	// exists is a bool which will be true if the value exists in the map
	if value, exists := locations[locationCode]; exists {
		s.location = value
	} else {
		s.location = "Unknown"
	}
}

type argT struct {
	cli.Helper
	Serial   string `cli:"s,serial"   usage:"serial to parse"`
	Filename string `cli:"f,filename" usage:"filename with serials to parse"`
}

var (
	helptext = `
Parses provided cisco serial and returns manufactured date

Examples:
./serial_to_date --serial FAA04459FNI
./serial_to_date --filename serials.txt
`
)

func main() {
	cli.Run(new(argT), func(ctx *cli.Context) error {
		argv := ctx.Argv().(*argT)

		// Read single serial
		if argv.Serial != "" {
			s := serial{serialNum: argv.Serial}
			s.parseSerial()
		}

		// Read filename
		if argv.Filename != "" {
			file, err := os.Open(argv.Filename)
			if err != nil {
				log.Fatal(err)
			}
			defer file.Close()

			scanner := bufio.NewScanner(file)
			for scanner.Scan() {
				s := serial{serialNum: scanner.Text()}
				s.parseSerial()
				fmt.Println("")
			}
		}

		// If neither flag, print help
		if argv.Serial == "" && argv.Filename == "" {
			log.Fatal(helptext)
		}

		return nil
	})
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"

	"github.com/DHowett/go-plist"
)

type diskList struct {
	WholeDisks []string `plist:"WholeDisks"`
}

func errprint(msg string) {
	fmt.Fprintf(os.Stderr, "%s", msg)
}

func errexit(msg string) {
	errprint(msg)
	os.Exit(1)
}

func getDisks() ([]string, error) {
	out, err := exec.Command("diskutil", "list", "-plist", "external").CombinedOutput()
	if err != nil {
		return nil, err
	}
	var disks diskList
	err = plist.NewDecoder(bytes.NewReader(out)).Decode(&disks)
	if err != nil {
		return nil, err
	}
	return disks.WholeDisks, nil
}

func eject(disk string) {
	out, err := exec.Command("diskutil", "eject", disk).CombinedOutput()
	if err != nil {
		errexit(string(out))
	}
}

func main() {
	disks, err := getDisks()
	if err != nil {
		errexit("get disks error")
	}
	for i := len(disks) - 1; i >= 0; i-- {
		eject(disks[i])
	}
}
<commit_msg>clean up<commit_after>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"

	"github.com/DHowett/go-plist"
)

type diskList struct {
	WholeDisks []string `plist:"WholeDisks"`
}

func errexit(msg string) {
	fmt.Fprintf(os.Stderr, "%s", msg)
	os.Exit(1)
}

func getDisks() ([]string, error) {
	out, err := exec.Command("diskutil", "list", "-plist", "external").CombinedOutput()
	if err != nil {
		return nil, err
	}
	var disks diskList
	err = plist.NewDecoder(bytes.NewReader(out)).Decode(&disks)
	if err != nil {
		return nil, err
	}
	return disks.WholeDisks, nil
}

func eject(disk string) {
	out, err := exec.Command("diskutil", "eject", disk).CombinedOutput()
	if err != nil {
		errexit(string(out))
	}
}

func main() {
	disks, err := getDisks()
	if err != nil {
		errexit("get disks error")
	}
	for i := len(disks) - 1; i >= 0; i-- {
		eject(disks[i])
	}
}
<|endoftext|>


<commit_before>package main

import (
	//"github.com/kisielk/whisper-go/whisper"
	whisper "github.com/robyoung/go-whisper"
	pickle "github.com/kisielk/og-rek"

	"net/http"
	"encoding/json"
	"path/filepath"
	"strings"
	"strconv"
	"math"
	"fmt"
)

var config = struct {
	WhisperData	string
}{
	WhisperData: "/var/lib/carbon/whisper",
	//WhisperData: "..",
}

type WhisperFetchResponse struct {
	Name        string      `json:"name"`
	StartTime   int         `json:"startTime"`
	StopTime    int         `json:"stopTime"`
	StepTime    int         `json:"stepTime"`
	Values      []float64   `json:"values"`
	IsAbsent    []bool      `json:"isAbsent"`
}

type WhisperGlobResponse struct {
	Name        string      `json:"name"`
	Paths       []string    `json:"paths"`
}

func findHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /metrics/find/?local=1&format=pickle&query=general.hadoop.lhr4.ha201jobtracker-01.jobtracker.NonHeapMemoryUsage.committed HTTP/1.1
//	http://localhost:8080/metrics/find/?query=test
	req.ParseForm()
	glob := req.FormValue("query")
	format := req.FormValue("format")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		return
	}

	/* things to glob:
	 * - carbon.relays  -> carbon.relays
	 * - carbon.re      -> carbon.relays, carbon.rewhatever
	 * - carbon.[rz]    -> carbon.relays, carbon.zipper
	 * - carbon.{re,zi} -> carbon.relays, carbon.zipper
	 * - implicit * at the end of each query
	 * - match is either dir or .wsp file
	 * unfortunately, filepath.Glob doesn't handle the curly brace
	 * expansion for us */
	lbrace := strings.Index(glob, "{")
	rbrace := -1
	if lbrace > -1 {
		rbrace = strings.Index(glob[lbrace:], "}")
		if rbrace > -1 {
			rbrace += lbrace
		}
	}
	files := make([]string, 0)
	if lbrace > -1 && rbrace > -1 {
		expansion := glob[lbrace + 1:rbrace]
		parts := strings.Split(expansion, ",")
		for _, sub := range parts {
			sglob := glob[:lbrace] + sub + glob[rbrace + 1:]
			path := config.WhisperData + "/" + strings.Replace(sglob, ".", "/", -1) + "*"
			nfiles, err := filepath.Glob(path)
			if err == nil {
				files = append(files, nfiles...)
			}
		}
	} else {
		path := config.WhisperData + "/" + strings.Replace(glob, ".", "/", -1) + "*"
		nfiles, err := filepath.Glob(path)
		if err == nil {
			files = append(files, nfiles...)
		}
	}

	leafs := make([]bool, len(files))
	for i, p := range files {
		p = p[len(config.WhisperData + "/"):]
		if strings.HasSuffix(p, ".wsp") {
			p = p[:len(p) - 4]
			leafs[i] = true
		} else {
			leafs[i] = false
		}
		files[i] = strings.Replace(p, "/", ".", -1)
	}

	if format == "json" {
		response := WhisperGlobResponse {
			Name:		glob,
			Paths:		make([]string, 0),
		}
		for _, p := range files {
			response.Paths = append(response.Paths, p)
		}
		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", glob, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		// [{'metric_path': 'metric', 'intervals': [(x,y)], 'isLeaf': True},]
		var metrics []map[string]interface{}
		var m map[string]interface{}

		for i, p := range files {
			m = make(map[string]interface{})
			m["metric_path"] = p
			// m["intervals"] = dunno how to do a tuple here
			m["isLeaf"] = leafs[i]
			metrics = append(metrics, m)
		}

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}
	fmt.Printf("find: %d hits for %s\n", len(files), glob)
	return
}

func fetchHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /render/?target=general.me.1.percent_time_active.pfnredis&format=pickle&from=1396008021&until=1396022421 HTTP/1.1
//	http://localhost:8080/render/?target=testmetric&format=json&from=1395961200&until=1395961800
	req.ParseForm()
	metric := req.FormValue("target")
	format := req.FormValue("format")
	from := req.FormValue("from")
	until := req.FormValue("until")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		http.Error(wr, "Bad request (unsupported format)", http.StatusBadRequest)
		return
	}

	path := config.WhisperData + "/" + strings.Replace(metric, ".", "/", -1) + ".wsp"
	w, err := whisper.Open(path)
	if err != nil {
		// the FE/carbonzipper often requests metrics we don't have
		//fmt.Printf("failed to open %s: %s\n", path, err)
		w = nil
	}

	i, err := strconv.Atoi(from)
	if err != nil {
		fmt.Printf("fromTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	fromTime := int(i)
	i, err = strconv.Atoi(until)
	if err != nil {
		fmt.Printf("untilTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	untilTime := int(i)

	if (w != nil) {
		defer w.Close()
	} else {
		http.Error(wr, "Bad request (invalid from/until time)", http.StatusBadRequest)
		return
	}

	points, err := w.Fetch(fromTime, untilTime)
	if err != nil {
		fmt.Printf("failed to getch points from %s: %s\n", path, err)
		return
	}
	values := points.Values()

	if format == "json" {
		response := WhisperFetchResponse {
			Name:		metric,
			StartTime:	points.FromTime(),
			StopTime:	points.UntilTime(),
			StepTime:	points.Step(),
			Values:		make([]float64, len(values)),
			IsAbsent:	make([]bool, len(values)),
		}

		for i, p := range values {
			if math.IsNaN(p) {
				response.Values[i] = 0
				response.IsAbsent[i] = true
			} else {
				response.Values[i] = p
				response.IsAbsent[i] = false
			}
		}

		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", path, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		//[{'start': 1396271100, 'step': 60, 'name': 'metric',
		//'values': [9.0, 19.0, None], 'end': 1396273140}
		var metrics []map[string]interface{}
		var m map[string]interface{}

		m = make(map[string]interface{})
		m["start"] = points.FromTime()
		m["step"] = points.Step()
		m["end"] = points.UntilTime()
		m["name"] = metric

		mv := make([]interface{}, len(values))
		for i, p := range values {
			if math.IsNaN(p) {
				mv[i] = nil
			} else {
				mv[i] = p
			}
		}

		m["values"] = mv
		metrics = append(metrics, m)

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}

	fmt.Printf("served %d points\n", len(values))
	return
}

func main() {
	http.HandleFunc("/metrics/find/", findHandler)
	http.HandleFunc("/render/", fetchHandler)

	http.ListenAndServe(":8080", nil)
}
<commit_msg>fetch: return 404 for metrics we don't have<commit_after>package main

import (
	//"github.com/kisielk/whisper-go/whisper"
	whisper "github.com/robyoung/go-whisper"
	pickle "github.com/kisielk/og-rek"

	"net/http"
	"encoding/json"
	"path/filepath"
	"strings"
	"strconv"
	"math"
	"fmt"
)

var config = struct {
	WhisperData	string
}{
	WhisperData: "/var/lib/carbon/whisper",
	//WhisperData: "..",
}

type WhisperFetchResponse struct {
	Name        string      `json:"name"`
	StartTime   int         `json:"startTime"`
	StopTime    int         `json:"stopTime"`
	StepTime    int         `json:"stepTime"`
	Values      []float64   `json:"values"`
	IsAbsent    []bool      `json:"isAbsent"`
}

type WhisperGlobResponse struct {
	Name        string      `json:"name"`
	Paths       []string    `json:"paths"`
}

func findHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /metrics/find/?local=1&format=pickle&query=general.hadoop.lhr4.ha201jobtracker-01.jobtracker.NonHeapMemoryUsage.committed HTTP/1.1
//	http://localhost:8080/metrics/find/?query=test
	req.ParseForm()
	glob := req.FormValue("query")
	format := req.FormValue("format")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		return
	}

	/* things to glob:
	 * - carbon.relays  -> carbon.relays
	 * - carbon.re      -> carbon.relays, carbon.rewhatever
	 * - carbon.[rz]    -> carbon.relays, carbon.zipper
	 * - carbon.{re,zi} -> carbon.relays, carbon.zipper
	 * - implicit * at the end of each query
	 * - match is either dir or .wsp file
	 * unfortunately, filepath.Glob doesn't handle the curly brace
	 * expansion for us */
	lbrace := strings.Index(glob, "{")
	rbrace := -1
	if lbrace > -1 {
		rbrace = strings.Index(glob[lbrace:], "}")
		if rbrace > -1 {
			rbrace += lbrace
		}
	}
	files := make([]string, 0)
	if lbrace > -1 && rbrace > -1 {
		expansion := glob[lbrace + 1:rbrace]
		parts := strings.Split(expansion, ",")
		for _, sub := range parts {
			sglob := glob[:lbrace] + sub + glob[rbrace + 1:]
			path := config.WhisperData + "/" + strings.Replace(sglob, ".", "/", -1) + "*"
			nfiles, err := filepath.Glob(path)
			if err == nil {
				files = append(files, nfiles...)
			}
		}
	} else {
		path := config.WhisperData + "/" + strings.Replace(glob, ".", "/", -1) + "*"
		nfiles, err := filepath.Glob(path)
		if err == nil {
			files = append(files, nfiles...)
		}
	}

	leafs := make([]bool, len(files))
	for i, p := range files {
		p = p[len(config.WhisperData + "/"):]
		if strings.HasSuffix(p, ".wsp") {
			p = p[:len(p) - 4]
			leafs[i] = true
		} else {
			leafs[i] = false
		}
		files[i] = strings.Replace(p, "/", ".", -1)
	}

	if format == "json" {
		response := WhisperGlobResponse {
			Name:		glob,
			Paths:		make([]string, 0),
		}
		for _, p := range files {
			response.Paths = append(response.Paths, p)
		}
		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", glob, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		// [{'metric_path': 'metric', 'intervals': [(x,y)], 'isLeaf': True},]
		var metrics []map[string]interface{}
		var m map[string]interface{}

		for i, p := range files {
			m = make(map[string]interface{})
			m["metric_path"] = p
			// m["intervals"] = dunno how to do a tuple here
			m["isLeaf"] = leafs[i]
			metrics = append(metrics, m)
		}

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}
	fmt.Printf("find: %d hits for %s\n", len(files), glob)
	return
}

func fetchHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /render/?target=general.me.1.percent_time_active.pfnredis&format=pickle&from=1396008021&until=1396022421 HTTP/1.1
//	http://localhost:8080/render/?target=testmetric&format=json&from=1395961200&until=1395961800
	req.ParseForm()
	metric := req.FormValue("target")
	format := req.FormValue("format")
	from := req.FormValue("from")
	until := req.FormValue("until")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		http.Error(wr, "Bad request (unsupported format)", http.StatusBadRequest)
		return
	}

	path := config.WhisperData + "/" + strings.Replace(metric, ".", "/", -1) + ".wsp"
	w, err := whisper.Open(path)
	if err != nil {
		// the FE/carbonzipper often requests metrics we don't have
		//fmt.Printf("failed to open %s: %s\n", path, err)
		http.Error(wr, "Metric not found", http.StatusNotFound)
		return
	}

	i, err := strconv.Atoi(from)
	if err != nil {
		fmt.Printf("fromTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	fromTime := int(i)
	i, err = strconv.Atoi(until)
	if err != nil {
		fmt.Printf("untilTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	untilTime := int(i)

	if (w != nil) {
		defer w.Close()
	} else {
		http.Error(wr, "Bad request (invalid from/until time)", http.StatusBadRequest)
		return
	}

	points, err := w.Fetch(fromTime, untilTime)
	if err != nil {
		fmt.Printf("failed to getch points from %s: %s\n", path, err)
		return
	}
	values := points.Values()

	if format == "json" {
		response := WhisperFetchResponse {
			Name:		metric,
			StartTime:	points.FromTime(),
			StopTime:	points.UntilTime(),
			StepTime:	points.Step(),
			Values:		make([]float64, len(values)),
			IsAbsent:	make([]bool, len(values)),
		}

		for i, p := range values {
			if math.IsNaN(p) {
				response.Values[i] = 0
				response.IsAbsent[i] = true
			} else {
				response.Values[i] = p
				response.IsAbsent[i] = false
			}
		}

		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", path, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		//[{'start': 1396271100, 'step': 60, 'name': 'metric',
		//'values': [9.0, 19.0, None], 'end': 1396273140}
		var metrics []map[string]interface{}
		var m map[string]interface{}

		m = make(map[string]interface{})
		m["start"] = points.FromTime()
		m["step"] = points.Step()
		m["end"] = points.UntilTime()
		m["name"] = metric

		mv := make([]interface{}, len(values))
		for i, p := range values {
			if math.IsNaN(p) {
				mv[i] = nil
			} else {
				mv[i] = p
			}
		}

		m["values"] = mv
		metrics = append(metrics, m)

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}

	fmt.Printf("served %d points\n", len(values))
	return
}

func main() {
	http.HandleFunc("/metrics/find/", findHandler)
	http.HandleFunc("/render/", fetchHandler)

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
  //"unicode/utf8"
  //"container/list"
  //"bytes"
	"net/http"
	//"encoding/json"
	//"net/url"
    "strings"
	// "database/sql"
	"os"
	"github.com/line/line-bot-sdk-go/linebot"
	// _ "github.com/go-sql-driver/mysql"
)

var bot *linebot.Client
var echo string
var op string
var bottun bool

type Data struct{
    resultType string `json:"resultType"`
    resultQuestion string `json:"resultQuestion"`
    resultContent []content `json:"resultContent"`
    requirementType string `json:"requirementType"`
}

type content struct{
    entity string `json:"entity"`
    Type string `json:"Type"`
}

var d Data

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
    http.HandleFunc("/", sayhelloName) // set router
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)

    bottun = false
}

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()  // parse arguments, you have to call this by yourself
    fmt.Println(r.Form)  // print form information in server side
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["user"])
    fmt.Println(r.Form["message"])
    bot.PushMessage(r.Form["user"][0], linebot.NewTextMessage(r.Form["message"][0])).Do()
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, r.Form["user"][0]+r.Form["message"][0]) // send data to client side
}

// func mysql(){
// 	var db, err = sql.Open("mysql","wmlab:wmlab@tcp(140.115.54.82:3306)/wmlab?charset=utf8")
// 	if err != nil {
// 		fmt.Println(err)
//          // Just for example purpose. You should use proper error handling instead of panic
//     }
//     defer db.Close()

//  	err = db.Ping()
// 	if err != nil {
// 		log.Fatal(err)
// 	}

// 	rows, err := db.Query("select * from test")
// 	if err != nil {
// 		log.Println(err)
// 	}

// 	defer rows.Close()
// 	var col1 int
// 	for rows.Next() {
// 		err := rows.Scan(&col1)
// 		if err != nil {
// 			log.Fatal(err)
// 		}
// 		dbinfo=col1
// 	}
// }
func httpGet(q string , id string) {

    echo = "OK"
    bottun = false
    op = ""

    q = strings.Replace( q , " " , "," , -1)
    //q = strings.Replace("oink oink oink", "oink", "moo", -1)
    resp, err := http.Get("http://140.115.54.93:8088/?q="+q+"&id="+id)
    if err != nil {
        // handle error
       panic(err.Error())
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        // handle error
       panic(err.Error())
    }

    echo = string(body)

    if echo == "location"{
       bottun = true
    }

    // _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(echo)).Do()

    //------------for Luis
    // var r =  map[string]interface{}{}
    // var tempString string
    // tempString =string(body)

    // temp1 := strings.Split(tempString,"entity")
    // temp2 := strings.Split(tempString,"\"Type")
    // entity := list.New()
    // Type := list.New()
    // for i := 0; i < len(temp1); i++ {
    //   if i>=1{
    //     entity.PushBack( strings.Split(strings.Split(temp1[i],"\",")[0],":\"")[1] )
    //   }
    // }
    // for i := 0; i < len(temp2); i++ {
    //   if i>=1{
    //     Type.PushBack( strings.Split(strings.Split(temp2[i],"\"}")[0],":\"")[1] )
    //   }
    // }
    // json.Unmarshal(body, &r)

    // if r["resultType"].(string) == "none" {
    //   echo = "我不了解你在說什麼～@@"
    // } else if r["resultType"].(string) == "greeting" {
    //   echo = "你好！我是LUIS！我可以提供您數學的教材或是練習題喔！"
    // } else if r["resultType"].(string) == "appreciation" {
    //   echo = "歡迎您再次使用LUIS!我很樂意再次提供您服務！"
    // } else if r["resultType"].(string) == "connectionError" {
    //   echo = "對不起，我出了點問題，現在沒辦法回答你問題@@"
    // } else if r["resultType"].(string) == "unknown" {
    //   echo = "不好意思，我不知道你問的定理是什麼QQ"
    // } else if r["resultType"].(string) == "question" {
    //   if r["requirementType"].(string) == "none" {
    //     bottun = true
    //     for e:= entity.Front();e!=nil;e = e.Next(){

    //      op += e.Value.(string)
    //     }
    //   }
    // }

    //-----------------for luis

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	//GG

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:

        if op!= ""{
          echo ="OK"
          bottun = false

        } else if event.Source.UserID == ""{
            _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(message.Text)).Do()
            if err != nil {
            // handle error
            //    ..
            echo = err.Error()
            }

        } else {
        	httpGet(message.Text,event.Source.UserID)
        }
				// mysql()
				//message.ID+":"+message.Text
        if bottun {
           //_, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(echo)).Do()
            // var ff string
            // var gg string
            // ff = "我要"+op+"的練習題"
            // gg = "我要"+op+"的教材"
            // leftBtn := linebot.NewMessageTemplateAction("練習題", ff)
            // rightBtn := linebot.NewMessageTemplateAction("教材", gg)
            uri := linebot.NewURITemplateAction("提供地點","line://nv/location")
            template := linebot.NewButtonsTemplate("請問您目前所處的地點是?","","", uri)

            templatemessgage := linebot.NewTemplateMessage("Sorry :(, please update your app.", template)
            _, err = bot.ReplyMessage(event.ReplyToken, templatemessgage).Do()
           //op=""

        } else {
           _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           // _, err = bot.PushMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           op=""
        }

			}
		}
	}
}
<commit_msg>FF<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
  //"unicode/utf8"
  //"container/list"
  //"bytes"
	"net/http"
	//"encoding/json"
	//"net/url"
    "strings"
	// "database/sql"
	"os"
	"github.com/line/line-bot-sdk-go/linebot"
	// _ "github.com/go-sql-driver/mysql"
)

var bot *linebot.Client
var echo string
var op string
var bottun bool

type Data struct{
    resultType string `json:"resultType"`
    resultQuestion string `json:"resultQuestion"`
    resultContent []content `json:"resultContent"`
    requirementType string `json:"requirementType"`
}

type content struct{
    entity string `json:"entity"`
    Type string `json:"Type"`
}

var d Data

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
    http.HandleFunc("/", sayhelloName) // set router
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)

    bottun = false
}

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()  // parse arguments, you have to call this by yourself
    fmt.Println(r.Form)  // print form information in server side
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["user"])
    fmt.Println(r.Form["message"])
    bot.PushMessage(r.Form["user"][0], linebot.NewTextMessage(r.Form["message"][0])).Do()
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, r.Form["user"][0]+r.Form["message"][0]) // send data to client side
}

// func mysql(){
// 	var db, err = sql.Open("mysql","wmlab:wmlab@tcp(140.115.54.82:3306)/wmlab?charset=utf8")
// 	if err != nil {
// 		fmt.Println(err)
//          // Just for example purpose. You should use proper error handling instead of panic
//     }
//     defer db.Close()

//  	err = db.Ping()
// 	if err != nil {
// 		log.Fatal(err)
// 	}

// 	rows, err := db.Query("select * from test")
// 	if err != nil {
// 		log.Println(err)
// 	}

// 	defer rows.Close()
// 	var col1 int
// 	for rows.Next() {
// 		err := rows.Scan(&col1)
// 		if err != nil {
// 			log.Fatal(err)
// 		}
// 		dbinfo=col1
// 	}
// }
func httpGet(q string , id string) {

    echo = "OK"
    bottun = false
    op = ""

    q = strings.Replace( q , " " , "," , -1)
    //q = strings.Replace("oink oink oink", "oink", "moo", -1)
    resp, err := http.Get("http://140.115.54.93:8088/?q="+q+"&id="+id)
    if err != nil {
        // handle error
       panic(err.Error())
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        // handle error
       panic(err.Error())
    }

    echo = string(body)

    if echo == "location"{
       bottun = true
    }

    // _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(echo)).Do()

    //------------for Luis
    // var r =  map[string]interface{}{}
    // var tempString string
    // tempString =string(body)

    // temp1 := strings.Split(tempString,"entity")
    // temp2 := strings.Split(tempString,"\"Type")
    // entity := list.New()
    // Type := list.New()
    // for i := 0; i < len(temp1); i++ {
    //   if i>=1{
    //     entity.PushBack( strings.Split(strings.Split(temp1[i],"\",")[0],":\"")[1] )
    //   }
    // }
    // for i := 0; i < len(temp2); i++ {
    //   if i>=1{
    //     Type.PushBack( strings.Split(strings.Split(temp2[i],"\"}")[0],":\"")[1] )
    //   }
    // }
    // json.Unmarshal(body, &r)

    // if r["resultType"].(string) == "none" {
    //   echo = "我不了解你在說什麼～@@"
    // } else if r["resultType"].(string) == "greeting" {
    //   echo = "你好！我是LUIS！我可以提供您數學的教材或是練習題喔！"
    // } else if r["resultType"].(string) == "appreciation" {
    //   echo = "歡迎您再次使用LUIS!我很樂意再次提供您服務！"
    // } else if r["resultType"].(string) == "connectionError" {
    //   echo = "對不起，我出了點問題，現在沒辦法回答你問題@@"
    // } else if r["resultType"].(string) == "unknown" {
    //   echo = "不好意思，我不知道你問的定理是什麼QQ"
    // } else if r["resultType"].(string) == "question" {
    //   if r["requirementType"].(string) == "none" {
    //     bottun = true
    //     for e:= entity.Front();e!=nil;e = e.Next(){

    //      op += e.Value.(string)
    //     }
    //   }
    // }

    //-----------------for luis

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	//GG

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:

        if op!= ""{
          echo ="OK"
          bottun = false

        } else if event.Source.UserID == ""{
            _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(message.Text)).Do()
            if err != nil {
            // handle error
            //    ..
            echo = err.Error()
            }

        } else {
        	httpGet(message.Text,event.Source.UserID)
        }
				// mysql()
				//message.ID+":"+message.Text
        if bottun {
           //_, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(echo)).Do()
            // var ff string
            // var gg string
            // ff = "我要"+op+"的練習題"
            // gg = "我要"+op+"的教材"
            // leftBtn := linebot.NewMessageTemplateAction("練習題", ff)
            // rightBtn := linebot.NewMessageTemplateAction("教材", gg)
            uri := linebot.NewURITemplateAction("提供地點","line://nv/location")
            template := linebot.NewButtonsTemplate("","地點","請問您目前所處的地點是?", uri)

            templatemessgage := linebot.NewTemplateMessage("Sorry :(, please update your app.", template)
            _, err = bot.ReplyMessage(event.ReplyToken, templatemessgage).Do()
           //op=""

        } else {
           _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           // _, err = bot.PushMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           op=""
        }

			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/fatih/color"
)

var (
	age      float64
	birthday time.Time
	err      error
	fp       *os.File
	input    string
	now      time.Time

	Bold = color.New(color.Bold).SprintFunc()
	Cyan = color.New(color.FgCyan, color.Bold).SprintfFunc()
)

func main() {
	getBirtday()
	showAge()
	fp.Close()
}

func getHomePath() string {
	return os.Getenv("HOME")
}

func getBirtday() {
	fp, err = os.OpenFile(getHomePath()+"/.age", os.O_RDWR|os.O_CREATE, os.ModePerm)
	defer fp.Close()
	fstat, _ := fp.Stat()
	if os.IsNotExist(err) || fstat.Size() != 10 {
		setBirtday()
	}
	buf := make([]byte, 10)
	fp.Read(buf)
	birthday, _ = time.Parse("2006/01/02", string(buf))
}

func setBirtday() {
	fmt.Printf("Please enter your birthday(format is %s),like %s\n", Bold("yyyy/MM/dd"), Bold("1991/03/04"))
	fmt.Scanf("%s", &input)
	birthday, err = time.Parse("2006/01/02", input)
	if err != nil {
		// Move the cursor to the origin, clean screen and show msg.
		fmt.Println("\033[0;0H\033[2JError date format,try again.")
		time.Sleep(5e8)
		setBirtday()
	}
	fp.WriteString(input)
	showAge()
}

func showAge() {
	for {
		now = time.Now()
		age = float64(now.UnixNano()-birthday.UnixNano()) / 1e9 / 86400 / 365
		fmt.Printf("Time flies, you've been %s years old.\r", Cyan("%3.9f", age))
		time.Sleep(3e7)
	}
}
<commit_msg>remove not used code.<commit_after>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/fatih/color"
)

var (
	age      float64
	birthday time.Time
	err      error
	fp       *os.File
	input    string
	now      time.Time

	Bold = color.New(color.Bold).SprintFunc()
	Cyan = color.New(color.FgCyan, color.Bold).SprintfFunc()
)

func main() {
	getBirtday()
	showAge()
}

func getHomePath() string {
	return os.Getenv("HOME")
}

func getBirtday() {
	fp, err = os.OpenFile(getHomePath()+"/.age", os.O_RDWR|os.O_CREATE, os.ModePerm)
	defer fp.Close()
	fstat, _ := fp.Stat()
	if os.IsNotExist(err) || fstat.Size() != 10 {
		setBirtday()
	}
	buf := make([]byte, 10)
	fp.Read(buf)
	birthday, _ = time.Parse("2006/01/02", string(buf))
}

func setBirtday() {
	fmt.Printf("Please enter your birthday(format is %s),like %s\n", Bold("yyyy/MM/dd"), Bold("1991/03/04"))
	fmt.Scanf("%s", &input)
	birthday, err = time.Parse("2006/01/02", input)
	if err != nil {
		// Move the cursor to the origin, clean screen and show msg.
		fmt.Println("\033[0;0H\033[2JError date format,try again.")
		time.Sleep(5e8)
		setBirtday()
	}
	fp.WriteString(input)
	showAge()
}

func showAge() {
	for {
		now = time.Now()
		age = float64(now.UnixNano()-birthday.UnixNano()) / 1e9 / 86400 / 365
		fmt.Printf("Time flies, you've been %s years old.\r", Cyan("%3.9f", age))
		time.Sleep(3e7)
	}
}
<|endoftext|>