<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"

	"github.com/layeh/gumble/gumble"
	"github.com/layeh/gumble/gumbleutil"
	"golang.org/x/net/html"
)

var redditUser string
var redditPassword string
var subreddit string

func init() {
	basicHTTPPattern = regexp.MustCompile(basicHTTPLinkPattern)
	imgurPattern = regexp.MustCompile(imgurLinkPattern)
	imgurAlbumPattern = regexp.MustCompile(imgurAlbumLinkPattern)
	youtubePattern = regexp.MustCompile(youtubeLinkPattern)

	flag.StringVar(&redditUser, "reddituser", "", "the reddit user to post as")
	flag.StringVar(&redditPassword, "redditpassword", "", "the reddit user password")
	flag.StringVar(&subreddit, "subreddit", "", "the subreddit to post to")
}

func extraInit(client *gumble.Client) {
	if redditUser == "" || redditPassword == "" || subreddit == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}
}

func connectEvent(e *gumble.ConnectEvent) {
	fmt.Printf("linkbot loaded\n")
}

func textEvent(e *gumble.TextMessageEvent) {
	if e.Sender == nil {
		return
	}
	youtubeMatches := youtubePattern.FindStringSubmatch(e.Message)
	if len(youtubeMatches) == 2 {
		go handleYoutubeLink(e.Client, e.Sender.Name, youtubeMatches[1])
		return
	}

	imgurAlbumMatches := imgurAlbumPattern.FindStringSubmatch(e.Message)
	if len(imgurAlbumMatches) == 2 {
		log.Println(`"` + imgurAlbumMatches[1] + `"`)
		go handleImgurAlbumLink(e.Client, e.Sender.Name, imgurAlbumMatches[1])
		return
	}

	imgurMatches := imgurPattern.FindStringSubmatch(e.Message)
	if len(imgurMatches) == 2 {
		log.Println(`"` + imgurMatches[1] + `"`)
		go handleImgurLink(e.Client, e.Sender.Name, imgurMatches[1])
		return
	}

	basicHTTPMatches := basicHTTPPattern.FindStringSubmatch(e.Message)
	if len(basicHTTPMatches) == 2 {
		go handlebasicHTTPInfo(e.Client, e.Sender.Name, basicHTTPMatches[1])
		return
	}
}

func main() {
	gul := gumbleutil.Listener{
		Connect:     connectEvent,
		TextMessage: textEvent,
	}
	gumbleutil.Main(extraInit, gul)
}

func getTitle(url string) string {
	response, err := http.Get(url)
	if err != nil {
		fmt.Println("Error while downloading", url, "-", err)
		return ""
	}
	defer response.Body.Close()
	var titleDepth int
	var title string
	z := html.NewTokenizer(response.Body)
	for {
		tt := z.Next()
		switch tt {
		case html.ErrorToken:
			return title
		case html.TextToken:
			if titleDepth > 0 {
				title = string(z.Text())
			}
		case html.StartTagToken, html.EndTagToken:
			tn, _ := z.TagName()
			if string(tn) == "title" {
				if tt == html.StartTagToken {
					titleDepth++
				} else {
					titleDepth--
				}
			}
		}
	}
	return strings.Trim(title, "\n\t ")
}
<commit_msg>Taught getTitle to use goquery<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"

	"github.com/PuerkitoBio/goquery"
	"github.com/layeh/gumble/gumble"
	"github.com/layeh/gumble/gumbleutil"
)

var redditUser string
var redditPassword string
var subreddit string

func init() {
	basicHTTPPattern = regexp.MustCompile(basicHTTPLinkPattern)
	imgurPattern = regexp.MustCompile(imgurLinkPattern)
	imgurAlbumPattern = regexp.MustCompile(imgurAlbumLinkPattern)
	youtubePattern = regexp.MustCompile(youtubeLinkPattern)

	flag.StringVar(&redditUser, "reddituser", "", "the reddit user to post as")
	flag.StringVar(&redditPassword, "redditpassword", "", "the reddit user password")
	flag.StringVar(&subreddit, "subreddit", "", "the subreddit to post to")
}

func extraInit(client *gumble.Client) {
	if redditUser == "" || redditPassword == "" || subreddit == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}
}

func connectEvent(e *gumble.ConnectEvent) {
	fmt.Printf("linkbot loaded\n")
}

func textEvent(e *gumble.TextMessageEvent) {
	if e.Sender == nil {
		return
	}
	youtubeMatches := youtubePattern.FindStringSubmatch(e.Message)
	if len(youtubeMatches) == 2 {
		go handleYoutubeLink(e.Client, e.Sender.Name, youtubeMatches[1])
		return
	}

	imgurAlbumMatches := imgurAlbumPattern.FindStringSubmatch(e.Message)
	if len(imgurAlbumMatches) == 2 {
		log.Println(`"` + imgurAlbumMatches[1] + `"`)
		go handleImgurAlbumLink(e.Client, e.Sender.Name, imgurAlbumMatches[1])
		return
	}

	imgurMatches := imgurPattern.FindStringSubmatch(e.Message)
	if len(imgurMatches) == 2 {
		log.Println(`"` + imgurMatches[1] + `"`)
		go handleImgurLink(e.Client, e.Sender.Name, imgurMatches[1])
		return
	}

	basicHTTPMatches := basicHTTPPattern.FindStringSubmatch(e.Message)
	if len(basicHTTPMatches) == 2 {
		go handlebasicHTTPInfo(e.Client, e.Sender.Name, basicHTTPMatches[1])
		return
	}
}

func main() {
	gul := gumbleutil.Listener{
		Connect:     connectEvent,
		TextMessage: textEvent,
	}
	gumbleutil.Main(extraInit, gul)
}

func getTitle(url string) string {
	title := ""
	doc, err := goquery.NewDocument(url)
	if err != nil {
		fmt.Println("Error while downloading", url, "-", err)
		return ""
	}
	doc.Find("title").Each(func(i int, s *goquery.Selection) {
		title = s.Text()
	})
	return strings.Trim(title, "\n\t ")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/ActiveState/tail"
	"github.com/op/go-logging"
	"net/http"
	"regexp"
	"strings"
	"sync"
	"time"
)

type Datasource struct {
	Name        string
	Create_date time.Time
	Params      string
}

type state struct {
	*sync.RWMutex // inherits locking methods
	Vals          []Datasource
}

// declare a globally scoped State variable, otherwise
// the request handlers can't get to it. If there is a better
// way to do this, plmk.
var State = &state{&sync.RWMutex{}, []Datasource{}}

func jsonHandler(w http.ResponseWriter, r *http.Request) {
	var log = logging.MustGetLogger("example")

	log.Notice("jsonHandler: acquiring read-lock")
	State.RLock()         // grab a lock, but then don't forget to
	defer State.RUnlock() // unlock it again once we're done

	log.Info(fmt.Sprintf("Request for %s\n", r.URL.Path))
	js, err := json.Marshal(State.Vals)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
}

func parseTime(s string) time.Time {
	// 24/08/2014 20:59:54
	var t , _ = time.Parse("2006-01-02 15:04:05","2011-01-19 22:15")
	fmt.Println(t)
	return t
}

func addItemToState(ds Datasource) {
	var log = logging.MustGetLogger("example")
	log.Notice("addItemToState: acquiring write-lock")
	State.Lock()
	defer State.Unlock()
	defer log.Notice("addItemToState: released write-lock")
	State.Vals = append(State.Vals, ds)
}

func tailLogfile(c chan string) {
	var log = logging.MustGetLogger("example")

	var dataPath = regexp.MustCompile(`.*out:(.*) :: \[creates\] creating database file .*/whisper/(.*)\.wsp (.*)`)
	t, err := tail.TailFile("./creates.log", tail.Config{Follow: true, ReOpen: true, MustExist: true})
	if err == nil {
		for line := range t.Lines {
			match := dataPath.FindStringSubmatch(line.Text)
			if len(match) > 0 {
				ds := fmt.Sprintf("%s", strings.Replace(match[2], `/`, `.`, -1))
				tmp := Datasource{Name: ds, Create_date: parseTime(match[1]), Params: match[3]}
				addItemToState(tmp)
				log.Notice(fmt.Sprintf("Found new datasource, total: %v, newly added: %+v", len(State.Vals), tmp))
			}
		}
	}
	c <- fmt.Sprintf("%s", err)
}

func main() {
	error_channel := make(chan string)
	var log = logging.MustGetLogger("example")
	var format = "%{color}%{time:15:04:05.000000} [%{pid}] ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}"

	// Setup logger https://github.com/op/go-logging/blob/master/examples/example.go
	logging.SetFormatter(logging.MustStringFormatter(format))
	log.Info("Graphite News -- Showing which new metrics are available since 2014\n")
	log.Notice("Graphite News -- Serving UI on: http://localhost:2934\n")

	http.HandleFunc("/json/", jsonHandler)
	go http.ListenAndServe(":2934", nil)
	go tailLogfile(error_channel)

	log.Notice("Graphite News -- Showing which new metrics are available since 2014\n")

	// Wait for errors to appear then shut down
	log.Error(<-error_channel)
}
<commit_msg>fixed date formatting<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/ActiveState/tail"
	"github.com/op/go-logging"
	"net/http"
	"regexp"
	"strings"
	"sync"
	"time"
)

type Datasource struct {
	Name        string
	Create_date time.Time
	Params      string
}

type state struct {
	*sync.RWMutex // inherits locking methods
	Vals          []Datasource
}

// declare a globally scoped State variable, otherwise
// the request handlers can't get to it. If there is a better
// way to do this, plmk.
var State = &state{&sync.RWMutex{}, []Datasource{}}

func jsonHandler(w http.ResponseWriter, r *http.Request) {
	var log = logging.MustGetLogger("example")

	log.Notice("jsonHandler: acquiring read-lock")
	State.RLock()         // grab a lock, but then don't forget to
	defer State.RUnlock() // unlock it again once we're done

	log.Info(fmt.Sprintf("Request for %s\n", r.URL.Path))
	js, err := json.Marshal(State.Vals)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
}

func parseTime(s string) time.Time {
	// 24/08/2014 20:59:54
	var t , _ = time.Parse("02/01/2006 15:04:05",s)
	fmt.Println(t)
	return t
}

func addItemToState(ds Datasource) {
	var log = logging.MustGetLogger("example")
	log.Notice("addItemToState: acquiring write-lock")
	State.Lock()
	defer State.Unlock()
	defer log.Notice("addItemToState: released write-lock")
	State.Vals = append(State.Vals, ds)
}

