<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 (
	"github.com/Matir/gobuster/client"
	"github.com/Matir/gobuster/filter"
	"github.com/Matir/gobuster/logging"
	"github.com/Matir/gobuster/results"
	"github.com/Matir/gobuster/robots"
	ss "github.com/Matir/gobuster/settings"
	"github.com/Matir/gobuster/util"
	"github.com/Matir/gobuster/wordlist"
	"github.com/Matir/gobuster/worker"
	"github.com/Matir/gobuster/workqueue"
	"net/url"
	"runtime"
)

// This is the main runner for gobuster.
// TODO: separate the actual scanning from all of the setup steps
func main() {
	util.EnableStackTraces()

	// Load scan settings
	settings, err := ss.GetScanSettings()
	if err != nil {
		logging.Logf(logging.LogFatal, err.Error())
		return
	}
	logging.ResetLog(settings.LogfilePath, settings.LogLevel)
	logging.Logf(logging.LogInfo, "Flags: %s", settings)

	// Set number of threads
	logging.Logf(logging.LogDebug, "Setting GOMAXPROCS to %d.", settings.Threads)
	runtime.GOMAXPROCS(settings.Threads)

	// Load wordlist
	var words []string
	if settings.WordlistPath != "" {
		words, err = wordlist.ReadWordlistFile(settings.WordlistPath)
	} else {
		words, err = wordlist.LoadDefaultWordlist()
	}
	if err != nil {
		logging.Logf(logging.LogFatal, "Unable to load wordlist: %s", err.Error())
		return
	}

	// Build an HTTP Client Factory
	logging.Logf(logging.LogDebug, "Creating Client Factory...")
	clientFactory := client.NewProxyClientFactory(settings.Proxies, settings.Timeout, settings.UserAgent)

	// Starting point
	scope, err := url.Parse(settings.BaseURL)
	if err != nil {
		logging.Logf(logging.LogFatal, "Unable to parse BaseURL: %s", err.Error())
		return
	}
	if scope.Path == "" {
		scope.Path = "/"
	}
	logging.Logf(logging.LogDebug, "BaseURL: %s", scope.String())

	// Setup the main workqueue
	logging.Logf(logging.LogDebug, "Starting work queue...")
	queue := workqueue.NewWorkQueue(settings.QueueSize, MakeScopeFunc(scope))
	queue.RunInBackground()

	logging.Logf(logging.LogDebug, "Creating expander and filter...")
	expander := filter.Expander{Wordlist: &words, Adder: queue.GetAddCount()}
	expander.ProcessWordlist()
	filter := filter.NewWorkFilter(settings, queue.GetDoneFunc())
	work := filter.Filter(expander.Expand(queue.GetWorkChan()))

	// Check robots mode
	if settings.RobotsMode == ss.ObeyRobots {
		robotsData, err := robots.GetRobotsForURL(scope, clientFactory)
		if err != nil {
			logging.Logf(logging.LogWarning, "Unable to get robots.txt data: %s", err)
		} else {
			for _, disallowed := range robotsData.GetForUserAgent(settings.UserAgent) {
				if pathURL, err := url.Parse(disallowed); err != nil {
					disallowedURL := scope.ResolveReference(pathURL)
					filter.FilterURL(disallowedURL)
				}
			}
		}
	}

	logging.Logf(logging.LogDebug, "Creating results manager...")
	rchan := make(chan results.Result, settings.QueueSize)
	resultsManager, err := results.GetResultsManager(settings)
	if err != nil {
		logging.Logf(logging.LogFatal, "Unable to start results manager: %s", err.Error())
		return
	}

	logging.Logf(logging.LogDebug, "Starting %d workers...", settings.Workers)
	workers := worker.StartWorkers(settings, clientFactory, work, queue.GetAddFunc(), queue.GetDoneFunc(), rchan)
	if settings.ParseHTML {
		htmlWorker := worker.NewHTMLWorker(queue.GetAddFunc())
		worker.SetPageWorkers(workers, htmlWorker)
	}

	logging.Logf(logging.LogDebug, "Starting results manager...")
	resultsManager.Run(rchan)

	// Kick things off with the seed URL
	logging.Logf(logging.LogDebug, "Adding starting URL: %s", scope)
	queue.AddURLs(scope)

	// Wait for work to be done
	logging.Logf(logging.LogDebug, "Main goroutine waiting for work...")
	queue.WaitPipe()
	logging.Logf(logging.LogDebug, "Work done.")

	// Cleanup
	queue.InputFinished()
	close(rchan)

	resultsManager.Wait()
	logging.Logf(logging.LogDebug, "Done!")
}

// Build a function to check if the target URL is in scope.
func MakeScopeFunc(scope *url.URL) func(*url.URL) bool {
	return func(target *url.URL) bool {
		return util.URLIsSubpath(scope, target)
	}
}
<commit_msg>Support seeding from robots.txt.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 (
	"github.com/Matir/gobuster/client"
	"github.com/Matir/gobuster/filter"
	"github.com/Matir/gobuster/logging"
	"github.com/Matir/gobuster/results"
	"github.com/Matir/gobuster/robots"
	ss "github.com/Matir/gobuster/settings"
	"github.com/Matir/gobuster/util"
	"github.com/Matir/gobuster/wordlist"
	"github.com/Matir/gobuster/worker"
	"github.com/Matir/gobuster/workqueue"
	"net/url"
	"runtime"
)

// This is the main runner for gobuster.
// TODO: separate the actual scanning from all of the setup steps
func main() {
	util.EnableStackTraces()

	// Load scan settings
	settings, err := ss.GetScanSettings()
	if err != nil {
		logging.Logf(logging.LogFatal, err.Error())
		return
	}
	logging.ResetLog(settings.LogfilePath, settings.LogLevel)
	logging.Logf(logging.LogInfo, "Flags: %s", settings)

	// Set number of threads
	logging.Logf(logging.LogDebug, "Setting GOMAXPROCS to %d.", settings.Threads)
	runtime.GOMAXPROCS(settings.Threads)

	// Load wordlist
	var words []string
	if settings.WordlistPath != "" {
		words, err = wordlist.ReadWordlistFile(settings.WordlistPath)
	} else {
		words, err = wordlist.LoadDefaultWordlist()
	}
	if err != nil {
		logging.Logf(logging.LogFatal, "Unable to load wordlist: %s", err.Error())
		return
	}

	// Build an HTTP Client Factory
	logging.Logf(logging.LogDebug, "Creating Client Factory...")
	clientFactory := client.NewProxyClientFactory(settings.Proxies, settings.Timeout, settings.UserAgent)

	// Starting point
	scope, err := url.Parse(settings.BaseURL)
	if err != nil {
		logging.Logf(logging.LogFatal, "Unable to parse BaseURL: %s", err.Error())
		return
	}
	if scope.Path == "" {
		scope.Path = "/"
	}
	logging.Logf(logging.LogDebug, "BaseURL: %s", scope.String())

	// Setup the main workqueue
	logging.Logf(logging.LogDebug, "Starting work queue...")
	queue := workqueue.NewWorkQueue(settings.QueueSize, MakeScopeFunc(scope))
	queue.RunInBackground()

	logging.Logf(logging.LogDebug, "Creating expander and filter...")
	expander := filter.Expander{Wordlist: &words, Adder: queue.GetAddCount()}
	expander.ProcessWordlist()
	filter := filter.NewWorkFilter(settings, queue.GetDoneFunc())
	work := filter.Filter(expander.Expand(queue.GetWorkChan()))

	// Check robots mode
	if settings.RobotsMode == ss.ObeyRobots {
		robotsData, err := robots.GetRobotsForURL(scope, clientFactory)
		if err != nil {
			logging.Logf(logging.LogWarning, "Unable to get robots.txt data: %s", err)
		} else {
			for _, disallowed := range robotsData.GetForUserAgent(settings.UserAgent) {
				if pathURL, err := url.Parse(disallowed); err != nil {
					disallowedURL := scope.ResolveReference(pathURL)
					filter.FilterURL(disallowedURL)
				}
			}
		}
	}

	logging.Logf(logging.LogDebug, "Creating results manager...")
	rchan := make(chan results.Result, settings.QueueSize)
	resultsManager, err := results.GetResultsManager(settings)
	if err != nil {
		logging.Logf(logging.LogFatal, "Unable to start results manager: %s", err.Error())
		return
	}

	logging.Logf(logging.LogDebug, "Starting %d workers...", settings.Workers)
	workers := worker.StartWorkers(settings, clientFactory, work, queue.GetAddFunc(), queue.GetDoneFunc(), rchan)
	if settings.ParseHTML {
		htmlWorker := worker.NewHTMLWorker(queue.GetAddFunc())
		worker.SetPageWorkers(workers, htmlWorker)
	}

	logging.Logf(logging.LogDebug, "Starting results manager...")
	resultsManager.Run(rchan)

	// Kick things off with the seed URL
	logging.Logf(logging.LogDebug, "Adding starting URL: %s", scope)
	queue.AddURLs(scope)

	// Potentially seed from robots
	if settings.RobotsMode == ss.SeedRobots {
		robotsData, err := robots.GetRobotsForURL(scope, clientFactory)
		if err != nil {
			logging.Logf(logging.LogWarning, "Unable to get robots.txt data: %s", err)
		} else {
			for _, path := range robotsData.GetAllPaths() {
				if pathURL, err := url.Parse(path); err != nil {
					// Filter will handle if this is out of scope
					queue.AddURLs(scope.ResolveReference(pathURL))
				}
			}
		}
	}

	// Wait for work to be done
	logging.Logf(logging.LogDebug, "Main goroutine waiting for work...")
	queue.WaitPipe()
	logging.Logf(logging.LogDebug, "Work done.")

	// Cleanup
	queue.InputFinished()
	close(rchan)

	resultsManager.Wait()
	logging.Logf(logging.LogDebug, "Done!")
}

// Build a function to check if the target URL is in scope.
func MakeScopeFunc(scope *url.URL) func(*url.URL) bool {
	return func(target *url.URL) bool {
		return util.URLIsSubpath(scope, target)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/NovemberFoxtrot/inebriati/calc"
)

var (
	StandardDrinks      = flag.Float64("drinks", 2.5, "How many drinks consumed")
	BodyWeightKiloGrams = flag.Float64("weight", 70.0, "Body weight in kilograms")
	DrinkingPeriodHours = flag.Float64("hours", 2.0, "How many hours it took to drink")
	Gender              = flag.String("gender", "male", "Specify male or female")
)

func main() {
	flag.Parse()

	i := inebriati.New(*StandardDrinks,*BodyWightKiloGrams,*DrinkingPeriod,*Gender)
	EstimatedBloodEthanolConcentration := i.Calc()
	fmt.Println(i)
}
<commit_msg>rm var<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/NovemberFoxtrot/inebriati/calc"
)

var (
	StandardDrinks      = flag.Float64("drinks", 2.5, "How many drinks consumed")
	BodyWeightKiloGrams = flag.Float64("weight", 70.0, "Body weight in kilograms")
	DrinkingPeriodHours = flag.Float64("hours", 2.0, "How many hours it took to drink")
	Gender              = flag.String("gender", "male", "Specify male or female")
)

func main() {
	flag.Parse()

	i := inebriati.New(*StandardDrinks,*BodyWightKiloGrams,*DrinkingPeriod,*Gender)
	i.Calc()

	fmt.Println(i)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "etcdsync"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "etcd-uri",
			Value: "localhost:2379",
			Usage: "uri where etcd can be found",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:    "diff",
			Aliases: []string{"d"},
			Usage:   "show differences between local fs & remote etcd",
			Action:  Diff,
		},
	}
}
<commit_msg>Add version<commit_after>package main