func tailLogfile(c chan string) {
	var log = logging.MustGetLogger("example")

	var dataPath = regexp.MustCompile(`.*out:(.*) :: \[creates\] creating database file .*/whisper/(.*)\.wsp (.*)`)
	t, err := tail.TailFile("./creates.log", tail.Config{Follow: true, ReOpen: true, MustExist: true})
	if err == nil {
		for line := range t.Lines {
			match := dataPath.FindStringSubmatch(line.Text)
			if len(match) > 0 {
				ds := fmt.Sprintf("%s", strings.Replace(match[2], `/`, `.`, -1))
				tmp := Datasource{Name: ds, Create_date: parseTime(match[1]), Params: match[3]}
				addItemToState(tmp)
				log.Notice(fmt.Sprintf("Found new datasource, total: %v, newly added: %+v", len(State.Vals), tmp))
			}
		}
	}
	c <- fmt.Sprintf("%s", err)
}

func main() {
	error_channel := make(chan string)
	var log = logging.MustGetLogger("example")
	var format = "%{color}%{time:15:04:05.000000} [%{pid}] ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}"

	// Setup logger https://github.com/op/go-logging/blob/master/examples/example.go
	logging.SetFormatter(logging.MustStringFormatter(format))
	log.Info("Graphite News -- Showing which new metrics are available since 2014\n")
	log.Notice("Graphite News -- Serving UI on: http://localhost:2934\n")

	http.HandleFunc("/json/", jsonHandler)
	go http.ListenAndServe(":2934", nil)
	go tailLogfile(error_channel)

	log.Notice("Graphite News -- Showing which new metrics are available since 2014\n")

	// Wait for errors to appear then shut down
	log.Error(<-error_channel)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/minotar/minecraft"
	"github.com/op/go-logging"
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

const (
	DefaultSize = uint(180)
	MaxSize     = uint(300)
	MinSize     = uint(8)

	SkinCache

	Minutes            uint = 60
	Hours                   = 60 * Minutes
	Days                    = 24 * Hours
	TimeoutActualSkin       = 2 * Days
	TimeoutFailedFetch      = 15 * Minutes

	MinotarVersion = "2.2"
)

var (
	config = &Configuration{}
	cache  Cache
)

type NotFoundHandler struct{}

func (h NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	fmt.Fprintf(w, "404 not found")
}

func notFoundPage(w http.ResponseWriter, r *http.Request) {
	nfh := NotFoundHandler{}
	nfh.ServeHTTP(w, r)
}
func serverErrorPage(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(500)
	fmt.Fprintf(w, "500 internal server error")
}

func rationalizeSize(inp string) uint {
	out64, err := strconv.ParseUint(inp, 10, 0)
	out := uint(out64)
	if err != nil {
		return DefaultSize
	} else if out > MaxSize {
		return MaxSize
	} else if out < MinSize {
		return MinSize
	}
	return out
}

func addCacheTimeoutHeader(w http.ResponseWriter, timeout uint) {
	w.Header().Add("Cache-Control", fmt.Sprintf("max-age=%d", timeout))
}

func timeBetween(timeA time.Time, timeB time.Time) int64 {
	// millis between two timestamps

	if timeB.Before(timeA) {
		timeA, timeB = timeB, timeA
	}
	return timeB.Sub(timeA).Nanoseconds() / 1000000
}

func fetchImageProcessThen(callback func(*mcSkin) error) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		timeReqStart := time.Now()

		vars := mux.Vars(r)

		username := strings.ToLower(vars["username"])
		size := rationalizeSize(vars["size"])
		ok := true

		skin := fetchSkin(username)
		var err error

		timeFetch := time.Now()

		err = callback(skin)
		if err != nil {
			serverErrorPage(w, r)
			return
		}
		timeProcess := time.Now()
		skin.Resize(size)
		timeResize := time.Now()

		w.Header().Add("Content-Type", "image/png")
		w.Header().Add("X-Requested", "processed")
		w.Header().Add("X-Skin-Hash", skin.Hash)
		var timeout uint
		if ok {
			w.Header().Add("X-Result", "ok")
			timeout = TimeoutActualSkin
		} else {
			w.Header().Add("X-Result", "failed")
			timeout = TimeoutFailedFetch
		}

		timing := fmt.Sprintf("%d+%d+%d=%dms", timeBetween(timeReqStart, timeFetch), timeBetween(timeFetch, timeProcess), timeBetween(timeProcess, timeResize), timeBetween(timeReqStart, timeResize))

		w.Header().Add("X-Timing", timing)
		addCacheTimeoutHeader(w, timeout)
		skin.WritePNG(w)

		log.Info("Serving skin for " + username + " (" + timing + ") md5: " + skin.Hash)
	}
}

func skinPage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	username := strings.ToLower(vars["username"])

	skin := fetchSkin(username)

	w.Header().Add("Content-Type", "image/png")
	w.Header().Add("X-Requested", "skin")
	w.Header().Add("X-Result", "ok")

	skin.WriteSkin(w)
}

func downloadPage(w http.ResponseWriter, r *http.Request) {
	headers := w.Header()
	headers.Add("Content-Disposition", "attachment; filename=\"skin.png\"")
	skinPage(w, r)
}

func fetchSkin(username string) *mcSkin {
	if cache.has(username) {
		return &mcSkin{Processed: nil, Skin: cache.pull(username)}
	}

	skin, err := minecraft.FetchSkinFromUrl(username)
	if err != nil {
		log.Error("Failed to get skin for " + username + " from Mojang (" + err.Error() + ")")
		skin, _ = minecraft.FetchSkinForChar()
	}

	cache.add(username, skin)
	return &mcSkin{Processed: nil, Skin: skin}

	/* We're not using this for now due to rate limiting restrictions
	skin, err := minecraft.GetSkin(minecraft.User{Name: username})
	if err != nil {
		// Problem with the returned image, probably means we have an incorrect username
		// Hit the accounts api
		user, err := minecraft.GetUser(username)

		if err != nil {
			// There's no account for this person, serve char
			skin, _ = minecraft.FetchSkinForChar()
		} else {
			// Get valid skin
			skin, err = minecraft.GetSkin(user)
			if err != nil {
				// Their skin somehow errored, fallback
				skin, _ = minecraft.FetchSkinForChar()
			}
		}
	}

	return skin
	*/
}

var log = logging.MustGetLogger("imgd")
var format = "[%{time:15:04:05.000000}] %{level:.4s} %{message}"

func setupConfig() {
	err := config.load()
	if err != nil {
		fmt.Printf("Error loading config: %s\n", err)
		return
	}
}

func setupCache() {
	cache = MakeCache(config.Cache)
	cache.setup()
}

func setupLog(logBackend *logging.LogBackend) {
	logging.SetBackend(logBackend)
	logging.SetFormatter(logging.MustStringFormatter(format))
}

func main() {
	logBackend := logging.NewLogBackend(os.Stdout, "", 0)
	setupConfig()
	setupLog(logBackend)
	setupCache()

	debug.SetGCPercent(10)

	avatarPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetHead()
	})
	helmPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetHelm()
	})
	bodyPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetBody()
	})
	bustPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetBust()
	})

	r := mux.NewRouter()
	r.NotFoundHandler = NotFoundHandler{}

	r.HandleFunc("/avatar/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", avatarPage)
	r.HandleFunc("/avatar/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", avatarPage)

	r.HandleFunc("/helm/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", helmPage)
	r.HandleFunc("/helm/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", helmPage)

	r.HandleFunc("/body/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", bodyPage)
	r.HandleFunc("/body/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", bodyPage)

	r.HandleFunc("/bust/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", bustPage)
	r.HandleFunc("/bust/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", bustPage)

	r.HandleFunc("/download/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", downloadPage)

	r.HandleFunc("/skin/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", skinPage)

	r.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "%s", MinotarVersion)
	})

	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://minotar.net/", 302)
	})

	http.Handle("/", r)
	err := http.ListenAndServe(config.Address, nil)
	log.Critical(err.Error())
}
<commit_msg>Only lowercase cache usernames<commit_after>package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/minotar/minecraft"
	"github.com/op/go-logging"
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

const (
	DefaultSize = uint(180)
	MaxSize     = uint(300)
	MinSize     = uint(8)

	SkinCache

	Minutes            uint = 60
	Hours                   = 60 * Minutes
	Days                    = 24 * Hours
	TimeoutActualSkin       = 2 * Days
	TimeoutFailedFetch      = 15 * Minutes

	MinotarVersion = "2.2"
)

var (
	config = &Configuration{}
	cache  Cache
)

type NotFoundHandler struct{}

func (h NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	fmt.Fprintf(w, "404 not found")
}

func notFoundPage(w http.ResponseWriter, r *http.Request) {
	nfh := NotFoundHandler{}
	nfh.ServeHTTP(w, r)
}
func serverErrorPage(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(500)
	fmt.Fprintf(w, "500 internal server error")
}

func rationalizeSize(inp string) uint {
	out64, err := strconv.ParseUint(inp, 10, 0)
	out := uint(out64)
	if err != nil {
		return DefaultSize
	} else if out > MaxSize {
		return MaxSize
	} else if out < MinSize {
		return MinSize
	}
	return out
}

func addCacheTimeoutHeader(w http.ResponseWriter, timeout uint) {
	w.Header().Add("Cache-Control", fmt.Sprintf("max-age=%d", timeout))
}

func timeBetween(timeA time.Time, timeB time.Time) int64 {
	// millis between two timestamps

	if timeB.Before(timeA) {
		timeA, timeB = timeB, timeA
	}
	return timeB.Sub(timeA).Nanoseconds() / 1000000
}

func fetchImageProcessThen(callback func(*mcSkin) error) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		timeReqStart := time.Now()

		vars := mux.Vars(r)

		username := vars["username"]
		size := rationalizeSize(vars["size"])
		ok := true

		skin := fetchSkin(username)
		var err error

		timeFetch := time.Now()

		err = callback(skin)
		if err != nil {
			serverErrorPage(w, r)
			return
		}
		timeProcess := time.Now()
		skin.Resize(size)
		timeResize := time.Now()

		w.Header().Add("Content-Type", "image/png")
		w.Header().Add("X-Requested", "processed")
		w.Header().Add("X-Skin-Hash", skin.Hash)
		var timeout uint
		if ok {
			w.Header().Add("X-Result", "ok")
			timeout = TimeoutActualSkin
		} else {
			w.Header().Add("X-Result", "failed")
			timeout = TimeoutFailedFetch
		}

		timing := fmt.Sprintf("%d+%d+%d=%dms", timeBetween(timeReqStart, timeFetch), timeBetween(timeFetch, timeProcess), timeBetween(timeProcess, timeResize), timeBetween(timeReqStart, timeResize))

		w.Header().Add("X-Timing", timing)
		addCacheTimeoutHeader(w, timeout)
		skin.WritePNG(w)

		log.Info("Serving skin for " + username + " (" + timing + ") md5: " + skin.Hash)
	}
}

func skinPage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	username := vars["username"]

	skin := fetchSkin(username)

	w.Header().Add("Content-Type", "image/png")
	w.Header().Add("X-Requested", "skin")
	w.Header().Add("X-Result", "ok")

	skin.WriteSkin(w)
}

func downloadPage(w http.ResponseWriter, r *http.Request) {
	headers := w.Header()
	headers.Add("Content-Disposition", "attachment; filename=\"skin.png\"")
	skinPage(w, r)
}

func fetchSkin(username string) *mcSkin {
	if cache.has(strings.ToLower(username)) {
		return &mcSkin{Processed: nil, Skin: cache.pull(strings.ToLower(username))}
	}

	skin, err := minecraft.FetchSkinFromUrl(username)
	if err != nil {
		log.Error("Failed to get skin for " + username + " from Mojang (" + err.Error() + ")")
		skin, _ = minecraft.FetchSkinForChar()
	}

	cache.add(strings.ToLower(username), skin)
	return &mcSkin{Processed: nil, Skin: skin}

	/* We're not using this for now due to rate limiting restrictions
	skin, err := minecraft.GetSkin(minecraft.User{Name: username})
	if err != nil {
		// Problem with the returned image, probably means we have an incorrect username
		// Hit the accounts api
		user, err := minecraft.GetUser(username)

		if err != nil {
			// There's no account for this person, serve char
			skin, _ = minecraft.FetchSkinForChar()
		} else {
			// Get valid skin
			skin, err = minecraft.GetSkin(user)
			if err != nil {
				// Their skin somehow errored, fallback
				skin, _ = minecraft.FetchSkinForChar()
			}
		}
	}

	return skin
	*/
}

var log = logging.MustGetLogger("imgd")
var format = "[%{time:15:04:05.000000}] %{level:.4s} %{message}"

func setupConfig() {
	err := config.load()
	if err != nil {
		fmt.Printf("Error loading config: %s\n", err)
		return
	}
}

func setupCache() {
	cache = MakeCache(config.Cache)
	cache.setup()
}

func setupLog(logBackend *logging.LogBackend) {
	logging.SetBackend(logBackend)
	logging.SetFormatter(logging.MustStringFormatter(format))
}

func main() {
	logBackend := logging.NewLogBackend(os.Stdout, "", 0)
	setupConfig()
	setupLog(logBackend)
	setupCache()

	debug.SetGCPercent(10)

	avatarPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetHead()
	})
	helmPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetHelm()
	})
	bodyPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetBody()
	})
	bustPage := fetchImageProcessThen(func(skin *mcSkin) error {
		return skin.GetBust()
	})

	r := mux.NewRouter()
	r.NotFoundHandler = NotFoundHandler{}

	r.HandleFunc("/avatar/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", avatarPage)
	r.HandleFunc("/avatar/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", avatarPage)

	r.HandleFunc("/helm/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", helmPage)
	r.HandleFunc("/helm/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", helmPage)

	r.HandleFunc("/body/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", bodyPage)
	r.HandleFunc("/body/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", bodyPage)

	r.HandleFunc("/bust/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", bustPage)
	r.HandleFunc("/bust/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", bustPage)

	r.HandleFunc("/download/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", downloadPage)

	r.HandleFunc("/skin/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", skinPage)

	r.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "%s", MinotarVersion)
	})

	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://minotar.net/", 302)
	})

	http.Handle("/", r)
	err := http.ListenAndServe(config.Address, nil)
	log.Critical(err.Error())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strings"
	"time"
)

const (
	horizontal int = iota
	horizontalReversed
	vertical
	verticalReversed
	diagonalLTR
	diagonalLTRReversed
	diagonalRTL
	diagonalRTLReversed
)

const (
	letterBytes     = "abcdefghijklmnopqrstuvwxyz"
	fitWordAttempts = 500
	boardAttempts   = 1000
)

type gameBoard [][]string

func readWordList(path string) (lines []string, err error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, strings.ToLower(scanner.Text()))
	}
	return lines, scanner.Err()
}

func makeBoard(x int, y int) (board gameBoard) {
	board = make(gameBoard, y)
	for i := range board {
		board[i] = make([]string, x)
	}
	return
}

func reverse(s string) string {
	chars := []rune(s)
	for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
		chars[i], chars[j] = chars[j], chars[i]
	}
	return string(chars)
}

func fitHorizontal(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = rand.Intn(y)
		found = iy+len(word) < y
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix][iy+j] == "" {
			(*board)[ix][iy+j] = c
		} else {
			return false
		}
	}
	return true
}

func fitHorizontalReversed(board *gameBoard, word string) bool {
	return fitHorizontal(board, reverse(word))
}

func fitVertical(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = rand.Intn(y)
		found = ix+len(word) < x
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix+j][iy] == "" {
			(*board)[ix+j][iy] = c
		} else {
			return false
		}
	}
	return true
}

func fitVerticalReversed(board *gameBoard, word string) bool {
	return fitVertical(board, reverse(word))
}

func fitDiagonalLTR(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = rand.Intn(y)
		found = ix+len(word) < x && iy+len(word) < y
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix+j][iy+j] == "" {
			(*board)[ix+j][iy+j] = c
		} else {
			return false
		}
	}
	return true
}

func fitDiagonalLTRReversed(board *gameBoard, word string) bool {
	return fitDiagonalLTR(board, reverse(word))
}

func fitDiagonalRTL(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = len(word) + rand.Intn(y-len(word))
		found = ix+len(word) < x && iy-len(word) >= 0
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix+j][iy-j] == "" {
			(*board)[ix+j][iy-j] = c
		} else {
			return false
		}
	}
	return true
}

func fitDiagonalRTLReversed(board *gameBoard, word string) bool {
	return fitDiagonalRTL(board, reverse(word))
}

func fitWord(board *gameBoard, word string) bool {
	wordDirection := rand.Intn(diagonalRTLReversed + 1)
	w := strings.Replace(word, " ", "", -1)
	switch wordDirection {
	case horizontal:
		return fitHorizontal(board, w)
	case horizontalReversed:
		return fitHorizontalReversed(board, w)
	case vertical:
		return fitVertical(board, w)
	case verticalReversed:
		return fitVerticalReversed(board, w)
	case diagonalLTR:
		return fitDiagonalLTR(board, w)
	case diagonalLTRReversed:
		return fitDiagonalLTRReversed(board, w)
	case diagonalRTL:
		return fitDiagonalRTL(board, w)
	case diagonalRTLReversed:
		return fitDiagonalRTLReversed(board, w)
	}
	return false
}

func buildBoard(board *gameBoard, words []string) bool {
	for _, word := range words {
		if !fitWord(board, word) {
			return false
		}
	}
	return true
}

func getRandomLetter() string {
	return string(letterBytes[rand.Intn(len(letterBytes))])
	// return "."
}

func fillBoard(board *gameBoard) {
	for i := range *board {
		for j := range (*board)[i] {
			if (*board)[i][j] == "" {
				(*board)[i][j] = getRandomLetter()
			}
		}
	}
}

func printBoard(board *gameBoard) {
	for i := range *board {
		for j := range (*board)[i] {
			c := (*board)[i][j]
			if c == "" {
				c = " "
			}
			fmt.Print(c)
		}
		fmt.Print("\n")
	}
}

func htmlBoard(board *gameBoard, words []string, output string) {
	f, err := os.Create(output)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return
	}
	defer f.Close()
	fmt.Fprintln(f, `<div style="float:left">`)
	fmt.Fprintln(f, `<table style="font-family:'Lucida Console', monospace">`)
	for i := range *board {
		fmt.Fprintln(f, `<tr style="padding: 0; margin: 0">`)
		for j := range (*board)[i] {
			c := (*board)[i][j]
			fmt.Fprintf(f, `<td style="padding: 0; margin: 0; height: 20px; width: 20px">%s</td>`, c)
		}
		fmt.Fprintln(f, "
")
	}
	fmt.Fprintln(f, "
")
	fmt.Fprintln(f, "
")
	fmt.Fprintln(f, `<div style="float:left">`)
	fmt.Fprintln(f, `<ul style="list-style: none;">`)
	for _, word := range words {
		fmt.Fprintf(f, "
%s
\n", word)
	}
	fmt.Fprintln(f, "
")
	fmt.Fprintln(f, "
")
}

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	wordList, err := readWordList("wordlist.txt")
	if err != nil {
		fmt.Println("Error:", err.Error())
		return
	}
	fmt.Println(wordList)
	for i := 0; i < boardAttempts; i++ {
		board := makeBoard(30, 30)
		built := buildBoard(&board, wordList)
		if built {
			fillBoard(&board)
			printBoard(&board)
			htmlBoard(&board, wordList, "output.html")
			fmt.Println("output.html saved")
			return
		}
	}
	fmt.Println("Error: couldn't fit words")
}
<commit_msg>tweak sizing and retry<commit_after>package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strings"
	"time"
)

const (
	horizontal int = iota
	horizontalReversed
	vertical
	verticalReversed
	diagonalLTR
	diagonalLTRReversed
	diagonalRTL
	diagonalRTLReversed
)

const (
	letterBytes     = "abcdefghijklmnopqrstuvwxyz"
	fitWordAttempts = 1000
	boardAttempts   = 5000
)

type gameBoard [][]string

func readWordList(path string) (lines []string, err error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, strings.ToLower(scanner.Text()))
	}
	return lines, scanner.Err()
}

func makeBoard(x int, y int) (board gameBoard) {
	board = make(gameBoard, y)
	for i := range board {
		board[i] = make([]string, x)
	}
	return
}

func reverse(s string) string {
	chars := []rune(s)
	for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
		chars[i], chars[j] = chars[j], chars[i]
	}
	return string(chars)
}

func fitHorizontal(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = rand.Intn(y)
		found = iy+len(word) < y
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix][iy+j] == "" {
			(*board)[ix][iy+j] = c
		} else {
			return false
		}
	}
	return true
}

func fitHorizontalReversed(board *gameBoard, word string) bool {
	return fitHorizontal(board, reverse(word))
}

func fitVertical(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = rand.Intn(y)
		found = ix+len(word) < x
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix+j][iy] == "" {
			(*board)[ix+j][iy] = c
		} else {
			return false
		}
	}
	return true
}

func fitVerticalReversed(board *gameBoard, word string) bool {
	return fitVertical(board, reverse(word))
}