import (
	"os"

	"github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "etcdsync"
	app.Version = "1.0.0"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "etcd-uri",
			Value:  "localhost:2379",
			Usage:  "uri where etcd can be found",
			EnvVar: "ETCDSYNC_ETCD_URI",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:    "diff",
			Aliases: []string{"d"},
			Usage:   "show differences between local fs & remote etcd",
			Action:  Diff,
		},
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"
	"log"
	"net/http"
	"regexp"
	"io"
	"strings"

	"golang.org/x/net/http2"
)

type User struct {
	nick   string
	roomID string
	lastSent time.Time
}

type Message struct {
	roomID    string
	nick      string
	text      string
	timestamp time.Time
}

type Chatroom struct {
	ID       string
	title    string
	members  []*User
	msg      []*Message
	numOfMsg int
}

var (
	userMap = make(map[string]User)
	chatroomMap = make(map[string]Chatroom)
)

func addUser(nick string) User {
	user := User{nick: nick}
	userMap[nick] = user
	return user
}

func (c Chatroom)addMessage(m Message) {
	if c.msg == nil {
		c.msg = make([]*Message, 100)
	}
	c.msg = append(c.msg, &m)
}

const mainJS = `console.log("hello world");`

const indexHTML = `

	<title>Hello</title>

`

const loginHTML = `
<title>Welcome to CHATTING GO</title>

<form action="/chatlist">
Nickname:

<input type="text" name="nickname">

<input type="submit" value="Submit">
</form>

`

var rString = regexp.MustCompile(`.+`)

func main() {
	sampleChat := Chatroom{ID: "asdf", title: "fda"}
	chatroomMap["asdf"] = sampleChat

	var srv http.Server
	srv.Addr = "localhost:7072"

	http.HandleFunc("/main.js", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, mainJS)
	})
	http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {

		pusher, ok := w.(http.Pusher)
		if ok { // Push is supported. Try pushing rather than waiting for the browser.
			if err := pusher.Push("/main.js", nil); err != nil {
				log.Printf("Failed to push: %v", err)
			}
		}
		fmt.Fprintf(w, indexHTML)
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, loginHTML)
	})

	http.HandleFunc("/chat/say", func(w http.ResponseWriter, r *http.Request) {
		roomID := r.URL.Query().Get("roomID")
		nickname := r.URL.Query().Get("nickname")
		text := r.URL.Query().Get("text")

		chatroom, ok := chatroomMap[roomID]

		if !ok {
			log.Printf("roomID doesn't exist")
			return
		}

		message := Message{roomID,nickname,text,time.Now()}

		chatroom.addMessage(message)

	})

	http.HandleFunc("/chat", func(w http.ResponseWriter, r *http.Request) {
		header := r.Proto
		roomID := r.URL.Query().Get("roomID")
		nickname := r.URL.Query().Get("nickname")
		log.Println(header)
		log.Println(roomID)
		log.Println(nickname)

		clientGone := w.(http.CloseNotifier).CloseNotify()
		w.Header().Set("Content-Type", "text/plain")
		ticker := time.NewTicker(1 * time.Second)
		defer ticker.Stop()
		fmt.Fprintf(w, "# ~1KB of junk to force browsers to start rendering immediately: \n")
		io.WriteString(w, strings.Repeat("# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", 13))
		for {
			fmt.Fprintf(w, "%v\n", time.Now())
			w.(http.Flusher).Flush()
			select {
			case <-ticker.C:
				log.Println("tick")
			case <-clientGone:
				log.Println("Client %v disconnected from the clock", r.RemoteAddr)
				return
			}
		}
	})

	http.HandleFunc("/chatlist/", func(w http.ResponseWriter, r *http.Request) {
		nickname := r.URL.Query().Get("nickname")
		if nickname == "" {
			log.Printf("nickname has no value")
			return
		}

		user, ok := userMap[nickname]
		if ok && user.roomID != "" {
			//TODO: redirect with params
			http.Redirect(w, r, fmt.Sprintf("/chat"), 301)
			return
		}

		if user == (User{}) {
			user = addUser(nickname)
		}

		fmt.Fprintf(w, "ID: ")
		fmt.Fprintf(w, user.nick)
		fmt.Fprintf(w, "\n\nChannel List Below\n")

		for k, _ := range chatroomMap {
			fmt.Fprintf(w, "\n")
			fmt.Fprintf(w, k)
		}

	})

	http2.ConfigureServer(&srv, &http2.Server{})

	// Run crypto/tls/generate_cert.go to generate cert.pem and key.pem.
	// See https://golang.org/src/crypto/tls/generate_cert.go
	log.Fatal(http.ListenAndServeTLS(":7072", "cert.pem", "key.pem", nil))
}
<commit_msg>channel protocol implemented<commit_after>package main

import (
	"fmt"
	"time"
	"log"
	"net/http"
	"io"
	"strings"

	"golang.org/x/net/http2"
)

type User struct {
	nick   string
	roomID string
	lastSent time.Time
}

type Message struct {
	nick      string
	text      string
	timestamp time.Time
}

func (m Message)String() string {
	return fmt.Sprintf("%s : %s , Sent at %s", m.nick, m.text, m.timestamp.String())
}

type Chatroom struct {
	ID       string
	title    string
	members  map[string]chan string
	msg      []*Message
}

func (c Chatroom) Say(m Message) {
	if c.msg == nil {
		c.msg = make([]*Message, 100)
	}
	c.msg = append(c.msg, &m)
	c.Broadcast(fmt.Sprintf("message : %s", m.String())) //TODO: string 그대로 보내는 것 개선
}

func (c Chatroom) Join(nick string, ch chan string) {
	c.members[nick] = ch
	c.Broadcast(fmt.Sprintf("%s has joined", nick))
}

func (c Chatroom) Leave(nick string) {
	delete(c.members, nick)
	log.Println("leave")
	c.Broadcast(fmt.Sprintf("%s has been leaved", nick))
}

func (c Chatroom) Broadcast(content string) {
	for key, ch := range c.members {
		log.Println(key)
		ch <- content
	}
}

var (
	userMap = make(map[string]User)
	chatroomMap = make(map[string]Chatroom)
)

func addUser(nick string) User {
	user := User{nick: nick}
	userMap[nick] = user
	return user
}

const loginHTML = `
<title>Welcome to CHATTING GO</title>

<form action="/chatlist">
Nickname:

<input type="text" name="nickname">

<input type="submit" value="Submit">
</form>

`

func main() {
	sampleChat := Chatroom{ID: "asdf", title: "fda", members: make(map[string]chan string)}
	chatroomMap["asdf"] = sampleChat

	var srv http.Server
	srv.Addr = "localhost:7072"

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, loginHTML)
	})

	http.HandleFunc("/chat", func(w http.ResponseWriter, r *http.Request) {
		header := r.Proto
		roomID := r.URL.Query().Get("roomID")
		nickname := r.URL.Query().Get("nickname")
		log.Println(header)
		log.Println(roomID)
		log.Println(nickname)

		chatroom, ok := chatroomMap[roomID]

		log.Println(ok)

		if !ok {
			log.Printf("roomID doesn't exist") //TODO: create chatroom
			return
		}

		clientGone := w.(http.CloseNotifier).CloseNotify()
		w.Header().Set("Content-Type", "text/plain")
		fmt.Fprintf(w, "# ~1KB of junk to force browsers to start rendering immediately: \n")
		io.WriteString(w, strings.Repeat("# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", 13))

		ch := make(chan string, 100)

		go func(w http.ResponseWriter, r *http.Request, ch chan string) {
			for {
				log.Println("in")
				w.(http.Flusher).Flush()
				select {
				case msg := <-ch:
					fmt.Fprintf(w, msg)
					log.Println("msg is ")
					log.Println(msg)
				case <-clientGone:
					chatroom.Leave(nickname)
					log.Println("Client %v disconnected from the clock", r.RemoteAddr)
					return
				}
			}
		}(w, r, ch)

		log.Println("a")
		chatroom.Join(nickname, ch)
		log.Println("b")
		for {
			time.Sleep(100 * time.Second)
		}
	})

	http.HandleFunc("/chatlist/", func(w http.ResponseWriter, r *http.Request) {
		nickname := r.URL.Query().Get("nickname")
		if nickname == "" {
			log.Printf("nickname has no value")
			return
		}

		user, ok := userMap[nickname]
		if ok && user.roomID != "" {
			//TODO: redirect with params
			http.Redirect(w, r, fmt.Sprintf("/chat"), 301)
			return
		}

		if user == (User{}) {
			user = addUser(nickname)
		}

		fmt.Fprintf(w, "ID: ")
		fmt.Fprintf(w, user.nick)
		fmt.Fprintf(w, "\n\nChannel List Below\n")

		for k, _ := range chatroomMap {
			fmt.Fprintf(w, "\n")
			fmt.Fprintf(w, k)
		}

	})

	http2.ConfigureServer(&srv, &http2.Server{})

	// Run crypto/tls/generate_cert.go to generate cert.pem and key.pem.
	// See https://golang.org/src/crypto/tls/generate_cert.go
	log.Fatal(http.ListenAndServeTLS(":7072", "cert.pem", "key.pem", nil))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/user"
	"path"
	"strconv"

	"github.com/andriykohut/gotable"
	"github.com/andriykohut/moldyfridge/fridgedb"
	"github.com/docopt/docopt-go"
)

func main() {
	usage := `moldyfridge.

Usage:
  moldyfridge (add | rm) <food>...
  moldyfridge (add | rm) <food> [--amount <amount>]
  moldyfridge ls
  moldyfridge search <food>
  moldyfridge reset

Options:
  -h --help     Show this screen.
  --version     Show version.`
	arguments, _ := docopt.Parse(usage, nil, true, "moldyfridge 0.1", false)
	usr, _ := user.Current()
	home := usr.HomeDir
	confdir := path.Join(home, ".moldyfridge")
	dbpath := path.Join(confdir, "fridge.db")
	fridge := fridgedb.NewFridge(dbpath)
	if fridge.CheckDb() {
		os.Mkdir(confdir, 0755)
		fridge.Init()
	}

	var amount int
	if arguments["<amount>"] != nil {
		amount, _ = strconv.Atoi(arguments["<amount>"].(string))
	} else {
		amount = 1
	}
	if arguments["add"] == true {
		for _, food := range arguments["<food>"].([]string) {
			fridge.AddFood(food, amount)
		}
	} else if arguments["rm"] == true {
		// TODO: Need to fix this shit
		if amount != 1 {
			fridge.RemoveFood(arguments["<food>"].([]string)[0], amount)
		} else {
			fridge.RemoveFood(arguments["<food>"].([]string)[0])
		}
	} else if arguments["ls"] == true {
		var food_rows []map[string]string
		for _, food := range fridge.GetFood() {
			food_rows = append(food_rows, map[string]string{
				"name": food.Name, "age": food.StringAge(),
				"amount": strconv.Itoa(food.Amount),
			})
		}
		table := gotable.NewTable(food_rows, true, []string{"name", "age", "amount"})
		fmt.Println(table.GetTable())
	} else if arguments["search"] == true {
		var food_rows []map[string]string
		for _, food := range fridge.SearchFood(arguments["<food>"].([]string)[0]) {
			food_rows = append(food_rows, map[string]string{
				"name": food.Name, "age": food.StringAge(),
				"amount": strconv.Itoa(food.Amount),
			})
		}
		table := gotable.NewTable(food_rows, true, []string{"name", "age", "amount"})
		fmt.Println(table.GetTable())
	} else if arguments["reset"] == true {
		fmt.Print("You really wan't to reset moldyfridge? (y/n): ")
		var choice string
		fmt.Scanf("%s", &choice)
		switch choice[0] {
		case 'y', 'Y':
			fridge.Destroy()
		case 'n', 'N':
			fmt.Println("ok, exiting")
		default:
			fmt.Println("what?")
		}
	}
}
<commit_msg>dont display tables for empty queries<commit_after>package main

import (
	"fmt"
	"os"
	"os/user"
	"path"
	"strconv"

	"github.com/andriykohut/gotable"
	"github.com/andriykohut/moldyfridge/fridgedb"
	"github.com/docopt/docopt-go"
)

func main() {
	usage := `moldyfridge.

Usage:
  moldyfridge (add | rm) <food>...
  moldyfridge (add | rm) <food> [--amount <amount>]
  moldyfridge ls
  moldyfridge search <food>
  moldyfridge reset

Options:
  -h --help     Show this screen.
  --version     Show version.`
	arguments, _ := docopt.Parse(usage, nil, true, "moldyfridge 0.1", false)
	usr, _ := user.Current()
	home := usr.HomeDir
	confdir := path.Join(home, ".moldyfridge")
	dbpath := path.Join(confdir, "fridge.db")
	fridge := fridgedb.NewFridge(dbpath)
	if fridge.CheckDb() {
		os.Mkdir(confdir, 0755)
		fridge.Init()
	}

	var amount int
	if arguments["<amount>"] != nil {
		amount, _ = strconv.Atoi(arguments["<amount>"].(string))
	} else {
		amount = 1
	}
	if arguments["add"] == true {
		for _, food := range arguments["<food>"].([]string) {
			fridge.AddFood(food, amount)
		}
	} else if arguments["rm"] == true {
		// TODO: Need to fix this shit
		if amount != 1 {
			fridge.RemoveFood(arguments["<food>"].([]string)[0], amount)
		} else {
			fridge.RemoveFood(arguments["<food>"].([]string)[0])
		}
	} else if arguments["ls"] == true {
		var food_rows []map[string]string
		for _, food := range fridge.GetFood() {
			food_rows = append(food_rows, map[string]string{
				"name": food.Name, "age": food.StringAge(),
				"amount": strconv.Itoa(food.Amount),
			})
		}
		if len(food_rows) != 0 {
			table := gotable.NewTable(food_rows, true, []string{"name", "age", "amount"})
			fmt.Println(table.GetTable())
		}
	} else if arguments["search"] == true {
		var food_rows []map[string]string
		for _, food := range fridge.SearchFood(arguments["<food>"].([]string)[0]) {
			food_rows = append(food_rows, map[string]string{
				"name": food.Name, "age": food.StringAge(),
				"amount": strconv.Itoa(food.Amount),
			})
		}
		if len(food_rows) != 0 {
			table := gotable.NewTable(food_rows, true, []string{"name", "age", "amount"})
			fmt.Println(table.GetTable())
		}
	} else if arguments["reset"] == true {
		fmt.Print("You really wan't to reset moldyfridge? (y/n): ")
		var choice string
		fmt.Scanf("%s", &choice)
		switch choice[0] {
		case 'y', 'Y':
			fridge.Destroy()
		case 'n', 'N':
			fmt.Println("ok, exiting")
		default:
			fmt.Println("what?")
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/exercism/cli/configuration"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	app := cli.NewApp()
	app.Name = "exercism"
	app.Usage = "A command line tool to interact with http://exercism.io"
	app.Version = VERSION
	app.Flags = []cli.Flag{
		cli.StringFlag{"config, c", configuration.Filename(configuration.HomeDir()), "path to config file"},
	}
	app.Commands = []cli.Command{
		{
			Name:      "current",
			ShortName: "c",
			Usage:     "Show the current assignments",
			Action: func(c *cli.Context) {
				var language string
				argc := len(c.Args())
				if argc != 0 && argc != 1 {
					fmt.Println("Usage: exercism current\n   or: exercism current LANGUAGE")
					return
				}

				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				currentAssignments, err := FetchAssignments(config, FetchEndpoints["current"])
				if err != nil {
					fmt.Println(err)
					return
				}

				if argc == 1 {
					language = c.Args()[0]
					fmt.Println("Current Assignments for", strings.Title(language))
				} else {
					fmt.Println("Current Assignments")
				}

				for _, a := range currentAssignments {
					if argc == 1 {
						if strings.ToLower(language) == strings.ToLower(a.Track) {
							fmt.Printf("%v: %v\n", strings.Title(a.Track), a.Slug)
						}
					} else {
						fmt.Printf("%v: %v\n", strings.Title(a.Track), a.Slug)
					}
				}
			},
		},
		{
			Name:      "demo",
			ShortName: "d",
			Usage:     "Fetch first assignment for each language from exercism.io",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					config, err = configuration.Demo()
					if err != nil {
						fmt.Println(err)
						return
					}
				}
				assignments, err := FetchAssignments(config, FetchEndpoints["demo"])
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "fetch",
			ShortName: "f",
			Usage:     "Fetch assignments from exercism.io",
			Action: func(c *cli.Context) {
				argCount := len(c.Args())
				if argCount < 0 || argCount > 2 {
					fmt.Println("Usage: exercism fetch\n   or: exercism fetch LANGUAGE\n   or: exercism fetch LANGUAGE EXERCISE")
					return
				}

				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					if argCount == 0 || argCount == 1 {
						fmt.Println("Are you sure you are logged in? Please login again.")
						return
					} else {
						config, err = configuration.Demo()
						if err != nil {
							fmt.Println(err)
							return
						}
					}
				}

				assignments, err := FetchAssignments(config, FetchEndpoint(c.Args()))
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}

				fmt.Printf("Exercises written to %s\n", config.ExercismDirectory)
			},
		},
		{
			Name:      "login",
			ShortName: "l",
			Usage:     "Save exercism.io api credentials",
			Action: func(c *cli.Context) {
				config, err := askForConfigInfo()
				if err != nil {
					fmt.Println(err)
					return
				}
				configuration.ToFile(c.GlobalString("config"), config)
			},
		},
		{
			Name:      "logout",
			ShortName: "o",
			Usage:     "Clear exercism.io api credentials",
			Action: func(c *cli.Context) {
				logout(c.GlobalString("config"))
			},
		},
		{
			Name:      "peek",
			ShortName: "p",
			Usage:     "Fetch upcoming assignment from exercism.io",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := FetchAssignments(config,
					FetchEndpoints["next"])
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "restore",
			ShortName: "r",
			Usage:     "Restore completed and current assignments from exercism.io",
			Description: "Restore will pull the latest revisions of exercises that have already been " +
				"submitted. It will *not* overwrite existing files.  If you have made changes " +
				"to a file and have not submitted it, and you're trying to restore the last " +
				"submitted version, first move that file out of the way, then call restore.",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				assignments, err := FetchAssignments(config, FetchEndpoints["restore"])
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}

				fmt.Printf("Exercises written to %s\n", config.ExercismDirectory)
			},
		},
		{
			Name:      "submit",
			ShortName: "s",
			Usage:     "Submit code to exercism.io on your current assignment",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				if len(c.Args()) == 0 {
					fmt.Println("Please enter a file name")
					return
				}

				filename := c.Args()[0]

				// Make filename relative to config.ExercismDirectory.
				absPath, err := absolutePath(filename)
				if err != nil {
					fmt.Printf("Couldn't find %v: %v\n", filename, err)
					return
				}
				exDir := config.ExercismDirectory + string(filepath.Separator)
				if !strings.HasPrefix(absPath, exDir) {
					fmt.Printf("%v is not under your exercism project path (%v)\n", absPath, exDir)
					return
				}
				filename = absPath[len(exDir):]

				if IsTest(filename) {
					fmt.Println("It looks like this is a test, please enter an example file name.")
					return
				}

				code, err := ioutil.ReadFile(absPath)
				if err != nil {
					fmt.Printf("Error reading %v: %v\n", absPath, err)
					return
				}

				response, err := SubmitAssignment(config, filename, code)
				if err != nil {
					fmt.Printf("There was an issue with your submission: %v\n", err)
					return
				}

				fmt.Printf("For feedback on your submission visit %s%s%s\n",
					config.Hostname, "/submissions/", response.Id)

			},
		},
		{
			Name:      "unsubmit",
			ShortName: "u",
			Usage:     "Delete the last submission",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				response, err := UnsubmitAssignment(config)
				if err != nil {
					fmt.Println(err)
					return
				}

				if response != "" {
					return
				}

				fmt.Println("The last submission was successfully deleted.")
			},
		},
		{
			Name:      "whoami",
			ShortName: "w",
			Usage:     "Get the github username that you are logged in as",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				fmt.Println(config.GithubUsername)
			},
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		fmt.Errorf("%v", err)
		os.Exit(1)
	}
}
<commit_msg>Display better message when no assignments were fetched<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/exercism/cli/configuration"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	app := cli.NewApp()
	app.Name = "exercism"
	app.Usage = "A command line tool to interact with http://exercism.io"
	app.Version = VERSION
	app.Flags = []cli.Flag{
		cli.StringFlag{"config, c", configuration.Filename(configuration.HomeDir()), "path to config file"},
	}
	app.Commands = []cli.Command{
		{
			Name:      "current",
			ShortName: "c",
			Usage:     "Show the current assignments",
			Action: func(c *cli.Context) {
				var language string
				argc := len(c.Args())
				if argc != 0 && argc != 1 {
					fmt.Println("Usage: exercism current\n   or: exercism current LANGUAGE")
					return
				}

				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				currentAssignments, err := FetchAssignments(config, FetchEndpoints["current"])
				if err != nil {
					fmt.Println(err)
					return
				}

				if argc == 1 {
					language = c.Args()[0]
					fmt.Println("Current Assignments for", strings.Title(language))
				} else {
					fmt.Println("Current Assignments")
				}

				for _, a := range currentAssignments {
					if argc == 1 {
						if strings.ToLower(language) == strings.ToLower(a.Track) {
							fmt.Printf("%v: %v\n", strings.Title(a.Track), a.Slug)
						}
					} else {
						fmt.Printf("%v: %v\n", strings.Title(a.Track), a.Slug)
					}
				}
			},
		},
		{
			Name:      "demo",
			ShortName: "d",
			Usage:     "Fetch first assignment for each language from exercism.io",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					config, err = configuration.Demo()
					if err != nil {
						fmt.Println(err)
						return
					}
				}
				assignments, err := FetchAssignments(config, FetchEndpoints["demo"])
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "fetch",
			ShortName: "f",
			Usage:     "Fetch assignments from exercism.io",
			Action: func(c *cli.Context) {
				argCount := len(c.Args())
				if argCount < 0 || argCount > 2 {
					fmt.Println("Usage: exercism fetch\n   or: exercism fetch LANGUAGE\n   or: exercism fetch LANGUAGE EXERCISE")
					return
				}

				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					if argCount == 0 || argCount == 1 {
						fmt.Println("Are you sure you are logged in? Please login again.")
						return
					} else {
						config, err = configuration.Demo()
						if err != nil {
							fmt.Println(err)
							return
						}
					}
				}

				assignments, err := FetchAssignments(config, FetchEndpoint(c.Args()))
				if err != nil {
					fmt.Println(err)
					return
				}

				if len(assignments) == 0 {
					noAssignmentMessage := "No assignments found"
					if argCount == 2 {
						fmt.Printf("%s for %s - %s\n", noAssignmentMessage, c.Args()[0], c.Args()[1])
					} else if argCount == 1 {
						fmt.Printf("%s for %s\n", noAssignmentMessage, c.Args()[0])
					} else {
						fmt.Printf("%s\n", noAssignmentMessage)
					}
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}

				fmt.Printf("Exercises written to %s\n", config.ExercismDirectory)
			},
		},
		{
			Name:      "login",
			ShortName: "l",
			Usage:     "Save exercism.io api credentials",
			Action: func(c *cli.Context) {
				config, err := askForConfigInfo()
				if err != nil {
					fmt.Println(err)
					return
				}
				configuration.ToFile(c.GlobalString("config"), config)
			},
		},
		{
			Name:      "logout",
			ShortName: "o",
			Usage:     "Clear exercism.io api credentials",
			Action: func(c *cli.Context) {
				logout(c.GlobalString("config"))
			},
		},
		{
			Name:      "peek",
			ShortName: "p",
			Usage:     "Fetch upcoming assignment from exercism.io",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := FetchAssignments(config,
					FetchEndpoints["next"])
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "restore",
			ShortName: "r",
			Usage:     "Restore completed and current assignments from exercism.io",
			Description: "Restore will pull the latest revisions of exercises that have already been " +
				"submitted. It will *not* overwrite existing files.  If you have made changes " +
				"to a file and have not submitted it, and you're trying to restore the last " +
				"submitted version, first move that file out of the way, then call restore.",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				assignments, err := FetchAssignments(config, FetchEndpoints["restore"])
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}

				fmt.Printf("Exercises written to %s\n", config.ExercismDirectory)
			},
		},
		{
			Name:      "submit",
			ShortName: "s",
			Usage:     "Submit code to exercism.io on your current assignment",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				if len(c.Args()) == 0 {
					fmt.Println("Please enter a file name")
					return
				}

				filename := c.Args()[0]

				// Make filename relative to config.ExercismDirectory.
				absPath, err := absolutePath(filename)
				if err != nil {
					fmt.Printf("Couldn't find %v: %v\n", filename, err)
					return
				}
				exDir := config.ExercismDirectory + string(filepath.Separator)
				if !strings.HasPrefix(absPath, exDir) {
					fmt.Printf("%v is not under your exercism project path (%v)\n", absPath, exDir)
					return
				}
				filename = absPath[len(exDir):]

				if IsTest(filename) {
					fmt.Println("It looks like this is a test, please enter an example file name.")
					return
				}

				code, err := ioutil.ReadFile(absPath)
				if err != nil {
					fmt.Printf("Error reading %v: %v\n", absPath, err)
					return
				}

				response, err := SubmitAssignment(config, filename, code)
				if err != nil {
					fmt.Printf("There was an issue with your submission: %v\n", err)
					return
				}

				fmt.Printf("For feedback on your submission visit %s%s%s\n",
					config.Hostname, "/submissions/", response.Id)

			},
		},
		{
			Name:      "unsubmit",
			ShortName: "u",
			Usage:     "Delete the last submission",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				response, err := UnsubmitAssignment(config)
				if err != nil {
					fmt.Println(err)
					return
				}

				if response != "" {
					return
				}

				fmt.Println("The last submission was successfully deleted.")
			},
		},
		{
			Name:      "whoami",
			ShortName: "w",
			Usage:     "Get the github username that you are logged in as",
			Action: func(c *cli.Context) {
				config, err := configuration.FromFile(c.GlobalString("config"))
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				fmt.Println(config.GithubUsername)
			},
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		fmt.Errorf("%v", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/blackbass1988/access_logs_stats/core"
	"log"
	"os"

	"io"
	"runtime"
	"runtime/pprof"
	"time"
)

func PrintHello() {
	log.Printf("%s ver.%s@%s", core.PROG_NAME, core.VERSION, core.BUILD_TIME)
}

func main() {
	var (
		fileconfig       string
		profile          bool
		exitAfterOneTick bool
	)

	PrintHello()

	flag.StringVar(&fileconfig, "c", "", "config path")
	flag.BoolVar(&profile, "p", false, "enable profiling")
	flag.BoolVar(&exitAfterOneTick, "one", false, "make one tick end exit")
	flag.Parse()

	if fileconfig == "" {
		log.Print("ERROR config not set")
		flag.PrintDefaults()
		os.Exit(2)
	}

	config, err := core.NewConfig(fileconfig)
	if err != nil {
		log.Fatal(err)
	}
	config.ExitAfterOneTick = exitAfterOneTick

	app, err := core.NewApp(config)
	if err != nil {
		log.Fatal(err)
	}

	if profile {
		go codeProfile()
	}

	app.Start()
}

func codeProfile() {
	m := &runtime.MemStats{}
	tick1m := time.Tick(1 * time.Minute)
	tick5s := time.Tick(5 * time.Second)

	f_cpu_profiling, err := os.Create("profile.prof")
	if err != nil {
		panic(err)
	}
	pprof.StartCPUProfile(f_cpu_profiling)
	defer func() {
		pprof.StopCPUProfile()
	}()

	for {
		select {
		case <-tick5s:
			runtime.ReadMemStats(m)
			log.Println("")
			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
			log.Printf("~ Goroutines count %d\n", runtime.NumGoroutine())
			log.Printf("~ Alloc %dKB\n", m.Alloc/1024)
			log.Printf("~ TotalAlloc %dKB\n", m.TotalAlloc/1024)
			log.Printf("~ Sys (sum of XxxSys below) %dKB\n", m.Sys/1024)
			log.Printf("~ Lookups (number of pointer lookups) %d\n", m.Lookups)
			log.Printf("~ Mallocs %d\n", m.Mallocs)
			log.Printf("~ Frees %d\n", m.Frees)

			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

			log.Printf("~ HeapAlloc %dKB\n", m.HeapAlloc/1024)
			log.Printf("~ HeapSys %dKB\n", m.HeapSys/1024)
			log.Printf("~ HeapIdle %dKB\n", m.HeapIdle/1024)
			log.Printf("~ HeapInuse %dKB\n", m.HeapInuse/1024)
			log.Printf("~ HeapReleased %dKB\n", m.HeapReleased/1024)
			log.Printf("~ HeapObjects %d\n", m.HeapObjects)

			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

			log.Printf("~ NextGC %d\n", m.NextGC)
			log.Printf("~ LastGC %v\n", time.Unix(0, int64(m.LastGC)))
			log.Printf("~ PauseTotalNs %d\n", m.PauseTotalNs)
			log.Printf("~ NumGC %d\n", m.PauseTotalNs)
			log.Printf("~ GCCPUFraction %f\n", m.GCCPUFraction)
			log.Printf("~ EnableGC %v\n", m.EnableGC)
			log.Printf("~ DebugGC %v\n", m.DebugGC)
			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
			log.Println("")

		case <-tick1m:
			var f_heap_profiling io.Writer
			f_heap_profiling, _ = os.Create("profile_heap.prof")
			pprof.WriteHeapProfile(f_heap_profiling)
			log.Println("~ head saved")
		}
	}
}
<commit_msg>started a lint<commit_after>package main

import (
	"flag"
	"github.com/blackbass1988/access_logs_stats/core"
	"log"
	"os"

	"io"
	"runtime"
	"runtime/pprof"
	"time"
)

func printHello() {
	log.Printf("%s ver.%s@%s", core.PROG_NAME, core.VERSION, core.BUILD_TIME)
}

func main() {
	var (
		fileconfig       string
		profile          bool
		exitAfterOneTick bool
	)

	printHello()

	flag.StringVar(&fileconfig, "c", "", "config path")
	flag.BoolVar(&profile, "p", false, "enable profiling")
	flag.BoolVar(&exitAfterOneTick, "one", false, "make one tick end exit")
	flag.Parse()

	if fileconfig == "" {
		log.Print("ERROR config not set")
		flag.PrintDefaults()
		os.Exit(2)
	}

	config, err := core.NewConfig(fileconfig)
	if err != nil {
		log.Fatal(err)
	}
	config.ExitAfterOneTick = exitAfterOneTick

	app, err := core.NewApp(config)
	if err != nil {
		log.Fatal(err)
	}

	if profile {
		go codeProfile()
	}

	app.Start()
}

func codeProfile() {
	m := &runtime.MemStats{}
	tick1m := time.Tick(1 * time.Minute)
	tick5s := time.Tick(5 * time.Second)

	fCPUProfiling, err := os.Create("profile.prof")
	if err != nil {
		panic(err)
	}
	pprof.StartCPUProfile(fCPUProfiling)
	defer func() {
		pprof.StopCPUProfile()
	}()

	for {
		select {
		case <-tick5s:
			runtime.ReadMemStats(m)
			log.Println("")
			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
			log.Printf("~ Goroutines count %d\n", runtime.NumGoroutine())
			log.Printf("~ Alloc %dKB\n", m.Alloc/1024)
			log.Printf("~ TotalAlloc %dKB\n", m.TotalAlloc/1024)
			log.Printf("~ Sys (sum of XxxSys below) %dKB\n", m.Sys/1024)
			log.Printf("~ Lookups (number of pointer lookups) %d\n", m.Lookups)
			log.Printf("~ Mallocs %d\n", m.Mallocs)
			log.Printf("~ Frees %d\n", m.Frees)

			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

			log.Printf("~ HeapAlloc %dKB\n", m.HeapAlloc/1024)
			log.Printf("~ HeapSys %dKB\n", m.HeapSys/1024)
			log.Printf("~ HeapIdle %dKB\n", m.HeapIdle/1024)
			log.Printf("~ HeapInuse %dKB\n", m.HeapInuse/1024)
			log.Printf("~ HeapReleased %dKB\n", m.HeapReleased/1024)
			log.Printf("~ HeapObjects %d\n", m.HeapObjects)

			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

			log.Printf("~ NextGC %d\n", m.NextGC)
			log.Printf("~ LastGC %v\n", time.Unix(0, int64(m.LastGC)))
			log.Printf("~ PauseTotalNs %d\n", m.PauseTotalNs)
			log.Printf("~ NumGC %d\n", m.PauseTotalNs)
			log.Printf("~ GCCPUFraction %f\n", m.GCCPUFraction)
			log.Printf("~ EnableGC %v\n", m.EnableGC)
			log.Printf("~ DebugGC %v\n", m.DebugGC)
			log.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
			log.Println("")

		case <-tick1m:
			var fHeapProfiling io.Writer
			fHeapProfiling, _ = os.Create("profile_heap.prof")
			pprof.WriteHeapProfile(fHeapProfiling)
			log.Println("~ head saved")
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"
	"github.com/unrolled/secure"
	"gopkg.in/reportportal/commons-go.v5/commons"
	"gopkg.in/reportportal/commons-go.v5/conf"
	"gopkg.in/reportportal/commons-go.v5/server"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

func main() {

	currDir, e := os.Getwd()
	if nil != e {
		log.Fatalf("Cannot get workdir: %s", e.Error())
	}

	cfg := conf.EmptyConfig()

	rpConf := struct {
		Cfg         *conf.ServerConfig
		StaticsPath string `env:"RP_STATICS_PATH"`
	}{
		Cfg:         cfg,
		StaticsPath: currDir,
	}

	err := conf.LoadConfig(&rpConf)
	if nil != err {
		log.Fatalf("Cannot log app config")
	}

	info := commons.GetBuildInfo()
	info.Name = "Service UI"

	srv := server.New(rpConf.Cfg, info)
	srv.WithRouter(func(router *chi.Mux) {

		//apply compression
		router.Use(middleware.DefaultCompress)
		router.Use(middleware.Logger)

		//content security policy
		csp := map[string][]string{
			"default-src": {"'self'", "'unsafe-inline'", "*.uservoice.com"},
			"script-src": {
				"'self'",
				"'unsafe-inline'",
				"'unsafe-eval'",
				"status.reportportal.io",
				"www.google-analytics.com",
				"stats.g.doubleclick.net",
				"*.saucelabs.com",
				"*.epam.com",
				"*.uservoice.com",
			},
            "font-src": {"'self'", "data:", "fonts.googleapis.com", "fonts.gstatic.com"},
            "media-src": {"'self'", "*.saucelabs.com"},
			"img-src":    {"'self'", "data:", "www.google-analytics.com", "stats.g.doubleclick.net", "*.epam.com", "*.uservoice.com", "*.saucelabs.com"},
			"object-src": {"'self'"},
		}

		//apply content security policies
		router.Use(func(next http.Handler) http.Handler {
			return secure.New(secure.Options{
				ContentTypeNosniff:    true,
				BrowserXssFilter:      true,
				ContentSecurityPolicy: buildCSP(csp),
				STSSeconds:            315360000,
				STSIncludeSubdomains:  true,
				STSPreload:            true,
			}).Handler(next)
		})

		err := os.Chdir(rpConf.StaticsPath)
		if nil != err {
			log.Fatalf("Dir %s not found", rpConf.StaticsPath)
		}

		router.Handle("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//trim query params
			ext := filepath.Ext(trimQuery(r.URL.String(), "?"))

			// never cache html
			if "/" == r.URL.String() || ".html" == ext {
				w.Header().Add("Cache-Control", "no-cache")
			}

			http.FileServer(http.Dir(rpConf.StaticsPath)).ServeHTTP(&redirectingRW{ResponseWriter: w, Request: r}, r)
		}))

	})

	srv.StartServer()

}

func trimQuery(s string, sep string) string {
	sepIndex := strings.Index(s, sep)
	if -1 != sepIndex {
		return s[:sepIndex]
	}
	return s
}

func buildCSP(csp map[string][]string) string {
	var instr []string
	for k, v := range csp {
		instr = append(instr, k+" "+strings.Join(v, " "))
	}
	return strings.Join(instr, "; ")

}

type redirectingRW struct {
	*http.Request
	http.ResponseWriter
	ignore bool
}

func (hrw *redirectingRW) Header() http.Header {
	return hrw.ResponseWriter.Header()
}

func (hrw *redirectingRW) WriteHeader(status int) {
	if status == 404 {
		hrw.ignore = true
		http.Redirect(hrw.ResponseWriter, hrw.Request, "/ui/#notfound", http.StatusTemporaryRedirect)
	} else {
		hrw.ResponseWriter.WriteHeader(status)
	}

}

func (hrw *redirectingRW) Write(p []byte) (int, error) {
	if hrw.ignore {
		return len(p), nil
	}
	return hrw.ResponseWriter.Write(p)
}
<commit_msg>EPMRPP-36908: fix - React: Markdown options are not applied<commit_after>package main

import (
	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"
	"github.com/unrolled/secure"
	"gopkg.in/reportportal/commons-go.v5/commons"
	"gopkg.in/reportportal/commons-go.v5/conf"
	"gopkg.in/reportportal/commons-go.v5/server"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

func main() {

	currDir, e := os.Getwd()
	if nil != e {
		log.Fatalf("Cannot get workdir: %s", e.Error())
	}

	cfg := conf.EmptyConfig()

	rpConf := struct {
		Cfg         *conf.ServerConfig
		StaticsPath string `env:"RP_STATICS_PATH"`
	}{
		Cfg:         cfg,
		StaticsPath: currDir,
	}

	err := conf.LoadConfig(&rpConf)
	if nil != err {
		log.Fatalf("Cannot log app config")
	}

	info := commons.GetBuildInfo()
	info.Name = "Service UI"

	srv := server.New(rpConf.Cfg, info)
	srv.WithRouter(func(router *chi.Mux) {

		//apply compression
		router.Use(middleware.DefaultCompress)
		router.Use(middleware.Logger)

		//content security policy
		csp := map[string][]string{
			"default-src": {"'self'", "'unsafe-inline'", "*.uservoice.com"},
			"script-src": {
				"'self'",
				"'unsafe-inline'",
				"'unsafe-eval'",
				"status.reportportal.io",
				"www.google-analytics.com",
				"stats.g.doubleclick.net",
				"*.saucelabs.com",
				"*.epam.com",
				"*.uservoice.com",
			},
            "font-src": {"'self'", "data:", "fonts.googleapis.com", "fonts.gstatic.com"},
            "media-src": {"'self'", "*.saucelabs.com"},
			"img-src": {"*", "'self'", "data:"},
			"object-src": {"'self'"},
		}

		//apply content security policies
		router.Use(func(next http.Handler) http.Handler {
			return secure.New(secure.Options{
				ContentTypeNosniff:    true,
				BrowserXssFilter:      true,
				ContentSecurityPolicy: buildCSP(csp),
				STSSeconds:            315360000,
				STSIncludeSubdomains:  true,
				STSPreload:            true,
			}).Handler(next)
		})

		err := os.Chdir(rpConf.StaticsPath)
		if nil != err {
			log.Fatalf("Dir %s not found", rpConf.StaticsPath)
		}

		router.Handle("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//trim query params
			ext := filepath.Ext(trimQuery(r.URL.String(), "?"))

			// never cache html
			if "/" == r.URL.String() || ".html" == ext {
				w.Header().Add("Cache-Control", "no-cache")
			}

			http.FileServer(http.Dir(rpConf.StaticsPath)).ServeHTTP(&redirectingRW{ResponseWriter: w, Request: r}, r)
		}))

	})

	srv.StartServer()

}

func trimQuery(s string, sep string) string {
	sepIndex := strings.Index(s, sep)
	if -1 != sepIndex {
		return s[:sepIndex]
	}
	return s
}

func buildCSP(csp map[string][]string) string {
	var instr []string
	for k, v := range csp {
		instr = append(instr, k+" "+strings.Join(v, " "))
	}
	return strings.Join(instr, "; ")

}

type redirectingRW struct {
	*http.Request
	http.ResponseWriter
	ignore bool
}

func (hrw *redirectingRW) Header() http.Header {
	return hrw.ResponseWriter.Header()
}

func (hrw *redirectingRW) WriteHeader(status int) {
	if status == 404 {
		hrw.ignore = true
		http.Redirect(hrw.ResponseWriter, hrw.Request, "/ui/#notfound", http.StatusTemporaryRedirect)
	} else {
		hrw.ResponseWriter.WriteHeader(status)
	}

}

func (hrw *redirectingRW) Write(p []byte) (int, error) {
	if hrw.ignore {
		return len(p), nil
	}
	return hrw.ResponseWriter.Write(p)
}
<|endoftext|>


<commit_before>// Prometheus tail_exporter - heavily heavily modified from the basic
// graphite_exporter by bbrazil.

package main

import (
	"bufio"
	"bytes"
	"flag"
	"io"
	"net"
	"net/http"
	"strconv"

	"github.com/hpcloud/tail"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/wrouesnel/tail_exporter/config"
	"sync"
	"os"
)

const Namespace string = "tail_collector"

var (
	listeningAddress = flag.String("web.listen-address", ":9130", "Address on which to expose metrics.")
	metricsPath      = flag.String("web.telemetry-path", "/metrics", "Path under which to expose Prometheus metrics.")
	collectorAddress = flag.String("collector.listen-address", ":9129", "TCP and UDP address on which to accept lines")
	configFile    	 = flag.String("config.file", "", "Configuration file path")
)

// TailCollector implements the main collector process.
type TailCollector struct {
	cfg *config.Config	// Configuration
	metrics map[string]*prometheus.MetricVec	// map of initialized metrics
	mmtx sync.Mutex	// Metric initialization lock for map writes

	regexCh []chan string	// list of regex processors

	numMetrics prometheus.Gauge	// our own metric + lets initialization succeed
	ingestedLines prometheus.Counter // number of lines we've ingested
	//rejectedLines *prometheus.CounterVec // number of rejected values
	//timedoutMetrics prometheus.Counter // number of metrics which have been dropped due to internal timeouts
}

func newTailCollector(cfg *config.Config) *TailCollector {
	c := TailCollector{}
	c.cfg = cfg
	c.metrics = make(map[string]*prometheus.MetricVec)

	c.regexCh = make([]chan string, len(cfg.MetricConfigs))

	// Initialize regex processors
	for idx, mp := range cfg.MetricConfigs {
		ch := make(chan string, 1)
		c.regexCh[idx] = ch
		go c.lineProcessor(ch,mp)
	}

	// Set constant metrics
	c.numMetrics = prometheus.NewGauge(
		prometheus.GaugeOpts{
			Namespace: Namespace,
			Name: "metric_regexes",
			Help: "currently configured number of metric regexes",
		},
	)

	c.ingestedLines = prometheus.NewCounter(
		prometheus.CounterOpts{
			Namespace: Namespace,
			Name: "ingested_lines_total",
			Help: "total number of lines ingested by collection inputs",
		},
	)

//	c.rejectedLines = prometheus.NewCounterVec(
//		prometheus.CounterOpts{
//			Namespace: Namespace,
//			Name: "rejected_lines_total",
//			Help: "total number of lines rejected during parsing",
//		},
//		[]string{"reason"},
//	)

	c.numMetrics.Set(float64(len(cfg.MetricConfigs)))
	return &c
}

// Reads until the current connection is closed
func (c *TailCollector) processReader(reader io.Reader) {
	lineScanner := bufio.NewScanner(reader)
	for {
		if ok := lineScanner.Scan(); !ok {
			break
		}
		c.IngestLine(lineScanner.Text())
	}
}

// Ingest a line
func (c *TailCollector) IngestLine(line string) {
	c.ingestedLines.Inc()
	// Dispatch the line to all active regex parsers
	for _, ch := range c.regexCh {
		ch <- line
	}
}

func (c *TailCollector) initalizeMetric(cfg *config.MetricParser) *prometheus.MetricVec {
	// Lock the map to writes (reads should be okay I think?)
	c.mmtx.Lock()
	defer c.mmtx.Unlock()

	// Setup the label set
	labelSet := make([]string, len(cfg.Labels))
	for idx, v := range cfg.Labels {
		labelSet[idx] = v.Name
	}

	var metricVec *prometheus.MetricVec

	switch cfg.Type {
	case config.METRIC_COUNTER:
		metricVec = &prometheus.NewCounterVec(
			prometheus.CounterOpts{
				Name: cfg.Name,
				Help: cfg.Help,
			},
			labelSet,
		).MetricVec

	case config.METRIC_GAUGE:
		metricVec = &prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: cfg.Name,
				Help: cfg.Help,
			},
			labelSet,
		).MetricVec
	default:
		metricVec = &prometheus.NewUntypedVec(
			prometheus.UntypedOpts{
				Name: cfg.Name,
				Help: cfg.Help,
			},
			labelSet,
		).MetricVec
	}
	c.metrics[cfg.Name] = metricVec
	return metricVec
}