func fitDiagonalLTR(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = rand.Intn(y)
		found = ix+len(word) < x && iy+len(word) < y
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix+j][iy+j] == "" {
			(*board)[ix+j][iy+j] = c
		} else {
			return false
		}
	}
	return true
}

func fitDiagonalLTRReversed(board *gameBoard, word string) bool {
	return fitDiagonalLTR(board, reverse(word))
}

func fitDiagonalRTL(board *gameBoard, word string) bool {
	x := len(*board)
	y := len((*board)[0])
	var ix, iy int
	found := false
	attempts := 0
	for !found {
		ix = rand.Intn(x)
		iy = len(word) + rand.Intn(y-len(word))
		found = ix+len(word) < x && iy-len(word) >= 0
		attempts++
		if attempts > fitWordAttempts {
			return false
		}
	}

	for j, c := range strings.Split(word, "") {
		if (*board)[ix+j][iy-j] == "" {
			(*board)[ix+j][iy-j] = c
		} else {
			return false
		}
	}
	return true
}

func fitDiagonalRTLReversed(board *gameBoard, word string) bool {
	return fitDiagonalRTL(board, reverse(word))
}

func fitWord(board *gameBoard, word string) bool {
	wordDirection := rand.Intn(diagonalRTLReversed + 1)
	w := strings.Replace(word, " ", "", -1)
	switch wordDirection {
	case horizontal:
		return fitHorizontal(board, w)
	case horizontalReversed:
		return fitHorizontalReversed(board, w)
	case vertical:
		return fitVertical(board, w)
	case verticalReversed:
		return fitVerticalReversed(board, w)
	case diagonalLTR:
		return fitDiagonalLTR(board, w)
	case diagonalLTRReversed:
		return fitDiagonalLTRReversed(board, w)
	case diagonalRTL:
		return fitDiagonalRTL(board, w)
	case diagonalRTLReversed:
		return fitDiagonalRTLReversed(board, w)
	}
	return false
}

func buildBoard(board *gameBoard, words []string) bool {
	for _, word := range words {
		if !fitWord(board, word) {
			return false
		}
	}
	return true
}

func getRandomLetter() string {
	return string(letterBytes[rand.Intn(len(letterBytes))])
	// return "."
}

func fillBoard(board *gameBoard) {
	for i := range *board {
		for j := range (*board)[i] {
			if (*board)[i][j] == "" {
				(*board)[i][j] = getRandomLetter()
			}
		}
	}
}

func printBoard(board *gameBoard) {
	for i := range *board {
		for j := range (*board)[i] {
			c := (*board)[i][j]
			if c == "" {
				c = " "
			}
			fmt.Print(c)
		}
		fmt.Print("\n")
	}
}