// Processes lines through the regexes we have loaded
func (c *TailCollector) lineProcessor(lineCh chan string, cfg config.MetricParser) {
	// Run all regexes
	labelValues := make([]string, len(cfg.Labels))

	processloop: for line := range lineCh {
		m := cfg.Regex.MatcherString(line,0)
		if !m.Matches() {
			continue
		}
		// Got a match. See if we have this metric already.
		var metricVec *prometheus.MetricVec
		var ok bool
		metricVec, ok = c.metrics[cfg.Name]
		if !ok {
			metricVec = c.initalizeMetric(&cfg)
		}

		// Calculate label values
		for idx, v := range cfg.Labels {
			switch v.Value.FieldType {
			case config.LVALUE_LITERAL:
				labelValues[idx] = v.Value.Literal
			case config.LVALUE_CAPTUREGROUP_NAMED:
				if !m.NamedPresent(v.Value.CaptureGroupName) {
					if v.HasDefault {
						labelValues[idx] = v.Default
					} else {
						log.With("name", cfg.Name).
							With("group_name", v.Value.CaptureGroupName).
							With("line", line).
							Warnln("Dropping unconvertible capture value")
						continue processloop
					}
				}
				labelValues[idx] = m.NamedString(v.Value.CaptureGroupName)
			case config.LVALUE_CAPTUREGROUP:
				if v.HasDefault && (m.GroupString(v.Value.CaptureGroup) == "") {
					labelValues[idx] = v.Default
				} else {
					labelValues[idx] = m.GroupString(v.Value.CaptureGroup)
				}
			default:
				log.Warnln("Got no recognized type - assuming literal")
				labelValues[idx] = v.Value.Literal
			}
		}

		// Get the metric we will adjust
		metric := metricVec.WithLabelValues(labelValues...)

		switch cfg.Value.FieldType {
		case config.VALUE_LITERAL:
			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Set(cfg.Value.Literal)
			case prometheus.Counter:
				t.Set(cfg.Value.Literal)
			case prometheus.Untyped:
				t.Set(cfg.Value.Literal)
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_CAPTUREGROUP:
			valstr := m.GroupString(cfg.Value.CaptureGroup)
			val, err := strconv.ParseFloat(valstr, 64)
			if err != nil {
				log.With("name", cfg.Name).
					With("group_name", cfg.Value.CaptureGroup).
					With("line",line).
					With("value",valstr).
					Warnln("Dropping line with unconvertible capture value")
				continue
			}

			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Set(val)
			case prometheus.Counter:
				t.Set(val)
			case prometheus.Untyped:
				t.Set(val)
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_CAPTUREGROUP_NAMED:
			if !m.NamedPresent(cfg.Value.CaptureGroupName) {
				log.With("name", cfg.Name).
					With("group_name", cfg.Value.CaptureGroup).
					With("line",line).
					Warnln("Dropping line with missing capture value")
				continue
			}
			valstr := m.NamedString(cfg.Value.CaptureGroupName)
			val, err := strconv.ParseFloat(valstr, 64)
			if err != nil {
				log.With("name", cfg.Name).
					With("group_name", cfg.Value.CaptureGroupName).
					With("line",line).
					With("value",valstr).
					Warnln("Dropping line with unconvertible capture value")
				continue
			}

			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Set(val)
			case prometheus.Counter:
				t.Set(val)
			case prometheus.Untyped:
				t.Set(val)
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_INC:
			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Inc()
			case prometheus.Counter:
				t.Inc()
			case prometheus.Untyped:
				t.Inc()
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_SUB:
			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Dec()
			case prometheus.Counter:
				t.Set(0) // Subtract means reset for a counter
			case prometheus.Untyped:
				t.Dec()
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}
		}
	}
}

// Collect implements prometheus.Collector.
func (c TailCollector) Collect(ch chan<- prometheus.Metric) {
	c.numMetrics.Collect(ch)
	c.ingestedLines.Collect(ch)
	//c.rejectedLines.Collect(ch)

	for _, v := range c.metrics {
		v.Collect(ch)
	}
}

// Describe implements prometheus.Collector.
func (c TailCollector) Describe(ch chan<- *prometheus.Desc) {
	c.numMetrics.Describe(ch)
	c.ingestedLines.Describe(ch)
	//c.rejectedLines.Describe(ch)

	for _, v := range c.metrics {
		v.Describe(ch)
	}
}

func main() {
	flag.Parse()
	http.Handle(*metricsPath, prometheus.Handler())

	cfg, err := config.LoadFile(*configFile)
	if err != nil {
		log.Fatalln("Configuration file could not be read.", err)
	}

	c := newTailCollector(cfg)
	prometheus.MustRegister(c)

	// If args then start file/fifo collectors
	if len(flag.Args()) > 0 {
		for _, filename := range flag.Args() {
			go func(filename string) {
				var isPipe bool
				st, err := os.Stat(filename)
				if err == nil {
					if st.Mode() & os.ModeNamedPipe == os.ModeNamedPipe {
						isPipe = true
					}
				} else {
					isPipe = false
				}

				t, err := tail.TailFile(filename, tail.Config{
					Location: &tail.SeekInfo{0,os.SEEK_END},
					ReOpen: true,
					Follow: isPipe,
				})

				for line := range t.Lines {
					c.IngestLine(line.Text)
				}

			}(filename)
		}
	}

	// If collector address present, then start port collector.
	if *collectorAddress != "" {
		tcpSock, err := net.Listen("tcp", *collectorAddress)
		if err != nil {
			log.Fatalf("Error binding to TCP socket: %s", err)
		}
		go func() {
			for {
				conn, err := tcpSock.Accept()
				if err != nil {
					log.Errorf("Error accepting TCP connection: %s", err)
					continue
				}
				go func() {
					defer conn.Close()
					c.processReader(conn)
				}()
			}
		}()

		udpAddress, err := net.ResolveUDPAddr("udp", *collectorAddress)
		if err != nil {
			log.Fatalf("Error resolving UDP address: %s", err)
		}
		udpSock, err := net.ListenUDP("udp", udpAddress)
		if err != nil {
			log.Fatalf("Error listening to UDP address: %s", err)
		}
		go func() {
			defer udpSock.Close()
			for {
				buf := make([]byte, 65536)
				chars, srcAddress, err := udpSock.ReadFromUDP(buf)
				if err != nil {
					log.Errorf("Error reading UDP packet from %s: %s", srcAddress, err)
					continue
				}
				go c.processReader(bytes.NewReader(buf[0:chars]))
			}
		}()
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
      <title>Tail Exporter</title>

TCP/UDP Tail Exporter

Accepting raw lines over TCP and UDP on ` + *collectorAddress + `

Watching files for lines:` + flags.Args() + `

<a href="` + *metricsPath + `">Metrics

Config

` +
      cfg.Original +
      `

      `))
	})

	log.Infof("Starting Server: %s", *listeningAddress)
	http.ListenAndServe(*listeningAddress, nil)
}
<commit_msg>Fix a silly typo.<commit_after>// Prometheus tail_exporter - heavily heavily modified from the basic
// graphite_exporter by bbrazil.

package main

import (
	"bufio"
	"bytes"
	"flag"
	"io"
	"net"
	"net/http"
	"strconv"

	"github.com/hpcloud/tail"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/wrouesnel/tail_exporter/config"
	"sync"
	"os"
)

const Namespace string = "tail_collector"

var (
	listeningAddress = flag.String("web.listen-address", ":9130", "Address on which to expose metrics.")
	metricsPath      = flag.String("web.telemetry-path", "/metrics", "Path under which to expose Prometheus metrics.")
	collectorAddress = flag.String("collector.listen-address", ":9129", "TCP and UDP address on which to accept lines")
	configFile    	 = flag.String("config.file", "", "Configuration file path")
)

// TailCollector implements the main collector process.
type TailCollector struct {
	cfg *config.Config	// Configuration
	metrics map[string]*prometheus.MetricVec	// map of initialized metrics
	mmtx sync.Mutex	// Metric initialization lock for map writes

	regexCh []chan string	// list of regex processors

	numMetrics prometheus.Gauge	// our own metric + lets initialization succeed
	ingestedLines prometheus.Counter // number of lines we've ingested
	//rejectedLines *prometheus.CounterVec // number of rejected values
	//timedoutMetrics prometheus.Counter // number of metrics which have been dropped due to internal timeouts
}

func newTailCollector(cfg *config.Config) *TailCollector {
	c := TailCollector{}
	c.cfg = cfg
	c.metrics = make(map[string]*prometheus.MetricVec)

	c.regexCh = make([]chan string, len(cfg.MetricConfigs))

	// Initialize regex processors
	for idx, mp := range cfg.MetricConfigs {
		ch := make(chan string, 1)
		c.regexCh[idx] = ch
		go c.lineProcessor(ch,mp)
	}

	// Set constant metrics
	c.numMetrics = prometheus.NewGauge(
		prometheus.GaugeOpts{
			Namespace: Namespace,
			Name: "metric_regexes",
			Help: "currently configured number of metric regexes",
		},
	)

	c.ingestedLines = prometheus.NewCounter(
		prometheus.CounterOpts{
			Namespace: Namespace,
			Name: "ingested_lines_total",
			Help: "total number of lines ingested by collection inputs",
		},
	)

//	c.rejectedLines = prometheus.NewCounterVec(
//		prometheus.CounterOpts{
//			Namespace: Namespace,
//			Name: "rejected_lines_total",
//			Help: "total number of lines rejected during parsing",
//		},
//		[]string{"reason"},
//	)

	c.numMetrics.Set(float64(len(cfg.MetricConfigs)))
	return &c
}

// Reads until the current connection is closed
func (c *TailCollector) processReader(reader io.Reader) {
	lineScanner := bufio.NewScanner(reader)
	for {
		if ok := lineScanner.Scan(); !ok {
			break
		}
		c.IngestLine(lineScanner.Text())
	}
}

// Ingest a line
func (c *TailCollector) IngestLine(line string) {
	c.ingestedLines.Inc()
	// Dispatch the line to all active regex parsers
	for _, ch := range c.regexCh {
		ch <- line
	}
}

func (c *TailCollector) initalizeMetric(cfg *config.MetricParser) *prometheus.MetricVec {
	// Lock the map to writes (reads should be okay I think?)
	c.mmtx.Lock()
	defer c.mmtx.Unlock()

	// Setup the label set
	labelSet := make([]string, len(cfg.Labels))
	for idx, v := range cfg.Labels {
		labelSet[idx] = v.Name
	}

	var metricVec *prometheus.MetricVec

	switch cfg.Type {
	case config.METRIC_COUNTER:
		metricVec = &prometheus.NewCounterVec(
			prometheus.CounterOpts{
				Name: cfg.Name,
				Help: cfg.Help,
			},
			labelSet,
		).MetricVec

	case config.METRIC_GAUGE:
		metricVec = &prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: cfg.Name,
				Help: cfg.Help,
			},
			labelSet,
		).MetricVec
	default:
		metricVec = &prometheus.NewUntypedVec(
			prometheus.UntypedOpts{
				Name: cfg.Name,
				Help: cfg.Help,
			},
			labelSet,
		).MetricVec
	}
	c.metrics[cfg.Name] = metricVec
	return metricVec
}

// Processes lines through the regexes we have loaded
func (c *TailCollector) lineProcessor(lineCh chan string, cfg config.MetricParser) {
	// Run all regexes
	labelValues := make([]string, len(cfg.Labels))

	processloop: for line := range lineCh {
		m := cfg.Regex.MatcherString(line,0)
		if !m.Matches() {
			continue
		}
		// Got a match. See if we have this metric already.
		var metricVec *prometheus.MetricVec
		var ok bool
		metricVec, ok = c.metrics[cfg.Name]
		if !ok {
			metricVec = c.initalizeMetric(&cfg)
		}

		// Calculate label values
		for idx, v := range cfg.Labels {
			switch v.Value.FieldType {
			case config.LVALUE_LITERAL:
				labelValues[idx] = v.Value.Literal
			case config.LVALUE_CAPTUREGROUP_NAMED:
				if !m.NamedPresent(v.Value.CaptureGroupName) {
					if v.HasDefault {
						labelValues[idx] = v.Default
					} else {
						log.With("name", cfg.Name).
							With("group_name", v.Value.CaptureGroupName).
							With("line", line).
							Warnln("Dropping unconvertible capture value")
						continue processloop
					}
				}
				labelValues[idx] = m.NamedString(v.Value.CaptureGroupName)
			case config.LVALUE_CAPTUREGROUP:
				if v.HasDefault && (m.GroupString(v.Value.CaptureGroup) == "") {
					labelValues[idx] = v.Default
				} else {
					labelValues[idx] = m.GroupString(v.Value.CaptureGroup)
				}
			default:
				log.Warnln("Got no recognized type - assuming literal")
				labelValues[idx] = v.Value.Literal
			}
		}

		// Get the metric we will adjust
		metric := metricVec.WithLabelValues(labelValues...)

		switch cfg.Value.FieldType {
		case config.VALUE_LITERAL:
			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Set(cfg.Value.Literal)
			case prometheus.Counter:
				t.Set(cfg.Value.Literal)
			case prometheus.Untyped:
				t.Set(cfg.Value.Literal)
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_CAPTUREGROUP:
			valstr := m.GroupString(cfg.Value.CaptureGroup)
			val, err := strconv.ParseFloat(valstr, 64)
			if err != nil {
				log.With("name", cfg.Name).
					With("group_name", cfg.Value.CaptureGroup).
					With("line",line).
					With("value",valstr).
					Warnln("Dropping line with unconvertible capture value")
				continue
			}

			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Set(val)
			case prometheus.Counter:
				t.Set(val)
			case prometheus.Untyped:
				t.Set(val)
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_CAPTUREGROUP_NAMED:
			if !m.NamedPresent(cfg.Value.CaptureGroupName) {
				log.With("name", cfg.Name).
					With("group_name", cfg.Value.CaptureGroup).
					With("line",line).
					Warnln("Dropping line with missing capture value")
				continue
			}
			valstr := m.NamedString(cfg.Value.CaptureGroupName)
			val, err := strconv.ParseFloat(valstr, 64)
			if err != nil {
				log.With("name", cfg.Name).
					With("group_name", cfg.Value.CaptureGroupName).
					With("line",line).
					With("value",valstr).
					Warnln("Dropping line with unconvertible capture value")
				continue
			}

			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Set(val)
			case prometheus.Counter:
				t.Set(val)
			case prometheus.Untyped:
				t.Set(val)
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_INC:
			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Inc()
			case prometheus.Counter:
				t.Inc()
			case prometheus.Untyped:
				t.Inc()
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}

		case config.VALUE_SUB:
			switch t := metric.(type) {
			case prometheus.Gauge:
				t.Dec()
			case prometheus.Counter:
				t.Set(0) // Subtract means reset for a counter
			case prometheus.Untyped:
				t.Dec()
			default:
				log.With("name", cfg.Name).Errorf("Unknown type for metric: %T", t)
			}
		}
	}
}

// Collect implements prometheus.Collector.
func (c TailCollector) Collect(ch chan<- prometheus.Metric) {
	c.numMetrics.Collect(ch)
	c.ingestedLines.Collect(ch)
	//c.rejectedLines.Collect(ch)

	for _, v := range c.metrics {
		v.Collect(ch)
	}
}

// Describe implements prometheus.Collector.
func (c TailCollector) Describe(ch chan<- *prometheus.Desc) {
	c.numMetrics.Describe(ch)
	c.ingestedLines.Describe(ch)
	//c.rejectedLines.Describe(ch)

	for _, v := range c.metrics {
		v.Describe(ch)
	}
}

func main() {
	flag.Parse()
	http.Handle(*metricsPath, prometheus.Handler())

	cfg, err := config.LoadFile(*configFile)
	if err != nil {
		log.Fatalln("Configuration file could not be read.", err)
	}

	c := newTailCollector(cfg)
	prometheus.MustRegister(c)

	// If args then start file/fifo collectors
	if len(flag.Args()) > 0 {
		for _, filename := range flag.Args() {
			go func(filename string) {
				var isPipe bool
				st, err := os.Stat(filename)
				if err == nil {
					if st.Mode() & os.ModeNamedPipe == os.ModeNamedPipe {
						isPipe = true
					}
				} else {
					isPipe = false
				}

				t, err := tail.TailFile(filename, tail.Config{
					Location: &tail.SeekInfo{0,os.SEEK_END},
					ReOpen: true,
					Follow: isPipe,
				})

				for line := range t.Lines {
					c.IngestLine(line.Text)
				}

			}(filename)
		}
	}

	// If collector address present, then start port collector.
	if *collectorAddress != "" {
		tcpSock, err := net.Listen("tcp", *collectorAddress)
		if err != nil {
			log.Fatalf("Error binding to TCP socket: %s", err)
		}
		go func() {
			for {
				conn, err := tcpSock.Accept()
				if err != nil {
					log.Errorf("Error accepting TCP connection: %s", err)
					continue
				}
				go func() {
					defer conn.Close()
					c.processReader(conn)
				}()
			}
		}()

		udpAddress, err := net.ResolveUDPAddr("udp", *collectorAddress)
		if err != nil {
			log.Fatalf("Error resolving UDP address: %s", err)
		}
		udpSock, err := net.ListenUDP("udp", udpAddress)
		if err != nil {
			log.Fatalf("Error listening to UDP address: %s", err)
		}
		go func() {
			defer udpSock.Close()
			for {
				buf := make([]byte, 65536)
				chars, srcAddress, err := udpSock.ReadFromUDP(buf)
				if err != nil {
					log.Errorf("Error reading UDP packet from %s: %s", srcAddress, err)
					continue
				}
				go c.processReader(bytes.NewReader(buf[0:chars]))
			}
		}()
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
      <title>Tail Exporter</title>

TCP/UDP Tail Exporter

Accepting raw lines over TCP and UDP on ` + *collectorAddress + `

Watching files for lines:` + flag.Args() + `

<a href="` + *metricsPath + `">Metrics

Config

` +
      cfg.Original +
      `

      `))
	})

	log.Infof("Starting Server: %s", *listeningAddress)
	http.ListenAndServe(*listeningAddress, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/tylerb/graceful"
	"github.com/yosisa/sigm"
	"github.com/yosisa/webutil"
)