func htmlBoard(board *gameBoard, words []string, output string) {
	f, err := os.Create(output)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return
	}
	defer f.Close()
	fmt.Fprintln(f, `<div style="float:left">`)
	fmt.Fprintln(f, `<table style="font-family:'Lucida Console', monospace">`)
	for i := range *board {
		fmt.Fprintln(f, `<tr style="padding: 0; margin: 0">`)
		for j := range (*board)[i] {
			c := (*board)[i][j]
			fmt.Fprintf(f, `<td style="padding: 0; margin: 0; height: 20px; width: 20px">%s</td>`, c)
		}
		fmt.Fprintln(f, "
")
	}
	fmt.Fprintln(f, "
")
	fmt.Fprintln(f, "
")
	fmt.Fprintln(f, `<div style="float:left">`)
	fmt.Fprintln(f, `<ul style="list-style: none;">`)
	for _, word := range words {
		fmt.Fprintf(f, "
%s
\n", word)
	}
	fmt.Fprintln(f, "
")
	fmt.Fprintln(f, "
")
}

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	wordList, err := readWordList("wordlist.txt")
	if err != nil {
		fmt.Println("Error:", err.Error())
		return
	}
	fmt.Println(wordList)
	boardSize := 15
	maxBoardSize := 35
	for i := 0; i < boardAttempts; i++ {
		if (i%1000) == 0 && boardSize < maxBoardSize {
			boardSize += 5
		}
		board := makeBoard(boardSize, boardSize)
		built := buildBoard(&board, wordList)
		if built {
			fillBoard(&board)
			printBoard(&board)
			htmlBoard(&board, wordList, "output.html")
			fmt.Println("output.html saved with board size:", boardSize)
			return
		}
	}
	fmt.Println("Error: couldn't fit words")
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"strings"
	"time"

	"github.com/arthurkiller/mqttState/packets"
)

var tcpconn = func(address string) (net.Conn, time.Duration, error) {
	var err error
	s := time.Now()
	conn, err := net.DialTimeout("TCP", address, 5*time.Second)
	t := time.Since(s)
	if err != nil {
		log.Println(err)
		return nil, time.Duration(0), err
	}
	return conn, t, nil
}

var dnslookup = func(address string) (string, time.Duration, error) {
	var err error
	s := time.Now()
	ns, err := net.LookupHost("www.baidu.com")
	t := time.Since(s)
	if err != nil {
		log.Println(err)
		return "", time.Duration(0), err
	}
	return ns[0], t, nil
}

var tlshandshake = func(conn net.Conn, cfg *tls.Config) (net.Conn, time.Duration, error) {
	var err error
	conntls := tls.Client(conn, cfg)
	s := time.Now()
	err = conntls.Handshake()
	t := time.Since(s)
	if err != nil {
		log.Println(err)
		return nil, time.Duration(0), err
	}
	return conntls, t, nil
}

var httprequest = func() {}

var buildMQTTpacket = func() packets.ControlPacket {
	mp := packets.NewControlPacket(packets.Connect).(*packets.ConnectPacket)
	mp.ClientIdentifier = "test"
	mp.ProtocolName = "MQTT"
	mp.ProtocolVersion = byte(4)
	mp.Username = "test"
	mp.Keepalive = uint16(1)
	mp.CleanSession = true
	mp.WillFlag = false
	mp.WillRetain = false
	mp.Dup = false
	mp.PasswordFlag = false
	mp.Qos = 1
	mp.Retain = false
	return mp
}

func main() {
	addr := flag.String("server", "tls://172.16.200.11:1884", "set for the addr with the style tcp:// | tls:// | http:// | https://")
	num := flag.Int("count", 20, "the testing secquence times")
	ca := flag.String("ca", "", "set the certific key path")
	pem := flag.String("pem", "", "set the certific pem path")
	tcpfilter := flag.Int("tcpfilter", 100, "the filter of tcp connecting cost")
	tlsfilter := flag.Int("tlsfilter", 150, "the filter of tls connecting cost")
	mqttfilter := flag.Int("mqttfilter", 100, "the filter of mqtt connecting cost")
	flag.Parse()
	_ = ca

	ss := strings.Split(*addr, "://")
	if len(ss) == 1 {
		flag.Usage()
		return
	}

	var sumdns time.Duration
	var sumtcp time.Duration
	var sumtls time.Duration
	var summqtt time.Duration
	var withTLS bool = false
	var needDNS bool = true
	var tlsConfig = &tls.Config{}

	if ss[0] == "https" || ss[0] == "tls" {
		withTLS = true
	}
	if ss[1][0] <= 57 && ss[1][0] >= 48 {
		needDNS = false
	}

	if withTLS {
		if *pem != "" && *ca != "" {
			ca_b, err := ioutil.ReadFile(*pem)
			if err != nil {
				return
			}
			cas, err := x509.ParseCertificate(ca_b)
			if err != nil {
				return
			}
			priv_b, err := ioutil.ReadFile(*ca)
			if err != nil {
				return
			}
			priv, err := x509.ParsePKCS1PrivateKey(priv_b)
			if err != nil {
				return
			}
			pool := x509.NewCertPool()
			pool.AddCert(cas)
			cert := tls.Certificate{
				Certificate: [][]byte{ca_b},
				PrivateKey:  priv,
			}

			tlsConfig = &tls.Config{
				ClientAuth:   tls.VerifyClientCertIfGiven,
				Certificates: []tls.Certificate{cert},
			}
		} else {
			tlsConfig = &tls.Config{InsecureSkipVerify: true, ClientAuth: tls.NoClientCert}
		}
	} else {
		tlsConfig = &tls.Config{InsecureSkipVerify: true, ClientAuth: tls.NoClientCert}
	}

	mp := buildMQTTpacket()

	for i := 0; i < *num; i++ {
		var server string
		var t0 time.Duration = 0
		if needDNS {
			s, t, err := dnslookup(ss[1])
			_ = server
			if err != nil {
				log.Println(err)
			}
			t0 = t
			server = s
			sumdns += t0
		}

		//do tcp cost test
		conn, t1, err := tcpconn(server)
		if err != nil {
			log.Println(err)
		}
		sumtcp += t1

		//do tls cost test
		var t2 time.Duration = 0
		if withTLS {
			conntls, t, err := tlshandshake(conn, tlsConfig)
			if err != nil {
				log.Println(err)
			}
			conn = conntls
			t2 = t
			sumtls += t
		}

		//with http

		//do mqtt test
		t := time.Now()
		mp.Write(conn)
		ca, err := packets.ReadPacket(conn)
		t3 := time.Since(t)
		if _, ok := ca.(*packets.ConnackPacket); err != nil || !ok {
			log.Println(err, ca)
		}
		summqtt += t3

		//do print
		trans := func(filter int) time.Duration {
			return time.Duration(time.Millisecond * time.Duration(filter))
		}

		if needDNS {
			if t1 > trans(*tcpfilter) || t2 > trans(*tlsfilter) || t3 > trans(*mqttfilter) {
				fmt.Printf("%c[1;40;31mIn connection sequence%4v: costs %12v %12v %12v %12v %c[0m\n", 0x1B, i, t0.String(), t1.String(), t2.String(), t3.String(), 0x1B)
			} else {
				fmt.Printf("In connection sequence%4v: costs %12v %12v %12v %12v \n", i, t0.String(), t1.String(), t2.String(), t3.String())
			}
		} else {
			if t1 > trans(*tcpfilter) || t2 > trans(*tlsfilter) || t3 > trans(*mqttfilter) {
				fmt.Printf("%c[1;40;31mIn connection sequence%4v: costs %12v %12v %12v %c[0m\n", 0x1B, i, t1.String(), t2.String(), t3.String(), 0x1B)
			} else {
				fmt.Printf("In connection sequence%4v: costs %12v %12v %12v \n", i, t1.String(), t2.String(), t3.String())
			}

		}
		conn.Close()
	}
	fmt.Println("tcp cost:", (sumtcp / time.Duration(*num)).String())
	fmt.Println("tls cost:", (sumtls / time.Duration(*num)).String())
	fmt.Println("mqtt cost:", (summqtt / time.Duration(*num)).String())
}
<commit_msg>make up print<commit_after>package main

import (
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"strings"
	"time"

	"github.com/arthurkiller/mqttState/packets"
)

var tcpconn = func(address string) (net.Conn, time.Duration, error) {
	var err error
	s := time.Now()
	conn, err := net.DialTimeout("TCP", address, 5*time.Second)
	t := time.Since(s)
	if err != nil {
		log.Println(err)
		return nil, time.Duration(0), err
	}
	return conn, t, nil
}

var dnslookup = func(address string) (string, time.Duration, error) {
	var err error
	s := time.Now()
	ns, err := net.LookupHost("www.baidu.com")
	t := time.Since(s)
	if err != nil {
		log.Println(err)
		return "", time.Duration(0), err
	}
	return ns[0], t, nil
}

var tlshandshake = func(conn net.Conn, cfg *tls.Config) (net.Conn, time.Duration, error) {
	var err error
	conntls := tls.Client(conn, cfg)
	s := time.Now()
	err = conntls.Handshake()
	t := time.Since(s)
	if err != nil {
		log.Println(err)
		return nil, time.Duration(0), err
	}
	return conntls, t, nil
}

var httprequest = func() {}

var buildMQTTpacket = func() packets.ControlPacket {
	mp := packets.NewControlPacket(packets.Connect).(*packets.ConnectPacket)
	mp.ClientIdentifier = "test"
	mp.ProtocolName = "MQTT"
	mp.ProtocolVersion = byte(4)
	mp.Username = "test"
	mp.Keepalive = uint16(1)
	mp.CleanSession = true
	mp.WillFlag = false
	mp.WillRetain = false
	mp.Dup = false
	mp.PasswordFlag = false
	mp.Qos = 1
	mp.Retain = false
	return mp
}

func main() {
	addr := flag.String("server", "tls://172.16.200.11:1884", "set for the addr with the style tcp:// | tls:// | http:// | https://")
	num := flag.Int("count", 20, "the testing secquence times")
	ca := flag.String("ca", "", "set the certific key path")
	pem := flag.String("pem", "", "set the certific pem path")
	tcpfilter := flag.Int("tcpfilter", 100, "the filter of tcp connecting cost")
	tlsfilter := flag.Int("tlsfilter", 150, "the filter of tls connecting cost")
	mqttfilter := flag.Int("mqttfilter", 100, "the filter of mqtt connecting cost")
	flag.Parse()
	_ = ca

	ss := strings.Split(*addr, "://")
	if len(ss) == 1 {
		flag.Usage()
		return
	}

	var sumdns time.Duration
	var sumtcp time.Duration
	var sumtls time.Duration
	var summqtt time.Duration
	var withTLS bool = false
	var needDNS bool = true
	var tlsConfig = &tls.Config{}

	if ss[0] == "https" || ss[0] == "tls" {
		withTLS = true
	}
	if ss[1][0] <= 57 && ss[1][0] >= 48 {
		needDNS = false
	}

	if withTLS {
		if *pem != "" && *ca != "" {
			ca_b, err := ioutil.ReadFile(*pem)
			if err != nil {
				return
			}
			cas, err := x509.ParseCertificate(ca_b)
			if err != nil {
				return
			}
			priv_b, err := ioutil.ReadFile(*ca)
			if err != nil {
				return
			}
			priv, err := x509.ParsePKCS1PrivateKey(priv_b)
			if err != nil {
				return
			}
			pool := x509.NewCertPool()
			pool.AddCert(cas)
			cert := tls.Certificate{
				Certificate: [][]byte{ca_b},
				PrivateKey:  priv,
			}

			tlsConfig = &tls.Config{
				ClientAuth:   tls.VerifyClientCertIfGiven,
				Certificates: []tls.Certificate{cert},
			}
		} else {
			tlsConfig = &tls.Config{InsecureSkipVerify: true, ClientAuth: tls.NoClientCert}
		}
	} else {
		tlsConfig = &tls.Config{InsecureSkipVerify: true, ClientAuth: tls.NoClientCert}
	}

	mp := buildMQTTpacket()

	for i := 0; i < *num; i++ {
		var server string
		var t0 time.Duration = 0
		if needDNS {
			s, t, err := dnslookup(ss[1])
			_ = server
			if err != nil {
				log.Println(err)
			}
			t0 = t
			server = s
			sumdns += t0
		}

		//do tcp cost test
		conn, t1, err := tcpconn(server)
		if err != nil {
			log.Println(err)
		}
		sumtcp += t1

		//do tls cost test
		var t2 time.Duration = 0
		if withTLS {
			conntls, t, err := tlshandshake(conn, tlsConfig)
			if err != nil {
				log.Println(err)
			}
			conn = conntls
			t2 = t
			sumtls += t
		}

		//with http

		//do mqtt test
		t := time.Now()
		mp.Write(conn)
		ca, err := packets.ReadPacket(conn)
		t3 := time.Since(t)
		if _, ok := ca.(*packets.ConnackPacket); err != nil || !ok {
			log.Println(err, ca)
		}
		summqtt += t3

		//do print
		trans := func(filter int) time.Duration {
			return time.Duration(time.Millisecond * time.Duration(filter))
		}

		if needDNS {
			if withTLS {
				if t1 > trans(*tcpfilter) || t2 > trans(*tlsfilter) || t3 > trans(*mqttfilter) {
					fmt.Printf("%c[1;40;31mIn connection sequence%4v: costs %12v %12v %12v %12v %c[0m\n", 0x1B, i, t0.String(), t1.String(), t2.String(), t3.String(), 0x1B)
				} else {
					fmt.Printf("In connection sequence%4v: costs %12v %12v %12v %12v \n", i, t0.String(), t1.String(), t2.String(), t3.String())
				}
			} else {
				if t1 > trans(*tcpfilter) || t2 > trans(*tlsfilter) || t3 > trans(*mqttfilter) {
					fmt.Printf("%c[1;40;31mIn connection sequence%4v: costs %12v %12v %12v %c[0m\n", 0x1B, i, t0.String(), t1.String(), t3.String(), 0x1B)
				} else {
					fmt.Printf("In connection sequence%4v: costs %12v %12v %12v \n", i, t0.String(), t1.String(), t3.String())
				}
			}
		} else {
			if withTLS {
				if t1 > trans(*tcpfilter) || t2 > trans(*tlsfilter) || t3 > trans(*mqttfilter) {
					fmt.Printf("%c[1;40;31mIn connection sequence%4v: costs %12v %12v %12v %c[0m\n", 0x1B, i, t1.String(), t2.String(), t3.String(), 0x1B)
				} else {
					fmt.Printf("In connection sequence%4v: costs %12v %12v %12v \n", i, t1.String(), t2.String(), t3.String())
				}
			} else {
				if t1 > trans(*tcpfilter) || t2 > trans(*tlsfilter) || t3 > trans(*mqttfilter) {
					fmt.Printf("%c[1;40;31mIn connection sequence%4v: costs %12v %12v %c[0m\n", 0x1B, i, t1.String(), t3.String(), 0x1B)
				} else {
					fmt.Printf("In connection sequence%4v: costs %12v %12v \n", i, t1.String(), t3.String())
				}
			}
		}
		conn.Close()
	}

	//summary
	if needDNS {
		fmt.Println("nds cost:", (sumdns / time.Duration(*num)).String())
	}
	fmt.Println("tcp cost:", (sumtcp / time.Duration(*num)).String())
	if withTLS {
		fmt.Println("tls cost:", (sumtls / time.Duration(*num)).String())
	}
	fmt.Println("mqtt cost:", (summqtt / time.Duration(*num)).String())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	r "reflect"
	"strings"
)

func main() {
	var fp *os.File
	var err error

	// パース対象の xml ファイル名を引数に受ける
	fp, err = os.Open(os.Args[1])
	if err != nil {
		panic(err)
	}
	defer fp.Close()

	reader := bufio.NewReaderSize(fp, 4096)

	var m map[string]string = map[string]string{}
	var shouldSet bool
	var key string
	d := xml.NewDecoder(reader)
	for {
		token, err := d.Token()
		if err == io.EOF {
			err = nil
			break
		}
		if err != nil {
			panic(err)
		}
		switch token.(type) {
		case xml.StartElement:
			if token.(xml.StartElement).Name.Local == "key" {
				shouldSet = false
			} else {
				shouldSet = true
			}
		case xml.EndElement:
			//do nothing
		case xml.CharData:
			if string(token.(xml.CharData)) == "Track ID" {
				// CharData が Track ID が来る＝今まで処理対象だったレコードの終了処理をする ＆ 次のレコードに処理を移す
				s1 := playData{}
				MapToStruct(m, &s1)
				fmt.Println(s1)
				m = map[string]string{}
			}
			if shouldSet && key != "" {
				m[key] = string(token.(xml.CharData))
				key = ""
			} else {
				key = string(token.(xml.CharData))
			}
		case xml.Comment:
			//do nothing
		case xml.ProcInst:
			//do nothing
		case xml.Directive:
			//do nothing
		default:
			panic("unknown xml token.")
		}
	}
}

func MapToStruct(mapVal map[string]string, val interface{}) (ok bool) {
	structVal := r.Indirect(r.ValueOf(val))
	for name, elem := range mapVal {
		// ここで来る name は　plist の key エレメントの値なのでスペースを含んでいる。
		// 一方 struct のフィールド名からはスペースを除去している。
		f := structVal.FieldByName(strings.Replace(name, " ", "", -1))
		if f.IsValid() {
			f.Set(r.ValueOf(elem))
		}
	}
	return
}

type playData struct {
	Artist               string
	Album                string
	Genre                string
	Kind                 string
	Size                 string
	TotalTime            string
	TrackNumber          string
	DateModified         string
	DateAdded            string
	BitRate              string
	SampleRate           string
	PersistentID         string
	TrackType            string
	Location             string
	FileFolderCount      string
	LibraryFolderCount   string
	PlayCount            string
	PlayDate             string
	PlayDateUTC          string
	Rating               string
	AlbumRating          string
	AlbumRatingComputed  string
	ArtworkCount         string
	SkipCount            string
	SkipDate             string
	Disabled             string
	SortAlbum            string
	Year                 string
	Comments             string
	SortName             string
	SortArtist           string
	VolumeAdjustment     string
	AlbumArtist          string
	DiscNumber           string
	DiscCount            string
	TrackCount           string
	ReleaseDate          string
	Protected            string
	Purchased            string
	Compilation          string
	Composer             string
	HasVideo             string
	VideoWidth           string
	VideoHeight          string
	Movie                string
	Master               string
	PlaylistID           string
	PlaylistPersistentID string
	Visible              string
	AllItems             string
	PlaylistItems        string
	SmartCriteria        string
}
<commit_msg>楽曲の再生情報をスライスに蓄積<commit_after>package main

import (
	"bufio"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	r "reflect"
	"strings"
)

func main() {
	var fp *os.File
	var err error

	// パース対象の xml ファイル名を引数に受ける
	fp, err = os.Open(os.Args[1])
	if err != nil {
		panic(err)
	}
	defer fp.Close()

	reader := bufio.NewReaderSize(fp, 4096)

	var m map[string]string = map[string]string{}
	var playDataList []playData
	var shouldSet bool
	var key string
	d := xml.NewDecoder(reader)
	for {
		token, err := d.Token()
		if err == io.EOF {
			err = nil
			break
		}
		if err != nil {
			panic(err)
		}
		switch token.(type) {
		case xml.StartElement:
			if token.(xml.StartElement).Name.Local == "key" {
				shouldSet = false
			} else {
				shouldSet = true
			}
		case xml.EndElement:
			//do nothing
		case xml.CharData:
			if string(token.(xml.CharData)) == "Track ID" {
				// CharData が Track ID が来る＝今まで処理対象だったレコードの終了処理をする ＆ 次のレコードに処理を移す
				d := playData{}
				MapToStruct(m, &d)

				if d.TrackNumber != "" {
					playDataList = append(playDataList, d)
					fmt.Println(d)
				}

				m = map[string]string{}
			}
			if shouldSet && key != "" {
				m[key] = string(token.(xml.CharData))
				key = ""
			} else {
				key = string(token.(xml.CharData))
			}
		case xml.Comment:
			//do nothing
		case xml.ProcInst:
			//do nothing
		case xml.Directive:
			//do nothing
		default:
			panic("unknown xml token.")
		}
	}
}

func MapToStruct(mapVal map[string]string, val interface{}) (ok bool) {
	structVal := r.Indirect(r.ValueOf(val))
	for name, elem := range mapVal {
		// ここで来る name は　plist の key エレメントの値なのでスペースを含んでいる。
		// 一方 struct のフィールド名からはスペースを除去している。
		f := structVal.FieldByName(strings.Replace(name, " ", "", -1))
		if f.IsValid() {
			f.Set(r.ValueOf(elem))
		}
	}
	return
}

type playData struct {
	Artist               string
	Album                string
	Genre                string
	Kind                 string
	Size                 string
	TotalTime            string
	TrackNumber          string
	DateModified         string
	DateAdded            string
	BitRate              string
	SampleRate           string
	PersistentID         string
	TrackType            string
	Location             string
	FileFolderCount      string
	LibraryFolderCount   string
	PlayCount            string
	PlayDate             string
	PlayDateUTC          string
	Rating               string
	AlbumRating          string
	AlbumRatingComputed  string
	ArtworkCount         string
	SkipCount            string
	SkipDate             string
	Disabled             string
	SortAlbum            string
	Year                 string
	Comments             string
	SortName             string
	SortArtist           string
	VolumeAdjustment     string
	AlbumArtist          string
	DiscNumber           string
	DiscCount            string
	TrackCount           string
	ReleaseDate          string
	Protected            string
	Purchased            string
	Compilation          string
	Composer             string
	HasVideo             string
	VideoWidth           string
	VideoHeight          string
	Movie                string
	Master               string
	PlaylistID           string
	PlaylistPersistentID string
	Visible              string
	AllItems             string
	PlaylistItems        string
	SmartCriteria        string
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"text/tabwriter"

	"github.com/alecthomas/kingpin"
	"github.com/getantibody/antibody/antibodylib"
	"github.com/getantibody/antibody/project"
	"github.com/getantibody/antibody/shell"
	"github.com/getantibody/folder"
	"golang.org/x/crypto/ssh/terminal"
)

// nolint: gochecknoglobals
var (
	version = "dev"

	app         = kingpin.New("antibody", "The fastest shell plugin manager")
	parallelism = app.Flag("parallelism", "max amount of tasks to launch in parallel").
			Short('p').
			Default(strconv.Itoa(runtime.NumCPU())).
			Int()
	bundleCmd = app.Command("bundle", "downloads a bundle and prints its source line")
	bundles   = bundleCmd.Arg("bundles", "bundle list").Strings()
	updateCmd = app.Command("update", "updates all previously bundled bundles")
	homeCmd   = app.Command("home", "prints where antibody is cloning the bundles")
	purgeCmd  = app.Command("purge", "purges a bundle from your computer")
	purgee    = purgeCmd.Arg("bundle", "bundle to be purged").Required().String()
	listCmd   = app.Command("list", "lists all currently installed bundles").Alias("ls")
	initCmd   = app.Command("init", "initializes the shell so Antibody can work as expected")
)

// nolint: gochecknoinits
func init() {
	log.SetOutput(os.Stderr)
	log.SetPrefix("antibody: ")
	log.SetFlags(0)
}

func main() {
	app.Author("Carlos Alexandro Becker <caarlos0@gmail.com>")
	app.Version("antibody version " + version)
	app.VersionFlag.Short('v')
	app.HelpFlag.Short('h')

	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case bundleCmd.FullCommand():
		bundle()
	case updateCmd.FullCommand():
		update()
	case homeCmd.FullCommand():
		fmt.Println(antibodylib.Home())
	case purgeCmd.FullCommand():
		purge()
	case listCmd.FullCommand():
		list()
	case initCmd.FullCommand():
		sh, err := shell.Init()
		app.FatalIfError(err, "failed to init")
		fmt.Println(sh)
	}
}

func bundle() {
	var input io.Reader
	if !terminal.IsTerminal(int(os.Stdin.Fd())) && len(*bundles) == 0 {
		input = os.Stdin
	} else {
		input = bytes.NewBufferString(strings.Join(*bundles, " "))
	}
	sh, err := antibodylib.New(antibodylib.Home(), input, *parallelism).Bundle()
	app.FatalIfError(err, "failed to bundle")
	fmt.Println(sh)
}

func update() {
	var home = antibodylib.Home()
	fmt.Printf("Updating all bundles in %v...\n", home)
	var err = project.Update(home, *parallelism)
	app.FatalIfError(err, "failed to update")
}

func purge() {
	fmt.Println("Removing", *purgee)
	var err = os.RemoveAll(project.New(antibodylib.Home(), *purgee).Path())
	app.FatalIfError(err, "failed to purge")
}

func list() {
	home := antibodylib.Home()
	projects, err := project.List(home)
	app.FatalIfError(err, "failed to list bundles")
	w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', tabwriter.TabIndent)
	for _, b := range projects {
		fmt.Fprintf(w, "%s\t%s\n", folder.ToURL(b), filepath.Join(home, b))
	}
	app.FatalIfError(w.Flush(), "failed to flush")
}
<commit_msg>fix: purge bundle that does not exist<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"text/tabwriter"

	"github.com/alecthomas/kingpin"
	"github.com/getantibody/antibody/antibodylib"
	"github.com/getantibody/antibody/project"
	"github.com/getantibody/antibody/shell"
	"github.com/getantibody/folder"
	"golang.org/x/crypto/ssh/terminal"
)

// nolint: gochecknoglobals
var (
	version = "dev"

	app         = kingpin.New("antibody", "The fastest shell plugin manager")
	parallelism = app.Flag("parallelism", "max amount of tasks to launch in parallel").
			Short('p').
			Default(strconv.Itoa(runtime.NumCPU())).
			Int()
	bundleCmd = app.Command("bundle", "downloads a bundle and prints its source line")
	bundles   = bundleCmd.Arg("bundles", "bundle list").Strings()
	updateCmd = app.Command("update", "updates all previously bundled bundles")
	homeCmd   = app.Command("home", "prints where antibody is cloning the bundles")
	purgeCmd  = app.Command("purge", "purges a bundle from your computer")
	purgee    = purgeCmd.Arg("bundle", "bundle to be purged").Required().String()
	listCmd   = app.Command("list", "lists all currently installed bundles").Alias("ls")
	initCmd   = app.Command("init", "initializes the shell so Antibody can work as expected")
)

// nolint: gochecknoinits
func init() {
	log.SetOutput(os.Stderr)
	log.SetPrefix("antibody: ")
	log.SetFlags(0)
}

func main() {
	app.Author("Carlos Alexandro Becker <caarlos0@gmail.com>")
	app.Version("antibody version " + version)
	app.VersionFlag.Short('v')
	app.HelpFlag.Short('h')

	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case bundleCmd.FullCommand():
		bundle()
	case updateCmd.FullCommand():
		update()
	case homeCmd.FullCommand():
		fmt.Println(antibodylib.Home())
	case purgeCmd.FullCommand():
		purge()
	case listCmd.FullCommand():
		list()
	case initCmd.FullCommand():
		sh, err := shell.Init()
		app.FatalIfError(err, "failed to init")
		fmt.Println(sh)
	}
}

func bundle() {
	var input io.Reader
	if !terminal.IsTerminal(int(os.Stdin.Fd())) && len(*bundles) == 0 {
		input = os.Stdin
	} else {
		input = bytes.NewBufferString(strings.Join(*bundles, " "))
	}
	sh, err := antibodylib.New(antibodylib.Home(), input, *parallelism).Bundle()
	app.FatalIfError(err, "failed to bundle")
	fmt.Println(sh)
}

func update() {
	var home = antibodylib.Home()
	fmt.Printf("Updating all bundles in %v...\n", home)
	var err = project.Update(home, *parallelism)
	app.FatalIfError(err, "failed to update")
}

func purge() {
	fmt.Printf("Removing %s...\n", *purgee)
	var path = project.New(antibodylib.Home(), *purgee).Path()
	if _, err := os.Stat(path); os.IsNotExist(err) {
		app.Fatalf("%s does not exist on expected location: %s", *purgee, path)
	}
	app.FatalIfError(os.RemoveAll(path), "failed to purge")
	fmt.Println("removed!")
}

func list() {
	home := antibodylib.Home()
	projects, err := project.List(home)
	app.FatalIfError(err, "failed to list bundles")
	w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', tabwriter.TabIndent)
	for _, b := range projects {
		fmt.Fprintf(w, "%s\t%s\n", folder.ToURL(b), filepath.Join(home, b))
	}
	app.FatalIfError(w.Flush(), "failed to flush")
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/victorystick/subfix/subtitles"
	"flag"
	"fmt"
	"os"
	"io/ioutil"
	"time"
)

// usage:
// subfix file delay
func main() {
	flag.Parse()

	if flag.NArg() < 1 || flag.NArg() > 2 {
		printUsage()
		os.Exit(0)
	}

	filename := flag.Arg(0)

	if flag.NArg() == 1 {
		validateSubtitles(filename)

		fmt.Println(filename + " was successfully parsed.")
	} else {
		shift, err := time.ParseDuration(flag.Arg(1))

		die(err)

		subs := shiftSubtitles(filename, shift)

		ioutil.WriteFile(filename, []byte(subs.Srt()), 0)
	}
}

func validateSubtitles(filename string) {
	_, err := subtitles.ReadFile(filename)

	die(err)
}

func shiftSubtitles(filename string, shift time.Duration) *subtitles.Subtitles {
	subs, err := subtitles.ReadFile(filename)

	die(err)

	subs.Shift(shift)

	return subs
}

func die(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func printUsage() {
	fmt.Println("subfix filename delay")
	fmt.Println("\tsupported filetypes:   srt")
	fmt.Println("\texample delays:        4.3s 1200ms")
}
<commit_msg>Added --output flag.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/victorystick/subfix/subtitles"
	"io/ioutil"
	"os"
	"time"
)

var (
	outfile string
)

// usage:
// subfix file delay
func main() {
	flag.StringVar(&outfile, "outfile", "", "Name ouf the output file.")

	flag.Parse()

	if flag.NArg() < 1 || flag.NArg() > 2 {
		printUsage()
		os.Exit(0)
	}

	filename := flag.Arg(0)

	if outfile == "" {
		outfile = filename
	}

	if flag.NArg() == 1 {
		validateSubtitles(filename)

		fmt.Println(filename + " was successfully parsed.")
	} else {
		ext, err := subtitles.Extension(outfile)

		die(err)

		shift, err := time.ParseDuration(flag.Arg(1))

		die(err)

		subs := shiftSubtitles(filename, shift)

		text, err := subs.As(ext)

		die(err)

		err = ioutil.WriteFile(outfile, []byte(text), 0666)

		die(err)
	}
}

func validateSubtitles(filename string) {
	_, err := subtitles.ReadFile(filename)

	die(err)
}

func shiftSubtitles(filename string, shift time.Duration) *subtitles.Subtitles {
	subs, err := subtitles.ReadFile(filename)

	die(err)

	subs.Shift(shift)

	return subs
}

func die(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func printUsage() {
	fmt.Println("subfix filename delay")
	fmt.Println("\tsupported filetypes:   srt")
	fmt.Println("\texample delays:        4.3s 1200ms")
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"github.com/tinzenite/core"
)

const path = "/home/tamino/Music"

func main() {
	var context *core.Context
	var err error
	if core.IsTinzenite(path) {
		context, err = core.Load(path)
	} else {
		context, err = core.Create("Test", path)
	}
	if err != nil {
		log.Fatal(err.Error())
		return
	}
	err = context.Run()
	if err != nil {
		log.Fatal(err.Error())
		return
	}
	context.Kill()
}
<commit_msg>adapted<commit_after>package main

import (
	"log"
	"os"
	"os/signal"

	"github.com/tinzenite/core"
)

const path = "/home/tamino/Music"

func main() {

	channel, err := core.CreateChannel("TestMe", nil)
	if err != nil {
		panic(err)
	}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	address, _ := channel.Address()
	log.Println("ID:\n" + address)
	select {
	case <-c:
		channel.Close()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"gopkg.in/alecthomas/kingpin.v2"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

var (
	version    = "0.4.1"
	user_agent = fmt.Sprint("github-markdown-toc.go v", version)
)

type GHToc []string

//
// Internal
//

// check checks if there whas an error and do panic if it was
func check(e error) {
	if e != nil {
		panic(e)
	}
}

// doHttpReq executes a particullar http request
func doHttpReq(req *http.Request) string {
	req.Header.Set("User-Agent", user_agent)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return ""
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}

	return string(body)
}

// Executes HTTP GET request
func httpGet(url_path string) string {
	req, err := http.NewRequest("GET", url_path, nil)
	if err != nil {
		return ""
	}
	return doHttpReq(req)
}

// httpPost executes HTTP POST with file content
func httpPost(url_path string, file_path string) string {
	file, err := os.Open(file_path)
	if err != nil {
		return ""
	}
	defer file.Close()

	body := &bytes.Buffer{}
	io.Copy(body, file)

	req, err := http.NewRequest("POST", url_path, body)
	req.Header.Set("Content-Type", "text/plain")

	return doHttpReq(req)
}

// removeStuf trims spaces, removes new lines and code tag from a string
func removeStuf(s string) string {
	res := strings.Replace(s, "\n", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.TrimSpace(res)

	return res
}

// Public

// Escapes special characters
func EscapeSpecChars(s string) string {
	specChar := []string{"\\", "`", "*", "_", "{", "}", "#", "+", "-", ".", "!"}
	res := s

	for _, c := range specChar {
		res = strings.Replace(res, c, "\\"+c, -1)
	}
	return res
}

// If path is url then just executes HTTP GET and
// Returns html for this url.
//
// If path is a local path then sends file to the GitHub's
// Markdown -> Html converter and returns html.
func GetHmtlBody(path string) string {
	if IsUrl(path) {
		return httpGet(path)
	} else {
		return ConvertMd2Html(path)
	}
}

// Check if string is url
func IsUrl(candidate string) bool {
	u, err := url.Parse(candidate)
	if err != nil || u.Scheme == "" {
		return false
	}
	return true
}

// Sends Markdown to the github converter
// and returns html.
func ConvertMd2Html(localpath string) string {
	return httpPost("https://api.github.com/markdown/raw", localpath)
}

// Create TOC by html from github
func GrabToc(html string) *GHToc {
	return GrabTocX(html, "")
}

func GrabTocX(html string, absPath string) *GHToc {
	re := `(?si)<h(?P<num>[1-6])>\s*` +
		`<a\s*id="user-content-[^"]*"\s*class="anchor"\s*` +
		`href="(?P<href>[^"]*)"[^>]*>\s*` +
		`<span[^<*]*</span>\s*</a>(?P<name>.*?)</h`
	r := regexp.MustCompile(re)

	toc := GHToc{}
	groups := make(map[string]string)
	for _, match := range r.FindAllStringSubmatch(html, -1) {
		// fill map for groups
		for i, name := range r.SubexpNames() {
			if i == 0 || name == "" {
				continue
			}
			groups[name] = removeStuf(match[i])
		}
		// format result
		n, _ := strconv.Atoi(groups["num"])
		link := groups["href"]
		if len(absPath) > 0 {
			link = absPath + link
		}
		toc_item := strings.Repeat("  ", n) + "* " +
			"[" + EscapeSpecChars(removeStuf(groups["name"])) + "]" +
			"(" + link + ")"
		//fmt.Println(toc_item)
		toc = append(toc, toc_item)
	}

	return &toc
}

// Generate TOC for document (path in filesystem or url)
func GenerateToc(path string) *GHToc {
	return GenerateTocX(path, false)
}

func GenerateTocX(path string, absPaths bool) *GHToc {
	htmlBody := GetHmtlBody(path)
	if absPaths {
		return GrabTocX(htmlBody, path)
	} else {
		return GrabToc(htmlBody)
	}
}

// PrintToc print on console string array
func PrintToc(toc *GHToc) {
	for _, toc_item := range *toc {
		fmt.Println(toc_item)
	}
	fmt.Println()
}

// Entry point
func main() {
	paths_desc := "Local path or URL of the document to grab TOC. " +
		"If not entered, then read Markdown from stdin."
	paths := kingpin.Arg("path", paths_desc).Strings()
	serial := kingpin.Flag("serial", "Grab TOCs in the serial mode").Bool()
	kingpin.Version(version)
	kingpin.Parse()

	pathsCount := len(*paths)

	if pathsCount == 1 {
		fmt.Println()
		fmt.Println("Table of Contents")
		fmt.Println("=================")
		fmt.Println()
	}

	// read file paths | urls from args
	absPathsInToc := pathsCount > 1
	ch := make(chan *GHToc, pathsCount)
	for _, p := range *paths {
		if *serial {
			ch <- GenerateTocX(p, absPathsInToc)
		} else {
			go func(path string, showAbsPath bool) {
				ch <- GenerateTocX(path, absPathsInToc)
			}(p, absPathsInToc)
		}
	}

	for i := 1; i <= pathsCount; i++ {
		PrintToc(<-ch)
	}

	// read md from stdin
	if pathsCount == 0 {
		file, err := ioutil.TempFile(os.TempDir(), "ghtoc")
		check(err)
		defer os.Remove(file.Name())
		file_path, err := filepath.Abs(file.Name())
		check(err)
		bytes, err := ioutil.ReadAll(os.Stdin)
		check(err)
		check(ioutil.WriteFile(file.Name(), bytes, 0644))
		PrintToc(GenerateToc(file_path))
	}

	fmt.Println("Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc.go)")
}
<commit_msg>0.5.0 (fixed new github's layout for readme)<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	version    = "0.5.0"
	user_agent = fmt.Sprint("github-markdown-toc.go v", version)
)

type GHToc []string

//
// Internal
//

// check checks if there whas an error and do panic if it was
func check(e error) {
	if e != nil {
		panic(e)
	}
}

// doHttpReq executes a particullar http request
func doHttpReq(req *http.Request) string {
	req.Header.Set("User-Agent", user_agent)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return ""
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}

	return string(body)
}

// Executes HTTP GET request
func httpGet(url_path string) string {
	req, err := http.NewRequest("GET", url_path, nil)
	if err != nil {
		return ""
	}
	return doHttpReq(req)
}

// httpPost executes HTTP POST with file content
func httpPost(url_path string, file_path string) string {
	file, err := os.Open(file_path)
	if err != nil {
		return ""
	}
	defer file.Close()

	body := &bytes.Buffer{}
	io.Copy(body, file)

	req, err := http.NewRequest("POST", url_path, body)
	req.Header.Set("Content-Type", "text/plain")

	return doHttpReq(req)
}

// removeStuf trims spaces, removes new lines and code tag from a string
func removeStuf(s string) string {
	res := strings.Replace(s, "\n", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.TrimSpace(res)

	return res
}

// Public

// Escapes special characters
func EscapeSpecChars(s string) string {
	specChar := []string{"\\", "`", "*", "_", "{", "}", "#", "+", "-", ".", "!"}
	res := s

	for _, c := range specChar {
		res = strings.Replace(res, c, "\\"+c, -1)
	}
	return res
}

// If path is url then just executes HTTP GET and
// Returns html for this url.
//
// If path is a local path then sends file to the GitHub's
// Markdown -> Html converter and returns html.
func GetHmtlBody(path string) string {
	if IsUrl(path) {
		return httpGet(path)
	} else {
		return ConvertMd2Html(path)
	}
}

// Check if string is url
func IsUrl(candidate string) bool {
	u, err := url.Parse(candidate)
	if err != nil || u.Scheme == "" {
		return false
	}
	return true
}

// Sends Markdown to the github converter
// and returns html.
func ConvertMd2Html(localpath string) string {
	return httpPost("https://api.github.com/markdown/raw", localpath)
}

// Create TOC by html from github
func GrabToc(html string) *GHToc {
	return GrabTocX(html, "")
}

func GrabTocX(html string, absPath string) *GHToc {
	re := `(?si)<h(?P<num>[1-6])>\s*` +
		`<a\s*id="user-content-[^"]*"\s*class="anchor"\s*` +
		`href="(?P<href>[^"]*)"[^>]*>\s*` +
		`.*?</a>(?P<name>.*?)</h`
	r := regexp.MustCompile(re)

	toc := GHToc{}
	groups := make(map[string]string)
	for _, match := range r.FindAllStringSubmatch(html, -1) {
		// fill map for groups
		for i, name := range r.SubexpNames() {
			if i == 0 || name == "" {
				continue
			}
			groups[name] = removeStuf(match[i])
		}
		// format result
		n, _ := strconv.Atoi(groups["num"])
		link := groups["href"]
		if len(absPath) > 0 {
			link = absPath + link
		}
		toc_item := strings.Repeat("  ", n) + "* " +
			"[" + EscapeSpecChars(removeStuf(groups["name"])) + "]" +
			"(" + link + ")"
		//fmt.Println(toc_item)
		toc = append(toc, toc_item)
	}

	return &toc
}

// Generate TOC for document (path in filesystem or url)
func GenerateToc(path string) *GHToc {
	return GenerateTocX(path, false)
}

func GenerateTocX(path string, absPaths bool) *GHToc {
	htmlBody := GetHmtlBody(path)
	if absPaths {
		return GrabTocX(htmlBody, path)
	} else {
		return GrabToc(htmlBody)
	}
}

// PrintToc print on console string array
func PrintToc(toc *GHToc) {
	for _, toc_item := range *toc {
		fmt.Println(toc_item)
	}
	fmt.Println()
}

// Entry point
func main() {
	paths_desc := "Local path or URL of the document to grab TOC. " +
		"If not entered, then read Markdown from stdin."
	paths := kingpin.Arg("path", paths_desc).Strings()
	serial := kingpin.Flag("serial", "Grab TOCs in the serial mode").Bool()
	kingpin.Version(version)
	kingpin.Parse()

	pathsCount := len(*paths)

	if pathsCount == 1 {
		fmt.Println()
		fmt.Println("Table of Contents")
		fmt.Println("=================")
		fmt.Println()
	}

	// read file paths | urls from args
	absPathsInToc := pathsCount > 1
	ch := make(chan *GHToc, pathsCount)
	for _, p := range *paths {
		if *serial {
			ch <- GenerateTocX(p, absPathsInToc)
		} else {
			go func(path string, showAbsPath bool) {
				ch <- GenerateTocX(path, absPathsInToc)
			}(p, absPathsInToc)
		}
	}

	for i := 1; i <= pathsCount; i++ {
		PrintToc(<-ch)
	}

	// read md from stdin
	if pathsCount == 0 {
		file, err := ioutil.TempFile(os.TempDir(), "ghtoc")
		check(err)
		defer os.Remove(file.Name())
		file_path, err := filepath.Abs(file.Name())
		check(err)
		bytes, err := ioutil.ReadAll(os.Stdin)
		check(err)
		check(ioutil.WriteFile(file.Name(), bytes, 0644))
		PrintToc(GenerateToc(file_path))
	}

	fmt.Println("Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc.go)")
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

var debug *bool

const pattConn string = `^([a-z]{3,}):\/\/([^:]+):?([0-9]+)?$`

func logDebug(msg interface{}) {
	if *debug {
		log.Print(msg)
	}
}

// Connection data
type Connection struct {
	Type   string
	Scheme string
	Port   int
	Host   string
}

func buildConn(host string, port int, fullConn string) *Connection {
	if host != "" {
		return &Connection{Type: "tcp", Host: host, Port: port}
	}

	if fullConn == "" {
		return nil
	}

	res := regexp.MustCompile(pattConn).FindAllStringSubmatch(fullConn, -1)[0]
	if len(res) != 4 {
		return nil
	}

	port, err := strconv.Atoi(res[3])
	if err != nil {
		port = 80
	}

	conn := &Connection{Type: res[1], Host: res[2], Port: port}
	if conn.Type != "tcp" {
		conn.Scheme = conn.Type
		conn.Type = "tcp"
	}

	if conn.Scheme == "https" {
		conn.Port = 443
	}

	return conn
}

func pingTCP(conn *Connection, timeoutSeconds int) error {
	timeout := time.Duration(timeoutSeconds) * time.Second
	start := time.Now()
	address := fmt.Sprintf("%s:%d", conn.Host, conn.Port)
	logDebug("Dial adress: " + address)

	for {
		_, err := net.DialTimeout(conn.Type, address, time.Second)
		logDebug("ping TCP")

		if err == nil {
			logDebug("Up")
			return nil
		}

		logDebug("Down")
		logDebug(err)
		if time.Since(start) > timeout {
			return err
		}

		time.Sleep(500 * time.Millisecond)
	}
}

func pingHTTP(conn *Connection, timeoutSeconds int) error {
	timeout := time.Duration(timeoutSeconds) * time.Second
	start := time.Now()
	address := fmt.Sprintf("%s://%s:%d", conn.Scheme, conn.Host, conn.Port)
	logDebug("HTTP adress: " + address)

	for {
		resp, err := http.Get(address)
		logDebug("ping HTTP " + resp.Status)

		if err == nil && resp.StatusCode < http.StatusInternalServerError {
			return nil
		}

		if time.Since(start) > timeout {
			return errors.New(resp.Status)
		}

		time.Sleep(500 * time.Millisecond)
	}
}

func main() {
	fullConn := flag.String("full-connection", "", "full connection")
	host := flag.String("host", "", "host to connect")
	port := flag.Int("port", 80, "port to connect")
	timeout := flag.Int("timeout", 10, "time to wait until port become available")
	version := flag.Bool("v", false, "show the current version")
	debug = flag.Bool("debug", false, "enable debug")

	flag.Parse()

	if *version {
		fmt.Println("waitforit version 1.2.2")
		return
	}

	conn := buildConn(*host, *port, *fullConn)
	if conn == nil {
		log.Fatal("Invalid connection")
	}

	logDebug("Waiting " + strconv.Itoa(*timeout) + " seconds")
	if err := pingTCP(conn, *timeout); err != nil {
		log.Fatal(err)
	}

	if conn.Scheme != "http" && conn.Scheme != "https" {
		return
	}

	if err := pingHTTP(conn, *timeout); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add support to check endpoints with URL path<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

var debug *bool

const regexAddressConn string = `^([a-z]{3,}):\/\/([^:]+):?([0-9]+)?$`
const regexPathAddressConn string = `^([^\/]+)(\/?.*)$`

func logDebug(msg interface{}) {
	if *debug {
		log.Print(msg)
	}
}

// Connection data
type Connection struct {
	Type   string
	Scheme string
	Port   int
	Host   string
	Path   string
}

func buildConn(host string, port int, fullConn string) *Connection {
	if host != "" {
		return &Connection{Type: "tcp", Host: host, Port: port}
	}

	if fullConn == "" {
		return nil
	}

	res := regexp.MustCompile(regexAddressConn).FindAllStringSubmatch(fullConn, -1)[0]
	if len(res) != 4 {
		return nil
	}

	port, err := strconv.Atoi(res[3])
	if err != nil {
		port = 80
	}

	hostAndPath := regexp.MustCompile(regexPathAddressConn).FindAllStringSubmatch(res[2], -1)[0]
	conn := &Connection{
		Type: res[1],
		Port: port,
		Host: hostAndPath[1],
		Path: hostAndPath[2],
	}

	if conn.Type != "tcp" {
		conn.Scheme = conn.Type
		conn.Type = "tcp"
	}

	if conn.Scheme == "https" {
		conn.Port = 443
	}

	return conn
}

func pingTCP(conn *Connection, timeoutSeconds int) error {
	timeout := time.Duration(timeoutSeconds) * time.Second
	start := time.Now()
	address := fmt.Sprintf("%s:%d", conn.Host, conn.Port)
	logDebug("Dial adress: " + address)

	for {
		_, err := net.DialTimeout(conn.Type, address, time.Second)
		logDebug("ping TCP")

		if err == nil {
			logDebug("Up")
			return nil
		}

		logDebug("Down")
		logDebug(err)
		if time.Since(start) > timeout {
			return err
		}

		time.Sleep(500 * time.Millisecond)
	}
}

func pingHTTP(conn *Connection, timeoutSeconds int) error {
	timeout := time.Duration(timeoutSeconds) * time.Second
	start := time.Now()
	address := fmt.Sprintf("%s://%s:%d%s", conn.Scheme, conn.Host, conn.Port, conn.Path)
	logDebug("HTTP adress: " + address)

	for {
		resp, err := http.Get(address)
		logDebug("ping HTTP " + resp.Status)

		if err == nil && resp.StatusCode < http.StatusInternalServerError {
			return nil
		}

		if time.Since(start) > timeout {
			return errors.New(resp.Status)
		}

		time.Sleep(500 * time.Millisecond)
	}
}

func main() {
	fullConn := flag.String("full-connection", "", "full connection")
	host := flag.String("host", "", "host to connect")
	port := flag.Int("port", 80, "port to connect")
	timeout := flag.Int("timeout", 10, "time to wait until port become available")
	version := flag.Bool("v", false, "show the current version")
	debug = flag.Bool("debug", false, "enable debug")

	flag.Parse()

	if *version {
		fmt.Println("waitforit version 1.2.2")
		return
	}

	conn := buildConn(*host, *port, *fullConn)
	if conn == nil {
		log.Fatal("Invalid connection")
	}

	logDebug("Waiting " + strconv.Itoa(*timeout) + " seconds")
	if err := pingTCP(conn, *timeout); err != nil {
		log.Fatal(err)
	}

	if conn.Scheme != "http" && conn.Scheme != "https" {
		return
	}

	if err := pingHTTP(conn, *timeout); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>