var (
	dataDir         = flag.String("data-dir", "./data", "Data directory")
	listen          = flag.String("listen", ":8000", "Listen address")
	gracefulTimeout = flag.Duration("graceful-timeout", 10*time.Second, "Wait until force shutdown")
	gcInterval      = flag.Duration("gc-interval", time.Hour, "GC interval for cleaning deleted files")
)

var tombstone = ".restfs-deleted"

type restfs struct {
	dir string
}

func (c *restfs) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fullpath := path.Join(c.dir, r.URL.Path)
	var err error
	switch r.Method {
	case "GET":
		if !fileAvailable(fullpath) {
			http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
			return
		}
		http.ServeFile(w, r, fullpath)
	case "PUT":
		err = c.saveFile(fullpath, r.Body)
		r.Body.Close()
	case "DELETE":
		var stat os.FileInfo
		stat, err = os.Stat(fullpath)
		if os.IsNotExist(err) {
			return
		}
		if stat.IsDir() {
			recursive, _ := strconv.ParseBool(r.URL.Query().Get("recursive"))
			if recursive {
				err = c.removeAll(fullpath)
			} else {
				w.WriteHeader(http.StatusBadRequest)
				fmt.Fprintf(w, "Cannot remove directory; forgot recursive=true?\n")
				return
			}
		} else {
			err = c.remove(fullpath)
		}
	}
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func (c *restfs) saveFile(fullpath string, r io.Reader) error {
	dir, _ := path.Split(fullpath)
	if err := os.MkdirAll(dir, 0777); err != nil {
		return err
	}
	f, err := os.OpenFile(fullpath, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		return err
	}
	if _, err := io.Copy(f, r); err != nil {
		return err
	}
	return nil
}

func (c *restfs) remove(fullpath string) error {
	f, err := os.Create(fullpath + tombstone)
	if err == nil {
		f.Close()
	}
	return err
}

func (c *restfs) removeAll(fullpath string) error {
	return filepath.Walk(fullpath, func(name string, stat os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if stat.IsDir() || strings.HasSuffix(name, tombstone) {
			return nil
		}
		return c.remove(name)
	})
}

type gc struct {
	dir    string
	invoke chan struct{}
}

func newGC(dir string) *gc {
	g := &gc{
		dir:    dir,
		invoke: make(chan struct{}, 1),
	}
	go g.loop()
	return g
}

func (g *gc) loop() {
	remove := func(s string) error {
		log.Printf("Remove %s", s)
		if err := os.Remove(s); err != nil && !os.IsNotExist(err) {
			return err
		}
		return nil
	}
	for range g.invoke {
		log.Print("GC started")
		start := time.Now()
		err := filepath.Walk(g.dir, func(name string, stat os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if stat.IsDir() || !strings.HasSuffix(name, tombstone) {
				return nil
			}
			fname := name[:len(name)-len(tombstone)]
			fstat, err := os.Stat(fname)
			if err == nil {
				if !fstat.ModTime().After(stat.ModTime()) {
					if err = remove(fname); err != nil {
						return err
					}
				}
				return remove(name)
			} else if os.IsNotExist(err) {
				return remove(name)
			}
			return err
		})
		took := time.Since(start)
		if err == nil {
			log.Printf("GC has finished in %v", took)
		} else {
			log.Printf("GC has aborted in %v with error: %v", took, err)
		}
	}
}

func (g *gc) Start() {
	select {
	case g.invoke <- struct{}{}:
	default:
	}
}

func fileAvailable(fullpath string) bool {
	astat, err := os.Stat(fullpath)
	if err != nil {
		return false
	}
	bstat, err := os.Stat(fullpath + tombstone)
	if err != nil {
		return os.IsNotExist(err)
	}
	return astat.ModTime().After(bstat.ModTime())
}

func main() {
	flag.Parse()
	h := webutil.Logger(&restfs{*dataDir}, webutil.ConsoleLogWriter(os.Stdout))
	h = webutil.Recoverer(h, os.Stderr)
	g := newGC(*dataDir)
	g.Start()
	sigm.Handle(syscall.SIGUSR1, g.Start)
	if *gcInterval > 0 {
		go func() {
			for range time.Tick(*gcInterval) {
				g.Start()
			}
		}()
	}
	graceful.Run(*listen, *gracefulTimeout, h)
}
<commit_msg>Fix status code on PUT/DELETE method<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/tylerb/graceful"
	"github.com/yosisa/sigm"
	"github.com/yosisa/webutil"
)

var (
	dataDir         = flag.String("data-dir", "./data", "Data directory")
	listen          = flag.String("listen", ":8000", "Listen address")
	gracefulTimeout = flag.Duration("graceful-timeout", 10*time.Second, "Wait until force shutdown")
	gcInterval      = flag.Duration("gc-interval", time.Hour, "GC interval for cleaning deleted files")
)

var tombstone = ".restfs-deleted"

type restfs struct {
	dir string
}

func (c *restfs) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fullpath := path.Join(c.dir, r.URL.Path)
	var err error
	switch r.Method {
	case "GET":
		if !fileAvailable(fullpath) {
			http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
			return
		}
		http.ServeFile(w, r, fullpath)
		return
	case "PUT":
		err = c.saveFile(fullpath, r.Body)
		r.Body.Close()
	case "DELETE":
		var stat os.FileInfo
		stat, err = os.Stat(fullpath)
		if os.IsNotExist(err) {
			return
		}
		if stat.IsDir() {
			recursive, _ := strconv.ParseBool(r.URL.Query().Get("recursive"))
			if recursive {
				err = c.removeAll(fullpath)
			} else {
				w.WriteHeader(http.StatusBadRequest)
				fmt.Fprintf(w, "Cannot remove directory; forgot recursive=true?\n")
				return
			}
		} else {
			err = c.remove(fullpath)
		}
	}
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
}

func (c *restfs) saveFile(fullpath string, r io.Reader) error {
	dir, _ := path.Split(fullpath)
	if err := os.MkdirAll(dir, 0777); err != nil {
		return err
	}
	f, err := os.OpenFile(fullpath, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		return err
	}
	if _, err := io.Copy(f, r); err != nil {
		return err
	}
	return nil
}

func (c *restfs) remove(fullpath string) error {
	f, err := os.Create(fullpath + tombstone)
	if err == nil {
		f.Close()
	}
	return err
}

func (c *restfs) removeAll(fullpath string) error {
	return filepath.Walk(fullpath, func(name string, stat os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if stat.IsDir() || strings.HasSuffix(name, tombstone) {
			return nil
		}
		return c.remove(name)
	})
}

type gc struct {
	dir    string
	invoke chan struct{}
}

func newGC(dir string) *gc {
	g := &gc{
		dir:    dir,
		invoke: make(chan struct{}, 1),
	}
	go g.loop()
	return g
}

func (g *gc) loop() {
	remove := func(s string) error {
		log.Printf("Remove %s", s)
		if err := os.Remove(s); err != nil && !os.IsNotExist(err) {
			return err
		}
		return nil
	}
	for range g.invoke {
		log.Print("GC started")
		start := time.Now()
		err := filepath.Walk(g.dir, func(name string, stat os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if stat.IsDir() || !strings.HasSuffix(name, tombstone) {
				return nil
			}
			fname := name[:len(name)-len(tombstone)]
			fstat, err := os.Stat(fname)
			if err == nil {
				if !fstat.ModTime().After(stat.ModTime()) {
					if err = remove(fname); err != nil {
						return err
					}
				}
				return remove(name)
			} else if os.IsNotExist(err) {
				return remove(name)
			}
			return err
		})
		took := time.Since(start)
		if err == nil {
			log.Printf("GC has finished in %v", took)
		} else {
			log.Printf("GC has aborted in %v with error: %v", took, err)
		}
	}
}

func (g *gc) Start() {
	select {
	case g.invoke <- struct{}{}:
	default:
	}
}

func fileAvailable(fullpath string) bool {
	astat, err := os.Stat(fullpath)
	if err != nil {
		return false
	}
	bstat, err := os.Stat(fullpath + tombstone)
	if err != nil {
		return os.IsNotExist(err)
	}
	return astat.ModTime().After(bstat.ModTime())
}

func main() {
	flag.Parse()
	h := webutil.Logger(&restfs{*dataDir}, webutil.ConsoleLogWriter(os.Stdout))
	h = webutil.Recoverer(h, os.Stderr)
	g := newGC(*dataDir)
	g.Start()
	sigm.Handle(syscall.SIGUSR1, g.Start)
	if *gcInterval > 0 {
		go func() {
			for range time.Tick(*gcInterval) {
				g.Start()
			}
		}()
	}
	graceful.Run(*listen, *gracefulTimeout, h)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"

	"github.com/techjanitor/pram-libs/auth"
	"github.com/techjanitor/pram-libs/config"
	"github.com/techjanitor/pram-libs/cors"
	"github.com/techjanitor/pram-libs/db"
	"github.com/techjanitor/pram-libs/redis"
	"github.com/techjanitor/pram-libs/validate"

	local "github.com/techjanitor/pram-post/config"
	c "github.com/techjanitor/pram-post/controllers"
	m "github.com/techjanitor/pram-post/middleware"
	u "github.com/techjanitor/pram-post/utils"
)

var (
	version = "0.9.1"
)

func init() {

	// Database connection settings
	dbase := db.Database{

		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	config.GetDatabaseSettings()

	// redis settings
	r := redis.Redis{
		// Redis address and max pool connections
		Protocol:       local.Settings.Redis.Protocol,
		Address:        local.Settings.Redis.Address,
		MaxIdle:        local.Settings.Redis.MaxIdle,
		MaxConnections: local.Settings.Redis.MaxConnections,
	}

	// Set up Redis connection
	redis.NewRedisCache()

	// set auth middleware secret
	auth.Secret = local.Settings.Session.Secret

	// print the starting info
	StartInfo()

	// Print out config
	config.Print()

	// Print out config
	local.Print()

	// check what services are available
	u.CheckServices()

	// Print capabilities
	u.Services.Print()

	// set cors domains
	cors.SetDomains(local.Settings.CORS.Sites, strings.Split("POST,DELETE", ","))

}

func main() {
	r := gin.Default()

	r.Use(cors.CORS())

	r.NoRoute(c.ErrorController)

	// all users
	public := r.Group("/")
	public.Use(auth.Auth(auth.All))

	public.POST("/thread/new", m.GetAntiSpamCookie(), c.ThreadController)
	public.POST("/thread/reply", m.GetAntiSpamCookie(), c.ReplyController)
	public.POST("/tag/new", m.GetAntiSpamCookie(), c.NewTagController)
	public.POST("/tag/add", m.GetAntiSpamCookie(), c.AddTagController)
	public.POST("/register", c.RegisterController)
	public.POST("/login", c.LoginController)

	// requires user perms
	users := r.Group("/user")
	users.Use(auth.Auth(auth.Registered))

	users.POST("/favorite", c.FavoritesController)
	users.POST("/password", c.PasswordController)
	users.POST("/email", c.EmailController)

	// requires mod perms
	mod := r.Group("/mod")
	mod.Use(validate.ValidateParams())
	mod.Use(auth.Auth(auth.Moderators))

	mod.DELETE("/tag/:id", c.DeleteTagController)
	mod.DELETE("/imagetag/:image/:tag", c.DeleteImageTagController)
	mod.DELETE("/thread/:id", c.DeleteThreadController)
	mod.DELETE("/post/:thread/:id", c.DeletePostController)
	mod.POST("/sticky/:thread", c.StickyThreadController)
	mod.POST("/close/:thread", c.CloseThreadController)

	// requires admin perms
	admin := r.Group("/admin")
	admin.Use(validate.ValidateParams())
	admin.Use(auth.Auth(auth.Admins))

	admin.DELETE("/thread/:id", c.PurgeThreadController)
	admin.DELETE("/post/:thread/:id", c.PurgePostController)
	//admin.POST("/ban/:ip", c.BanIpController)
	//admin.DELETE("/flushcache", c.DeleteCacheController)

	s := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", local.Settings.Post.Address, local.Settings.Post.Port),
		Handler: r,
	}

	gracehttp.Serve(s)

}

func StartInfo() {

	fmt.Println(strings.Repeat("*", 60))
	fmt.Printf("%-20v\n\n", "PRAM-POST")
	fmt.Printf("%-20v%40v\n", "Version", version)
	fmt.Println(strings.Repeat("*", 60))

}
<commit_msg>add redis and audit libs<commit_after>package main

import (
	"fmt"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"

	"github.com/techjanitor/pram-libs/auth"
	"github.com/techjanitor/pram-libs/config"
	"github.com/techjanitor/pram-libs/cors"
	"github.com/techjanitor/pram-libs/db"
	"github.com/techjanitor/pram-libs/redis"
	"github.com/techjanitor/pram-libs/validate"

	local "github.com/techjanitor/pram-post/config"
	c "github.com/techjanitor/pram-post/controllers"
	m "github.com/techjanitor/pram-post/middleware"
	u "github.com/techjanitor/pram-post/utils"
)

var (
	version = "0.9.1"
)

func init() {

	// Database connection settings
	dbase := db.Database{

		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	config.GetDatabaseSettings()

	// redis settings
	r := redis.Redis{
		// Redis address and max pool connections
		Protocol:       local.Settings.Redis.Protocol,
		Address:        local.Settings.Redis.Address,
		MaxIdle:        local.Settings.Redis.MaxIdle,
		MaxConnections: local.Settings.Redis.MaxConnections,
	}

	// Set up Redis connection
	r.NewRedisCache()

	// set auth middleware secret
	auth.Secret = local.Settings.Session.Secret

	// print the starting info
	StartInfo()

	// Print out config
	config.Print()

	// Print out config
	local.Print()

	// check what services are available
	u.CheckServices()

	// Print capabilities
	u.Services.Print()

	// set cors domains
	cors.SetDomains(local.Settings.CORS.Sites, strings.Split("POST,DELETE", ","))

}

func main() {
	r := gin.Default()

	r.Use(cors.CORS())

	r.NoRoute(c.ErrorController)

	// all users
	public := r.Group("/")
	public.Use(auth.Auth(auth.All))

	public.POST("/thread/new", m.GetAntiSpamCookie(), c.ThreadController)
	public.POST("/thread/reply", m.GetAntiSpamCookie(), c.ReplyController)
	public.POST("/tag/new", m.GetAntiSpamCookie(), c.NewTagController)
	public.POST("/tag/add", m.GetAntiSpamCookie(), c.AddTagController)
	public.POST("/register", c.RegisterController)
	public.POST("/login", c.LoginController)

	// requires user perms
	users := r.Group("/user")
	users.Use(auth.Auth(auth.Registered))

	users.POST("/favorite", c.FavoritesController)
	users.POST("/password", c.PasswordController)
	users.POST("/email", c.EmailController)

	// requires mod perms
	mod := r.Group("/mod")
	mod.Use(validate.ValidateParams())
	mod.Use(auth.Auth(auth.Moderators))

	mod.DELETE("/tag/:id", c.DeleteTagController)
	mod.DELETE("/imagetag/:image/:tag", c.DeleteImageTagController)
	mod.DELETE("/thread/:id", c.DeleteThreadController)
	mod.DELETE("/post/:thread/:id", c.DeletePostController)
	mod.POST("/sticky/:thread", c.StickyThreadController)
	mod.POST("/close/:thread", c.CloseThreadController)

	// requires admin perms
	admin := r.Group("/admin")
	admin.Use(validate.ValidateParams())
	admin.Use(auth.Auth(auth.Admins))

	admin.DELETE("/thread/:id", c.PurgeThreadController)
	admin.DELETE("/post/:thread/:id", c.PurgePostController)
	//admin.POST("/ban/:ip", c.BanIpController)
	//admin.DELETE("/flushcache", c.DeleteCacheController)

	s := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", local.Settings.Post.Address, local.Settings.Post.Port),
		Handler: r,
	}

	gracehttp.Serve(s)

}

func StartInfo() {

	fmt.Println(strings.Repeat("*", 60))
	fmt.Printf("%-20v\n\n", "PRAM-POST")
	fmt.Printf("%-20v%40v\n", "Version", version)
	fmt.Println(strings.Repeat("*", 60))

}
<|endoftext|>